feat(replay): R1 replay core — clock injection + replay of archived cycles
Re-executes BayesianStrategy.evaluate() over the R0 archive and stores results in replay_runs/replay_decisions, tagged with git sha + a hash of the strategy constants (same hash vs archive = determinism check, different hash = counterfactual run). - bayesian.py: optional as_of param on evaluate()/_days_to_resolution() (clock injection; default None = wall clock, prod behavior unchanged — the only touch to frozen code, purely additive) - bot/replay.py: replay engine + CLI (python -m bot.replay --from --to); ReplayNews feeds archived sentiment back (GNews never called, per-cycle budget bypassed — archived sentiment already encodes it); manifold/db not wired (observational-only in prod); recorded-vs-replayed compare at 1e-9 tolerance - schema.sql: replay_runs + replay_decisions (+ indexes), idempotent - db.py: 6 replay accessors/writers - tests: 19 new round-trip fidelity tests (104 total green) Validated against a real prod cycle (2026-07-02T14:03:15Z, 46 markets, 4 skip paths incl. the Georgia confidence record): 46/46 matched, max float delta 0.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
eb4f67414a
commit
0ac48ba7f8
@@ -370,3 +370,64 @@ CREATE TABLE IF NOT EXISTS ext_snapshots (
|
||||
total_market_cap_change DOUBLE PRECISION,
|
||||
valid BOOLEAN
|
||||
);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- Replay R1: replay core — re-execute evaluate() over the R0 archive
|
||||
--
|
||||
-- A replay run reads cycles from signals + ext_snapshots + markets, rebuilds
|
||||
-- the exact inputs (including archived news_sentiment — GNews is never called),
|
||||
-- re-runs BayesianStrategy.evaluate() with the archived cycle_ts as clock, and
|
||||
-- writes one replay_decisions row per (cycle, market).
|
||||
--
|
||||
-- replay_runs tags every run with the code (git_sha) and strategy constants
|
||||
-- (config_hash) that produced it: two runs over the same window with different
|
||||
-- config_hash values are a counterfactual comparison; same config_hash against
|
||||
-- the recorded rows is a determinism check (mismatches should be 0, modulo
|
||||
-- day-boundary crossings between cycle_ts and the original wall-clock).
|
||||
--
|
||||
-- matched: replayed decision equals the recorded one (skip_reason, probs,
|
||||
-- confidence, direction). NULL when not comparable — e.g. reentry_guard
|
||||
-- rows, recorded outside evaluate() with no decision fields to compare;
|
||||
-- the replay still re-evaluates them, which is extra calibration data.
|
||||
-- mismatch_field: first field that differed, for triage.
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS replay_runs (
|
||||
run_id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
git_sha TEXT,
|
||||
config_hash TEXT,
|
||||
config_json TEXT,
|
||||
from_ts TIMESTAMPTZ,
|
||||
to_ts TIMESTAMPTZ,
|
||||
cycles INTEGER,
|
||||
decisions INTEGER,
|
||||
matched INTEGER,
|
||||
mismatched INTEGER,
|
||||
note TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS replay_decisions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
run_id TEXT NOT NULL,
|
||||
cycle_ts TIMESTAMPTZ NOT NULL,
|
||||
market_id TEXT NOT NULL,
|
||||
-- replayed outputs (same semantics as the signals columns)
|
||||
skip_reason TEXT,
|
||||
prior_prob DOUBLE PRECISION,
|
||||
estimated_prob DOUBLE PRECISION,
|
||||
raw_final_prob DOUBLE PRECISION,
|
||||
edge_gross DOUBLE PRECISION,
|
||||
edge_net DOUBLE PRECISION,
|
||||
regime_min_edge DOUBLE PRECISION,
|
||||
days_to_resolution INTEGER,
|
||||
confidence DOUBLE PRECISION,
|
||||
direction TEXT,
|
||||
would_trade BOOLEAN,
|
||||
-- fidelity vs the recorded signals row
|
||||
recorded_skip_reason TEXT,
|
||||
matched BOOLEAN,
|
||||
mismatch_field TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_replay_decisions_run ON replay_decisions(run_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_replay_decisions_mkt ON replay_decisions(market_id);
|
||||
|
||||
Reference in New Issue
Block a user