Files
signal-platform/.gitignore
T
dennisthiessenandClaude Opus 5 c3ae5ad949 feat(research): commit the regime-monitor replay harness, and reproduce v2/v3
v3 was calibrated by replaying the series offline, but that harness was never
committed -- so its published numbers could not be re-derived, and a v4 cut would
have had to choose anchors by argument rather than measurement. This is that
harness, and it reproduces the published figures.

scripts/run_regime_monitor_calibration.py replays State/Warning session by
session from the same inputs the live job uses (Alpaca for all 33 symbols, FRED
for VIX and HY OAS), with no database: breadth and divergence come from
breadth_service's pure helpers. It never reimplements an unchanged live sensor --
_compute_index, _score_pillars, P2, P4 and the Warning sensors are imported and
called. Only candidate formulas (proposed v4) and retired ones (v2, gone from the
codebase) are defined here and patched onto the module for a variant's duration.

Reproduction of the 408 sessions ending 2026-07-24, against the figures in
docs/research/regime-monitor-v3.md:

  v2 State avg      22.6   ->  22.68
  v2 State p80      35.1   ->  35.1     exact
  v2 State max      91.2   ->  91.2     exact
  v2 P3 pegged        39   ->    39     exact
  v2 W1 live         108   ->   108     exact
  v3 State max      87.4   ->  87.4     exact
  v3 band shares  73.3/15.0/8.3/3.4 -> 73.0/15.4/8.1/3.4

Three things the harness had to get right to reach that, each of which was
initially wrong and caught by a gate rather than by inspection:

  - "W1 live 108" counts NONZERO sessions, not non-null ones. v2's divergence
    gate returned 0.0 during any decline (v3 tapers instead), so the retired
    divergence formula had to be reconstructed too.
  - v2 sliced HY_OAS_REFERENCE_YEARS = 10.0 per session, not v3's 700 days. The
    percentile leg ranks against that window, so replaying it short shifted the
    middle of the distribution while leaving the max exact.
  - The published v2 numbers correspond to FULL OAS coverage. Replaying v2 with
    the 400-calendar-day fetch it shipped with yields max 100.0 and 133
    credit-less sessions -- so that truncation was not in force when the figures
    were taken. Recorded rather than assumed.

The script refuses to emit a band recommendation unless every hard gate passes
(33 symbols fetched, per-symbol warm-up and final bar, full basket on every
session, calendar anchors, 100% coverage, and a row-wise state_v4 <= state_v3
invariant), and exits non-zero. It is meant to be structurally impossible to read
a calibration result out of a run whose pipeline did not validate. No v4 code
ships in this commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 20:05:12 +02:00

60 lines
1.2 KiB
Plaintext

# Python
__pycache__/
*.py[cod]
*.egg-info/
*.egg
dist/
build/
.venv/
.env
# Hypothesis (PBT)
.hypothesis/
# Pytest
.pytest_cache/
# IDE
.vscode/
.idea/
.claude/settings.local.json
*.swp
*.swo
# Local AI tool metadata
mcps/
# OS
.DS_Store
Thumbs.db
# Frontend
frontend/node_modules/
frontend/dist/
frontend/tsconfig.tsbuildinfo
# Alembic
alembic/versions/__pycache__/
# Generated SSL bundle
combined-ca-bundle.pem
# Dolt local dev clones. Production keeps clones in DOLT_DATA_DIR OUTSIDE the
# repo tree (deploy is rsync --delete of the tree); this dir is dev-only.
dolt-data/
# Local research artifacts
# Backtest reports in reports/ are tracked: they are the evidence behind the
# production baseline in the README. The snapshot DBs they run against are not.
backtest_snapshots/
# Rebuildable pickle caches are local accelerators, not decision evidence.
reports/*.pkl
reports/*.pk1
reports/.cache/
# Runtime A5 parity bundles are generated on the production server. Research
# conclusions belong in docs/research, not as an ever-growing artifact archive.
reports/fundamentals-parity/
# Calibration harness raw-pull cache (Alpaca/FRED); regenerable, not a record.
.calib-cache/