Commit Graph
14 Commits
Author SHA1 Message Date
dennisthiessenandClaude Opus 5 3143477a62 feat(regime): cut the risk monitor to v4 — desaturate VIX and the trend break
Two sensors saturated in exactly the range where resolution matters, and the top
State band had no headroom. Calibrated with scripts/run_regime_monitor_calibration.py
over the 408 sessions ending 2026-07-24; the shipped code reproduces that run's
band shares exactly (78.9 / 13.0 / 4.7 / 3.4).

V1 read VIX 30, 50 and 82 as an identical 100 — the same defect v3 had just
removed from P3, left in place one sensor over. In the window it flattened five
distinct April-2025 prints (52.33, 46.98, 45.31, 40.72, 38.57) into one value.
Now an anchor table reaching full scale at 55, not at 2020's ~82: anchoring the
top at a once-in-a-generation print would make VIX 50 read only ~70. Pegged on
14 of 408 sessions before; none now.

_under_200 returned a bare 0/100, so P1 printed 100 the moment SMH and QQQ were
both under their average — and since the price pillar takes max(P1, P2, P3),
that pinned the pillar and stopped P3's ladder resolving for the whole of a
selloff. Now graded by depth below the 200-DMA, with a deliberate floor of 20 at
the crossing: the break is a genuine binary event, only its depth is graded.
Pegged on 46 of 408 sessions before; none now. A 2% break reads ~30, not 100.

max() was KEPT — the defect was the step function feeding it, not the vote, and
v3's "one capped vote for correlated reads" rationale still holds. P1 is the sole
price argmax on 17 of 408 sessions (4.2%), so the P1_SCORE_CAP fallback drafted
during design was measured as unnecessary and not shipped.

STATE_BANDS breaking 80 -> 65, and only that threshold. Credit returns 0.0 (not
None) when calm, so it holds its 20 points pinned at zero and price + breadth +
volatility at literal maximum summed to exactly 80.0 — v3's threshold to the
decimal, with nothing above it. The sensor is deliberately unchanged: a
calm-credit selloff genuinely is less stressed. What was stale is the band, fit
on v2 while credit's since-removed percentile leg still contributed. A
2022-style AI/tech drawdown with calm credit computes to 70.3 (no death cross) or
74.0 (with one); 70 would have left 0.33 points of headroom, reproducing the
defect. Chosen by scenario arithmetic, and the realized breaking share then lands
on 3.4% — the same as v3's, arrived at independently.

"v4" added to CATEGORICAL_FUNDAMENTAL_METHODOLOGIES in this same commit, which is
load-bearing: that set is checked against the STORED blob, so bumping without it
discards the collected observation on first write, leaving fetched_at null and
locked false — and update_regime_monitor then fires a paid LLM refresh on every
run, forever. Now guarded by a test parametrised over v2 and v3 stored blobs.

SENSOR_REVISION deliberately stays 2: a METHODOLOGY change already forces a full
reseed via _parse_snapshot, and bumping both would imply the reseed was
revision-driven.

QUADRANT_STATE_DIVIDER stays 50 because only breaking moved, so alert_service,
RegimeChart and the quadrant tests need no change. A new test enforces
divider == band boundary on both axes, which nothing did before.

Doc renamed to regime-monitor-v4.md with a tombstone at the old path (commit
messages cite it), the three open questions converted to resolved with the
reasoning that closed them, and indexed in docs/research/README.md for the first
time. The P2 limit is stated honestly: _death_cross pegs at a -5% MA gap, so a
deep selloff still reaches 100 via P2 — v4 repairs the shallow-to-moderate break,
not "the price pillar no longer pegs".

DEPLOY: the first run reseeds ~464 sessions. Expect one phantom quadrant alert
(the dedup key carries basket_hash, not methodology) and re-run the Event Study
manually — its cached report self-invalidates but does not self-regenerate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 20:34:25 +02:00
dennisthiessenandClaude Opus 5 f5d4b516ab docs: land capacity-study evidence and share the rank-map helper
Deploy / lint (push) Successful in 10s
Deploy / test (push) Successful in 1m21s
Deploy / deploy (push) Successful in 37s
Brings the durable artifacts of research/portfolio-capacity-rebalancing onto
main so the rationale for raising the count cap lives with the code that cites
it. The matrix runner, the research simulator hooks and the study's unit tests
are deliberately left behind; they remain at tag research/portfolio-capacity-final.

