@spfunctions/cli 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/client.d.ts +6 -0
  2. package/dist/client.js +20 -0
  3. package/dist/commands/agent.d.ts +1 -0
  4. package/dist/commands/agent.js +914 -14
  5. package/dist/commands/announcements.d.ts +3 -0
  6. package/dist/commands/announcements.js +28 -0
  7. package/dist/commands/balance.d.ts +3 -0
  8. package/dist/commands/balance.js +17 -0
  9. package/dist/commands/cancel.d.ts +5 -0
  10. package/dist/commands/cancel.js +41 -0
  11. package/dist/commands/dashboard.d.ts +11 -0
  12. package/dist/commands/dashboard.js +195 -0
  13. package/dist/commands/explore.d.ts +13 -0
  14. package/dist/commands/explore.js +110 -0
  15. package/dist/commands/fills.d.ts +4 -0
  16. package/dist/commands/fills.js +29 -0
  17. package/dist/commands/forecast.d.ts +4 -0
  18. package/dist/commands/forecast.js +53 -0
  19. package/dist/commands/history.d.ts +3 -0
  20. package/dist/commands/history.js +38 -0
  21. package/dist/commands/milestones.d.ts +8 -0
  22. package/dist/commands/milestones.js +56 -0
  23. package/dist/commands/orders.d.ts +4 -0
  24. package/dist/commands/orders.js +28 -0
  25. package/dist/commands/publish.d.ts +15 -0
  26. package/dist/commands/publish.js +39 -0
  27. package/dist/commands/rfq.d.ts +5 -0
  28. package/dist/commands/rfq.js +35 -0
  29. package/dist/commands/schedule.d.ts +3 -0
  30. package/dist/commands/schedule.js +38 -0
  31. package/dist/commands/settlements.d.ts +6 -0
  32. package/dist/commands/settlements.js +50 -0
  33. package/dist/commands/setup.d.ts +2 -0
  34. package/dist/commands/setup.js +45 -3
  35. package/dist/commands/signal.js +12 -1
  36. package/dist/commands/strategies.d.ts +11 -0
  37. package/dist/commands/strategies.js +130 -0
  38. package/dist/commands/trade.d.ts +12 -0
  39. package/dist/commands/trade.js +78 -0
  40. package/dist/config.d.ts +2 -0
  41. package/dist/config.js +13 -0
  42. package/dist/index.js +182 -3
  43. package/dist/kalshi.d.ts +71 -0
  44. package/dist/kalshi.js +257 -17
  45. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ export declare function announcementsCommand(opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.announcementsCommand = announcementsCommand;
4
+ const kalshi_js_1 = require("../kalshi.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ async function announcementsCommand(opts) {
7
+ const announcements = await (0, kalshi_js_1.getExchangeAnnouncements)();
8
+ if (opts.json) {
9
+ console.log(JSON.stringify(announcements, null, 2));
10
+ return;
11
+ }
12
+ if (announcements.length === 0) {
13
+ console.log(`${utils_js_1.c.dim}No announcements.${utils_js_1.c.reset}`);
14
+ return;
15
+ }
16
+ console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}Exchange Announcements${utils_js_1.c.reset}`);
17
+ console.log(`${utils_js_1.c.dim}${'─'.repeat(70)}${utils_js_1.c.reset}`);
18
+ for (const a of announcements.slice(0, 20)) {
19
+ const time = a.created_time ? new Date(a.created_time).toLocaleDateString() : '';
20
+ const type = a.type ? `[${a.type}]` : '';
21
+ console.log(` ${utils_js_1.c.dim}${time}${utils_js_1.c.reset} ${type} ${a.title || a.message || ''}`);
22
+ if (a.body) {
23
+ const body = String(a.body).slice(0, 120);
24
+ console.log(` ${utils_js_1.c.dim}${body}${utils_js_1.c.reset}`);
25
+ }
26
+ }
27
+ console.log(`\n${utils_js_1.c.dim}${announcements.length} announcement(s)${utils_js_1.c.reset}`);
28
+ }
@@ -0,0 +1,3 @@
1
+ export declare function balanceCommand(opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.balanceCommand = balanceCommand;
4
+ const kalshi_js_1 = require("../kalshi.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ async function balanceCommand(opts) {
7
+ const result = await (0, kalshi_js_1.getBalance)();
8
+ if (!result)
9
+ throw new Error('Kalshi not configured. Set KALSHI_API_KEY_ID + KALSHI_PRIVATE_KEY_PATH.');
10
+ if (opts.json) {
11
+ console.log(JSON.stringify(result, null, 2));
12
+ return;
13
+ }
14
+ console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}Kalshi Account${utils_js_1.c.reset}`);
15
+ console.log(` Balance: $${result.balance.toFixed(2)}`);
16
+ console.log(` Portfolio Value: $${result.portfolioValue.toFixed(2)}`);
17
+ }
@@ -0,0 +1,5 @@
1
+ export declare function cancelCommand(orderId: string | undefined, opts: {
2
+ all?: boolean;
3
+ ticker?: string;
4
+ yesIAmSure?: boolean;
5
+ }): Promise<void>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cancelCommand = cancelCommand;
4
+ const kalshi_js_1 = require("../kalshi.js");
5
+ const config_js_1 = require("../config.js");
6
+ const utils_js_1 = require("../utils.js");
7
+ async function cancelCommand(orderId, opts) {
8
+ (0, config_js_1.requireTrading)();
9
+ if (opts.all) {
10
+ const result = await (0, kalshi_js_1.getOrders)({ status: 'resting', limit: 200 });
11
+ if (!result)
12
+ throw new Error('Kalshi not configured.');
13
+ let toCancel = result.orders;
14
+ if (opts.ticker) {
15
+ toCancel = toCancel.filter((o) => (o.ticker || '').startsWith(opts.ticker));
16
+ }
17
+ if (toCancel.length === 0) {
18
+ console.log(`\n ${utils_js_1.c.dim}No resting orders to cancel.${utils_js_1.c.reset}\n`);
19
+ return;
20
+ }
21
+ console.log(`\n Cancelling ${toCancel.length} order(s)...`);
22
+ if (!opts.yesIAmSure) {
23
+ for (let i = 3; i > 0; i--) {
24
+ process.stdout.write(` Executing in ${i}... (Ctrl+C to cancel)\r`);
25
+ await new Promise(r => setTimeout(r, 1000));
26
+ }
27
+ process.stdout.write(' Executing... \n');
28
+ }
29
+ for (let i = 0; i < toCancel.length; i += 20) {
30
+ const batch = toCancel.slice(i, i + 20).map((o) => o.order_id);
31
+ await (0, kalshi_js_1.batchCancelOrders)(batch);
32
+ }
33
+ console.log(`\n ${utils_js_1.c.green}✓${utils_js_1.c.reset} Cancelled ${toCancel.length} order(s).\n`);
34
+ return;
35
+ }
36
+ if (!orderId) {
37
+ throw new Error('Usage: sf cancel <orderId> or sf cancel --all');
38
+ }
39
+ await (0, kalshi_js_1.cancelOrder)(orderId);
40
+ console.log(`\n ${utils_js_1.c.green}✓${utils_js_1.c.reset} Order ${orderId} cancelled.\n`);
41
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * sf dashboard — Portfolio overview
3
+ *
4
+ * One-screen summary: theses, positions, risk exposure, top unpositioned edges.
5
+ * Uses existing APIs + local Kalshi positions.
6
+ */
7
+ export declare function dashboardCommand(opts?: {
8
+ json?: boolean;
9
+ apiKey?: string;
10
+ apiUrl?: string;
11
+ }): Promise<void>;
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ /**
3
+ * sf dashboard — Portfolio overview
4
+ *
5
+ * One-screen summary: theses, positions, risk exposure, top unpositioned edges.
6
+ * Uses existing APIs + local Kalshi positions.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.dashboardCommand = dashboardCommand;
10
+ const client_js_1 = require("../client.js");
11
+ const kalshi_js_1 = require("../kalshi.js");
12
+ // ── Risk category mapping by Kalshi ticker prefix ────────────────────────────
13
+ const RISK_CATEGORIES = {
14
+ KXWTIMAX: 'Oil',
15
+ KXWTI: 'Oil',
16
+ KXRECSSNBER: 'Recession',
17
+ KXAAAGASM: 'Gas',
18
+ KXCPI: 'Inflation',
19
+ KXINXY: 'S&P 500',
20
+ KXFEDDECISION: 'Fed Rate',
21
+ KXUNEMPLOYMENT: 'Unemployment',
22
+ KXCLOSEHORMUZ: 'Hormuz',
23
+ };
24
+ function categorize(ticker) {
25
+ // Match longest prefix first
26
+ const sorted = Object.keys(RISK_CATEGORIES).sort((a, b) => b.length - a.length);
27
+ for (const prefix of sorted) {
28
+ if (ticker.startsWith(prefix))
29
+ return RISK_CATEGORIES[prefix];
30
+ }
31
+ return 'Other';
32
+ }
33
+ function timeAgo(dateStr) {
34
+ const diff = Date.now() - new Date(dateStr).getTime();
35
+ const mins = Math.floor(diff / 60000);
36
+ if (mins < 60)
37
+ return `${mins}m ago`;
38
+ const hrs = Math.floor(mins / 60);
39
+ if (hrs < 24)
40
+ return `${hrs}h ago`;
41
+ const days = Math.floor(hrs / 24);
42
+ return `${days}d ago`;
43
+ }
44
+ async function dashboardCommand(opts) {
45
+ const client = new client_js_1.SFClient(opts?.apiKey, opts?.apiUrl);
46
+ // ── Fetch data in parallel ─────────────────────────────────────────────────
47
+ const [thesesResult, positions] = await Promise.all([
48
+ client.listTheses(),
49
+ (0, kalshi_js_1.getPositions)().catch(() => null),
50
+ ]);
51
+ const theses = thesesResult.theses || thesesResult;
52
+ // Fetch context for each thesis (edges)
53
+ const contexts = [];
54
+ for (const t of theses) {
55
+ try {
56
+ const ctx = await client.getContext(t.id);
57
+ contexts.push(ctx);
58
+ }
59
+ catch {
60
+ contexts.push(null);
61
+ }
62
+ }
63
+ // Enrich positions with live prices
64
+ if (positions) {
65
+ for (const pos of positions) {
66
+ const livePrice = await (0, kalshi_js_1.getMarketPrice)(pos.ticker);
67
+ if (livePrice !== null) {
68
+ pos.current_value = livePrice;
69
+ pos.unrealized_pnl = Math.round((livePrice - pos.average_price_paid) * pos.quantity);
70
+ }
71
+ }
72
+ }
73
+ // ── Collect all edges across all theses ────────────────────────────────────
74
+ const allEdges = [];
75
+ for (const ctx of contexts) {
76
+ if (!ctx?.edges)
77
+ continue;
78
+ for (const e of ctx.edges) {
79
+ allEdges.push(e);
80
+ }
81
+ }
82
+ // Dedupe edges by marketId (keep highest absolute edge)
83
+ const edgeMap = new Map();
84
+ for (const e of allEdges) {
85
+ const existing = edgeMap.get(e.marketId);
86
+ if (!existing || Math.abs(e.edge) > Math.abs(existing.edge)) {
87
+ edgeMap.set(e.marketId, e);
88
+ }
89
+ }
90
+ // Find positioned tickers
91
+ const positionedTickers = new Set(positions?.map((p) => p.ticker) || []);
92
+ // Unpositioned edges = edges where no position exists on that marketId
93
+ const unpositionedEdges = [...edgeMap.values()]
94
+ .filter(e => !positionedTickers.has(e.marketId))
95
+ .sort((a, b) => Math.abs(b.edge) - Math.abs(a.edge))
96
+ .slice(0, 10);
97
+ // ── JSON output ────────────────────────────────────────────────────────────
98
+ if (opts?.json) {
99
+ console.log(JSON.stringify({
100
+ theses,
101
+ positions,
102
+ unpositionedEdges,
103
+ }, null, 2));
104
+ return;
105
+ }
106
+ // ── Formatted output ───────────────────────────────────────────────────────
107
+ console.log();
108
+ console.log(' SimpleFunctions Dashboard');
109
+ console.log(' ' + '─'.repeat(50));
110
+ console.log();
111
+ // ── Theses ─────────────────────────────────────────────────────────────────
112
+ console.log(' Theses');
113
+ if (theses.length === 0) {
114
+ console.log(' (none)');
115
+ }
116
+ else {
117
+ for (let i = 0; i < theses.length; i++) {
118
+ const t = theses[i];
119
+ const ctx = contexts[i];
120
+ const id = t.id.slice(0, 8);
121
+ const title = (t.title || '').slice(0, 35).padEnd(35);
122
+ const conf = t.confidence != null ? `${Math.round(t.confidence * 100)}%` : '?%';
123
+ const edgeCount = ctx?.edges?.length || 0;
124
+ const updated = t.updatedAt ? timeAgo(t.updatedAt) : '?';
125
+ console.log(` ${id} ${title} ${conf.padStart(4)} ${String(edgeCount).padStart(2)} edges updated ${updated}`);
126
+ }
127
+ }
128
+ console.log();
129
+ // ── Positions ──────────────────────────────────────────────────────────────
130
+ console.log(' Positions');
131
+ if (!positions || positions.length === 0) {
132
+ console.log(' (no Kalshi positions or Kalshi not configured)');
133
+ }
134
+ else {
135
+ let totalCost = 0;
136
+ let totalPnl = 0;
137
+ for (const p of positions) {
138
+ const ticker = (p.ticker || '').padEnd(22);
139
+ const qty = String(p.quantity || 0).padStart(5);
140
+ const avg = `${p.average_price_paid || 0}¢`;
141
+ const now = typeof p.current_value === 'number' ? `${p.current_value}¢` : '?¢';
142
+ const pnlCents = p.unrealized_pnl || 0;
143
+ const pnlDollars = (pnlCents / 100).toFixed(2);
144
+ const pnlStr = pnlCents >= 0 ? `+$${pnlDollars}` : `-$${Math.abs(parseFloat(pnlDollars)).toFixed(2)}`;
145
+ const cost = (p.average_price_paid || 0) * (p.quantity || 0);
146
+ totalCost += cost;
147
+ totalPnl += pnlCents;
148
+ console.log(` ${ticker} ${qty} @ ${avg.padEnd(5)} now ${now.padEnd(5)} ${pnlStr}`);
149
+ }
150
+ console.log(' ' + '─'.repeat(45));
151
+ const totalCostDollars = (totalCost / 100).toFixed(0);
152
+ const totalPnlDollars = (totalPnl / 100).toFixed(2);
153
+ const pnlDisplay = totalPnl >= 0 ? `+$${totalPnlDollars}` : `-$${Math.abs(parseFloat(totalPnlDollars)).toFixed(2)}`;
154
+ console.log(` Total cost: $${totalCostDollars} | P&L: ${pnlDisplay}`);
155
+ }
156
+ console.log();
157
+ // ── Risk Exposure ──────────────────────────────────────────────────────────
158
+ if (positions && positions.length > 0) {
159
+ console.log(' Risk Exposure');
160
+ const riskGroups = new Map();
161
+ for (const p of positions) {
162
+ const cat = categorize(p.ticker || '');
163
+ const existing = riskGroups.get(cat) || { cost: 0, contracts: 0, tickers: [] };
164
+ const cost = (p.average_price_paid || 0) * (p.quantity || 0);
165
+ existing.cost += cost;
166
+ existing.contracts += p.quantity || 0;
167
+ if (!existing.tickers.includes(p.ticker))
168
+ existing.tickers.push(p.ticker);
169
+ riskGroups.set(cat, existing);
170
+ }
171
+ // Sort by cost descending
172
+ const sorted = [...riskGroups.entries()].sort((a, b) => b[1].cost - a[1].cost);
173
+ for (const [category, data] of sorted) {
174
+ const costDollars = `$${(data.cost / 100).toFixed(0)}`;
175
+ const tickerSummary = data.tickers.length <= 2
176
+ ? ` (${data.tickers.join('+')})`
177
+ : ` (${data.tickers.length} markets)`;
178
+ console.log(` ${(category + tickerSummary + ':').padEnd(35)} ${costDollars.padStart(7)} cost | ${String(data.contracts).padStart(5)} contracts`);
179
+ }
180
+ console.log();
181
+ }
182
+ // ── Top Unpositioned Edges ─────────────────────────────────────────────────
183
+ if (unpositionedEdges.length > 0) {
184
+ console.log(' Top Unpositioned Edges');
185
+ for (const e of unpositionedEdges) {
186
+ const name = (e.market || e.marketId || '').slice(0, 25).padEnd(25);
187
+ const mkt = `${e.marketPrice}¢`;
188
+ const thesis = `${e.thesisPrice}¢`;
189
+ const edge = e.edge > 0 ? `+${e.edge}` : `${e.edge}`;
190
+ const liq = e.orderbook?.liquidityScore || '?';
191
+ console.log(` ${name} ${mkt.padStart(5)} → ${thesis.padStart(5)} edge ${edge.padStart(4)} ${liq}`);
192
+ }
193
+ console.log();
194
+ }
195
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * sf explore [slug]
3
+ *
4
+ * Browse public theses. No authentication required.
5
+ *
6
+ * Usage:
7
+ * sf explore — List all public theses
8
+ * sf explore us-iran-war — View a specific public thesis
9
+ * sf explore us-iran-war --json — JSON output (for agents)
10
+ */
11
+ export declare function exploreCommand(slug?: string, opts?: {
12
+ json?: boolean;
13
+ }): Promise<void>;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /**
3
+ * sf explore [slug]
4
+ *
5
+ * Browse public theses. No authentication required.
6
+ *
7
+ * Usage:
8
+ * sf explore — List all public theses
9
+ * sf explore us-iran-war — View a specific public thesis
10
+ * sf explore us-iran-war --json — JSON output (for agents)
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.exploreCommand = exploreCommand;
14
+ const BASE_URL = 'https://simplefunctions.dev';
15
+ async function exploreCommand(slug, opts) {
16
+ if (!slug) {
17
+ // List all public theses
18
+ const res = await fetch(`${BASE_URL}/api/public/theses`);
19
+ if (!res.ok) {
20
+ console.error(` Error: ${res.status} ${await res.text()}`);
21
+ return;
22
+ }
23
+ const { theses } = await res.json();
24
+ if (opts?.json) {
25
+ console.log(JSON.stringify(theses, null, 2));
26
+ return;
27
+ }
28
+ console.log('\n Public Theses\n');
29
+ if (theses.length === 0) {
30
+ console.log(' No public theses yet.\n');
31
+ return;
32
+ }
33
+ for (const t of theses) {
34
+ const conf = t.confidence != null ? Math.round(t.confidence * 100) : '?';
35
+ const ret = t.impliedReturn != null ? `${t.impliedReturn > 0 ? '+' : ''}${t.impliedReturn}%` : '';
36
+ console.log(` ${(t.slug || '').padEnd(35)} ${String(conf).padStart(3)}% ${ret.padStart(8)} ${(t.status || '').padEnd(8)} ${(t.title || '').slice(0, 45)}`);
37
+ }
38
+ console.log(`\n ${theses.length} public theses. Use: sf explore <slug>\n`);
39
+ return;
40
+ }
41
+ // View a specific public thesis
42
+ const res = await fetch(`${BASE_URL}/api/public/thesis/${slug}`);
43
+ if (!res.ok) {
44
+ if (res.status === 404) {
45
+ console.error(` Not found: ${slug}`);
46
+ }
47
+ else {
48
+ console.error(` Error: ${res.status} ${await res.text()}`);
49
+ }
50
+ return;
51
+ }
52
+ const data = await res.json();
53
+ if (opts?.json) {
54
+ console.log(JSON.stringify(data, null, 2));
55
+ return;
56
+ }
57
+ // Formatted output
58
+ const t = data.thesis;
59
+ const ir = data.impliedReturns;
60
+ console.log(`\n ${t.title}`);
61
+ console.log(` ${t.slug} | ${t.confidence != null ? Math.round(t.confidence * 100) : '?'}% | ${t.status} | published ${t.publishedAt?.slice(0, 10) || '?'}`);
62
+ if (t.description)
63
+ console.log(` ${t.description}`);
64
+ console.log('');
65
+ // Causal tree
66
+ if (data.causalTree?.nodes?.length) {
67
+ console.log(' Causal Tree');
68
+ for (const n of data.causalTree.nodes) {
69
+ const bar = '█'.repeat(Math.round((n.probability || 0) * 10)) + '░'.repeat(10 - Math.round((n.probability || 0) * 10));
70
+ console.log(` ${n.id} ${(n.label || '').slice(0, 35).padEnd(35)} ${Math.round((n.probability || 0) * 100)}% ${bar}`);
71
+ if (n.children) {
72
+ for (const c of n.children) {
73
+ const cbar = '█'.repeat(Math.round((c.probability || 0) * 10)) + '░'.repeat(10 - Math.round((c.probability || 0) * 10));
74
+ console.log(` ${c.id} ${(c.label || '').slice(0, 33).padEnd(33)} ${Math.round((c.probability || 0) * 100)}% ${cbar}`);
75
+ }
76
+ }
77
+ }
78
+ console.log('');
79
+ }
80
+ // Implied returns
81
+ if (ir && ir.edges?.length > 0) {
82
+ console.log(` Implied Returns (equal-weight, since ${ir.trackedSince?.slice(0, 10) || '?'})`);
83
+ console.log(` Avg: ${ir.avgReturnPct > 0 ? '+' : ''}${ir.avgReturnPct}% | Win rate: ${ir.winRate}% (${ir.winners}W ${ir.losers}L)`);
84
+ console.log('');
85
+ for (const e of ir.edges.slice(0, 10)) {
86
+ const ret = e.returnPct > 0 ? `+${e.returnPct}%` : `${e.returnPct}%`;
87
+ console.log(` ${(e.market || '').slice(0, 35).padEnd(35)} ${e.entryPrice}¢ → ${e.currentPrice}¢ ${ret}`);
88
+ }
89
+ console.log('');
90
+ }
91
+ // Recent evaluations
92
+ if (data.confidenceHistory?.length > 0) {
93
+ console.log(' Recent Evaluations');
94
+ for (const h of data.confidenceHistory.slice(-5)) {
95
+ const d = h.delta > 0 ? `+${Math.round(h.delta * 100)}` : `${Math.round(h.delta * 100)}`;
96
+ console.log(` ${(h.evaluatedAt || '').slice(0, 16)} ${Math.round(h.confidence * 100)}% (${d}) ${(h.summary || '').slice(0, 60)}`);
97
+ }
98
+ console.log('');
99
+ }
100
+ // Top edges
101
+ if (data.edges?.length > 0) {
102
+ console.log(' Top Edges');
103
+ const sorted = [...data.edges].sort((a, b) => Math.abs(b.edge) - Math.abs(a.edge)).slice(0, 10);
104
+ for (const e of sorted) {
105
+ const liq = e.orderbook?.liquidityScore || '?';
106
+ console.log(` ${(e.market || '').slice(0, 35).padEnd(35)} ${e.marketPrice}¢ → ${e.thesisPrice}¢ edge ${e.edge > 0 ? '+' : ''}${e.edge} ${liq}`);
107
+ }
108
+ console.log('');
109
+ }
110
+ }
@@ -0,0 +1,4 @@
1
+ export declare function fillsCommand(opts: {
2
+ ticker?: string;
3
+ json?: boolean;
4
+ }): Promise<void>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fillsCommand = fillsCommand;
4
+ const kalshi_js_1 = require("../kalshi.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ async function fillsCommand(opts) {
7
+ const result = await (0, kalshi_js_1.getFills)({ ticker: opts.ticker, limit: 50 });
8
+ if (!result)
9
+ throw new Error('Kalshi not configured. Set KALSHI_API_KEY_ID + KALSHI_PRIVATE_KEY_PATH.');
10
+ if (opts.json) {
11
+ console.log(JSON.stringify(result.fills, null, 2));
12
+ return;
13
+ }
14
+ if (result.fills.length === 0) {
15
+ console.log(`${utils_js_1.c.dim}No fills.${utils_js_1.c.reset}`);
16
+ return;
17
+ }
18
+ console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}Recent Fills${utils_js_1.c.reset}`);
19
+ console.log(`${utils_js_1.c.dim}${'─'.repeat(80)}${utils_js_1.c.reset}`);
20
+ for (const f of result.fills) {
21
+ const price = f.yes_price_dollars ? `${parseFloat(f.yes_price_dollars) * 100}¢` : `${f.yes_price || '?'}¢`;
22
+ const side = f.side === 'yes' ? `${utils_js_1.c.green}YES${utils_js_1.c.reset}` : `${utils_js_1.c.red}NO${utils_js_1.c.reset}`;
23
+ const action = f.action || 'buy';
24
+ const count = f.count_fp || f.count || '?';
25
+ const time = f.created_time ? new Date(f.created_time).toLocaleString() : '';
26
+ console.log(` ${(f.ticker || '').padEnd(35)} ${action.padEnd(5)} ${side} ${price.padEnd(8)} x${count} ${utils_js_1.c.dim}${time}${utils_js_1.c.reset}`);
27
+ }
28
+ console.log(`\n${utils_js_1.c.dim}${result.fills.length} fill(s)${utils_js_1.c.reset}`);
29
+ }
@@ -0,0 +1,4 @@
1
+ export declare function forecastCommand(eventTicker: string, opts: {
2
+ days?: string;
3
+ json?: boolean;
4
+ }): Promise<void>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.forecastCommand = forecastCommand;
4
+ const kalshi_js_1 = require("../kalshi.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ const KALSHI_API_BASE = 'https://api.elections.kalshi.com/trade-api/v2';
7
+ async function forecastCommand(eventTicker, opts) {
8
+ const days = parseInt(opts.days || '7');
9
+ // Get series ticker from event
10
+ const evtRes = await fetch(`${KALSHI_API_BASE}/events/${eventTicker}`, {
11
+ headers: { 'Accept': 'application/json' },
12
+ });
13
+ if (!evtRes.ok)
14
+ throw new Error(`Event not found: ${eventTicker}`);
15
+ const evtData = await evtRes.json();
16
+ const seriesTicker = evtData.event?.series_ticker;
17
+ if (!seriesTicker)
18
+ throw new Error(`No series_ticker for ${eventTicker}`);
19
+ // Align timestamps to midnight UTC — Kalshi API rejects unaligned/future timestamps
20
+ const todayMidnight = new Date();
21
+ todayMidnight.setUTCHours(0, 0, 0, 0);
22
+ const endTs = Math.floor(todayMidnight.getTime() / 1000);
23
+ const startTs = endTs - days * 86400;
24
+ const history = await (0, kalshi_js_1.getForecastHistory)({
25
+ seriesTicker,
26
+ eventTicker,
27
+ percentiles: [5000, 7500, 9000],
28
+ startTs,
29
+ endTs,
30
+ periodInterval: 1440,
31
+ });
32
+ if (!history || history.length === 0) {
33
+ console.log(`${utils_js_1.c.dim}No forecast data for ${eventTicker}${utils_js_1.c.reset}`);
34
+ return;
35
+ }
36
+ if (opts.json) {
37
+ console.log(JSON.stringify(history, null, 2));
38
+ return;
39
+ }
40
+ console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}Forecast: ${evtData.event?.title || eventTicker}${utils_js_1.c.reset}`);
41
+ console.log(`${utils_js_1.c.dim}Series: ${seriesTicker} | ${days} days${utils_js_1.c.reset}`);
42
+ console.log();
43
+ console.log(`${utils_js_1.c.bold}${'Date'.padEnd(14)} ${'P50'.padEnd(12)} ${'P75'.padEnd(12)} P90${utils_js_1.c.reset}`);
44
+ console.log(`${utils_js_1.c.dim}${'─'.repeat(52)}${utils_js_1.c.reset}`);
45
+ for (const point of history) {
46
+ const date = new Date(point.end_period_ts * 1000).toISOString().slice(0, 10);
47
+ const pts = point.percentile_points || [];
48
+ const p50 = pts.find((p) => p.percentile === 5000)?.formatted_forecast || '-';
49
+ const p75 = pts.find((p) => p.percentile === 7500)?.formatted_forecast || '-';
50
+ const p90 = pts.find((p) => p.percentile === 9000)?.formatted_forecast || '-';
51
+ console.log(` ${date.padEnd(14)} ${p50.padEnd(12)} ${p75.padEnd(12)} ${p90}`);
52
+ }
53
+ }
@@ -0,0 +1,3 @@
1
+ export declare function historyCommand(ticker: string, opts: {
2
+ json?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.historyCommand = historyCommand;
4
+ const kalshi_js_1 = require("../kalshi.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ async function historyCommand(ticker, opts) {
7
+ const market = await (0, kalshi_js_1.getHistoricalMarket)(ticker);
8
+ if (!market) {
9
+ console.log(`${utils_js_1.c.dim}No historical data for ${ticker}${utils_js_1.c.reset}`);
10
+ return;
11
+ }
12
+ if (opts.json) {
13
+ console.log(JSON.stringify(market, null, 2));
14
+ return;
15
+ }
16
+ console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}${market.title || ticker}${utils_js_1.c.reset}`);
17
+ console.log(`${utils_js_1.c.dim}${'─'.repeat(60)}${utils_js_1.c.reset}`);
18
+ console.log(` Ticker: ${market.ticker || ticker}`);
19
+ console.log(` Event: ${market.event_ticker || '-'}`);
20
+ console.log(` Status: ${market.status || '-'}`);
21
+ console.log(` Result: ${market.result || market.market_result || '-'}`);
22
+ if (market.last_price_dollars) {
23
+ console.log(` Last Price: ${Math.round(parseFloat(market.last_price_dollars) * 100)}¢`);
24
+ }
25
+ if (market.settlement_value !== undefined) {
26
+ console.log(` Settlement: ${market.settlement_value}`);
27
+ }
28
+ if (market.volume) {
29
+ console.log(` Volume: ${market.volume}`);
30
+ }
31
+ if (market.open_interest) {
32
+ console.log(` Open Int: ${market.open_interest}`);
33
+ }
34
+ if (market.expiration_time) {
35
+ console.log(` Expired: ${market.expiration_time}`);
36
+ }
37
+ console.log();
38
+ }
@@ -0,0 +1,8 @@
1
+ export declare function milestonesCommand(opts: {
2
+ category?: string;
3
+ thesis?: string;
4
+ hours?: string;
5
+ json?: boolean;
6
+ apiKey?: string;
7
+ apiUrl?: string;
8
+ }): Promise<void>;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.milestonesCommand = milestonesCommand;
4
+ const client_js_1 = require("../client.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ const KALSHI_API_BASE = 'https://api.elections.kalshi.com/trade-api/v2';
7
+ async function milestonesCommand(opts) {
8
+ const hours = parseInt(opts.hours || '168');
9
+ const now = new Date();
10
+ const cutoff = new Date(now.getTime() + hours * 3600000);
11
+ // Fetch milestones (public endpoint)
12
+ const url = `${KALSHI_API_BASE}/milestones?limit=200&minimum_start_date=${now.toISOString()}` +
13
+ (opts.category ? `&category=${opts.category}` : '');
14
+ const res = await fetch(url, { headers: { 'Accept': 'application/json' } });
15
+ if (!res.ok)
16
+ throw new Error(`Kalshi API ${res.status}`);
17
+ const data = await res.json();
18
+ let milestones = (data.milestones || []).filter((m) => new Date(m.start_date).getTime() <= cutoff.getTime());
19
+ // If thesis specified, filter to matching event tickers
20
+ if (opts.thesis) {
21
+ const client = new client_js_1.SFClient(opts.apiKey, opts.apiUrl);
22
+ const ctx = await client.getContext(opts.thesis);
23
+ const edgeEventTickers = new Set((ctx.edges || []).map((e) => e.eventTicker).filter(Boolean));
24
+ // Also match by related_event_tickers overlap
25
+ const edgeSeriesTickers = new Set((ctx.edges || []).map((e) => e.seriesTicker).filter(Boolean));
26
+ milestones = milestones.filter((m) => {
27
+ const related = m.related_event_tickers || m.primary_event_tickers || [];
28
+ return related.some((t) => edgeEventTickers.has(t) || edgeSeriesTickers.has(t.split('-')[0]));
29
+ });
30
+ }
31
+ if (opts.json) {
32
+ console.log(JSON.stringify(milestones, null, 2));
33
+ return;
34
+ }
35
+ if (milestones.length === 0) {
36
+ console.log(`${utils_js_1.c.dim}No milestones in the next ${hours} hours.${utils_js_1.c.reset}`);
37
+ return;
38
+ }
39
+ // Sort by date
40
+ milestones.sort((a, b) => new Date(a.start_date).getTime() - new Date(b.start_date).getTime());
41
+ console.log(`${utils_js_1.c.bold}${utils_js_1.c.cyan}Upcoming Milestones (next ${hours}h)${utils_js_1.c.reset}`);
42
+ console.log(`${utils_js_1.c.dim}${'─'.repeat(80)}${utils_js_1.c.reset}`);
43
+ for (const m of milestones) {
44
+ const date = new Date(m.start_date);
45
+ const hoursUntil = Math.round((date.getTime() - now.getTime()) / 3600000);
46
+ const timeStr = hoursUntil <= 24
47
+ ? `${utils_js_1.c.bold}${hoursUntil}h${utils_js_1.c.reset}`
48
+ : `${utils_js_1.c.dim}${Math.round(hoursUntil / 24)}d${utils_js_1.c.reset}`;
49
+ const cat = `${utils_js_1.c.dim}[${m.category}]${utils_js_1.c.reset}`;
50
+ const tickers = (m.related_event_tickers || []).slice(0, 3).join(', ');
51
+ console.log(` ${timeStr.padEnd(12)} ${cat.padEnd(25)} ${m.title}`);
52
+ if (tickers)
53
+ console.log(` ${' '.repeat(10)} ${utils_js_1.c.dim}${tickers}${utils_js_1.c.reset}`);
54
+ }
55
+ console.log(`\n${utils_js_1.c.dim}${milestones.length} milestone(s)${utils_js_1.c.reset}`);
56
+ }
@@ -0,0 +1,4 @@
1
+ export declare function ordersCommand(opts: {
2
+ status?: string;
3
+ json?: boolean;
4
+ }): Promise<void>;