@gonzih/polymarket-arb 1.0.11 → 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.
- package/dist/backtest.d.ts +80 -76
- package/dist/backtest.d.ts.map +1 -1
- package/dist/backtest.js +202 -295
- package/dist/backtest.js.map +1 -1
- package/dist/backtestRunner.d.ts.map +1 -1
- package/dist/backtestRunner.js +61 -116
- package/dist/backtestRunner.js.map +1 -1
- package/package.json +1 -1
package/dist/backtest.d.ts
CHANGED
|
@@ -1,96 +1,100 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
3
|
-
export
|
|
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 = {
|
|
14
|
+
firedAt: number;
|
|
15
|
+
symbol: string;
|
|
16
|
+
direction: "UP" | "DOWN";
|
|
17
|
+
momentum: number;
|
|
18
|
+
price: number;
|
|
19
|
+
confidence: number;
|
|
20
|
+
};
|
|
21
|
+
export type RawTrade = {
|
|
22
|
+
price: string | number;
|
|
23
|
+
timestamp: string | number;
|
|
24
|
+
};
|
|
25
|
+
export type PolymarketMarket = {
|
|
4
26
|
id: string;
|
|
5
27
|
conditionId: string;
|
|
6
28
|
clobTokenId: string;
|
|
7
29
|
question: string;
|
|
30
|
+
yesPrice: number;
|
|
8
31
|
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
32
|
};
|
|
18
|
-
export type
|
|
19
|
-
firedAt: number;
|
|
20
|
-
oddsAtSignal: number;
|
|
21
|
-
direction: "YES" | "NO";
|
|
22
|
-
momentum: number;
|
|
23
|
-
};
|
|
24
|
-
export type ClaudeDecision = "BUY_YES" | "BUY_NO" | "PASS" | "ERROR";
|
|
25
|
-
export type BacktestResult = {
|
|
33
|
+
export type OddsMove = {
|
|
26
34
|
marketId: string;
|
|
27
35
|
question: string;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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;
|
|
36
55
|
};
|
|
37
|
-
export declare function fetchResolvedMarkets(limit?: number): Promise<ResolvedMarket[]>;
|
|
38
56
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* empty data for resolved/closed markets. Price history is only available for
|
|
42
|
-
* currently active markets, and typically has very few data points.
|
|
43
|
-
* marketId should be a clobTokenId (the long numeric string from clobTokenIds[0]).
|
|
57
|
+
* Fetch 1-minute (or custom granularity) OHLCV candles from Coinbase REST API.
|
|
58
|
+
* Coinbase returns newest-first; we reverse to chronological order.
|
|
44
59
|
*/
|
|
45
|
-
export declare function
|
|
60
|
+
export declare function fetchCoinbaseCandles(product?: string, granularity?: number, limit?: number): Promise<Candle[]>;
|
|
46
61
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
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.
|
|
49
64
|
*/
|
|
50
|
-
export declare function
|
|
51
|
-
success: number;
|
|
52
|
-
errors: number;
|
|
53
|
-
avgLatencyMs: number;
|
|
54
|
-
sample: BacktestResult[];
|
|
55
|
-
}>;
|
|
65
|
+
export declare function replaySignals(candles: Candle[], symbol?: string): CandleSignal[];
|
|
56
66
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* window and 5% threshold suited to hourly prediction market data (0-1 price range).
|
|
67
|
+
* Fetch active Polymarket markets from the CLOB API.
|
|
68
|
+
* Handles both array and {data:[]} response shapes.
|
|
60
69
|
*/
|
|
61
|
-
export declare function
|
|
70
|
+
export declare function fetchPolymarketMarkets(limit?: number): Promise<PolymarketMarket[]>;
|
|
62
71
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Capped at 10% maximum.
|
|
72
|
+
* Fetch recent trades for a Polymarket market token from the CLOB.
|
|
73
|
+
* Returns empty array on any error.
|
|
66
74
|
*/
|
|
67
|
-
export declare function
|
|
68
|
-
export declare function computePnl(decision: ClaudeDecision, odds: number, resolution: number, kellySizePct: number): number;
|
|
75
|
+
export declare function fetchMarketTrades(tokenId: string): Promise<RawTrade[]>;
|
|
69
76
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
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.
|
|
72
80
|
*/
|
|
73
|
-
export declare function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
export
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
export declare function generateReport(results: BacktestResult[], marketsAnalyzed: number): BacktestReport;
|
|
94
|
-
export declare function formatReport(report: BacktestReport, date: string): string;
|
|
95
|
-
export declare function writeReport(text: string, date: string): string;
|
|
81
|
+
export declare function findCorrelatedMoves(signal: CandleSignal, markets: PolymarketMarket[], tradesByMarket: Record<string, RawTrade[]>, oddsThreshold?: number, windowMinutes?: number): OddsMove[];
|
|
82
|
+
/**
|
|
83
|
+
* Build a human-readable signal log for Claude interpretation.
|
|
84
|
+
*/
|
|
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;
|
|
96
100
|
//# sourceMappingURL=backtest.d.ts.map
|
package/dist/backtest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backtest.d.ts","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"backtest.d.ts","sourceRoot":"","sources":["../src/backtest.ts"],"names":[],"mappings":"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"}
|
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
|
|
5
|
-
const CLOB_API = "https://clob.polymarket.com";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
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,354 +77,201 @@ function parseJsonField(field) {
|
|
|
17
77
|
return [];
|
|
18
78
|
}
|
|
19
79
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
clobTokenId,
|
|
99
|
+
return {
|
|
100
|
+
id: m.id ?? "",
|
|
101
|
+
conditionId: m.conditionId ?? m.id ?? "",
|
|
102
|
+
clobTokenId: tokenIds[0] ?? "",
|
|
65
103
|
question: m.question ?? "",
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* empty data for resolved/closed markets. Price history is only available for
|
|
90
|
-
* currently active markets, and typically has very few data points.
|
|
91
|
-
* marketId should be a clobTokenId (the long numeric string from clobTokenIds[0]).
|
|
116
|
+
* Fetch recent trades for a Polymarket market token from the CLOB.
|
|
117
|
+
* Returns empty array on any error.
|
|
92
118
|
*/
|
|
93
|
-
export async function
|
|
119
|
+
export async function fetchMarketTrades(tokenId) {
|
|
94
120
|
try {
|
|
95
|
-
const url = `${CLOB_API}/
|
|
121
|
+
const url = `${CLOB_API}/trades?market=${encodeURIComponent(tokenId)}&limit=500`;
|
|
96
122
|
const res = await fetch(url);
|
|
97
123
|
if (!res.ok)
|
|
98
124
|
return [];
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
return history.sort((a, b) => a.t - b.t);
|
|
125
|
+
const raw = (await res.json());
|
|
126
|
+
return Array.isArray(raw) ? raw : (raw.data ?? []);
|
|
102
127
|
}
|
|
103
128
|
catch {
|
|
104
129
|
return [];
|
|
105
130
|
}
|
|
106
131
|
}
|
|
107
132
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
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.
|
|
110
136
|
*/
|
|
111
|
-
export
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (decision === "ERROR")
|
|
122
|
-
errors++;
|
|
123
|
-
const correct = decision === "BUY_YES"
|
|
124
|
-
? market.resolution === 1
|
|
125
|
-
: decision === "BUY_NO"
|
|
126
|
-
? market.resolution === 0
|
|
127
|
-
: false;
|
|
128
|
-
results.push({
|
|
129
|
-
marketId: market.id,
|
|
130
|
-
question: market.question,
|
|
131
|
-
signalFiredAt: 0,
|
|
132
|
-
oddsAtSignal: odds,
|
|
133
|
-
claudeDecision: decision,
|
|
134
|
-
claudeLatencyMs: latencyMs,
|
|
135
|
-
actualResolution: market.resolution,
|
|
136
|
-
correct,
|
|
137
|
-
kellySizePct: 0,
|
|
138
|
-
hypotheticalPnl: 0,
|
|
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;
|
|
139
147
|
});
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
success: sample.length - errors,
|
|
143
|
-
errors,
|
|
144
|
-
avgLatencyMs: sample.length > 0 ? totalLatency / sample.length : 0,
|
|
145
|
-
sample: results,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Replays the EXISTING momentum signal logic against prediction market price history.
|
|
150
|
-
* Adapted from SignalEngine in signal.ts: same % change concept, but uses a 4-hour
|
|
151
|
-
* window and 5% threshold suited to hourly prediction market data (0-1 price range).
|
|
152
|
-
*/
|
|
153
|
-
export function replaySignals(history) {
|
|
154
|
-
const signals = [];
|
|
155
|
-
if (history.length < BACKTEST_WINDOW_HOURS + 1)
|
|
156
|
-
return signals;
|
|
157
|
-
let lastSignalAtMs = 0;
|
|
158
|
-
const COOLDOWN_MS = 12 * 60 * 60 * 1000; // 12-hour cooldown between signals per market
|
|
159
|
-
for (let i = BACKTEST_WINDOW_HOURS; i < history.length; i++) {
|
|
160
|
-
const windowStart = history[i - BACKTEST_WINDOW_HOURS];
|
|
161
|
-
const current = history[i];
|
|
162
|
-
if (windowStart.p === 0)
|
|
148
|
+
if (windowTrades.length < 2)
|
|
163
149
|
continue;
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
momentum,
|
|
176
|
-
});
|
|
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",
|
|
159
|
+
});
|
|
160
|
+
}
|
|
177
161
|
}
|
|
178
|
-
return
|
|
162
|
+
return correlated;
|
|
179
163
|
}
|
|
180
164
|
/**
|
|
181
|
-
*
|
|
182
|
-
* where b = net odds (profit per $ risked), p = win probability, q = 1 - p
|
|
183
|
-
* Capped at 10% maximum.
|
|
165
|
+
* Build a human-readable signal log for Claude interpretation.
|
|
184
166
|
*/
|
|
185
|
-
export function
|
|
186
|
-
if (
|
|
187
|
-
return
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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.";
|
|
170
|
+
}
|
|
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}`);
|
|
202
188
|
}
|
|
203
|
-
return
|
|
189
|
+
return lines.join("\n");
|
|
204
190
|
}
|
|
205
191
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
192
|
+
* Spawn claude --print and ask for signal pattern analysis.
|
|
193
|
+
* Returns Claude's response text or a fallback message on failure.
|
|
208
194
|
*/
|
|
209
|
-
export async function askClaude(
|
|
210
|
-
const
|
|
211
|
-
|
|
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}`;
|
|
212
199
|
return new Promise((resolve) => {
|
|
213
200
|
const proc = spawn("claude", ["--print", "--model", "claude-haiku-4-5-20251001"], {
|
|
214
201
|
env: { ...process.env },
|
|
215
202
|
stdio: ["pipe", "pipe", "pipe"],
|
|
216
203
|
});
|
|
217
|
-
// Send prompt via stdin then close it so claude knows there is no more input
|
|
218
204
|
proc.stdin.write(prompt);
|
|
219
205
|
proc.stdin.end();
|
|
220
206
|
let stdout = "";
|
|
221
|
-
let stderr = "";
|
|
222
207
|
let timedOut = false;
|
|
223
208
|
proc.stdout.on("data", (chunk) => {
|
|
224
209
|
stdout += chunk.toString();
|
|
225
210
|
});
|
|
226
|
-
proc.stderr.on("data", (
|
|
227
|
-
stderr += chunk.toString();
|
|
228
|
-
});
|
|
211
|
+
proc.stderr.on("data", () => { }); // suppress stderr noise
|
|
229
212
|
const timer = setTimeout(() => {
|
|
230
213
|
timedOut = true;
|
|
231
214
|
proc.kill("SIGTERM");
|
|
232
|
-
},
|
|
215
|
+
}, 60_000);
|
|
233
216
|
proc.on("close", (code) => {
|
|
234
217
|
clearTimeout(timer);
|
|
235
|
-
const latencyMs = Date.now() - start;
|
|
236
218
|
if (timedOut || code !== 0) {
|
|
237
|
-
|
|
238
|
-
? "timeout after 30s"
|
|
239
|
-
: `exit code ${code}${stderr ? ": " + stderr.slice(0, 200) : ""}`;
|
|
240
|
-
log("warn", { source: "backtest", event: "claude_error", error: err });
|
|
241
|
-
resolve({ decision: "ERROR", latencyMs });
|
|
219
|
+
resolve("(Claude interpretation unavailable — subprocess error or timeout)");
|
|
242
220
|
return;
|
|
243
221
|
}
|
|
244
|
-
|
|
245
|
-
let decision = "PASS";
|
|
246
|
-
if (text.includes("BUY_YES"))
|
|
247
|
-
decision = "BUY_YES";
|
|
248
|
-
else if (text.includes("BUY_NO"))
|
|
249
|
-
decision = "BUY_NO";
|
|
250
|
-
log("info", {
|
|
251
|
-
source: "backtest",
|
|
252
|
-
event: "claude_decision",
|
|
253
|
-
question: question.slice(0, 60),
|
|
254
|
-
decision,
|
|
255
|
-
latencyMs,
|
|
256
|
-
});
|
|
257
|
-
resolve({ decision, latencyMs });
|
|
222
|
+
resolve(stdout.trim() || "(No interpretation returned)");
|
|
258
223
|
});
|
|
259
|
-
proc.on("error", (
|
|
224
|
+
proc.on("error", () => {
|
|
260
225
|
clearTimeout(timer);
|
|
261
|
-
|
|
262
|
-
log("warn", { source: "backtest", event: "claude_error", error: String(err) });
|
|
263
|
-
resolve({ decision: "ERROR", latencyMs });
|
|
226
|
+
resolve("(Claude interpretation unavailable — spawn error)");
|
|
264
227
|
});
|
|
265
228
|
});
|
|
266
229
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
claudeErrors,
|
|
284
|
-
avgLatencyMs,
|
|
285
|
-
maxLatencyMs,
|
|
286
|
-
buyYesTotal: buyYes.length,
|
|
287
|
-
buyYesCorrect: buyYes.filter((r) => r.correct).length,
|
|
288
|
-
buyNoTotal: buyNo.length,
|
|
289
|
-
buyNoCorrect: buyNo.filter((r) => r.correct).length,
|
|
290
|
-
passCount: passes.length,
|
|
291
|
-
avgKellyPct,
|
|
292
|
-
totalPnl,
|
|
293
|
-
results,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
export function formatReport(report, date) {
|
|
297
|
-
const totalDecisions = report.buyYesTotal + report.buyNoTotal;
|
|
298
|
-
const totalCorrect = report.buyYesCorrect + report.buyNoCorrect;
|
|
299
|
-
const winRate = totalDecisions > 0 ? (totalCorrect / totalDecisions) * 100 : 0;
|
|
300
|
-
const signalRate = report.marketsAnalyzed > 0
|
|
301
|
-
? (report.signalsFired / report.marketsAnalyzed) * 100
|
|
302
|
-
: 0;
|
|
303
|
-
const yesAcc = report.buyYesTotal > 0
|
|
304
|
-
? `${report.buyYesCorrect}/${report.buyYesTotal} (${((report.buyYesCorrect / report.buyYesTotal) * 100).toFixed(1)}%)`
|
|
305
|
-
: "0/0 (n/a)";
|
|
306
|
-
const noAcc = report.buyNoTotal > 0
|
|
307
|
-
? `${report.buyNoCorrect}/${report.buyNoTotal} (${((report.buyNoCorrect / report.buyNoTotal) * 100).toFixed(1)}%)`
|
|
308
|
-
: "0/0 (n/a)";
|
|
309
|
-
const claudeStatus = report.claudeErrors === 0
|
|
310
|
-
? ` ✓ All ${report.claudeSuccesses} calls succeeded`
|
|
311
|
-
: ` ✓ ${report.claudeSuccesses} calls succeeded\n ✗ ${report.claudeErrors} error${report.claudeErrors !== 1 ? "s" : ""}`;
|
|
312
|
-
let verdict;
|
|
313
|
-
if (totalDecisions === 0) {
|
|
314
|
-
verdict =
|
|
315
|
-
"INSUFFICIENT DATA: No actionable signals. Either no price history from API, " +
|
|
316
|
-
"signals never crossed the 5% threshold, or all signals fired after market resolution.";
|
|
317
|
-
}
|
|
318
|
-
else if (totalDecisions < 5) {
|
|
319
|
-
verdict =
|
|
320
|
-
`TOO FEW TRADES: Only ${totalDecisions} trade${totalDecisions !== 1 ? "s" : ""} — ` +
|
|
321
|
-
"cannot distinguish edge from luck. Need 30+ trades for statistical significance.";
|
|
322
|
-
}
|
|
323
|
-
else if (winRate > 60) {
|
|
324
|
-
verdict =
|
|
325
|
-
`POSSIBLE EDGE: Win rate ${winRate.toFixed(1)}% exceeds 50% baseline. ` +
|
|
326
|
-
`P&L: ${report.totalPnl >= 0 ? "+" : ""}${(report.totalPnl * 100).toFixed(1)}% of bankroll. ` +
|
|
327
|
-
"Needs larger sample (30+ trades) to confirm.";
|
|
328
|
-
}
|
|
329
|
-
else if (winRate > 50) {
|
|
330
|
-
verdict =
|
|
331
|
-
`WEAK SIGNAL: Win rate ${winRate.toFixed(1)}% slightly above baseline. ` +
|
|
332
|
-
"Cannot yet distinguish from noise. More data needed.";
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
verdict =
|
|
336
|
-
`NO EDGE DETECTED: Win rate ${winRate.toFixed(1)}% at or below 50% baseline. ` +
|
|
337
|
-
"Current signal parameters not predictive on this historical data.";
|
|
338
|
-
}
|
|
339
|
-
const lines = [
|
|
340
|
-
"=== POLYMARKET-ARB BACKTEST REPORT ===",
|
|
341
|
-
`Date: ${date}`,
|
|
342
|
-
"",
|
|
343
|
-
`Markets analyzed: ${report.marketsAnalyzed}`,
|
|
344
|
-
`Signals fired: ${report.signalsFired} (${signalRate.toFixed(1)}% of markets)`,
|
|
345
|
-
`Claude Code: ${report.claudeSuccesses}/${report.signalsFired} decisions returned (${report.claudeErrors} error${report.claudeErrors !== 1 ? "s" : ""})`,
|
|
346
|
-
`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}`,
|
|
347
246
|
"",
|
|
348
|
-
"
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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)}%`,
|
|
352
254
|
"",
|
|
353
|
-
"
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
255
|
+
"## Signal Log",
|
|
256
|
+
"| Time | Symbol | Momentum | Direction | Market Move |",
|
|
257
|
+
"|------|--------|----------|-----------|-------------|",
|
|
258
|
+
...signalRows,
|
|
357
259
|
"",
|
|
358
|
-
"
|
|
359
|
-
|
|
260
|
+
"## Interpretation",
|
|
261
|
+
report.claudeInterpretation,
|
|
360
262
|
"",
|
|
361
|
-
|
|
362
|
-
];
|
|
363
|
-
return lines.join("\n");
|
|
263
|
+
].join("\n");
|
|
364
264
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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);
|
|
368
275
|
return reportPath;
|
|
369
276
|
}
|
|
370
277
|
//# sourceMappingURL=backtest.js.map
|
package/dist/backtest.js.map
CHANGED
|
@@ -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":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,MAAM,CAAC,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAChE,MAAM,CAAC,MAAM,QAAQ,GAAG,6BAA6B,CAAC;AACtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAC,+BAA+B;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,CAAC,eAAe;AAC1D,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAK7C,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAmD5B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAO,GAAG,SAAS,EACnB,WAAW,GAAG,EAAE,EAChB,KAAK,GAAG,GAAG;IAEX,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,YAAY,aAAa,kBAAkB,CAAC,OAAO,CAAC,wBAAwB,WAAW,UAAU,KAAK,EAAE,CAAC;QACxH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,wBAAwB,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACzF,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAa,CAAC;QAC5C,+BAA+B;QAC/B,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,4BAA4B,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7F,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAiB,EAAE,MAAM,GAAG,SAAS;IACjE,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAClC,MAAM,cAAc,GAAkC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAEzE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QACnC,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QAE/B,IAAI,IAAI,KAAK,CAAC;YAAE,SAAS;QAEzB,MAAM,QAAQ,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,kBAAkB;YAAE,SAAS;QAEtD,MAAM,SAAS,GAAkB,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9D,MAAM,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC;QAE1B,IAAI,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,WAAW;YAAE,SAAS;QAEhE,cAAc,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC;YACX,OAAO;YACP,MAAM;YACN,SAAS;YACT,QAAQ;YACR,KAAK,EAAE,KAAK;YACZ,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC;SACvE,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,KAAwB;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAYD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAAK,GAAG,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,QAAQ,2CAA2C,KAAK,EAAE,CAAC;QAC1E,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,0BAA0B,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAC3F,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6D,CAAC;QAC3F,MAAM,OAAO,GAA0B,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAEnF,OAAO,OAAO;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAClC,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;YACxD,OAAO;gBACL,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE;gBACd,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE;gBACxC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE;gBAC9B,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;gBAC1B,QAAQ;gBACR,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;aAC7C,CAAC;QACJ,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,8BAA8B,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/F,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,QAAQ,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC;QACjF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAsC,CAAC;QACpE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAoB,EACpB,OAA2B,EAC3B,cAA0C,EAC1C,aAAa,GAAG,qBAAqB,EACrC,aAAa,GAAG,0BAA0B;IAE1C,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC7C,MAAM,YAAY,GAAG,cAAc,GAAG,aAAa,GAAG,EAAE,CAAC;IACzD,MAAM,UAAU,GAAe,EAAE,CAAC;IAElC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACvC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;YACrD,OAAO,KAAK,IAAI,cAAc,IAAI,KAAK,IAAI,YAAY,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAEtC,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;QAEzC,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,aAAa,EAAE,CAAC;YAC1C,UAAU,CAAC,IAAI,CAAC;gBACd,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;gBAChC,SAAS,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;aAC1C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAuB;IACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,mGAAmG,CAAC;IAC7G,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9E,MAAM,KAAK,GAAG;QACZ,kBAAkB,OAAO,CAAC,MAAM,EAAE;QAClC,yCAAyC,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE;QACvE,qBAAqB,CAAC,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QACxE,EAAE;QACF,aAAa;KACd,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,OAAO,GACX,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;YAC1B,CAAC,CAAC,CAAC,CAAC,eAAe;iBACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,CAAC;iBAC7F,IAAI,CAAC,IAAI,CAAC;YACf,CAAC,CAAC,qBAAqB,CAAC;QAC5B,KAAK,CAAC,IAAI,CACR,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,GAAG,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAChI,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAiB;IAC/C,MAAM,MAAM,GACV,sFAAsF;QACtF,4GAA4G;QAC5G,oDAAoD,SAAS,EAAE,CAAC;IAElE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,2BAA2B,CAAC,EAAE;YAChF,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;YACvB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QAEjB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACvC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,wBAAwB;QAE1D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,QAAQ,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,mEAAmE,CAAC,CAAC;gBAC7E,OAAO;YACT,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,8BAA8B,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,mDAAmD,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAsB;IAC3D,MAAM,UAAU,GACd,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACvB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;YACvD,MAAM,UAAU,GACd,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;gBAC1B,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAChF,CAAC,CAAC,GAAG,CAAC;YACV,OAAO,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,SAAS,MAAM,UAAU,IAAI,CAAC;QAC3F,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC;IAEhC,OAAO;QACL,2BAA2B,MAAM,CAAC,IAAI,EAAE;QACxC,EAAE;QACF,YAAY;QACZ,uBAAuB,MAAM,CAAC,eAAe,EAAE;QAC/C,oBAAoB,MAAM,CAAC,YAAY,EAAE;QACzC,kBAAkB,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU;QAC9D,iCAAiC,MAAM,CAAC,cAAc,EAAE;QACxD,kDAAkD,MAAM,CAAC,iBAAiB,EAAE;QAC5E,uBAAuB,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAC3D,EAAE;QACF,eAAe;QACf,wDAAwD;QACxD,wDAAwD;QACxD,GAAG,UAAU;QACb,EAAE;QACF,mBAAmB;QACnB,MAAM,CAAC,oBAAoB;QAC3B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,IAAY,EAAE,GAAG,GAAG,UAAU;IACtE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,IAAI,KAAK,CAAC,CAAC;IACjE,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backtestRunner.d.ts","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"AAoBA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"backtestRunner.d.ts","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"AAoBA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAiFjD"}
|
package/dist/backtestRunner.js
CHANGED
|
@@ -1,129 +1,74 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const
|
|
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
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
" •
|
|
16
|
-
" •
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
});
|
|
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
|
+
}
|
|
79
34
|
}
|
|
35
|
+
process.stdout.write("\n");
|
|
80
36
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
console.log(
|
|
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);
|
|
96
69
|
const reportPath = writeReport(reportText, date);
|
|
97
70
|
console.log(`\nReport written to: ${reportPath}`);
|
|
98
|
-
|
|
99
|
-
console.warn(`\nWARNING: ${probe.errors} Claude call(s) failed.\n` +
|
|
100
|
-
"Check that CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_AUTH_TOKEN is set.");
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function buildFullReport(report, probe, marketsNoHistory, marketsTotal, date) {
|
|
104
|
-
let text = formatBaseReport(report, date);
|
|
105
|
-
if (marketsNoHistory === marketsTotal) {
|
|
106
|
-
text +=
|
|
107
|
-
"\n\nAPI FINDING: CLOB /prices-history endpoint returned empty data for all " +
|
|
108
|
-
marketsTotal +
|
|
109
|
-
" resolved markets.\n" +
|
|
110
|
-
"Investigation results:\n" +
|
|
111
|
-
" • GET /prices-history returns {history:[]} for all closed/resolved markets\n" +
|
|
112
|
-
" • Active markets: price history exists but only ~2 data points (insufficient for 4h window)\n" +
|
|
113
|
-
" • The end_date_min filter works to find recent markets efficiently\n" +
|
|
114
|
-
" • Recommendation: use a dedicated historical data provider (Dune Analytics, TheGraph) for future backtests\n";
|
|
115
|
-
}
|
|
116
|
-
text +=
|
|
117
|
-
"\n\nCLAUDE INTEGRATION PROBE (5 markets, no momentum signal required):\n" +
|
|
118
|
-
` ${probe.success}/5 calls succeeded (${probe.errors} errors)\n` +
|
|
119
|
-
` Avg latency: ${(probe.avgLatencyMs / 1000).toFixed(1)}s\n`;
|
|
120
|
-
for (const r of probe.sample) {
|
|
121
|
-
const icon = r.claudeDecision === "ERROR" ? "✗" : "✓";
|
|
122
|
-
text +=
|
|
123
|
-
` ${icon} "${r.question.slice(0, 50)}" → ${r.claudeDecision} ` +
|
|
124
|
-
`(${(r.claudeLatencyMs / 1000).toFixed(1)}s, resolved: ${r.actualResolution === 1 ? "YES" : "NO"})\n`;
|
|
125
|
-
}
|
|
126
|
-
return text;
|
|
71
|
+
console.log("\n" + reportText);
|
|
127
72
|
}
|
|
128
73
|
// Run when invoked directly (not imported)
|
|
129
74
|
const selfPath = process.argv[1] ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backtestRunner.js","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"backtestRunner.js","sourceRoot":"","sources":["../src/backtestRunner.ts"],"names":[],"mappings":"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"}
|