Corrects conclusions that were reached on EV per trade and are now superseded:
the findings doc's decisions 1 (keep cap 10) and 4 (run the risk-floor A/B) are
struck through and answered in a new correction section, and the research README
and phase-A matrix entries are updated to match. The frozen specification itself
is untouched -- its recorded SHA-256 f1e37783 still verifies.

effective-risk-floor-ab.md is retained but marked CLOSED/NEGATIVE: the study it
proposes is already answered by cap15 vs cash_unbounded (-0.753pp CAGR while
EV/trade rises), and its EV-based pass rule would have shipped it.

scripts/research_rankings.py replaces a fourth copy of the historical rank-map
helper; run_research_matrix, run_execution_recovery_matrix and
run_daily_reentry_matrix now share it. The shared version adds a duplicate
observation guard and a deterministic symbol tie-break the copies lacked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:08:29 +02:00
dennisthiessen 9717d8176b research: archive Task 1 sector residual as CLOSED/REJECTED
Deep masked retest failed the iron IC bar (0.027 < 0.03). Log as rejected #13 in
research README; close sector-residual and history-depth docs. Production market
residual unchanged.
2026-07-19 11:45:15 +02:00
dennisthiessen 2311999e57 research: park Phase B fip breadth; race guard and compact evidence
Log the 21:14 orphan as a snapshot-build race, rewrite the context table to
authoritative ICs only, and soften the vol-tilt warning. Add extender completion
manifest + breadth refuse guard; strip intermediate/orphaned reports; park the
thread (no book sim, no deploy).
2026-07-19 00:32:20 +02:00
dennisthiessen ceaaadc49f research: fip breadth diagnostics + compositional read
Add lagged/tier/prod-subset/mom-conditional checks on research.sqlite.
Log: unconditional sign is a winner/bleeder tug-of-war; mom-conditional
fip stays negative and reliable; warn on high-vol tilt if universe broadens.
2026-07-18 21:40:05 +02:00
dennisthiessen 9704e0d85a feat: Phase B fip_id liquid-breadth research tooling
Deploy / lint (push) Successful in 9s
Deploy / deploy (push) Canceled after 0s
Deploy / test (push) Canceled after 1m5s
Add research-only snapshot extender, PIT dollar-volume mask for signal IC,
rank-only harness path, fingerprint+breadth runner, and docs. Fingerprint
reproduced IC -0.045 / t -2.91 on prod.sqlite. No production gate/schedule changes.
2026-07-18 20:22:11 +02:00
dennisthiessen 5a61b164f6 docs: lock execution-recovery decisions and ops constraints
Record monotone fill-timing gradient, live [1.57,1.77] bracket, recover-flag
interpretation, gap-cap as third tail-trim, and pre-scheduler ops checklist.
2026-07-18 17:07:22 +02:00
dennisthiessen 3eb6192a1e feat: log Phase A decisions and add execution-recovery matrix
Document Phase A (max-hold/vol/corr closed; next-open as decision baseline).
Add stale_close and next_open gap-cap fill modes plus a small matrix to test
whether near-close scheduling recovers overnight momentum drift.
2026-07-18 16:27:10 +02:00
dennisthiessen cad4b49e7c fix: harden Structural S/R after OHLCV writes and surface cleanup failures
Deploy / lint (push) Successful in 8s
Deploy / test (push) Successful in 1m18s
Deploy / deploy (push) Successful in 40s
Honor custom S/R tolerance as a transient detect, refresh levels after OHLCV
mutations without failing committed price writes, report per-ticker S/R
rebuild failures from admin cleanup, and warn in the admin UI when refresh is partial.
2026-07-18 13:44:34 +02:00
dennisthiessen c9c6967c9c chore: consolidate post-stop research artifacts
Deploy / lint (push) Successful in 11s
Deploy / test (push) Successful in 1m18s
Deploy / deploy (push) Successful in 39s
2026-07-17 20:46:21 +02:00
dennisthiessen d858475ddb docs: document post-stop gate reset results 2026-07-17 19:58:40 +02:00
dennisthiessen dc1570877c Document Gate Target Ladder architecture 2026-07-13 11:47:23 +02:00
dennisthiessenandClaude Opus 4.8 ea11efe3d1 Sweep the R:R floor; fix a holdout metric artifact
Deploy / lint (push) Successful in 10s
Deploy / test (push) Successful in 1m9s
Deploy / deploy (push) Successful in 37s
min_rr = 2.0 was hand-set in Admin (2026-06-24) and never swept — the gate
ablation only tested the floor on-vs-off, never its level. It was the last
un-swept knob in the live gate.

