feat(replay): R0 snapshot recorder — archive per-cycle decisions into signals
The signals and markets tables existed since Phase 2/5 but never had a writer; the replay engine (phase plan line 2.1) needs a per-(market, cycle) archive of what the strategy saw and decided. This wires them up: - signals: one row per evaluated market per cycle, now carrying INPUTS (news_sentiment, feat_*_lo, volume_24h, days_to_resolution) plus the existing outputs (probs, edges, gates, skip_reason). skip_reason is granular: unsupported/no_signals/prior_extreme/family/edge_net/ confidence/reentry_guard. news_budget_skipped distinguishes "GNews not asked" (5-query budget) from "no news". - ext_snapshots: one row per cycle with the ExternalSignals snapshot; signals rows join on cycle_ts. - markets: metadata upserted each cycle (replay rebuilds Market from it). - Retention: prune > SIGNALS_RETENTION_DAYS (default 90) once a day. - SIGNAL_RECORDER_ENABLED (default true) gates all DB writes; every write is try/except — the recorder can never break trading. Strategy changes are purely additive (record accumulation at each exit path of evaluate()); no weights, thresholds, gates or sizing touched, per the freeze in the current phase plan. Tests: 10 new deterministic tests (85 total passing). Schema migration dry-run validated against prod postgres inside a rolled-back transaction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
117d2b33b2
commit
919fe1617a
@@ -318,3 +318,55 @@ CREATE TABLE IF NOT EXISTS manifold_eval_cooldown (
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mfld_cooldown_retry ON manifold_eval_cooldown(retry_after);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- Replay R0: snapshot recorder — the archive the replay engine reads from
|
||||
--
|
||||
-- The signals table (Phase 2/5 schema) never had a writer; R0 makes it the
|
||||
-- per-(market, cycle) decision archive. One row per evaluated market per
|
||||
-- cycle, carrying both the INPUTS the strategy saw (external signals, news
|
||||
-- sentiment, per-feature log-odds) and the OUTPUTS it produced (probs, edges,
|
||||
-- gates, skip_reason). A replay run rebuilds Market/ExternalSignals from
|
||||
-- these rows plus ext_snapshots and re-executes evaluate() deterministically.
|
||||
--
|
||||
-- cycle_ts groups all rows of one trading cycle and joins them to their
|
||||
-- ext_snapshots row (same timestamp; no FK to keep writes independent).
|
||||
-- days_to_resolution is persisted so replay does not depend on wall-clock.
|
||||
-- news_budget_skipped distinguishes "GNews had nothing" from "GNews was not
|
||||
-- asked this cycle" (5-query budget) — without it politics replay would treat
|
||||
-- budget starvation as absence of news.
|
||||
-- Retention: rows older than SIGNALS_RETENTION_DAYS (default 90) are pruned.
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS cycle_ts TIMESTAMPTZ;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS category TEXT;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS prior_prob DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS raw_final_prob DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS days_to_resolution INTEGER;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS volume_24h DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS news_sentiment DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS news_budget_skipped BOOLEAN;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS guardrail_applied BOOLEAN;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS guardrail_changed_decision BOOLEAN;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS feat_fg_lo DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS feat_mom_lo DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS feat_news_lo DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS feat_mfld_lo DOUBLE PRECISION;
|
||||
ALTER TABLE signals ADD COLUMN IF NOT EXISTS feat_btc_dom_lo DOUBLE PRECISION;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_signals_cycle ON signals(cycle_ts);
|
||||
|
||||
-- One row per trading cycle: the ExternalSignals snapshot every market in
|
||||
-- that cycle was evaluated against. Written once per cycle before the
|
||||
-- evaluation loop; signals rows join on cycle_ts.
|
||||
CREATE TABLE IF NOT EXISTS ext_snapshots (
|
||||
cycle_ts TIMESTAMPTZ PRIMARY KEY,
|
||||
btc_price DOUBLE PRECISION,
|
||||
btc_change_24h DOUBLE PRECISION,
|
||||
eth_price DOUBLE PRECISION,
|
||||
eth_change_24h DOUBLE PRECISION,
|
||||
btc_dominance DOUBLE PRECISION,
|
||||
fear_greed_index INTEGER,
|
||||
fear_greed_label TEXT,
|
||||
total_market_cap_change DOUBLE PRECISION,
|
||||
valid BOOLEAN
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user