Files
investor-flow/app/server/scripts/dealer-map-replay.ts
T

85 lines
2.3 KiB
TypeScript
Raw Normal View History

#!/usr/bin/env npx tsx
/**
* CLI: backtest GEX/VEX integrity by replaying chains as-of a timestamp.
*
* npx tsx scripts/dealer-map-replay.ts --symbol IREN --as-of 2026-08-07T13:14:00.000Z
* npx tsx scripts/dealer-map-replay.ts --symbol IREN --from-snapshots --days 7
*
* Exit 1 if integrity incomplete or snapshot drift too large.
*/
import { DatabaseSync } from 'node:sqlite';
import { resolve } from 'node:path';
import { replayDealerMapAt, replayFromSnapshots } from '../src/analysis/dealerMapReplay.ts';
function arg(name: string): string | undefined {
const i = process.argv.indexOf(name);
if (i < 0 || i + 1 >= process.argv.length) return undefined;
return process.argv[i + 1];
}
function has(name: string): boolean {
return process.argv.includes(name);
}
const symbol = (arg('--symbol') ?? 'IREN').toUpperCase();
const asOf = arg('--as-of');
const days = Number(arg('--days') ?? '7');
const fromSnapshots = has('--from-snapshots');
const dbPath =
arg('--db') ??
resolve(process.cwd(), 'data/investor-flow.db');
const db = new DatabaseSync(dbPath, { readOnly: true });
function printResult(r: ReturnType<typeof replayDealerMapAt>) {
console.log('---');
console.log(r.symbol, r.asOf);
console.log(' ok:', r.ok, '|', r.integrity.status);
console.log(' ', r.summary);
if (r.map?.levels.king) {
console.log(
' king:',
r.map.levels.king.strike,
r.map.levels.king.expiry,
`gex=${(r.map.levels.king.gex / 1000).toFixed(1)}K`,
);
}
console.log(
' metrics:',
JSON.stringify(r.integrity.metrics),
);
const fails = r.integrity.checks.filter((c) => !c.ok);
if (fails.length) {
console.log(' failed checks:');
for (const c of fails) {
console.log(` [${c.level}] ${c.id}: ${c.detail}`);
}
}
}
let anyFail = false;
if (fromSnapshots) {
const results = replayFromSnapshots(db, symbol, days);
if (results.length === 0) {
console.error('No snapshots for', symbol);
process.exit(2);
}
for (const r of results) {
printResult(r);
if (!r.ok) anyFail = true;
}
} else if (asOf) {
const r = replayDealerMapAt(db, symbol, asOf);
printResult(r);
if (!r.ok) anyFail = true;
} else {
console.error('Usage: --symbol SYM --as-of ISO | --from-snapshots [--days N] [--db path]');
process.exit(2);
}
db.close();
process.exit(anyFail ? 1 : 0);