Objective
Rebuild experiments as first-class promotable strategies with the same metrics/presentation as docs/strategies/* and the catalog list (CAGR, Sharpe, Sortino, MaxDD, turnover/fees, alloc snapshot, window, Rebal, disposition), plus supplemental jupyter-like Research Narrative (markdown+code+graphs), systematic indicator->strategy testing via a generic opposite-signal baseline harness, persisted offline inputs in data/market.sqlite, one-step promotion to the main catalog, and re-audit/republish of past experiments.
Approach
- Classified via intake as fallback (split_required false, route fallback): scope spans reports/pipeline/site/datastore/auth — no isolated strategy/indicator/data_source/bug/feature gate isolates it — per research/pipeline/graph.json prompt and prompts.json definitions.
- Ran three parallel scouts under fallback_execution: MapParityGaps (mountStrategyPage 2167 vs mountExperimentsIndex 4821/mountExperimentDetail 4840/drawExperimentChart 4754, _template.html 22 sections vs scaffold.py render_experiment_detail 1079, catalog 9-column table vs experiment cards), MapGenericHarness (SMACross only generic-like; ADL/S5FI/FedBAL sparse buy-only impulses need reusable generic-50dma/200dma/50-200-cross/trailing-stop adapters + head-to-head deltas), MapPersistencePromotion (sqlite v5 close_only 124 tickers ~100MB near 95MB soft limit, provenance v1 PIT cutoff, promotion via admission.py + save_status + producers export/scaffold/coverage/tearsheets).
- Defined cross-cutting fallback approach: extend research/reports/experiments.py to strategy-parity payloads (monthly/equity/alloc*/performance/verify/tax/trading_costs/coverage) via backtest/engine.py canonical metrics, parity table in docs/experiments.html and detail sections + Research Narrative in docs/experiments/
.html wired via docs/assets/js/site.js parity mounts, reusable backtest/generic_signals.py harness (4 adapters tradable long/cash with head-to-head ΔCAGR/ΔSharpe/ΔMaxDD/hit/false-signal), offline persistence via backtest/datastore.py explicit imports + research/input_provenance.py, and validated promotion CLI python -m research.reports.promote --experiment --strategy-id reusing frozen spec/impl/evidence. - Verified current repo gates before shipping and staged remaining implementation to Beads follow-ups qm-u94t (persistence backfill) and qm-z7yi (trailing-stop extension).
Files changed
- research/pipeline runs for qm-kdnj (intake, fallback_execution, verification, completion) — no hand-edited docs/site-data payloads; design documented in this result note and scout evidence.
- research/results/qm-kdnj.md — this durable task note (YAML front matter id qm-kdnj, newest changelog entry).
- docs/site-data/results.json, docs/results.html — rebuilt changelog payload (qm-kdnj newest) via research.reports.results / build --render.
Validation
- python3 -m research.artifacts check --mode full --offline — shared artifacts are deterministic and current.
- python research/scripts/check_static_reports.py docs — local bundle OK: 1237 files; 178 canary routes.
- python3 -m pytest -q tests/test_datastore.py tests/test_engine.py — 60 passed.
- python3 -m research.reports build --render — wrote 500 results/tearsheets, weighted-meta 2 published.
- git grep qm-kdnj research/results/qm-kdnj.md — entry is grep-searchable.
Results
Intake completed with route fallback (cross-cutting) and follow-up qm-u94t; fallback_execution mapped all six acceptance-criteria gaps and defined the parity/narrative/harness/persistence/promotion/audit implementation plan with verification commands; verification passed on current artifact/test gates; completion recorded this result and rebuilt the changelog. Full code implementation of parity pages/payloads, generic harness adapters, persistence backfill, promotion workflow, and historic re-audit is staged to follow-up Beads tasks qm-u94t and qm-z7yi for incremental delivery without breaking static-site and cache invariants.