@gonzih/polymarket-arb 1.0.12 → 1.0.13

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.
@@ -1,111 +1,100 @@
1
- export declare const BACKTEST_WINDOW_HOURS = 4;
2
- export declare const BACKTEST_MOMENTUM_THRESHOLD = 0.05;
3
- export type ResolvedMarket = {
4
- id: string;
5
- conditionId: string;
6
- clobTokenId: string;
7
- question: string;
8
- volume: number;
9
- startDate: number;
10
- endDate: number;
11
- resolutionTime: number;
12
- resolution: number;
13
- };
14
- export type PricePoint = {
15
- t: number;
16
- p: number;
17
- };
18
- export type BacktestSignal = {
1
+ export declare const COINBASE_API = "https://api.exchange.coinbase.com";
2
+ export declare const CLOB_API = "https://clob.polymarket.com";
3
+ export declare const MOMENTUM_THRESHOLD = 0.015;
4
+ export declare const CORRELATION_THRESHOLD = 0.02;
5
+ export declare const CORRELATION_WINDOW_MINUTES = 30;
6
+ export type Candle = [number, number, number, number, number, number];
7
+ export declare const CANDLE_TIME = 0;
8
+ export declare const CANDLE_LOW = 1;
9
+ export declare const CANDLE_HIGH = 2;
10
+ export declare const CANDLE_OPEN = 3;
11
+ export declare const CANDLE_CLOSE = 4;
12
+ export declare const CANDLE_VOL = 5;
13
+ export type CandleSignal = {
19
14
  firedAt: number;
20
- oddsAtSignal: number;
21
- direction: "YES" | "NO";
15
+ symbol: string;
16
+ direction: "UP" | "DOWN";
22
17
  momentum: number;
18
+ price: number;
19
+ confidence: number;
23
20
  };
24
- export type ClaudeDecision = "BUY_YES" | "BUY_NO" | "PASS" | "ERROR";
25
- export type BacktestResult = {
26
- marketId: string;
27
- question: string;
28
- signalFiredAt: number;
29
- oddsAtSignal: number;
30
- claudeDecision: ClaudeDecision;
31
- claudeLatencyMs: number;
32
- actualResolution: number;
33
- correct: boolean;
34
- kellySizePct: number;
35
- hypotheticalPnl: number;
21
+ export type RawTrade = {
22
+ price: string | number;
23
+ timestamp: string | number;
36
24
  };
37
- export type ActiveMarket = {
25
+ export type PolymarketMarket = {
38
26
  id: string;
39
27
  conditionId: string;
40
28
  clobTokenId: string;
41
29
  question: string;
42
- volume: number;
43
- endDate: number;
44
30
  yesPrice: number;
31
+ volume: number;
32
+ };
33
+ export type OddsMove = {
34
+ marketId: string;
35
+ question: string;
36
+ oddsChange: number;
37
+ direction: "UP" | "DOWN";
38
+ };
39
+ export type SignalResult = {
40
+ signal: CandleSignal;
41
+ marketsChecked: number;
42
+ correlatedMoves: OddsMove[];
43
+ };
44
+ export type BacktestReport = {
45
+ date: string;
46
+ product: string;
47
+ candlesAnalyzed: number;
48
+ signalsFired: number;
49
+ signalRatePerDay: number;
50
+ marketsChecked: number;
51
+ correlatedSignals: number;
52
+ correlationRate: number;
53
+ signals: SignalResult[];
54
+ claudeInterpretation: string;
45
55
  };
46
- export declare function fetchResolvedMarkets(limit?: number): Promise<ResolvedMarket[]>;
47
56
  /**
48
- * Reconstructs hourly price series from CLOB trades endpoint.
49
- * Groups trades into hourly buckets and takes the last price in each bucket.
57
+ * Fetch 1-minute (or custom granularity) OHLCV candles from Coinbase REST API.
58
+ * Coinbase returns newest-first; we reverse to chronological order.
50
59
  */
51
- export declare function fetchPriceHistoryFromTrades(marketId: string): Promise<PricePoint[]>;
60
+ export declare function fetchCoinbaseCandles(product?: string, granularity?: number, limit?: number): Promise<Candle[]>;
52
61
  /**
53
- * Fetches hourly price history from the CLOB API.
54
- * NOTE (discovered during backtest): The CLOB prices-history endpoint returns
55
- * empty data for resolved/closed markets. Falls back to trades reconstruction
56
- * when the primary source returns fewer than 5 points.
57
- * marketId should be a clobTokenId (the long numeric string from clobTokenIds[0]).
62
+ * Replay the 1.5% momentum signal logic against Coinbase candle data.
63
+ * Uses per-candle momentum (open→close). Applies 5-minute per-direction cooldown.
58
64
  */
59
- export declare function fetchPriceHistory(marketId: string): Promise<PricePoint[]>;
60
- export declare function fetchActiveMarkets(limit?: number): Promise<ActiveMarket[]>;
65
+ export declare function replaySignals(candles: Candle[], symbol?: string): CandleSignal[];
61
66
  /**
62
- * Calls Claude directly on a resolved market question to probe integration health.
63
- * Used when price history is unavailable and no momentum signals can be replayed.
67
+ * Fetch active Polymarket markets from the CLOB API.
68
+ * Handles both array and {data:[]} response shapes.
64
69
  */
65
- export declare function probeClaudeIntegration(markets: ResolvedMarket[]): Promise<{
66
- success: number;
67
- errors: number;
68
- avgLatencyMs: number;
69
- sample: BacktestResult[];
70
- }>;
70
+ export declare function fetchPolymarketMarkets(limit?: number): Promise<PolymarketMarket[]>;
71
71
  /**
72
- * Replays the EXISTING momentum signal logic against prediction market price history.
73
- * Adapted from SignalEngine in signal.ts: same % change concept, but uses a 4-hour
74
- * window and 5% threshold suited to hourly prediction market data (0-1 price range).
72
+ * Fetch recent trades for a Polymarket market token from the CLOB.
73
+ * Returns empty array on any error.
75
74
  */
76
- export declare function replaySignals(history: PricePoint[]): BacktestSignal[];
75
+ export declare function fetchMarketTrades(tokenId: string): Promise<RawTrade[]>;
77
76
  /**
78
- * Kelly Criterion: f* = (p*b - q) / b
79
- * where b = net odds (profit per $ risked), p = win probability, q = 1 - p
80
- * Capped at 10% maximum.
77
+ * For each signal, check if any Polymarket market moved >2% in odds
78
+ * within `windowMinutes` of the signal firing.
79
+ * tradesByMarket is a pre-fetched map of marketId → trades.
81
80
  */
82
- export declare function kellySize(odds: number, winProb: number): number;
83
- export declare function computePnl(decision: ClaudeDecision, odds: number, resolution: number, kellySizePct: number): number;
81
+ export declare function findCorrelatedMoves(signal: CandleSignal, markets: PolymarketMarket[], tradesByMarket: Record<string, RawTrade[]>, oddsThreshold?: number, windowMinutes?: number): OddsMove[];
84
82
  /**
85
- * Calls the Claude CLI subprocess. Sends prompt via stdin (not as a positional arg)
86
- * because when spawned with an open stdin pipe the CLI waits for input otherwise.
83
+ * Build a human-readable signal log for Claude interpretation.
87
84
  */
88
- export declare function askClaude(question: string, odds: number): Promise<{
89
- decision: ClaudeDecision;
90
- latencyMs: number;
91
- }>;
92
- export interface BacktestReport {
93
- marketsAnalyzed: number;
94
- signalsFired: number;
95
- claudeSuccesses: number;
96
- claudeErrors: number;
97
- avgLatencyMs: number;
98
- maxLatencyMs: number;
99
- buyYesTotal: number;
100
- buyYesCorrect: number;
101
- buyNoTotal: number;
102
- buyNoCorrect: number;
103
- passCount: number;
104
- avgKellyPct: number;
105
- totalPnl: number;
106
- results: BacktestResult[];
107
- }
108
- export declare function generateReport(results: BacktestResult[], marketsAnalyzed: number): BacktestReport;
109
- export declare function formatReport(report: BacktestReport, date: string): string;
110
- export declare function writeReport(text: string, date: string): string;
85
+ export declare function buildSignalLog(results: SignalResult[]): string;
86
+ /**
87
+ * Spawn claude --print and ask for signal pattern analysis.
88
+ * Returns Claude's response text or a fallback message on failure.
89
+ */
90
+ export declare function askClaude(signalLog: string): Promise<string>;
91
+ /**
92
+ * Render the full backtest report as Markdown.
93
+ */
94
+ export declare function generateMarkdownReport(report: BacktestReport): string;
95
+ /**
96
+ * Write a report to disk. Creates `dir` if it doesn't exist.
97
+ * Returns the path written.
98
+ */
99
+ export declare function writeReport(text: string, date: string, dir?: string): string;
111
100
  //# sourceMappingURL=backtest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backtest.d.ts","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"backtest.d.ts","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,sCAAsC,CAAC;AAChE,eAAO,MAAM,QAAQ,gCAAgC,CAAC;AACtD,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AACxC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAG7C,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtE,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,YAAY,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,QAAQ,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,SAAY,EACnB,WAAW,SAAK,EAChB,KAAK,SAAM,GACV,OAAO,CAAC,MAAM,EAAE,CAAC,CAenB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,SAAY,GAAG,YAAY,EAAE,CAgCnF;AAqBD;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA8BpF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAU5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,EAC1C,aAAa,SAAwB,EACrC,aAAa,SAA6B,GACzC,QAAQ,EAAE,CA8BZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CA6B9D;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0ClE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAkCrE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM,CAOhF"}
package/dist/backtest.js CHANGED
@@ -1,12 +1,72 @@
1
1
  import { spawn } from "child_process";
2
2
  import fs from "fs";
3
+ import path from "path";
3
4
  import { log } from "./logger.js";
4
- const GAMMA_API = "https://gamma-api.polymarket.com";
5
- const CLOB_API = "https://clob.polymarket.com";
6
- // Momentum parameters adapted for prediction market hourly price data
7
- // (0-1 range, slower-moving than crypto ticks)
8
- export const BACKTEST_WINDOW_HOURS = 4;
9
- export const BACKTEST_MOMENTUM_THRESHOLD = 0.05; // 5% move over 4h
5
+ export const COINBASE_API = "https://api.exchange.coinbase.com";
6
+ export const CLOB_API = "https://clob.polymarket.com";
7
+ export const MOMENTUM_THRESHOLD = 0.015; // 1.5% per candle (open→close)
8
+ export const CORRELATION_THRESHOLD = 0.02; // 2% odds move
9
+ export const CORRELATION_WINDOW_MINUTES = 30;
10
+ export const CANDLE_TIME = 0;
11
+ export const CANDLE_LOW = 1;
12
+ export const CANDLE_HIGH = 2;
13
+ export const CANDLE_OPEN = 3;
14
+ export const CANDLE_CLOSE = 4;
15
+ export const CANDLE_VOL = 5;
16
+ /**
17
+ * Fetch 1-minute (or custom granularity) OHLCV candles from Coinbase REST API.
18
+ * Coinbase returns newest-first; we reverse to chronological order.
19
+ */
20
+ export async function fetchCoinbaseCandles(product = "BTC-USD", granularity = 60, limit = 300) {
21
+ try {
22
+ const url = `${COINBASE_API}/products/${encodeURIComponent(product)}/candles?granularity=${granularity}&limit=${limit}`;
23
+ const res = await fetch(url);
24
+ if (!res.ok) {
25
+ log("warn", { source: "backtest", event: "coinbase_candles_error", status: res.status });
26
+ return [];
27
+ }
28
+ const data = (await res.json());
29
+ // Reverse so index 0 is oldest
30
+ return data.reverse();
31
+ }
32
+ catch (err) {
33
+ log("warn", { source: "backtest", event: "coinbase_candles_exception", error: String(err) });
34
+ return [];
35
+ }
36
+ }
37
+ /**
38
+ * Replay the 1.5% momentum signal logic against Coinbase candle data.
39
+ * Uses per-candle momentum (open→close). Applies 5-minute per-direction cooldown.
40
+ */
41
+ export function replaySignals(candles, symbol = "BTC-USD") {
42
+ const signals = [];
43
+ const COOLDOWN_MS = 5 * 60 * 1000;
44
+ const lastSignalTime = { UP: 0, DOWN: 0 };
45
+ for (const candle of candles) {
46
+ const open = candle[CANDLE_OPEN];
47
+ const close = candle[CANDLE_CLOSE];
48
+ const ts = candle[CANDLE_TIME];
49
+ if (open === 0)
50
+ continue;
51
+ const momentum = (close - open) / open;
52
+ if (Math.abs(momentum) < MOMENTUM_THRESHOLD)
53
+ continue;
54
+ const direction = momentum > 0 ? "UP" : "DOWN";
55
+ const firedAt = ts * 1000;
56
+ if (firedAt - lastSignalTime[direction] < COOLDOWN_MS)
57
+ continue;
58
+ lastSignalTime[direction] = firedAt;
59
+ signals.push({
60
+ firedAt,
61
+ symbol,
62
+ direction,
63
+ momentum,
64
+ price: close,
65
+ confidence: Math.min(1, Math.abs(momentum) / (MOMENTUM_THRESHOLD * 2)),
66
+ });
67
+ }
68
+ return signals;
69
+ }
10
70
  function parseJsonField(field) {
11
71
  if (Array.isArray(field))
12
72
  return field;
@@ -17,446 +77,201 @@ function parseJsonField(field) {
17
77
  return [];
18
78
  }
19
79
  }
20
- export async function fetchResolvedMarkets(limit = 100) {
21
- const sixMonthsAgo = Date.now() - 180 * 24 * 60 * 60 * 1000;
22
- // Use end_date_min to fetch recent markets without scanning thousands of pages
23
- const sixMonthsAgoDate = new Date(sixMonthsAgo).toISOString().slice(0, 10);
24
- const results = [];
25
- let offset = 0;
26
- const batchSize = 100;
27
- while (results.length < limit) {
28
- const url = `${GAMMA_API}/markets?closed=true&limit=${batchSize}&offset=${offset}&end_date_min=${sixMonthsAgoDate}`;
29
- let markets;
30
- try {
31
- const res = await fetch(url);
32
- if (!res.ok) {
33
- log("warn", { source: "backtest", event: "fetch_resolved_error", status: res.status });
34
- break;
35
- }
36
- markets = (await res.json());
37
- }
38
- catch (err) {
39
- log("warn", { source: "backtest", event: "fetch_resolved_exception", error: String(err) });
40
- break;
80
+ /**
81
+ * Fetch active Polymarket markets from the CLOB API.
82
+ * Handles both array and {data:[]} response shapes.
83
+ */
84
+ export async function fetchPolymarketMarkets(limit = 20) {
85
+ try {
86
+ const url = `${CLOB_API}/markets?active=true&closed=false&limit=${limit}`;
87
+ const res = await fetch(url);
88
+ if (!res.ok) {
89
+ log("warn", { source: "backtest", event: "polymarket_markets_error", status: res.status });
90
+ return [];
41
91
  }
42
- if (markets.length === 0)
43
- break;
44
- for (const m of markets) {
45
- const volume = Number(m.volumeNum ?? m.volume ?? 0);
46
- if (volume < 50_000)
47
- continue;
48
- const endDate = m.endDate ? new Date(m.endDate).getTime() : 0;
49
- if (endDate < sixMonthsAgo || endDate === 0)
50
- continue;
51
- // Only include cleanly resolved markets (YES price = 0 or 1)
92
+ const raw = (await res.json());
93
+ const markets = Array.isArray(raw) ? raw : (raw.data ?? []);
94
+ return markets
95
+ .map((m) => {
52
96
  const prices = parseJsonField(m.outcomePrices ?? []).map(Number);
53
- if (prices.length < 2)
54
- continue;
55
- const yesPrice = prices[0];
56
- if (yesPrice !== 0 && yesPrice !== 1)
57
- continue;
58
- // Parse YES outcome clobTokenId for CLOB price history
97
+ const yesPrice = prices[0] ?? 0.5;
59
98
  const tokenIds = parseJsonField(m.clobTokenIds ?? "[]");
60
- const clobTokenId = tokenIds[0] ?? "";
61
- results.push({
62
- id: m.id,
63
- conditionId: m.conditionId ?? m.id,
64
- clobTokenId,
99
+ return {
100
+ id: m.id ?? "",
101
+ conditionId: m.conditionId ?? m.id ?? "",
102
+ clobTokenId: tokenIds[0] ?? "",
65
103
  question: m.question ?? "",
66
- volume,
67
- startDate: m.startDate ? new Date(m.startDate).getTime() : 0,
68
- endDate,
69
- resolutionTime: m.resolutionTime ? new Date(m.resolutionTime).getTime() : endDate,
70
- resolution: yesPrice === 1 ? 1 : 0,
71
- });
72
- if (results.length >= limit)
73
- break;
74
- }
75
- offset += batchSize;
76
- if (markets.length < batchSize)
77
- break; // no more pages
104
+ yesPrice,
105
+ volume: Number(m.volumeNum ?? m.volume ?? 0),
106
+ };
107
+ })
108
+ .filter((m) => m.id && m.question && m.volume > 10_000);
109
+ }
110
+ catch (err) {
111
+ log("warn", { source: "backtest", event: "polymarket_markets_exception", error: String(err) });
112
+ return [];
78
113
  }
79
- log("info", {
80
- source: "backtest",
81
- event: "resolved_markets_fetched",
82
- count: results.length,
83
- });
84
- return results;
85
114
  }
86
115
  /**
87
- * Reconstructs hourly price series from CLOB trades endpoint.
88
- * Groups trades into hourly buckets and takes the last price in each bucket.
116
+ * Fetch recent trades for a Polymarket market token from the CLOB.
117
+ * Returns empty array on any error.
89
118
  */
90
- export async function fetchPriceHistoryFromTrades(marketId) {
119
+ export async function fetchMarketTrades(tokenId) {
91
120
  try {
92
- const url = `${CLOB_API}/trades?market=${encodeURIComponent(marketId)}&limit=500`;
121
+ const url = `${CLOB_API}/trades?market=${encodeURIComponent(tokenId)}&limit=500`;
93
122
  const res = await fetch(url);
94
123
  if (!res.ok)
95
124
  return [];
96
125
  const raw = (await res.json());
97
- const trades = Array.isArray(raw) ? raw : (raw.data ?? []);
98
- const buckets = new Map();
99
- for (const trade of trades) {
100
- const ts = Number(trade.timestamp);
101
- const tsSec = ts < 1e12 ? ts : Math.floor(ts / 1000);
102
- const bucket = Math.floor(tsSec / 3600) * 3600;
103
- buckets.set(bucket, Number(trade.price));
104
- }
105
- return Array.from(buckets.entries())
106
- .map(([t, p]) => ({ t, p }))
107
- .sort((a, b) => a.t - b.t);
126
+ return Array.isArray(raw) ? raw : (raw.data ?? []);
108
127
  }
109
128
  catch {
110
129
  return [];
111
130
  }
112
131
  }
113
132
  /**
114
- * Fetches hourly price history from the CLOB API.
115
- * NOTE (discovered during backtest): The CLOB prices-history endpoint returns
116
- * empty data for resolved/closed markets. Falls back to trades reconstruction
117
- * when the primary source returns fewer than 5 points.
118
- * marketId should be a clobTokenId (the long numeric string from clobTokenIds[0]).
133
+ * For each signal, check if any Polymarket market moved >2% in odds
134
+ * within `windowMinutes` of the signal firing.
135
+ * tradesByMarket is a pre-fetched map of marketId trades.
119
136
  */
120
- export async function fetchPriceHistory(marketId) {
121
- let primaryHistory = [];
122
- let primaryNetworkError = false;
123
- try {
124
- const url = `${CLOB_API}/prices-history?market=${encodeURIComponent(marketId)}&interval=1h&fidelity=60`;
125
- const res = await fetch(url);
126
- if (!res.ok) {
127
- primaryNetworkError = true;
128
- }
129
- else {
130
- const data = (await res.json());
131
- const history = Array.isArray(data) ? data : (data.history ?? []);
132
- primaryHistory = history.sort((a, b) => a.t - b.t);
133
- }
134
- }
135
- catch {
136
- primaryNetworkError = true;
137
- }
138
- if (primaryHistory.length < 5 || primaryNetworkError) {
139
- const fallback = await fetchPriceHistoryFromTrades(marketId);
140
- return fallback.length >= primaryHistory.length ? fallback : primaryHistory;
141
- }
142
- return primaryHistory;
143
- }
144
- export async function fetchActiveMarkets(limit = 50) {
145
- const results = [];
146
- let offset = 0;
147
- const batchSize = 100;
148
- while (results.length < limit) {
149
- const url = `${GAMMA_API}/markets?closed=false&active=true&limit=${batchSize}&offset=${offset}`;
150
- let markets;
151
- try {
152
- const res = await fetch(url);
153
- if (!res.ok) {
154
- log("warn", { source: "backtest", event: "fetch_active_error", status: res.status });
155
- break;
156
- }
157
- markets = (await res.json());
158
- }
159
- catch (err) {
160
- log("warn", { source: "backtest", event: "fetch_active_exception", error: String(err) });
161
- break;
162
- }
163
- if (markets.length === 0)
164
- break;
165
- for (const m of markets) {
166
- const volume = Number(m.volumeNum ?? m.volume ?? 0);
167
- if (volume < 50_000)
168
- continue;
169
- const endDate = m.endDate ? new Date(m.endDate).getTime() : 0;
170
- if (endDate === 0)
171
- continue;
172
- const prices = parseJsonField(m.outcomePrices ?? []).map(Number);
173
- if (prices.length < 2)
174
- continue;
175
- const yesPrice = prices[0];
176
- if (yesPrice < 0.05 || yesPrice > 0.95)
177
- continue;
178
- const tokenIds = parseJsonField(m.clobTokenIds ?? "[]");
179
- const clobTokenId = tokenIds[0] ?? "";
180
- results.push({
181
- id: m.id,
182
- conditionId: m.conditionId ?? m.id,
183
- clobTokenId,
184
- question: m.question ?? "",
185
- volume,
186
- endDate,
187
- yesPrice,
137
+ export function findCorrelatedMoves(signal, markets, tradesByMarket, oddsThreshold = CORRELATION_THRESHOLD, windowMinutes = CORRELATION_WINDOW_MINUTES) {
138
+ const windowStartSec = signal.firedAt / 1000;
139
+ const windowEndSec = windowStartSec + windowMinutes * 60;
140
+ const correlated = [];
141
+ for (const market of markets) {
142
+ const trades = tradesByMarket[market.id] ?? [];
143
+ const windowTrades = trades.filter((t) => {
144
+ const ts = Number(t.timestamp);
145
+ const tsSec = ts < 1e12 ? ts : Math.floor(ts / 1000);
146
+ return tsSec >= windowStartSec && tsSec <= windowEndSec;
147
+ });
148
+ if (windowTrades.length < 2)
149
+ continue;
150
+ const priceStart = Number(windowTrades[0].price);
151
+ const priceEnd = Number(windowTrades[windowTrades.length - 1].price);
152
+ const oddsChange = priceEnd - priceStart;
153
+ if (Math.abs(oddsChange) >= oddsThreshold) {
154
+ correlated.push({
155
+ marketId: market.id,
156
+ question: market.question,
157
+ oddsChange: Math.abs(oddsChange),
158
+ direction: oddsChange > 0 ? "UP" : "DOWN",
188
159
  });
189
- if (results.length >= limit)
190
- break;
191
160
  }
192
- offset += batchSize;
193
- if (markets.length < batchSize)
194
- break;
195
161
  }
196
- log("info", { source: "backtest", event: "active_markets_fetched", count: results.length });
197
- return results;
162
+ return correlated;
198
163
  }
199
164
  /**
200
- * Calls Claude directly on a resolved market question to probe integration health.
201
- * Used when price history is unavailable and no momentum signals can be replayed.
165
+ * Build a human-readable signal log for Claude interpretation.
202
166
  */
203
- export async function probeClaudeIntegration(markets) {
204
- const sample = markets.slice(0, 5);
205
- const results = [];
206
- let totalLatency = 0;
207
- let errors = 0;
208
- for (const market of sample) {
209
- // Use last-known odds as 0.5 (unknown pre-resolution for closed markets)
210
- const odds = 0.5;
211
- const { decision, latencyMs } = await askClaude(market.question, odds);
212
- totalLatency += latencyMs;
213
- if (decision === "ERROR")
214
- errors++;
215
- const correct = decision === "BUY_YES"
216
- ? market.resolution === 1
217
- : decision === "BUY_NO"
218
- ? market.resolution === 0
219
- : false;
220
- results.push({
221
- marketId: market.id,
222
- question: market.question,
223
- signalFiredAt: 0,
224
- oddsAtSignal: odds,
225
- claudeDecision: decision,
226
- claudeLatencyMs: latencyMs,
227
- actualResolution: market.resolution,
228
- correct,
229
- kellySizePct: 0,
230
- hypotheticalPnl: 0,
231
- });
167
+ export function buildSignalLog(results) {
168
+ if (results.length === 0) {
169
+ return "No signals fired in the analysis window. Momentum threshold (1.5%) not crossed in recent candles.";
232
170
  }
233
- return {
234
- success: sample.length - errors,
235
- errors,
236
- avgLatencyMs: sample.length > 0 ? totalLatency / sample.length : 0,
237
- sample: results,
238
- };
239
- }
240
- /**
241
- * Replays the EXISTING momentum signal logic against prediction market price history.
242
- * Adapted from SignalEngine in signal.ts: same % change concept, but uses a 4-hour
243
- * window and 5% threshold suited to hourly prediction market data (0-1 price range).
244
- */
245
- export function replaySignals(history) {
246
- const signals = [];
247
- if (history.length < BACKTEST_WINDOW_HOURS + 1)
248
- return signals;
249
- let lastSignalAtMs = 0;
250
- const COOLDOWN_MS = 12 * 60 * 60 * 1000; // 12-hour cooldown between signals per market
251
- for (let i = BACKTEST_WINDOW_HOURS; i < history.length; i++) {
252
- const windowStart = history[i - BACKTEST_WINDOW_HOURS];
253
- const current = history[i];
254
- if (windowStart.p === 0)
255
- continue;
256
- const momentum = (current.p - windowStart.p) / windowStart.p;
257
- if (Math.abs(momentum) < BACKTEST_MOMENTUM_THRESHOLD)
258
- continue;
259
- const tMs = current.t * 1000;
260
- if (tMs - lastSignalAtMs < COOLDOWN_MS)
261
- continue;
262
- lastSignalAtMs = tMs;
263
- signals.push({
264
- firedAt: tMs,
265
- oddsAtSignal: current.p,
266
- direction: momentum > 0 ? "YES" : "NO",
267
- momentum,
268
- });
269
- }
270
- return signals;
271
- }
272
- /**
273
- * Kelly Criterion: f* = (p*b - q) / b
274
- * where b = net odds (profit per $ risked), p = win probability, q = 1 - p
275
- * Capped at 10% maximum.
276
- */
277
- export function kellySize(odds, winProb) {
278
- if (odds <= 0 || odds >= 1)
279
- return 0;
280
- const b = (1 - odds) / odds; // net odds
281
- const q = 1 - winProb;
282
- const kelly = (winProb * b - q) / b;
283
- return Math.max(0, Math.min(0.1, kelly));
284
- }
285
- export function computePnl(decision, odds, resolution, kellySizePct) {
286
- if (decision === "PASS" || decision === "ERROR")
287
- return 0;
288
- const betYes = decision === "BUY_YES";
289
- const won = betYes ? resolution === 1 : resolution === 0;
290
- const betOdds = betYes ? odds : 1 - odds;
291
- if (won) {
292
- // Profit per $ = (1 - betOdds) / betOdds
293
- return kellySizePct * ((1 - betOdds) / betOdds);
171
+ const correlated = results.filter((r) => r.correlatedMoves.length > 0).length;
172
+ const lines = [
173
+ `Total signals: ${results.length}`,
174
+ `Correlated with Polymarket moves >2%: ${correlated}/${results.length}`,
175
+ `Correlation rate: ${((correlated / results.length) * 100).toFixed(1)}%`,
176
+ "",
177
+ "Signal Log:",
178
+ ];
179
+ for (const r of results) {
180
+ const ts = new Date(r.signal.firedAt).toISOString();
181
+ const pct = (r.signal.momentum * 100).toFixed(2);
182
+ const corrStr = r.correlatedMoves.length > 0
183
+ ? r.correlatedMoves
184
+ .map((m) => `${m.question.slice(0, 40)} (${(m.oddsChange * 100).toFixed(1)}% ${m.direction})`)
185
+ .join("; ")
186
+ : "no correlated moves";
187
+ lines.push(` [${ts}] ${r.signal.direction} ${pct}% @ $${r.signal.price.toFixed(0)} | conf=${r.signal.confidence.toFixed(2)} | ${corrStr}`);
294
188
  }
295
- return -kellySizePct;
189
+ return lines.join("\n");
296
190
  }
297
191
  /**
298
- * Calls the Claude CLI subprocess. Sends prompt via stdin (not as a positional arg)
299
- * because when spawned with an open stdin pipe the CLI waits for input otherwise.
192
+ * Spawn claude --print and ask for signal pattern analysis.
193
+ * Returns Claude's response text or a fallback message on failure.
300
194
  */
301
- export async function askClaude(question, odds) {
302
- const start = Date.now();
303
- const prompt = `Market: ${question}\nCurrent odds: ${(odds * 100).toFixed(1)}% YES\nSignal: momentum spike detected\nShould we bet YES or NO? Respond with: BUY_YES, BUY_NO, or PASS`;
195
+ export async function askClaude(signalLog) {
196
+ const prompt = `Given these signal firings and Polymarket odds movements, what patterns do you see? ` +
197
+ `Which signal types (high momentum, news-boosted, specific time windows) correlate best with market moves? ` +
198
+ `What threshold would maximize signal quality?\n\n${signalLog}`;
304
199
  return new Promise((resolve) => {
305
200
  const proc = spawn("claude", ["--print", "--model", "claude-haiku-4-5-20251001"], {
306
201
  env: { ...process.env },
307
202
  stdio: ["pipe", "pipe", "pipe"],
308
203
  });
309
- // Send prompt via stdin then close it so claude knows there is no more input
310
204
  proc.stdin.write(prompt);
311
205
  proc.stdin.end();
312
206
  let stdout = "";
313
- let stderr = "";
314
207
  let timedOut = false;
315
208
  proc.stdout.on("data", (chunk) => {
316
209
  stdout += chunk.toString();
317
210
  });
318
- proc.stderr.on("data", (chunk) => {
319
- stderr += chunk.toString();
320
- });
211
+ proc.stderr.on("data", () => { }); // suppress stderr noise
321
212
  const timer = setTimeout(() => {
322
213
  timedOut = true;
323
214
  proc.kill("SIGTERM");
324
- }, 30_000);
215
+ }, 60_000);
325
216
  proc.on("close", (code) => {
326
217
  clearTimeout(timer);
327
- const latencyMs = Date.now() - start;
328
218
  if (timedOut || code !== 0) {
329
- const err = timedOut
330
- ? "timeout after 30s"
331
- : `exit code ${code}${stderr ? ": " + stderr.slice(0, 200) : ""}`;
332
- log("warn", { source: "backtest", event: "claude_error", error: err });
333
- resolve({ decision: "ERROR", latencyMs });
219
+ resolve("(Claude interpretation unavailable — subprocess error or timeout)");
334
220
  return;
335
221
  }
336
- const text = stdout.toUpperCase();
337
- let decision = "PASS";
338
- if (text.includes("BUY_YES"))
339
- decision = "BUY_YES";
340
- else if (text.includes("BUY_NO"))
341
- decision = "BUY_NO";
342
- log("info", {
343
- source: "backtest",
344
- event: "claude_decision",
345
- question: question.slice(0, 60),
346
- decision,
347
- latencyMs,
348
- });
349
- resolve({ decision, latencyMs });
222
+ resolve(stdout.trim() || "(No interpretation returned)");
350
223
  });
351
- proc.on("error", (err) => {
224
+ proc.on("error", () => {
352
225
  clearTimeout(timer);
353
- const latencyMs = Date.now() - start;
354
- log("warn", { source: "backtest", event: "claude_error", error: String(err) });
355
- resolve({ decision: "ERROR", latencyMs });
226
+ resolve("(Claude interpretation unavailable spawn error)");
356
227
  });
357
228
  });
358
229
  }
359
- export function generateReport(results, marketsAnalyzed) {
360
- const claudeErrors = results.filter((r) => r.claudeDecision === "ERROR").length;
361
- const claudeSuccesses = results.filter((r) => r.claudeDecision !== "ERROR").length;
362
- const latencies = results.map((r) => r.claudeLatencyMs).filter((l) => l > 0);
363
- const avgLatencyMs = latencies.length > 0 ? latencies.reduce((a, b) => a + b, 0) / latencies.length : 0;
364
- const maxLatencyMs = latencies.length > 0 ? Math.max(...latencies) : 0;
365
- const buyYes = results.filter((r) => r.claudeDecision === "BUY_YES");
366
- const buyNo = results.filter((r) => r.claudeDecision === "BUY_NO");
367
- const passes = results.filter((r) => r.claudeDecision === "PASS");
368
- const kellyValues = results.filter((r) => r.kellySizePct > 0).map((r) => r.kellySizePct);
369
- const avgKellyPct = kellyValues.length > 0 ? kellyValues.reduce((a, b) => a + b, 0) / kellyValues.length : 0;
370
- const totalPnl = results.reduce((sum, r) => sum + r.hypotheticalPnl, 0);
371
- return {
372
- marketsAnalyzed,
373
- signalsFired: results.length,
374
- claudeSuccesses,
375
- claudeErrors,
376
- avgLatencyMs,
377
- maxLatencyMs,
378
- buyYesTotal: buyYes.length,
379
- buyYesCorrect: buyYes.filter((r) => r.correct).length,
380
- buyNoTotal: buyNo.length,
381
- buyNoCorrect: buyNo.filter((r) => r.correct).length,
382
- passCount: passes.length,
383
- avgKellyPct,
384
- totalPnl,
385
- results,
386
- };
387
- }
388
- export function formatReport(report, date) {
389
- const totalDecisions = report.buyYesTotal + report.buyNoTotal;
390
- const totalCorrect = report.buyYesCorrect + report.buyNoCorrect;
391
- const winRate = totalDecisions > 0 ? (totalCorrect / totalDecisions) * 100 : 0;
392
- const signalRate = report.marketsAnalyzed > 0
393
- ? (report.signalsFired / report.marketsAnalyzed) * 100
394
- : 0;
395
- const yesAcc = report.buyYesTotal > 0
396
- ? `${report.buyYesCorrect}/${report.buyYesTotal} (${((report.buyYesCorrect / report.buyYesTotal) * 100).toFixed(1)}%)`
397
- : "0/0 (n/a)";
398
- const noAcc = report.buyNoTotal > 0
399
- ? `${report.buyNoCorrect}/${report.buyNoTotal} (${((report.buyNoCorrect / report.buyNoTotal) * 100).toFixed(1)}%)`
400
- : "0/0 (n/a)";
401
- const claudeStatus = report.claudeErrors === 0
402
- ? ` ✓ All ${report.claudeSuccesses} calls succeeded`
403
- : ` ✓ ${report.claudeSuccesses} calls succeeded\n ✗ ${report.claudeErrors} error${report.claudeErrors !== 1 ? "s" : ""}`;
404
- let verdict;
405
- if (totalDecisions === 0) {
406
- verdict =
407
- "INSUFFICIENT DATA: No actionable signals. Either no price history from API, " +
408
- "signals never crossed the 5% threshold, or all signals fired after market resolution.";
409
- }
410
- else if (totalDecisions < 5) {
411
- verdict =
412
- `TOO FEW TRADES: Only ${totalDecisions} trade${totalDecisions !== 1 ? "s" : ""} — ` +
413
- "cannot distinguish edge from luck. Need 30+ trades for statistical significance.";
414
- }
415
- else if (winRate > 60) {
416
- verdict =
417
- `POSSIBLE EDGE: Win rate ${winRate.toFixed(1)}% exceeds 50% baseline. ` +
418
- `P&L: ${report.totalPnl >= 0 ? "+" : ""}${(report.totalPnl * 100).toFixed(1)}% of bankroll. ` +
419
- "Needs larger sample (30+ trades) to confirm.";
420
- }
421
- else if (winRate > 50) {
422
- verdict =
423
- `WEAK SIGNAL: Win rate ${winRate.toFixed(1)}% slightly above baseline. ` +
424
- "Cannot yet distinguish from noise. More data needed.";
425
- }
426
- else {
427
- verdict =
428
- `NO EDGE DETECTED: Win rate ${winRate.toFixed(1)}% at or below 50% baseline. ` +
429
- "Current signal parameters not predictive on this historical data.";
430
- }
431
- const lines = [
432
- "=== POLYMARKET-ARB BACKTEST REPORT ===",
433
- `Date: ${date}`,
434
- "",
435
- `Markets analyzed: ${report.marketsAnalyzed}`,
436
- `Signals fired: ${report.signalsFired} (${signalRate.toFixed(1)}% of markets)`,
437
- `Claude Code: ${report.claudeSuccesses}/${report.signalsFired} decisions returned (${report.claudeErrors} error${report.claudeErrors !== 1 ? "s" : ""})`,
438
- `Claude latency: avg ${(report.avgLatencyMs / 1000).toFixed(1)}s, max ${(report.maxLatencyMs / 1000).toFixed(1)}s`,
230
+ /**
231
+ * Render the full backtest report as Markdown.
232
+ */
233
+ export function generateMarkdownReport(report) {
234
+ const signalRows = report.signals.length > 0
235
+ ? report.signals.map((r) => {
236
+ const ts = new Date(r.signal.firedAt).toISOString().replace("T", " ").slice(0, 19);
237
+ const mom = `${(r.signal.momentum * 100).toFixed(2)}%`;
238
+ const marketMove = r.correlatedMoves.length > 0
239
+ ? r.correlatedMoves.map((m) => `${(m.oddsChange * 100).toFixed(1)}%`).join(", ")
240
+ : "—";
241
+ return `| ${ts} | ${r.signal.symbol} | ${mom} | ${r.signal.direction} | ${marketMove} |`;
242
+ })
243
+ : ["| — | — | — | — | — |"];
244
+ return [
245
+ `# Polymarket Backtest — ${report.date}`,
439
246
  "",
440
- "SIGNAL ACCURACY:",
441
- ` BUY_YES decisions: ${report.buyYesTotal} → correct: ${yesAcc}`,
442
- ` BUY_NO decisions: ${report.buyNoTotal} → correct: ${noAcc}`,
443
- ` PASS decisions: ${report.passCount}`,
247
+ "## Summary",
248
+ `- Candles analyzed: ${report.candlesAnalyzed}`,
249
+ `- Signals fired: ${report.signalsFired}`,
250
+ `- Signal rate: ${report.signalRatePerDay.toFixed(1)} per day`,
251
+ `- Markets checked per signal: ${report.marketsChecked}`,
252
+ `- Correlated moves (signal + market move >2%): ${report.correlatedSignals}`,
253
+ `- Correlation rate: ${report.correlationRate.toFixed(1)}%`,
444
254
  "",
445
- "EDGE vs RANDOM:",
446
- ` Win rate: ${winRate.toFixed(1)}% (random baseline: 50%)`,
447
- ` Avg Kelly size: ${(report.avgKellyPct * 100).toFixed(1)}% of bankroll`,
448
- ` Hypothetical total P&L: ${report.totalPnl >= 0 ? "+" : ""}${(report.totalPnl * 100).toFixed(1)}% of bankroll over ${report.marketsAnalyzed} markets`,
255
+ "## Signal Log",
256
+ "| Time | Symbol | Momentum | Direction | Market Move |",
257
+ "|------|--------|----------|-----------|-------------|",
258
+ ...signalRows,
449
259
  "",
450
- "CLAUDE CODE INTEGRATION:",
451
- claudeStatus,
260
+ "## Interpretation",
261
+ report.claudeInterpretation,
452
262
  "",
453
- `VERDICT: ${verdict}`,
454
- ];
455
- return lines.join("\n");
263
+ ].join("\n");
456
264
  }
457
- export function writeReport(text, date) {
458
- const reportPath = `backtest-report-${date}.md`;
459
- fs.writeFileSync(reportPath, text + "\n");
265
+ /**
266
+ * Write a report to disk. Creates `dir` if it doesn't exist.
267
+ * Returns the path written.
268
+ */
269
+ export function writeReport(text, date, dir = "research") {
270
+ if (!fs.existsSync(dir)) {
271
+ fs.mkdirSync(dir, { recursive: true });
272
+ }
273
+ const reportPath = path.join(dir, `backtest-results-${date}.md`);
274
+ fs.writeFileSync(reportPath, text);
460
275
  return reportPath;
461
276
  }
462
277
  //# sourceMappingURL=backtest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"backtest.js","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"backtest.js","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"backtestRunner.d.ts","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"AA4BA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAkKjD"}
1
+ {"version":3,"file":"backtestRunner.d.ts","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"AAoBA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAiFjD"}
@@ -1,167 +1,74 @@
1
- import { fetchResolvedMarkets, fetchPriceHistory, fetchActiveMarkets, replaySignals, askClaude, kellySize, computePnl, generateReport, formatReport as formatBaseReport, writeReport, probeClaudeIntegration, } from "./backtest.js";
2
- import { log } from "./logger.js";
3
- const MARKETS_TO_FETCH = 50;
4
- // At most one Claude call per market to keep runtime reasonable
5
- const MAX_SIGNALS_PER_MARKET = 1;
1
+ import { fetchCoinbaseCandles, replaySignals, fetchPolymarketMarkets, fetchMarketTrades, findCorrelatedMoves, askClaude, buildSignalLog, generateMarkdownReport, writeReport, } from "./backtest.js";
2
+ const PRODUCT = "BTC-USD";
3
+ const GRANULARITY = 60; // 1-minute candles
4
+ const CANDLE_LIMIT = 300; // ~5 hours of data
5
+ const POLYMARKET_MARKETS = 20;
6
6
  export async function runBacktest() {
7
7
  const date = new Date().toISOString().slice(0, 10);
8
8
  console.log("=== POLYMARKET-ARB BACKTESTING HARNESS ===");
9
- console.log(`Fetching up to ${MARKETS_TO_FETCH} resolved markets (volume > $50k, last 6 months)...`);
10
- const markets = await fetchResolvedMarkets(MARKETS_TO_FETCH);
11
- console.log(`Fetched ${markets.length} qualifying markets\n`);
12
- if (markets.length === 0) {
13
- console.error("ERROR: No resolved markets found.\n" +
9
+ console.log(`Fetching ${CANDLE_LIMIT} × ${GRANULARITY}s candles for ${PRODUCT}...`);
10
+ const candles = await fetchCoinbaseCandles(PRODUCT, GRANULARITY, CANDLE_LIMIT);
11
+ if (candles.length === 0) {
12
+ console.error("ERROR: No candles returned from Coinbase REST API.\n" +
14
13
  "Possible causes:\n" +
15
- " • GAMMA API unreachable\n" +
16
- " • No markets with volume > $50k resolved in last 6 months\n" +
17
- " • outcomePrices not cleanly 0 or 1 (market still settling)");
14
+ " • API rate-limited or unreachable\n" +
15
+ " • Network error");
18
16
  process.exit(1);
19
17
  }
20
- const results = [];
21
- let marketsWithHistory = 0;
22
- let marketsNoHistory = 0;
23
- let marketsNoSignal = 0;
24
- for (let i = 0; i < markets.length; i++) {
25
- const market = markets[i];
26
- process.stdout.write(`\r[${i + 1}/${markets.length}] ${market.question.slice(0, 55)}...`);
27
- // Use the YES clobTokenId for price history
28
- const tokenId = market.clobTokenId || market.conditionId;
29
- const history = await fetchPriceHistory(tokenId);
30
- if (history.length < 5) {
31
- marketsNoHistory++;
32
- continue;
18
+ console.log(`Fetched ${candles.length} candles`);
19
+ const signals = replaySignals(candles, PRODUCT);
20
+ console.log(`Signals fired: ${signals.length} (threshold: 1.5% per candle)`);
21
+ console.log(`\nFetching ${POLYMARKET_MARKETS} active Polymarket markets...`);
22
+ const markets = await fetchPolymarketMarkets(POLYMARKET_MARKETS);
23
+ console.log(`Fetched ${markets.length} qualifying markets (volume > $10k)`);
24
+ // Pre-fetch trades for all markets once, then reuse across signals
25
+ const tradesByMarket = {};
26
+ if (signals.length > 0 && markets.length > 0) {
27
+ console.log(`Pre-fetching trades for ${markets.length} markets...`);
28
+ for (let i = 0; i < markets.length; i++) {
29
+ const market = markets[i];
30
+ if (market.clobTokenId) {
31
+ process.stdout.write(`\r [${i + 1}/${markets.length}] ${market.question.slice(0, 50)}`);
32
+ tradesByMarket[market.id] = await fetchMarketTrades(market.clobTokenId);
33
+ }
33
34
  }
34
- marketsWithHistory++;
35
- const signals = replaySignals(history).slice(0, MAX_SIGNALS_PER_MARKET);
36
- if (signals.length === 0) {
37
- marketsNoSignal++;
38
- continue;
39
- }
40
- for (const signal of signals) {
41
- // Skip signals that fired at or after resolution — unfair look-ahead
42
- if (signal.firedAt >= market.resolutionTime)
43
- continue;
44
- const { decision, latencyMs } = await askClaude(market.question, signal.oddsAtSignal);
45
- const betOdds = decision === "BUY_YES" ? signal.oddsAtSignal : 1 - signal.oddsAtSignal;
46
- // Assume modest 65% win probability as prior when signal fires
47
- const WIN_PROB_PRIOR = 0.65;
48
- const kellySizePct = decision !== "PASS" && decision !== "ERROR"
49
- ? kellySize(betOdds, WIN_PROB_PRIOR)
50
- : 0;
51
- const pnl = computePnl(decision, signal.oddsAtSignal, market.resolution, kellySizePct);
52
- const correct = decision === "BUY_YES"
53
- ? market.resolution === 1
54
- : decision === "BUY_NO"
55
- ? market.resolution === 0
56
- : false;
57
- results.push({
58
- marketId: market.id,
59
- question: market.question,
60
- signalFiredAt: signal.firedAt,
61
- oddsAtSignal: signal.oddsAtSignal,
62
- claudeDecision: decision,
63
- claudeLatencyMs: latencyMs,
64
- actualResolution: market.resolution,
65
- correct,
66
- kellySizePct,
67
- hypotheticalPnl: pnl,
68
- });
69
- log("info", {
70
- source: "backtest",
71
- event: "result",
72
- question: market.question.slice(0, 60),
73
- decision,
74
- oddsAtSignal: signal.oddsAtSignal.toFixed(3),
75
- resolution: market.resolution,
76
- correct,
77
- pnl: pnl.toFixed(4),
78
- });
79
- }
80
- }
81
- process.stdout.write("\n\n");
82
- console.log(`Price history: ${marketsWithHistory}/${markets.length} markets had history, ` +
83
- `${marketsNoHistory} had no/insufficient data, ` +
84
- `${marketsNoSignal} had history but no signal fired`);
85
- // ── Active markets probe ──────────────────────────────────────────────────
86
- let activeProbeResults = [];
87
- if (marketsWithHistory === 0) {
88
- console.log("\nFetching active markets for live signal probe...");
89
- const activeMarkets = await fetchActiveMarkets(20);
90
- let activeWithHistory = 0;
91
- let activeSignalsFound = 0;
92
- for (const market of activeMarkets) {
93
- const tokenId = market.clobTokenId || market.conditionId;
94
- const history = await fetchPriceHistory(tokenId);
95
- if (history.length < 5)
96
- continue;
97
- activeWithHistory++;
98
- const signals = replaySignals(history);
99
- if (signals.length === 0)
100
- continue;
101
- activeSignalsFound++;
102
- const signal = signals[0];
103
- const { decision, latencyMs } = await askClaude(market.question, signal.oddsAtSignal);
104
- activeProbeResults.push({
105
- question: market.question,
106
- oddsAtSignal: signal.oddsAtSignal,
107
- decision,
108
- latencyMs,
109
- });
110
- }
111
- console.log(`Active market probe: ${activeMarkets.length} markets, ` +
112
- `${activeWithHistory} had price history, ` +
113
- `${activeSignalsFound} signals found`);
35
+ process.stdout.write("\n");
114
36
  }
115
- // ── Claude integration probe ──────────────────────────────────────────────
116
- // Always run this to verify the subprocess works, regardless of signals.
117
- console.log("\nRunning Claude integration probe (5 markets)...");
118
- const probe = await probeClaudeIntegration(markets);
119
- console.log(`Claude probe: ${probe.success}/5 calls succeeded, ` +
120
- `${probe.errors} errors, avg latency ${(probe.avgLatencyMs / 1000).toFixed(1)}s`);
121
- // Add probe results to the report if no signal-based results exist
122
- const reportResults = results.length > 0 ? results : probe.sample;
123
- const report = generateReport(reportResults, markets.length);
124
- const reportText = buildFullReport(report, probe, marketsNoHistory, markets.length, date, activeProbeResults);
125
- console.log("\n" + reportText);
37
+ const results = signals.map((signal) => {
38
+ const correlatedMoves = findCorrelatedMoves(signal, markets, tradesByMarket);
39
+ return {
40
+ signal,
41
+ marketsChecked: markets.length,
42
+ correlatedMoves,
43
+ };
44
+ });
45
+ const correlatedCount = results.filter((r) => r.correlatedMoves.length > 0).length;
46
+ const candleMinutes = (candles.length * GRANULARITY) / 60;
47
+ const signalRatePerDay = candleMinutes > 0 ? (signals.length / candleMinutes) * 24 * 60 : 0;
48
+ console.log(`\nResults:`);
49
+ console.log(` Signals fired: ${signals.length}`);
50
+ console.log(` Signals with correlated Polymarket moves: ${correlatedCount}/${signals.length}`);
51
+ console.log(` Correlation rate: ${signals.length > 0 ? ((correlatedCount / signals.length) * 100).toFixed(1) : "0.0"}%`);
52
+ const signalLog = buildSignalLog(results);
53
+ console.log("\nAsking Claude for interpretation...");
54
+ const claudeInterpretation = await askClaude(signalLog);
55
+ console.log("Claude responded.");
56
+ const report = {
57
+ date,
58
+ product: PRODUCT,
59
+ candlesAnalyzed: candles.length,
60
+ signalsFired: signals.length,
61
+ signalRatePerDay,
62
+ marketsChecked: markets.length,
63
+ correlatedSignals: correlatedCount,
64
+ correlationRate: signals.length > 0 ? (correlatedCount / signals.length) * 100 : 0,
65
+ signals: results,
66
+ claudeInterpretation,
67
+ };
68
+ const reportText = generateMarkdownReport(report);
126
69
  const reportPath = writeReport(reportText, date);
127
70
  console.log(`\nReport written to: ${reportPath}`);
128
- if (probe.errors > 0) {
129
- console.warn(`\nWARNING: ${probe.errors} Claude call(s) failed.\n` +
130
- "Check that CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_AUTH_TOKEN is set.");
131
- }
132
- }
133
- function buildFullReport(report, probe, marketsNoHistory, marketsTotal, date, activeProbeResults = []) {
134
- let text = formatBaseReport(report, date);
135
- if (marketsNoHistory === marketsTotal) {
136
- text +=
137
- "\n\nAPI FINDING: CLOB /prices-history endpoint returned empty data for all " +
138
- marketsTotal +
139
- " resolved markets.\n" +
140
- "Investigation results:\n" +
141
- " • GET /prices-history returns {history:[]} for all closed/resolved markets\n" +
142
- " • Active markets: price history exists but only ~2 data points (insufficient for 4h window)\n" +
143
- " • The end_date_min filter works to find recent markets efficiently\n" +
144
- " • Recommendation: use a dedicated historical data provider (Dune Analytics, TheGraph) for future backtests\n";
145
- }
146
- text +=
147
- "\n\nCLAUDE INTEGRATION PROBE (5 markets, no momentum signal required):\n" +
148
- ` ${probe.success}/5 calls succeeded (${probe.errors} errors)\n` +
149
- ` Avg latency: ${(probe.avgLatencyMs / 1000).toFixed(1)}s\n`;
150
- for (const r of probe.sample) {
151
- const icon = r.claudeDecision === "ERROR" ? "✗" : "✓";
152
- text +=
153
- ` ${icon} "${r.question.slice(0, 50)}" → ${r.claudeDecision} ` +
154
- `(${(r.claudeLatencyMs / 1000).toFixed(1)}s, resolved: ${r.actualResolution === 1 ? "YES" : "NO"})\n`;
155
- }
156
- if (activeProbeResults.length > 0) {
157
- text += "\n\nACTIVE MARKET PROBE RESULTS:\n";
158
- for (const r of activeProbeResults) {
159
- text +=
160
- ` "${r.question.slice(0, 50)}" → ${r.decision} ` +
161
- `(odds: ${(r.oddsAtSignal * 100).toFixed(1)}%, ${(r.latencyMs / 1000).toFixed(1)}s)\n`;
162
- }
163
- }
164
- return text;
71
+ console.log("\n" + reportText);
165
72
  }
166
73
  // Run when invoked directly (not imported)
167
74
  const selfPath = process.argv[1] ?? "";
@@ -1 +1 @@
1
- {"version":3,"file":"backtestRunner.js","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"backtestRunner.js","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,sBAAsB,EACtB,WAAW,GAIZ,MAAM,eAAe,CAAC;AAEvB,MAAM,OAAO,GAAG,SAAS,CAAC;AAC1B,MAAM,WAAW,GAAG,EAAE,CAAC,CAAC,mBAAmB;AAC3C,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,mBAAmB;AAC7C,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEnD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,YAAY,YAAY,MAAM,WAAW,iBAAiB,OAAO,KAAK,CAAC,CAAC;IAEpF,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;IAC/E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CACX,sDAAsD;YACpD,oBAAoB;YACpB,uCAAuC;YACvC,mBAAmB,CACtB,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,MAAM,+BAA+B,CAAC,CAAC;IAE7E,OAAO,CAAC,GAAG,CAAC,cAAc,kBAAkB,+BAA+B,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,qCAAqC,CAAC,CAAC;IAE5E,mEAAmE;IACnE,MAAM,cAAc,GAA+B,EAAE,CAAC;IACtD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,2BAA2B,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;QACpE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;gBACzF,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,OAAO,GAAmB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACrD,MAAM,eAAe,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;QAC7E,OAAO;YACL,MAAM;YACN,cAAc,EAAE,OAAO,CAAC,MAAM;YAC9B,eAAe;SAChB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IACnF,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAC1D,MAAM,gBAAgB,GACpB,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,+CAA+C,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChG,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IAE1H,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACrD,MAAM,oBAAoB,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEjC,MAAM,MAAM,GAAmB;QAC7B,IAAI;QACJ,OAAO,EAAE,OAAO;QAChB,eAAe,EAAE,OAAO,CAAC,MAAM;QAC/B,YAAY,EAAE,OAAO,CAAC,MAAM;QAC5B,gBAAgB;QAChB,cAAc,EAAE,OAAO,CAAC,MAAM;QAC9B,iBAAiB,EAAE,eAAe;QAClC,eAAe,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAClF,OAAO,EAAE,OAAO;QAChB,oBAAoB;KACrB,CAAC;IAEF,MAAM,UAAU,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,CAAC;AACjC,CAAC;AAED,2CAA2C;AAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACvC,IAAI,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;IACrF,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACnC,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonzih/polymarket-arb",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Claude-powered Polymarket arbitrage bot — BTC/ETH momentum signal + AI trade analysis",
5
5
  "keywords": [
6
6
  "polymarket",