Swept against portfolio Sharpe under the real exit, with a parity self-check
(reproduces_production_gate: the row at the live floor must rebuild production's
exact 1,089-setup qualified set — it does).

  min_rr   qualified   in-sample Sh/CAGR   OOS Sh/CAGR (entries >= 2024-07)
  0.0        6636      1.98 / 58.5%        2.02 / 66.2%
  1.2        3897      1.34 / 33.9%        1.12 / 28.8%
  1.5        3127      1.20 / 29.6%        1.12 / 28.8%
  1.75       1974      1.64 / 44.5%        1.15 / 27.4%
  2.0 (live) 1089      2.04 / 50.4%        2.78 / 73.3%
  2.25        577      1.64 / 31.8%        1.71 / 31.9%
  2.5         286      1.67 / 29.0%        0.68 /  8.7%

KEEP 2.0. It is the optimum in both windows, and a peak that reproduces in data
it was never fitted to is real evidence. But treat it as fragile: unlike the ATR
trail (a plateau), this is a spike with a trough beside it — +/-0.25 costs ~0.4
Sharpe in-sample and ~1.6 out-of-sample — and the curve is bimodal (floor-off is
good, 1.2-1.75 is bad, 2.0 is good). The hand-set value landed on the peak by
luck, not by tuning. Do not nudge it.

Worth knowing: turning the floor OFF entirely is the second-best row in both
windows, with substantially higher CAGR (58.5% / 66.2%) and more trades. If CAGR
ever outranks Sharpe here, "no R:R floor" is a live option — and it would sever
the gate's last dependency on the weak S/R detector.

Also fixes a metric artifact in the holdout harness. The train book's equity curve
ran to the end of the data while its entries stopped at the split, so it sat in
flat cash for two years and deflated its own CAGR/Sharpe (reported 0.95 / 14.6%;
actually 1.31 / 29.6%). _simulate_portfolio now truncates the calendar to
hold_days after the last entry when end_date is set — it only triggers on the
holdout train window, so no other number moves. The clear-air OOS verdict is
unaffected: it rests on the test row, whose entries and curve both start at the
split and were always clean. Both holdout reports regenerated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 16:45:59 +02:00
dennisthiessenandClaude Opus 4.8 906d1db7d1 Docs: state the actual strategy, add an end-to-end diagram, add a research log
The README opened with "find the path of least resistance, key S/R zones, and
asymmetric R:R setups" — a description of a strategy we do not run. What we run
is a long-only cross-sectional momentum book with a trailing exit. The S/R
engine, the composite score, sentiment and fundamentals are screening and
display; none has a measured edge.

- Rewrites the intro/philosophy around the real strategy, and says plainly what
  is NOT the edge.
- Adds a mermaid decision graph, universe -> qualified -> ranked -> opened ->
  closed, with the real exit distribution on the terminal nodes: initial stop 45%,
  trailing stop 31%, max hold 24%, S/R target 0%. Validated against the mermaid
  parser, not eyeballed.
- Documents that the R:R and touch-probability are GATE INPUTS, not forecasts of
  the trade — the single easiest way to misread this app.
- Adds win rate, best/worst R and the exit-reason split to the production
  baseline table.
- New docs/research/README.md: every strategy tested, the result, the decision,
  and why we stay with the current one. 12 rejected ideas (take-profit exits,
  clear-air gate relaxation, EV gate, regime overlay, inverse-vol sizing, shorts,
  standalone vol, FIP, ...), the confirmed tuning knobs, the open leads, and the
  method rules we learned the hard way (nested lookbacks are not out-of-sample; a
  rising win rate is a warning, not a win).
- Documents the research flags and the holdout harness, and warns that the
  portfolio_monitor lookbacks are nested windows, NOT a holdout.
- Notes the snapshot must copy paper_% settings or it silently diverges from prod.

All baseline numbers re-verified against reports/backtest-20260711-prod-baseline.json
(506 tickers, 1,089 qualified, CAGR 50.4%, +413.8% vs SPY +95.7%, DD -21.4%,
Sharpe 2.04, 320 trades, 15.3d avg hold, and all five promotion contenders). No
corrections were needed — the numbers were right, the framing was not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 15:40:34 +02:00