Status: Single forward-looking source of truth for strategy improvements as of Aug 21, 2026 (PKG-357 #366 DEPLOYED — $10k capital, S2c sizing, B-4 table, C-1 re-close, RES M1+M5, CLB-1, B-5 pilot; see the Aug-17–21 banner below). Baseline before that: Jul 5, 2026 (Finding #330 — RuleB FAILED-GAUNTLET reversal). Prior baseline: May 31, 2026 (Findings #314.c sizing-sweep [KEEP vs lowering; RAISING gauntlet-PASS at live 1.40 cap] + #314.d hybrid-gate KEEP $1k + #314.e 4 SKIP-rule candidates analysis-only + #315 exposure-cap re-validation [KEEP 1.40, #313 cap-raise inert]; Findings #311 + #312 + #313 SHIPPED — gate $1k + v2 #6 + PR 3.a priority/capital).
🛑 Jul 5, 2026 — Finding #330: RuleB (±90 min no-stop window) FAILED-GAUNTLET — Phase-2 active flip CANCELLED (simulator gap-fill bug; NO live trading change). The operator-directed Jul 5 strategy review found
simulate_window_onlyfilled window-blocked stops at the STOP PRICE even when the price was still through the stop at rearm — a fill the as-shipped #305 cancel-and-rearm mechanism cannot achieve (a re-placed STP-LMT triggers instantly and fills near market;simulate_finding_a_hardmodels exactly this asrearm_gap_open, the arm that retracted FA_hard in #228 at −$1,545/100). Gap-aware fix + prod re-run (n=129): RuleB headline −$209/100 (was +$224), ex-top-2 −$194/100 (was +$122), ex-repeat −$227/100 — FAIL on every §K check; optimism bias ≈ $535/129 trades. RuleG also flips negative (−$30/100 headline). Live corroboration: all four June in-window stops (LULU/ADBE/ACN/KR) were correct stops — RuleB-active would have worsened each (ACN −$26 actual vs ~−$134 held). NO stop-loss rule variant currently survives the gauntlet. Consequences: RuleB Action-Queue row → FAILED-GAUNTLET; v3 D + v3 E lose their RuleB dependency (re-evaluate as pure selection rules at trade #150+ / SHORT n≥30); #323.b's "0.92-0.99 conditional on RuleB active" lever is dead. Phase-1 dry-run code remained (logging-only; duplicate-log spam fixed — 8,026 lines → once per position) until Aug 21, 2026 (#380): the whole RuleB apparatus was REMOVED (operator A-12 option (b); the harness had been structurally blind since mid-June — its logs validated nothing). Seedocs/FINDINGS.md#330 + #380. Sections below written before Jul 5 that call RuleB "the only surviving stop-loss rule" are historical narrative.🔬 May 31, 2026 — Finding #319: PR 5 depth-gate v2 widened reconstruction — the "unreliable orderbook" skip is a roughly break-even low-information-signal filter → KEEP (offline-only; closes Finding #283; Phase 3 simulator PR 1-5 COMPLETE). Answers "has the depth/spread gate ever saved us from a bad trade?" at proper sample size. Depth-logging only began 2026-04-14 (~4 kills); widened by replaying the REAL
ConvictionCalculator.get_conviction_at_entry_timepoint-in-time over the full 915-market universe. NEWscripts/phase3_simulator/depth_gate_variants.py+replay_depth_gate_v2.py. 22 binding kills: 13 losers BLOCKED (−$142.56), 9 winners KILLED (+$165.09), net removal +$22.54 over ~7 months (≈ noise). So YES it has saved us — reversing the n=4 read (which showed 0 losers blocked = small-sample mirage). Kill cause 18/22snapshot_reliability(hollow 1¢/99¢ book → sparse/unstable price-snapshot conviction), 1 spread → a low-information-signal filter, not the pure spread gate #283 implied. remove_all +$22.54 / carveout_real_trade +$22.78 (≈ identical) → adds variance for ~$0 EV. Operator-confirmed KEEP; production gate UNCHANGED. 395 tests PASS. Seedocs/FINDINGS.md#319.🔬 May 31, 2026 — Finding #318: PR 4 regime classifier v2 sweep — faster detectors add no robust ROI → KEEP
compound_v1(offline-only; closes Finding #278). Tests whether a faster downtrend detector improves Rule #1 (Skip LONGs in downtrend, #304) vs the production compound rule (median 31-trading-day lag from SPY peak). NEWscripts/phase3_simulator/regime_classifiers.py(point-in-timeSpyDailyHistory+ 6 classifiers) +replay_regime_v2.py(re-classify point-in-time prior-close → re-apply Rule #1 → recompute P&L viarun_sizing_sweep/apply_sizing_gauntletvs compound_v1, on live-only primary + capacity-aware 1.40 cross-check). Prod (568 signals):below_ema20(fastest; skips ~40% of LONGs vs compound's 17%) gains +$70.31 PASS on live-only but −$17.02 FAIL-EX-TOP-2 on the capacity-aware universe — the live-only win is selection luck that doesn't generalize (same reversal as #315 "don't look in isolation").compound_or_dd5(#278 option B) +below_ma50inert;dd_3pct+compound_symmetricFAIL. The only durable effect is a better worst-week tail (5p −$98.60→−$57.08) at ~breakeven P&L (downside trade-off, not a money-maker). Methodology validated: PIT compound_v1 reproduces the live recorded regime 95.3%. Operator-confirmed KEEPcompound_v1(Rule #1 optimizes for ROI; faster detection adds no robust ROI). Closes #278; VIX deferred to Phase 4. 375 tests PASS. Seedocs/FINDINGS.md#318.🔬 May 31, 2026 — Finding #314.e: 4 deferred SKIP-rule candidates (PR 3.b.3) — ANALYSIS-ONLY, ship deferred to operator. Re-evaluated the 4 Finding #313 deferred SKIP cells REAL-SCALED (not hypothetical $10k-notional) + capacity-aware + 5-check gauntlet. Real-scaling corrected 2 cells: Large+SHORT+$2k-$5k is only n=3 (not 12 → can't gauntlet); Large+LONG[0.80,0.90)+$1k-$2k is net-POSITIVE on real data (+$0.93 avg; hyp said −$20 → skipping it HURTS, FAIL-EX-TOP-2). Gauntlet-PASS ship-eligible candidates: skip Large+LONG[0.80,0.90)+vol≥$10k (+$2.04/wk, PASS, improves maxDD); skip Mid+LONG[0.80,0.90)+$1k-$2k (+$1.12/wk, PASS); combined skip-all-4 (+$5.42/wk, PASS, best maxDD −$220, WR 39.1%). Per operator ship-bar (C) nothing shipped — per-candidate ship decision pending operator AskQuestion. See
docs/FINDINGS.md#314.e. (Partially advances thesizing-priority-v2deferred item — the per-direction/per-cell SKIP-rule arm.)🔬 May 31, 2026 — Finding #314.d: Hybrid seasonal gate variant (PR 3.b.5) — KEEP uniform $1k (NO production change). Operator idea: gate $2k in peak earnings-weeks / $1k off-peak (peak periods have plenty of $2k+ markets so $1k "just adds noise"). Verified the academic peak-week classifier tracks PM data first (peak windows = 57.7% of 977 markets / 60% of vol≥$1k). On the 568-signal simulator universe the hybrid removes 144 peak-week $1k-$2k signals → +$8.08/wk vs uniform $1k +$16.86/wk (Δ −$8.78/wk, FAIL-SPILLOVER), nearly reverting to uniform $2k (+$6.70/wk). Premise REFUTED — those peak-week $1k-$2k markets are net-positive (#314.b $1k-$2k bucket +$423), so removing them gives back most of Finding #311's lift; the capacity-reallocation hope doesn't materialize (cap-skips 58→5 but freed slots not refilled, maxDD worsens). Decision: KEEP uniform $1k (Finding #311 unchanged). See
docs/FINDINGS.md#314.d.🔬 May 31, 2026 — Finding #314.c: Sizing variants sweep (PR 3.b.4) — KEEP-30/22/15 (the then-live tiers, since superseded by flat-25 #314.f → S2c #366) holds only vs LOWERING; RAISING is gauntlet-PASS at the LIVE cap (NO production change). 🔁 CORRECTION (per Finding #315): the original run used
exposure_cap=2.0but the live cap isMAX_DAILY_EXPOSURE=1.40. Re-run at 1.40: lowering sizing still FAILS (all FAIL-SPILLOVER), but flat 25/25/25 (+$4.18/wk) and 35/25/18 (+$4.63/wk) now PASS the gauntlet — at the tighter real cap, concentrating capital into bigger positions wins. These are now ship-eligible candidates (operator decision; caveats: exceed the staleMAX_POSITION_SIZE_PCT=0.15+ small-cap 5% stop/squeeze risk). First sweep on the size-aware capital simulator (offline). Operator hypothesis: capacity binds at 99% (Finding #314.b) → lower sizing to fit more concurrent positions and lift P&L. REFUTED. On the 568-signal / 36-wk universe ($2.5k × 2.0 = $5k max gross), lowering sizing admits more positions but total P&L drops — 20/15/10 fits +28 more trades (437 vs 409) yet loses −$6.80/wk; all four lower-sizing variants (25/18/12, 20/15/10, 22/16/11, flat 18/18/18) FAIL-SPILLOVER (marginal capacity-freed trades are low-EV per #314.b, shrinking good positions costs more). Raise/flat variants give only tiny non-robust lift (flat 25/25/25 +$1.41/wk FAIL-EX-REPEAT-TICKERS; 35/25/18 +$0.75/wk WARN-OUTLIER-DOMINATED + worse maxDD/5p). All 8 sit on the Pareto frontier (lower sizing trades E[wk] for better DD/5p — so the bias gauntlet, not Pareto, is the decider; no variant has a gauntlet-PASS positive lift). Decision: KEEP Large 30% / Mid 22% / Small 15% (Finding #211 unchanged). Partially closes thesizing-priority-v2deferred item (sizing arm). Simulator gainedscale_pnl_with_size(design §12 PR3) +gauntlet.apply_sizing_gauntlet; 296/296 tests PASS. Seedocs/FINDINGS.md#314.c.🚀 May 30, 2026 LATE LATE evening — Finding #313 SHIPPED: PR 3.a — Volume-tier priority bump + capital cap raise + NYSE dead-code cleanup. THIRD real-money strategy ship of the day. Priority scale 0-6 → 0-8 (kept Mar 9 mcap × conviction ordering since live LONG WR Large 45.7% > Mid 34.3% still holds; ADDED volume bump since live LONG WR jumps 36% NULL → 64% $2-5k → 83% $5k+). MAX_TOTAL_EXPOSURE_PCT 1.40 → 2.00 (matches Reg T overnight ceiling, +43% capacity). NYSE/NASDAQ branching dropped (verified dead post Finding #185 Feb 15 unification). 617/618 tests PASS. Operator follow-up: re-validate $1k gate (#311) against new volume-tier data — $1k-$2k bucket has been the ONLY losing bucket historically. 4 SKIP rule candidates DEFERRED until simulator framework is ready.
🚀 May 30, 2026 LATE evening — Finding #312 SHIPPED: v2 #6 Daily 3-stop session breaker + DirectionPolicySpec doc-bug fix. Second real-money strategy ship of the day. Pure-decision module
src/earnings/session_stop_breaker.py+_count_todays_stops()helper + skip block insignal_generator._build_trading_signalafter Queue Rule #1 long_downtrend. DefaultsSESSION_STOP_BREAKER_ENABLED=True,SESSION_STOP_BREAKER_THRESHOLD=3. Historical evidence: 9 sessions in production with ≥3 stop-exits in a single ET-day (2026-02-03 through 2026-04-29). Estimated +$1/wk + ~-$50 Max DD improvement (heuristic). Plus DirectionPolicySpec correction:production_strategy_may30()factory now accurately models prod thresholds (0.70/0.30 with 0.90 over-confident skip + raw_prob conviction_fn) instead of the wrong Phase α defaults (0.55/0.45/abs_distance_x2). 79 tests PASS local (38 phase3_simulator + 22 session_stop_breaker pure + 8 integration + 11 regression). NO integrity-monitor rule count change.🚀 May 30, 2026 evening — Finding #311 SHIPPED: gate_uniform_$1000 first real-money strategy ship since Mar 9, 2026.
SIGNAL_MIN_VOLUME_TOTALdefault lowered $2,000 → $1,000 insrc/earnings/config.py. After full operator-driven correctness audit (6 errors found, all fixed) + Phase ε/α/β/γ/δ/ζ unified strategy framework completion. Per-tier empirical scaling (Large $537 / Mid $339 / Small $205) replaced wrong hardcoded $245. Phase γ+δ replay shows: Δ E[wk P&L] +$21/wk (~+$1,092/yr at $2,450 capital), Δ max DD -$46 (within -$735 = 30% capital target), outlier alarm fixed (production ex-top-5 -$152 → +$582 post-admit), Pareto-optimal among 12 candidates. Other 2 ship-eligible variants RETRACTED-IN-FAVOR-OF gate_uniform_$1000 (operator picked simplest single-axis change). 38/38 phase3_simulator tests PASS. Production strategy now lives inproduction_strategy_may30()factory;production_strategy_may29()is backward-compat alias.Verified still current as of May 30, 2026 — Phase 3 simulator PR 2 COMPLETE (Finding #310.c). PR 1 (foundation + cross-check + gauntlet) shipped May 28; PR 2 (volume-gate retune sweep) shipped May 29 across 3 sub-commits (PR 2.a gate_variants + PR 2.b counterfactual_admission + PR 2.c sweep + dashboard). The seasonality preflight that gated PR 2 (operator-requested INFERENCE DISCIPLINE check) REFUTED the pure-seasonality hypothesis — Dec 2025 off-season was healthy at 98.1% gate-pass + $14,522 median volume, while Mar+2026 off-season collapsed to 27.8% + $0 median. This is a REAL STRUCTURAL collapse starting March 2026, NOT seasonality. The PR 2 sweep (262 usable counterfactual markets, all in collapse period; pre-coding aggregate +$3,180 P&L if all admitted) produces ship-recommendation candidates per the 3-condition conservative-ship policy (Q3 (C): full-pop gauntlet PASS + ≥20 admitted in collapse + ex-top-2 stays positive) — operator AskQuestion required per qualifying variant before any production gate change. Dashboard 🧪 Phase 3 — Gate Retune Sweep section is live. PR 3-5 now COMPLETE (#306-#319) + Phase 4 dashboard consolidation COMPLETE (#306-#322) — PR 3.a priority/capital (#313), sizing/exposure-cap evaluation (#314.c/#315/#317), PR 4 regime KEEP
compound_v1(#318), PR 5 depth-gate KEEP (#319). See §1 banner above +docs/PHASE_3_SIMULATOR_DESIGN.md§12.Earlier — May 28, 2026 LATE evening — Phase 3 simulator PR 1 COMPLETE. No strategy rule added or retracted between Apr 25 and May 28; two queue rules SHIPPED today (Rule #1 + RuleB Phase 1 DRY-RUN) and the Phase 3 unified simulator PR 1 foundation landed across 5 commits (#306.a foundation skeleton + #306.b cost-model + replay + reference_adapter + cross-check script + #306.c gauntlet + H-rule self-validation + reproducibility + JSON output + #307 #273 conditional-label fix + #308 Bug #6 hyp_pnl re-run + structural-ceiling discovery). All 4 PR 1 acceptance gates PASS: §10.1 cross-check vs
analyze_finding_a_full.py(100% match within $1 on all 7 rules / max drift $0.00 across 121 trades on prod May 28 LATE evening); §10.2 reproducibility (2 runs = 0-byte diff after masking generated_at — verified on real prod data + unit-test); §10.3 H-rule self-validation (FAIL-EX-TOP-2 pertest_h_rule_synthetic_returns_fail_ex_top_2); Phase 0 §0.6 Gate 1/4 corrected per #308 structural ceiling. Live baseline gauntlet on prod: RuleB verdict PASS, per-100 $+90.74 headline, $+39.93 ex-top-2 vs A_base baseline — ship recommendation SHIP. (The reference simulator's narrative numbers were variant-vs-LIVE: +$236/100 / +$127/100 ex-top-2; the gap is the intentional difference between replay-vs-baseline and replay-vs-recorded semantics — both are correct; replay-vs-baseline is the right default for PR 2's gate-variant comparisons.) PR 2 (volume-gate retune sweep — highest-leverage per May-28 PM volume-collapse evidence) begins next session perdocs/PHASE_3_SIMULATOR_DESIGN.md§12.Apr 26 → May 28 intervening work, none of which was a strategy rule change until the May-28 Phase 3 sprint: - Strategy Analysis Revamp Phase 1/2/2.x — Findings #234-#247 - Database Integrity Audit Phases 0-6 — Findings #250-#261 - Dashboard 500 incident chain #262 - Rigorous §B re-audit + ancillary fixes — Findings #263-#274 - Apr 28 deferral parking — Findings #278 (regime detection v2) + #279 (sizing & priority v2) - Apr 29 dashboard UX — Findings #280 (outcome badges) + #281 + .v2 + .v3 (trade-chart modal) - Apr 30 volume policy fix — Findings #282 + .v2 (max(DB, Gamma) + shared single-shot fetcher) + UX rename #283 ("LOW OB" → "WIDE SPREAD") - May 6 P&L Summary enrichment — Finding #284 (tooltips + Trading Capital ROI panel) - May 9 exposure-cap correctness — Finding #285 Phase A (greedy-fill in BMO + AMC loops + opportunity_log emission) - May 9-10 — Pre-Phase-3 housekeeping batch + Dome→Polymarket migration + plan-(C) follow-ups + new follow-ups all shipped (Findings #269 / #270 / #273 / #274 / #286 / #287 / #288 / #288.v2 / #288.v3 / #289 / #289.v2 / #289.a / #289.b / #290 / #291 / #291.v2 / #292 / #293 / #294 / #295). NONE of these are strategy rule changes — all infrastructure / data-quality / cleanup / observability. - May 11-28 — Operational hygiene + observability close-outs (5 findings + 1 doc-only rule codification + 2 factual corrections): #296 (May 11 —
_check_systemd_unit_last_resultbranch reorder); #297 (May 17 —api_health_checkerWARN-but-exit-0 cry-wolf fix); May 27 factual correction commitd3e3e9c(Sunday 2FA reconnects DO require operator push approval — corrected the May-17 / May-24 entries); May 28 codification of the🚨 INFERENCE DISCIPLINErule in.cursor/memory.md(commit875f6e3, companion to NO SHORTCUTS, triggered by an agent false-alarm on AMC scheduling that should have been a 60-second model-vs-code verification); #302 (May 28 —polymarket-backup.timercollision with apt-daily-upgrade.timer, moved to 05:00 UTC); #303 (May 28 —deploy_from_github.shpre-pull hygiene for recurring working-tree drift). Plus 2 IBKR Sunday 2FA reconnects (May 17, May 24) and 1 mid-week auto-recovery (May 28 04:12 UTC, 6m 17s downtime, no operator action). NONE are strategy rule changes. - May 28 — Phase 3 sprint (5 PR-1 commits + Phase 3 unified simulator PR 1 COMPLETE): Finding #279 Phase B amendment (PM earnings-market volume collapse evidence folded in); Finding #304 Rule #1 Skip-LONGs-in-downtrend SHIPPED active (first Phase-3 strategy rule); Finding #305 RuleB ±90min no-stop window Phase 1 DRY-RUN SHIPPED (second Phase-3 strategy rule; hardware cancel-and-rearm pattern; RULEB_ENABLED=false in prod by default); Finding #306.a Phase 3 simulator foundation skeleton (scripts/phase3_simulator/package + RuleSet dataclasses + CLI stub); Finding #306.b cost_model + replay + reference_adapter + cross_check_baseline script (§10.1 acceptance gate satisfied: 100% match within $1 on all 7 rules vsanalyze_finding_a_full.pyacross 121 trades on prod); Finding #306.c gauntlet.py (5 checks per memory §K) + output.py (deterministic JSON schema) + runner.py--run-gauntlet(§10.2 reproducibility 0-byte diff + §10.3 H-rule FAIL-EX-TOP-2 acceptance gates satisfied; live RuleB verdict PASS on prod); Finding #307 snapshot_schema conditional-label fix atsignal_generator.py:1041(closes original Finding #273 Phase 1); Finding #308 Bug #6 hyp_pnl re-run + structural-ceiling discovery (~69% generate_signal / ~28% depth are deadband-conviction ceiling, not gaps). All 4 PR-1 acceptance gates PASS; PR 2 (volume-gate retune sweep) begins next session.The Action Queue in §2 has 2 rules moved from IN-QUEUE → IMPLEMENTED today (Rule #1 + RuleB Phase 1 DRY-RUN). May 28 regen of
scripts/strategy_performance_analysis.py+scripts/analyze_finding_a_full.pyalready done — fresh numbers in the §1 verdict-banner above; RuleB ex-top-2 strengthened to +$127/100 (gauntlet PASS); ~117 closed trades / +$212 net / ~37 % WR / 51.7 % stop rate / pre-trade-#150.✅ UPDATE (May 31, 2026) — this deferred bundle is now CLOSED: $2k volume-gate retune SHIPPED $1k (#311); 0-6 tiers re-validated + extended to 0-8 (#313); rare/normal/busy exposure cap collapsed to uniform 140% (#317, after #316 showed the rare discount near-inert); regime detection v2 → KEEP
compound_v1(#318); depth-quality gate v2 → KEEP (#319). The historical parking narrative below is preserved verbatim.Apr 28 → May 28, 2026 — four larger items parked for post-Phase-3 review (§7 "DEFERRED-POST-PHASE-3"): regime detection v2 (current classifier lags SPY peaks by median 31 trading days; Finding #278), sizing + priority tier system + exposure-cap re-evaluation v2 + $2k volume-gate retune (Mar 9 percentages + 0-6 tiers not re-validated, AND rare-day exposure cap fires on majority of trading days per Finding #285 Phase B, AND PM earnings-market volume collapsed ~109× Jan→May with $2k-gate pass rate now 1.9 % — May 28 evidence folded into Phase B; bundled together since they all gate which valid-signal trades actually enter; Findings #279 + #285 Phase B + PM-volume- collapse amendment), Polymarket depth-quality gate v2 (37/38 historical kills were spread-dominated; gate decomposition + threshold re-tuning needed; Finding #283), and pm_v2 schema NULL bid/spread on
signal_emittedrows fix in lockstep with the simulator ship (Finding #273). All four surface on the dashboard 🎯 Action Queue under theDEFERRED-POST-PHASE-3status filter.Combines: v3 audit (
docs/STRATEGY_AUDIT_v3.md, Apr 22) + Apr 25 Finding-A retraction simulator (docs/FINDINGS.mdFinding #228) + Apr 25 evening queue re-validation (Finding #232) + corrected stop-loss classification (Finding #233) + the dashboard Strategy Analysis tab. The dashboard tab is the operational view of this same data; this file is the narrative + decision rationale.Audience: - The next agent / human picking up the project. - The operator deciding what to ship next.
Read order: 1. §1 current verdict 2. §2 ranked action queue (= what to ship next) 3. §3 verified findings — mechanism + evidence + bias check 4. §4 retracted / failed findings — so they don't get re-suggested 5. §5 mandatory bias gauntlet 6. §6 implementation notes per rule (file + LOC + acceptance test) 7. §7 deferred questions / data gaps 8. §8 cross-references (scripts, docs, dashboard)
Before any strategy edit on this doc or any rule change in build_action_queue():
no shortcuts, ever. If the operator says "verify all 4 bias-gauntlet checks,"
verify all 4 — not "the top 2 are clearly fine." If they say "re-run the
simulator on every variant," re-run every variant — not "the headline ones."
If they say "ex-top-2 numbers alongside headline," include both — not "I'll
add ex-top-2 in a follow-up." Strategy work has the highest capital risk on
this project; shortcut discipline matters MOST here.
Anchoring example + full rule: see .cursor/memory.md "🚨🚨🚨 NO SHORTCUTS — EVER 🚨🚨🚨"
section (codified May 10, 2026 from a doc-cleanup shortcut incident — the
operator's framing was "if there is one thing that you must always know about
this project is this: no shortcuts! ever!").
May 28, 2026 refresh (live regen of
scripts/strategy_analysis_report.jsonandscripts/finding_a_full.csv): Strategy population on the sametrade_audit_log-with-reconciliation-filter is now 116 clean closed trades (43 W / 73 L) at WR 37.07 %, net +$212.21, avg +$1.83/trade, with the all-trades (incl. 3 bug-affected) population at 119 / +$207.72 / WR 36.97 %. Stop rate 51.72 % (was 49 % Apr-25 baseline — slightly worse). The strategy has accumulated 0 new clean trades in the 33 days Apr-25 → May-28: last clean closure was 2026-05-07 (id=162 MCD), next entry was 2026-05-27 (id=163 HPQ, still open as of May-28 12:30 UTC). The 21-day entry drought is consequential, not idle — see the PM earnings-market volume-collapse evidence indocs/FINDINGS.mdFinding #279 "Phase B framing premise" subsection (Jan→May avg cumulative volume dropped ~109×; May $2k-gate pass rate 1.9 % = 3/154 markets). RuleB simulator re-run on fresh data is now n=121 / per-100=+$236 headline / per-100=+$127 ex-top-2 (was n=51 / +$123/100 on Apr-25 baseline — RuleB has STRENGTHENED on robustness). RuleG headline +$242 ex-top-2 +$105 — higher headline than RuleB but less robust; RuleB was the recommended next stop-loss ship and has since SHIPPED as Phase-1 DRY-RUN (#305, May 28). FA_hard retraction reasoning still holds:rearm_gap_openarm n=24 at −$1,545/100. (May 31 update: live population is now ~117 closed trades — see live dashboard — and all 4 deferred-bundle items are now CLOSED, not DEFERRED: #311 gate $1k / #313 priority 0-8 / #317 uniform 140% / #318 regime KEEP / #319 depth KEEP.) The Apr-25 narrative below is preserved verbatim because the underlying conclusions (5-outlier curse, stops-eat-winners, selection-rules-first) are unchanged.
Strategy state on ~117 closed trades (May-28 refresh): net P&L +$212 at a ~37 % win rate (Apr-25 figure was +$167 / 33.6 %; morning handoff was +$61 / 109). The strategy picks direction correctly 83 % of the time — the leak is in conversion to P&L on the stop-loss leg.
Stops are the single biggest leak: across ~117 closed trades stops are
the dominant P&L drag (current stop rate per the live dashboard / FINDINGS;
corrected via exit_reason ILIKE '%stop%' — the stop_triggered
boolean undercounted at 1.7 % and is broken; see Finding #233). Stops have
cost the strategy −$676 in aggregate (avg −$11.86 per stopped trade).
Non-stops have contributed +$843, so stops are erasing ~80 % of the gross
alpha. Mar 9 #202 wider stops dropped frequency from 50 % → 45.5 % but
raised average loss per stop from −$9.66 → −$22.23.
5-outlier curse (renamed Apr 25 from 3-outlier — Finding #232): GPRO + DELL + SWBI + TXN (NEW Apr 22, +$92, LONG large) + STUB (NEW Mar 4, +$58, SHORT mid downtrend) together carry ~$430 of the ~+$212 net. Ex-them the strategy is −$263 across 111 trades. Any analysis that includes them looks great; any analysis that excludes them is structurally negative. Always report ex-top-2 alongside the headline; for any slice containing 2+ of the named 5 outliers, also report ex-them.
After Findings #229 (volume backfill, +319 markets) and #230 (conviction backfill, +384 markets) and a few hours of organic resolution, the Universe View now covers 604 of 900 earnings markets (67 %, up from 31 % this morning). In-band markets pass the bot's $1k volume gate (#311; gate lowered from $2k → $1k May 30) — see the live Universe View for the current pass % (the Apr-25 snapshot was 90.4 %, 546 of 604, measured at the then-$2k gate), up from 35 % positive-volume coverage that morning. This is the operational signal-quality denominator for every "is the bot's signal worth pursuing?" question. Detailed breakdowns + live numbers refresh every report run on the dashboard 🌐 Universe View section.
scripts/analyze_finding_a_full.py) showed v3 Finding A
is either inert (rule as written) or net-negative (only effective form:
−$418/100), and Findings D / G fail the 4-check bias gauntlet.RULEB_ENABLED=false in prod until operator flips active.)The (formerly) IN-QUEUE rules (B + RuleB + 3-stop breaker) are now all IMPLEMENTED — Rule #1 skip-LONG-downtrend (#304), RuleB ±90min dry-run (#305), daily 3-stop session breaker (#312); F dropped — plus indirect RESOLVED-BY-OTHER-RULE potential on D + E if RuleB closes their stop bleed: estimated +$190 to +$310 / 100 trades realistic combined lift. Flips the current run rate of +$1.44/trade to +$3.30 to +$4.50 per trade average. The only meta item still open is the trade-#150+ full re-audit.
Frozen snapshot. SSOT is
scripts/phase1_pnl_record.json(prodtrade_audit_logread-only SELECT 2026-09-26; filter =TRADE_METRICS_FILTER_SQL; net =PNL_EFFECTIVE_SQL; boundary =Config.PHASE1_START_ET/ #367). Do not invent net-liq. Do not hand-edit the generated block.
SSOT: frozen
scripts/phase1_pnl_record.json(prod read-only 2026-09-26). Net of commissions viaPNL_EFFECTIVE_SQL(#331) except BBW id 274 (brokerrealized_pnl− recorded commission; storednet_pnl_after_financingis a stale $37.25 stop stamp). BoundaryConfig.PHASE1_START_ET(#367). Do not invent net-liq. Do not invent BBW's missing exit commission.
2026-09-26T15:59:19.928748+00:00realized_pnl sum): $-912.23< Aug 21 ET): n=193 net +$194.16 (#367 post-deploy 193 closed; this snapshot n=193 net +$194.16)trading_errors ledger: n=6 sum $-248.79 (no rows after Jul 31; #353)| # | id | symbol | dir | shares | entry (UTC) | exit (UTC) | reason | net | running |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 267 | BOX | LONG | 75 | 2026-08-25T14:34:06 | 2026-08-25T20:05:11 | stop_loss:hardware | $-148.77 | $-148.77 |
| 2 | 268 | BBWI | LONG | 142 | 2026-08-25T19:58:05 | 2026-08-26T11:28:27 | stop_loss:hardware | $-142.91 | $-291.68 |
| 3 | 271 | HPQ | LONG | 82 | 2026-08-26T14:34:06 | 2026-08-26T20:17:21 | instant_exit:stop_timeout_escalation | $-101.51 | $-393.19 |
| 4 | 273 | DG | LONG | 20 | 2026-08-26T19:58:08 | 2026-08-27T14:31:56 | scheduled_exit | +$127.63 | $-265.55 |
| 5 | 274 | BBW | LONG | 62 | 2026-08-26T19:58:11 | 2026-08-27T10:52:10 | stop_loss:hardware | $-282.46 † | $-548.02 |
| 6 | 276 | MRVL | LONG | 9 | 2026-08-27T14:34:06 | 2026-08-27T20:05:08 | stop_loss:hardware | $-90.51 | $-638.52 |
| 7 | 285 | CPB | LONG | 99 | 2026-09-02T19:58:09 | 2026-09-03T11:20:03 | stop_loss:hardware | $-108.67 | $-747.19 |
| 8 | 290 | KFY | LONG | 28 | 2026-09-08T19:58:06 | 2026-09-09T13:50:17 | stop_loss:hardware | $-126.85 | $-874.04 |
| 9 | 291 | ORCL | LONG | 14 | 2026-09-10T14:34:06 | 2026-09-10T19:51:41 | stop_loss:hardware | $-67.20 | $-941.24 |
| 10 | 292 | KR | LONG | 40 | 2026-09-10T19:58:05 | 2026-09-11T11:13:27 | stop_loss:hardware | $-94.77 | $-1,036.00 |
| 11 | 293 | CBRL | LONG | 22 | 2026-09-11T19:58:06 | 2026-09-14T14:31:58 | scheduled_exit | +$24.01 | $-1,011.99 |
| 12 | 294 | LEN | SHORT | 28 | 2026-09-16T14:34:06 | 2026-09-17T19:56:55 | scheduled_exit | +$36.57 | $-975.43 |
| 13 | 295 | CBRL | LONG | 49 | 2026-09-22T19:58:06 | 2026-09-23T14:31:54 | scheduled_exit | +$53.14 | $-922.28 |
| As of | Net liq | PDT reserve | Trading capital | Source |
|---|---|---|---|---|
| Aug 21 2026 04:34 UTC (#366 deploy) | +$27,504.38 | $17,450 | +$10,054.38 | FINDINGS #366 post-deploy §G probe (Aug 21, 2026 04:34 UTC): trading capital $10,054.38 = NetLiq $27,504.38 − PDT_RESERVE_CAPITAL 17,450. Changelog monitor for #366. Do not invent net-liq. |
| Sep 26 2026 IBKR snapshot | +$26,585.44 | $17,450 | +$9,135.44 | prod ibkr_account_snapshot read-only 2026-09-26T16:11:47.867459+00:00 (fetched_at); trading_capital = net_liquidation − Config.PDT_RESERVE_CAPITAL 17450 (#366/#405). Do not invent net-liq. |
† BBW id 274 canonical net uses broker realized_pnl − recorded entry commission; stored net_pnl_after_financing remains −$121.52.
Playbook §2 current queue and the dashboard 🎯 Action Queue are both produced by
scripts/strategy_performance_analysis.py:build_action_queue()(memory.md §K/N). Edit that function, never a surface. The generated block is markedBEGIN GENERATED: action_queue. Live evidence numbers in the dashboard are recomputed on every report run from the same DB the trader uses.
The trade-#150+ audit trigger FIRED and was executed as Finding #357 (n=183;
docs/STRATEGY_REVALIDATION_2026_08.md, re-issued as Parts I–IV). The operator then decided (Part I — Finding #360, Aug 16) and APPROVED the three open Part II decisions on Aug 17 (Finding #361) — every #357-program decision is now made. The authoritative current queue is the dashboard Action Queue + the357 section's ordered action plan; summary:
- DECIDED Aug 16 — IMPLEMENTED Aug 20 (#366), DEPLOYED Aug 21, 2026 (rank-1 package
package-10k-s2c-b4-357; SoT: FINDINGS #366): C-Q1 trading capital → $10,000 under the HARD PDT constraint (account equity ≥$25k at ALL times; reserve ≈$17,450 NOT withdrawn; no day-trade counting exists in code) + S2c sizing (enter everything / equal split / shrink-to-fit / ≤25% per position) + the B-4 3-tier priority table (rank 3 = LONG 70–75 any mcap · 2 = LONG 80–85 large/mid · 1 = rest · 0 = skip; all volume bumps + the mcap spine removed — F-001/F-002 refuted). The package's decision set is COMPLETE (C-1 + RES approved Aug 17 — #361); ships as ONE reviewed package on the operator's EXPLICIT go; prerequisite fix A-7; arms the K-S2C/K-B4/K-RES/M-C1 (+K-B5) re-check contracts (all alert-only — self-alerting since #389/#392, the operator decides every outcome). Changelog entries at SHIP time (#338 convention).- Implemented + DEPLOYED (Aug 16, 2026 20:22 UTC): #358 (PM print-density collector fixes = A-8)
359 (B-3 stale-signal guard; closed A-4) + #360 (this reconciliation) — single
deploy_from_github.shrun atefebe45; reaper closed 1,288 stale rows on first run.- APPROVED Aug 17, 2026 (#361) — IMPLEMENTED Aug 20 (#366), DEPLOYED Aug 21, 2026: C-1 re-close of the 0.90–0.95 LONG band (recommendation CLOSE accepted; §14 settled the contest; M-C1 shadow monitor ARMED) · RES the M1+M5 reservation mechanism (observed-set + rank-3 AMC carve-out, multi-day component dropped; K-RES ARMED) · B-5 small-cap LONG 0.80–0.95 pre-registered pilot (K-B5 ARMED, §12.5 revert terms unchanged — alert-only since the #392 amendment, Aug 21: the operator decides the revert). All three are live in production.
- Still OPEN (strategic, time-gated — not part of the package): C-Q3 (Oct capacity). C-Q2 DECIDED Sep 26, 2026 — keep (#478; next at the count trigger).
- Queue effects below: the "Re-validate full audit at trade #150+" row is DONE (#357); §7's VIX true-sim ask is DISCHARGED (D-2 deep dive — no rule ships; shadow monitor instead); the #314.e SKIP candidates are RETIRED (superseded by B-4); v3 D is folded into B-4; v3 E re-keys to the D-5 SHORT re-test (≥40 CF cases) / B-008 (≥20). All 17 armed monitors/triggers/contracts (16 from #360/#361 + D-9 #363; SoT:
build_revalidation_357()['monitors']) live in ONE table:STRATEGY_REVALIDATION_2026_08.md§II.7 (KILL, D-1…D-9, M-C1, M-VOL, K-S2C, K-B4, K-B5, K-RES, G-RS), rendered on the dashboard.
SSOT:
scripts/strategy_performance_analysis.py:build_action_queue(). Do not hand-edit this block. History tables below stay as dated narrative.
Generated from 50 Action Queue rows.
| id | title | date | sources |
|---|---|---|---|
gate-2k-reprice-357 |
Re-test trigger (#357): $1k→$2k volume-gate raise — re-price at n≈240 canonical trades with the freed-slot REFILL RATE as the explicit ship criterion | — | Finding #357 W1 (A-001 WEAKENED: post-Jul $1k–2k real fills −$7.04/trade, n=11, ex-top-2 robust); Finding #357 W6 §3 (full-window $2k gauntlet FAIL; freed slots refill only 18%); docs/STRATEGY_REVALIDATION_2026_08.md §5 Class D-1 |
| id | title | date | sources |
|---|---|---|---|
T2.11 |
ON-HOLD: ssl.CERT_NONE on the DigitalOcean DB connect | — | code-audit reconciliation 2026-08 T2.11; docs/CODE_AUDIT_RECONCILIATION_2026_08.md |
T2.13 |
ON-HOLD: detector maps — TTL on read, no global prune; _pending_content_claims not cleared on remove | — | code-audit reconciliation 2026-08 T2.13; docs/CODE_AUDIT_RECONCILIATION_2026_08.md |
T2.15 |
ON-HOLD: TIER 2 hygiene bundle — test gaps, naive datetime.now(), stale comments, bare except | — | code-audit reconciliation 2026-08 T2.15; docs/CODE_AUDIT_RECONCILIATION_2026_08.md |
T2.2 |
ON-HOLD: IH-SNIPER tree — 26k+ lines in polymarket_sniper/ + 11k in resolution_sniper.py + dead systemd units | — | code-audit reconciliation 2026-08 T2.2; docs/CODE_AUDIT_RECONCILIATION_2026_08.md |
T2.6 |
ON-HOLD: EventBus disk sink with zero subscribe() in src/ | — | code-audit reconciliation 2026-08 T2.6; docs/CODE_AUDIT_RECONCILIATION_2026_08.md |
T2.8 |
ON-HOLD: dashboard twins — conviction/depth helper, hypertable COUNT(*) on the hot path, TRADE? label | — | code-audit reconciliation 2026-08 T2.8; docs/CODE_AUDIT_RECONCILIATION_2026_08.md |
v3 D |
Skip Mid-cap LONGs at conviction ≥ 80 % | — | v3 audit Apr 22 §3 Finding D; Apr 25 universe view (mcap split); Apr 25 evening operator decision |
v3 E |
Skip SHORTs in non-downtrend regimes | — | v3 audit Apr 22 §3 Finding E; Apr 25 evening operator decision — n too small + KEEP set GPRO+STUB-dominated; Apr 25 evening re-validation (Finding #232) — sideways SHORT 83% stop rate confirmed |
| id | title | date | sources |
|---|---|---|---|
package-10k-s2c-b4-357 |
IMPLEMENTED Aug 20, 2026 (#366) — DEPLOYED Aug 21, 2026 04:34 UTC (overnight market-safe window): the $10k package — C-Q1 capital → $10,000 (HARD PDT constraint: account equity ≥$25k at all times; reserve ≈$17,450 NOT withdrawn; manual prod .env line at deploy) + S2c sizing (enter everything / equal split / shrink-to-fit / ≤25% per position; $9k activation gate) + B-4 3-tier priority table (rank 3 = LONG 70–75 any mcap; 2 = LONG 80–85 large/mid; 1 = rest; 0 = skip) + C-1 re-close at 0.90 + RES M1+M5 + WAVE-RT + CLB-1/A-6 + B-5 pilot (own commit) + M-VOL — the full ONE-PACKAGE manifest confirmed Aug 19, 2026 (#364), shipped on PKG-GO Aug 20 | 2026-08-20 | docs/STRATEGY_REVALIDATION_2026_08.md Part I (C-Q1, S2c, B-4 decision records); Part IV §8 (sizing deep dive — S2c full-gauntlet PASS at $10k), §9 (priority-table deep dive — $0 P&L under S2c, ordering/safety infrastructure), §14 (the $10k head-to-head synthesis) |
class-a-fixes-357 |
Class A data/code fixes (#357): COMPLETE — all 14 shipped. A-14 SHIPPED Aug 21 2026 (#384 silent coverage bugs: closed-market conviction fallback fixed via closed=true retry + channel-window leaks stamped timing_channel_leak at ERROR + 2 HIGH coverage integrity rules; DEPLOYED Aug 21 15:17 UTC, trader restart; explicit detector AMENDED #414 already-admitted); A-13 SHIPPED Aug 21 2026 (#381 counterfactual window-truncation fixed: pricing library refuses unsettled/uncovered windows, cron + resolver never persist refusals, cf_window_truncation integrity rule armed, ~1,100-row backlog re-queued; deployed live, no trader restart); A-1 SHIPPED Aug 21 2026 (#382 resolution-as-truth implemented per approved #372 + §F backfill landed; detector basis guard DEPLOYED Aug 21 15:17 UTC, trader restart); A-12 SHIPPED Aug 21 2026 (#380 RuleB apparatus removed entirely per operator option (b) + the 2.3GB trader-log contradiction resolved: BOTH prior claims were half-right about different files; logrotate now covers [hidden]/logs + journald bounded 2G/14d; code deletion DEPLOYED Aug 21 15:17 UTC, trader restart); A-9 SHIPPED Aug 21 2026 (#379 PRNewswire corroboration-only + BusinessWire poller removed; DEPLOYED Aug 21 15:17 UTC, trader restart); A-5 SHIPPED Aug 21 2026 (#378 admitted-stage rows restored; DEPLOYED Aug 21 15:17 UTC, trader restart); A-3 SHIPPED Aug 21 2026 (#375 volume-integrity 5-part bundle); A-11 CLOSED Aug 21 2026 (#374 doc-drift framework + hygiene bundle); A-2 SHIPPED Aug 21 2026 (#371 resolver-lockout fix); A-7 SHIPPED Aug 20 2026 (#366, own commit, S2c prerequisite cleared); A-4 done via #359, A-8 done via #358, A-6 + A-10 done inside the #366 package | Aug 21, 2026 (final item A-14) | docs/STRATEGY_REVALIDATION_2026_08.md Part II §II.6 (Class A table, incl. A-13/A-14 added by §11) |
PR 2 Refinement Plan |
PR 2 multi-phase re-validation: backfill 580 historical markets + quarterly classifier + cross-season sweep [PR 2.d.1 + 2.d.2 + 2.d.3 + 2.e + 2.f COMPLETE] | May 29, 2026 | Operator review May 29, 2026 (UTC+4 morning): 3 structural flaws in PR 2.c sweep flagged; External validation: FINRA / Investopedia / Wall Street Horizon / SEC filing data / ScienceDirect 247K-firm study all converge on quarterly-cycle earnings model (peak weeks 4/17/30/43 of year); Backfill feasibility check (May 29 prod): 842 markets reconstructable from trades table + earnings_markets outcomes + Polygon bars |
Apr 21–22 — Learning loop (Finding #227) |
Outcome resolver + counterfactual + regime/VIX capture (data infrastructure) | Apr 22, 2026 | Finding #227 (Apr 21-22, 2026) |
Apr — Volume gate $2K (Findings #222–#226) |
Effective cumulative volume gate (max(DB, Gamma) — Apr 30 fix Finding #282; previously 'DB else Gamma'). Originally $2K (Apr 16); SUPERSEDED → $1K uniform by Finding #311 (May 30) | Apr 16, 2026 | Findings #222 / #223 / #224 / #225 / #226 (Apr 2026); Finding #311 ($2K→$1K, May 30, 2026) |
Audit re-validation |
Re-validate full audit at trade #150+ via the gauntlet — DONE Aug 16, 2026: executed as Finding #357 (the full strategy re-validation at n=183) | Aug 16, 2026 | memory.md §K; docs/STRATEGY_REVALIDATION_2026_08.md (Finding #357, 9 workstreams + 8 deep dives, re-issued Parts I–IV) |
Feb — BMO 10:32 AM exit (extended hold) |
BMO exit moved from 09:32 → 10:32 AM ET | Feb 5, 2026 | Strategy timing analysis Feb 2026 |
Feb — STOP-LIMIT all exchanges (Finding #179) |
All stop-loss orders use STOP-LIMIT with 2 % buffer | Feb 10, 2026 | Finding #179 (Feb 10, 2026) |
Mar 31 — MCAP DB enrichment (Finding #219) |
earnings_markets.market_cap_category populated DB-first | Mar 31, 2026 | Finding #219 (Mar 31, 2026) |
Mar 9 — Skip 90%+ LONG conviction |
Skip over-confident LONGs — cap RELAXED ≥0.90 → ≥0.95 on Jul 11, 2026 (Finding #333; the ≥0.95 skip remains) | Mar 9, 2026 (cap 0.90); relaxed to 0.95 Jul 11, 2026 | v2 audit Finding #5; live data Mar 2026; Jul 10-11, 2026 gap-aware replay + operator relax decision (Finding #333) |
Mar 9 — Wider stop sizes (3/4/5 %) |
Stop distances widened to Large 3 % / Mid 4 % / Small 5 % | Mar 9, 2026 | v2 audit + What-If wider-stop scenarios |
PR 2 — gate_uniform_$1000 |
Lower SIGNAL_MIN_VOLUME_TOTAL gate from $2,000 → $1,000 uniform [SHIPPED May 30, 2026 — Finding #311] | May 30, 2026 | docs/FINDINGS.md Finding #310.c (PR 2.c sweep, May 29, 2026); scripts/phase3_simulator_gate_retune_sweep.json |
breaker-retire-363 |
IMPLEMENTED Aug 20, 2026 (PKG-357 #366) — DEPLOYED Aug 21, 2026 — CLB-1 — the consecutive-loss circuit breaker (3/5/7 losses → 4h/24h/manual) is RETIRED in code, counter DELETED (N17 option b); the daily-loss breaker at 5% of capital is the sole loss brake — restart-proof (A-6 derive-from-DB), DB-anchored day P&L, true-ET-open resume; sizing re-keyed to day-P&L tiers −2.5%/−4% | 2026-08-20 | docs/STRATEGY_REVALIDATION_2026_08.md §II.8 (CLB-1) + Appendix §15 (the #363 breaker audit); docs/FINDINGS.md Finding #363 + Finding #364 (approval record + the ONE-PACKAGE manifest); scripts/analysis_357/rb_breaker_audit_report.md + rb_replay.py (package-scale breaker replay) |
busy-week-capital-335 |
SHIPPED Jul 11, 2026: busy-week capital bundle (Finding #335) — exposure cap 1.40 → 1.50 (exactly 6 flat-25% slots; 1.40 stranded 15%/night) + AMC/BMO admission now nets out about-to-exit positions (pre-fix a 5-position overnight book auto-rejected EVERY next-morning AMC at '150% > 140%' although real exposure at entry was ~0) + BMO reservation check now uses the strategy budget instead of raw IBKR day-trade buying power (~$110k — reservation NEVER bound at admission) | Jul 11, 2026 | Jul 11, 2026 operator-directed busy-week deep-dive (Jul-14 bank wave: 3+/day expected, overlapping AMC/BMO holds); docs/FINDINGS.md Finding #335 |
reservation-m1m5-357 |
IMPLEMENTED Aug 20, 2026 (#366) — DEPLOYED Aug 21, 2026: reservation mechanism M1+M5 (#357 §13): tonight-only observed-set BMO reservation (10:30 ET count) + rank-3 AMC carve-out; multi-day component REMOVED; computed INDEPENDENT of breaker state (#363); A-10 twin override branches deleted; K-RES ARMED at the Aug 21 deploy | 2026-08-20 | docs/STRATEGY_REVALIDATION_2026_08.md Part II (RES row) + Part IV §13 (reservation redesign for the S2c era); Register row E-008 (BMO reservation HOLDS-neutral; S2c-era form specified in §13) |
sizing-priority-v2 |
Sizing + priority + exposure-cap + volume-gate v2 — core sub-items SHIPPED (gate $1k #311 · priority 0-8 #313 · exposure uniform 1.40 #315/#317 · sizing KEEP #314.c); residual SHORT≤10% + regime-conditioned sizing deferred to post-PR-4 | May 30-31, 2026 | Apr 28, 2026 operator request; docs/FINDINGS.md Findings #279 + #311 + #313 + #314.c/.e + #315 + #316 + #317; Finding #218 (position-sizing quintile analysis) |
sizing-up-2026-07 |
Sizing-up SHIPPED (Jul 6, 2026 — Finding #314.f): FLAT 25/25/25 replaces (was 30/22/15) (operator chose flat25 over 35/25/18; both were gauntlet-PASS at the live 1.40 cap) | Jul 6, 2026 | Finding #314.c (May 31, 2026 — original sweep); Jul 5, 2026 operator-directed strategy review + capacity-aware re-run (replay_sizing_variants.py --exposure-cap 1.40, 578 signals / 39.0 wks incl. June trades) |
smallcap-long-b5-357 |
IMPLEMENTED Aug 20, 2026 (#366, own commit) — DEPLOYED Aug 21, 2026: B-5 (#357 §12): small-cap LONG relaxation as a PRE-REGISTERED PILOT — approved band 0.80–0.95, effective 0.80–0.90 under the C-1 global cap; ≤2 concurrent (all 4 admission loops), pilot_tag end-to-end (migration 031), K-B5 revert conditions ENCODED as an alert-only contract reminder (contract:k_b5_revert_decision — was consistency:b5_pilot_auto_revert until the #392 operator amendment); revert = operator decision, B5_PILOT_ENABLED=false | 2026-08-20 | docs/STRATEGY_REVALIDATION_2026_08.md Part II (B-5 row) + Part IV §12.4/§12.5 (commissioned small-cap study); Priors: #207 (Mar 9 ban), #323.c (counterfactual = 3-name mirage), #323.d (entry-aligned: 80–90 blocked band $−1.6/trade) |
v2 #6 |
Daily session stop breaker (tail-risk cap) [SHIPPED May 30, 2026 at 3 stops — Finding #312; threshold RAISED 3→4 Jul 11, 2026 — Finding #335.b, operator choice for the busy week] | May 30, 2026 | v2 audit #6; Apr 25 evening re-validation (Finding #232) — 9 historical ≥3-stop sessions confirmed (one additional fire on Apr 29 since the original count of 8) |
v3 B / v2 #1 |
Skip LONGs in downtrend regime | May 28, 2026 | v3 audit Apr 22 §3 Finding B; v2 audit #1; Apr 25 evening re-validation (Finding #232) — bias check stronger |
wave-scale-retunes-363 |
IMPLEMENTED Aug 20, 2026 (PKG-357 #366) — DEPLOYED Aug 21, 2026 — WAVE-RT — wave-scale retunes of controls sized for 6-position batches: #354 batch-prep deadline scaled min(45+5×(n−6), 90)s (BATCH-1); execution-quality slippage breaker counts per-batch (EQ-1 — also WIRED: pre-#366 record_slippage had zero callers); MAX_SHORT_POSITIONS held at 2 (MSP-1 record-only, revisit at K-S2C); RES computes reservations independent of breaker state (homed on the RES row) | 2026-08-20 | docs/STRATEGY_REVALIDATION_2026_08.md Appendix §15.4; docs/FINDINGS.md Finding #363 (Part 2 inventory: 24 SAFE · 6 NEEDS-RETUNE · 3 REDESIGN) + Finding #364 (the ONE-PACKAGE manifest, item 7); docs/IMPLEMENTATION_PLAN_2026_08.md P1 row WAVE-RT + the #364 manifest section |
| id | title | date | sources |
|---|---|---|---|
Sim RuleB |
RuleB — ±90 min no-stop window: FAILED-GAUNTLET after the Finding #330 gap-aware rearm fix; Phase-2 active flip CANCELLED | May 28, 2026 (Phase 1 DRY-RUN only; Phase 2 CANCELLED Jul 5, 2026) | Apr 25 simulator (Finding #228 §10.5); Apr 25 evening re-validation (Finding #232) — PROMOTED rank 4 → 2; May 28, 2026 simulator re-run (n=121, ex-top-2 +$127/100) |
v3 D-stop / G-stop |
ATR-based stops (k=2.0) and window+ATR combinations | — | v3 audit alternatives; Apr 25 simulator (Finding #228 §10.4) |
vix-2025-truesim-357 |
D-2 DISCHARGED Aug 16, 2026 (#357 §7 deep dive): the true-simulator replay WAS RUN — every candidate VIX cap FAILS the era-consistency check and the counterfactual universe refuses to confirm; NO rule ships. Replaced by the D-2 VIX≥20 LONG shadow monitor | — | Finding #357 W9 §7.1 (volunteer cell, observationally §K-robust); Finding #357 W8 §2 (D-009 ladder inert; retunes era-confounded); docs/STRATEGY_REVALIDATION_2026_08.md Part IV §7 (D-2 deep dive) + scripts/analysis_357/d2_vix_report.md |
| id | title | date | sources |
|---|---|---|---|
relax-202-9095 |
FAILED RE-GAUNTLET Aug 16, 2026 (#357): the Jul-11 #333 relax (LONG cap ≥0.90 → ≥0.95) failed its contractual re-gauntlet on REAL fills — 18 band fills since Jul-11 delivered −$1.90/trade vs the promised +$6.19 (WR 33%, stop-rate 50%, ex-top-2 −$163). Operator decision C-1 (re-close at 0.90) APPROVED Aug 17, 2026 (#361) — the re-close SHIPPED with the package (#366) and went LIVE at the Aug 21, 2026 deploy: the band is CLOSED at 0.90 in prod (stale .env 0.95 override fixed at deploy); M-C1 shadow monitor ARMED | Jul 11, 2026 | Jul 10, 2026 operator question (trade more markets / conviction expansion); scripts/analyze_90_95_bucket.py (NEW — gap-aware per #330, commission-aware per #331/#332, flat-25% sizing per #314.f); docs/FINDINGS.md Finding #333 (+ #323.b prior real-fill contrary evidence) |
| id | title | date | sources |
|---|---|---|---|
Old rec — 'Do Not Filter SHORT Signals' |
OLD RECOMMENDATION: keep all SHORT signals | — | pre-v3 dashboard recommendation #8 |
PR 2 — gate_quarterly_$1000peak_$500other |
Quarterly seasonal gate: $1,000 peak / $500 other [RETRACTED in favor of gate_uniform_$1000 (Finding #311 SHIP May 30, 2026)] | — | docs/FINDINGS.md Finding #310.c (PR 2.c sweep, May 29, 2026); scripts/phase3_simulator_gate_retune_sweep.json |
PR 2 — gate_quarterly_$2000peak_$1000other |
Quarterly seasonal gate: $2,000 peak / $1,000 other [RETRACTED in favor of gate_uniform_$1000 (Finding #311 SHIP May 30, 2026)] | — | docs/FINDINGS.md Finding #310.c (PR 2.c sweep, May 29, 2026); scripts/phase3_simulator_gate_retune_sweep.json |
drop-5k-volume-bump-357 |
C-2 (#357): DROP the +2 priority volume bump at ≥$5k — SUPERSEDED Aug 16 by the DECIDED B-4 3-tier priority table (§9), which removes ALL volume bumps AND the market-cap spine in one redesign (both refuted: F-001/F-002) | — | Finding #357 W3 §5.2 (F-002 REFUTED); Finding #357 W6 §4 (bump-drop test P&L-neutral); docs/STRATEGY_REVALIDATION_2026_08.md Part I B-4 + Part IV §9 (priority-table deep dive) |
v2 #4 (RETRACTED) |
VIX 22+ is the BEST bucket | — | v2 audit #4 (claim); v3 audit Apr 22 §2 (retraction) |
v2 #6 (RETRACTED) |
L 70-80% is the only profitable LONG band | — | v2 audit #6 (claim); v3 audit Apr 22 §2 (retraction) |
v2 H-rule (RETRACTED) |
ATR > 5% pre-screen (skip high-volatility tickers) | — | v2 audit H-rule (claim); v3 audit Apr 22 §1 (retraction) |
v3 A |
Block all stop-loss execution outside RTH (09:30–16:00 ET) | — | v3 audit Apr 22 §3 Finding A (claim); Apr 25 simulator (retraction, Finding #228) |
v3 C |
Skip LONGs with pre-event drift ≥ 2 % from prior-day close | — | v3 audit Apr 22 §3 Finding C (claim); Apr 25 universe view (5-day drift bias-check); Apr 25 evening operator decision — option 3 (drop, rely on B+D+E) |
v3 F |
BMO + VIX-bucket sizing (1.2× <18, 0.6× 18-22, 1.0× ≥22) | — | v3 audit Apr 22 §3 Finding F (claim); Apr 25 evening re-validation (Finding #232) — bias gauntlet split verdict |
| id | title | date | sources |
|---|---|---|---|
conviction-band-revalidation |
Conviction-band exclusions re-validated → ALL HOLD incl. LONG ≥0.90 (#202): the counterfactual RuleB 'flip' is CONTRADICTED by the real #202 trades (Findings #323 + #323.b) | Jun 1, 2026 | Jun 1, 2026 operator question + RuleB-confound insight; scripts/analyze_conviction_buckets.py + analyze_raise_cap_gauntlet.py + scripts/phase3_simulator/replay_deadzone.py + replay_deadzone_ruleb.py; docs/FINDINGS.md Findings #323 + #323.b |
depth-gate-v2 |
Polymarket depth-quality gate v2 — widened reconstruction shows a break-even low-information-signal filter → KEEP (PR 5) | May 31, 2026 | Apr 30, 2026 operator-flagged MRNA 'LOW OB' badge; May 31, 2026 PR 5 widened reconstruction (scripts/phase3_simulator/replay_depth_gate_v2.py); docs/FINDINGS.md Findings #283 + #319 |
regime-detection-v2 |
Market regime detection v2 — faster detectors add no robust ROI → KEEP compound_v1 (PR 4) | May 31, 2026 | Apr 28, 2026 empirical lag analysis (scripts/analyze_regime_detection_lag.py); May 31, 2026 PR 4 sweep (scripts/phase3_simulator/replay_regime_v2.py); docs/FINDINGS.md Findings #278 + #318 |
| id | title | date | sources |
|---|---|---|---|
#315 exposure cap |
MAX_TOTAL_EXPOSURE_PCT has no live consumer — #313 cap-raise inert; operative cap is MAX_DAILY_EXPOSURE (1.40 at the time; raised to 1.50 Jul 11 2026 by #335) [Finding #315] | — | Finding #315 (May 31, 2026 docs audit discovery + exposure-cap sweep) |
INFO — exit timing |
INFO: exit timing is near-optimal — no change | — | Q3 2025 cohort backtest (winsorized) |
PR 3.b capacity sims |
Capacity-aware simulator: $1k gate re-validation + sizing + hybrid-gate + SKIP-rule sweeps [ANALYSIS — Findings #314 / #314.b / #314.c / #314.d / #314.e] | — | Finding #314 (capital_simulator foundation); Finding #314.b (capacity re-val of #311); Finding #314.c (sizing sweep) |
Apr 25 LATE evening updates (Finding #232 + #233 re-validation): - v3 Finding F (BMO + VIX sizing) DROPPED to RETRACTED — deep bias gauntlet showed 1.2× scale-UP arm fails ex-top-3 (+$100 concentrated in STT/VZ/ALLY); direct modeling gives only +$36/100 not +$60; operator dropped both arms. - RuleB PROMOTED rank 4 → 2 — corrected stop classification (Finding #233; old
stop_triggeredfield undercounted at 1.7 % vs real 49 %) revealed stops are bleeding −$676 / 57 stopped trades, the strategy's biggest leak. RuleB is the only stop-loss rule that survives the gauntlet. (SHIPPED May 28 as Phase-1 DRY-RUN — Finding #305.) - v2 #6 (3-stop session breaker) confirmed has historical fire — 9 sessions of ≥3 stops in history (Feb 19 had 5); was wrongly believed to have zero historical evidence. (SHIPPED May 30 — Finding #312.) - v3 Finding D (Mid-cap 80%+ skip) REASONING REINFORCED — Mid 80-90% has 52 % stop rate, Mid 90-95% has 86.7 % stop rate (massacre). Stops-eat-winners hypothesis vindicated; KEEP RuleB dependency. - v3 Finding E (non-downtrend SHORT skip) REASONING REINFORCED — sideways SHORT 83.3 % stop rate (was claimed 67 %). RuleB likely fixes; KEEP dependency. - 5-outlier curse (renamed Apr 25 from 3-outlier — Finding #232 + memory §K): GPRO + DELL + SWBI + TXN + STUB carry ~$430 of $167 net.Apr 25 earlier evening updates (kept for context): - v3 Finding C (drift filter) RETRACTED via option 3 (drop and rely on B+D+E + selection rules; universe view weakened the bias check).
| # | Rule | Category | Sources | Est. lift / 100 | Files to touch |
|---|---|---|---|---|---|
| ~~1~~ | ✅ ~~Skip LONGs in downtrend regime~~ — SHIPPED May 28, 2026 (Finding #304); moved to IMPLEMENTED table below | selection | v3 audit Apr 22 §3 Finding B · v2 audit #1 · Apr 25 re-val (Finding #232) · May 28 ship (#304) | +$140 to +$200 estimated; live measurement slow at current 1.9 % volume-gate pass rate | signal_generator.py (helper + skip block) + tests/unit/test_signal_regime_gate.py |
| ~~1 (was 2)~~ | ✅ ~~RuleB — ±90 min no-stop window around earnings release~~ — SHIPPED May 28, 2026 (Finding #305 Phase 1 DRY-RUN); moved to IMPLEMENTED table below | stop-loss | Apr 25 simulator (Finding #228 §10.5) · Apr 25 re-val (#232) · May 28 simulator re-run (n=121, ex-top-2 +$127/100 STRENGTHENED) · May 28 Phase-1 ship (#305) | +$127 ex-top-2 (May 28 fresh sim) | ruleb_window_gate.py (NEW pure-decision module) + trading_orchestrator.py (dispatcher + cancel/rearm) + config.py (RULEB_* env vars) + test_ruleb_window_gate.py (25 tests) |
| ~~1 (was 3)~~ | ✅ ~~Daily 3-stop session breaker~~ — SHIPPED May 30, 2026 (Finding #312); moved to IMPLEMENTED table below | behavioral | v2 audit #6 · Apr 25 re-val (Finding #232) · May 30 fresh prod query (9 historical sessions confirmed) · May 30 ship (#312) | +$1/wk + ~-$50 Max DD (heuristic) | session_stop_breaker.py (NEW) + signal_generator.py (helper + skip block) + config.py (2 env vars) + 30 unit tests |
| ~~1 (was 2)~~ | ✅ ~~Re-validate full audit at trade #150+~~ — DONE Aug 16, 2026: executed as Finding #357 at n=183 (see the banner above); re-arms ~trade #300 | data | memory §K · #357 | meta | re-run scripts/strategy_performance_analysis.py + scripts/analyze_finding_a_full.py |
Operator-directed after the Jul-14-week deep-dive (bank wave: 3+/day expected, overlapping AMC/BMO holds — busiest week on record). (1) Exposure cap 1.40 → 1.50 (
MAX_DAILY_EXPOSURE+ unwiredMAX_TOTAL_EXPOSURE_PCTlockstep): flat-25% sizing fit only 5 positions (125%) under 1.40 — 15%/night structurally stranded; 1.50 fits exactly 6. Targeted granularity fix; NOT the broad 2.0 raise #315 declined. Margin-safe (6×$676 ≈ $4.05k vs enforced 2.0× Reg-T gate ≈ $5.4k). (2) Admission freed-capital fix:can_open_positionnow nets out positions exiting before the new entry time — pre-fix a full overnight book auto-rejected EVERY next-morning AMC ("would exceed cap" at 10:30 although the book exits 10:32); Jan-28 fix covered batch sizing only. (3) BMO reservation re-based: available capital = strategy budget bounded by IBKR BP (was RAW day-trade BP ~$110k → reservation never bound). Session breaker (#312) threshold RAISED 3 → 4 (#335.b, operator choice): 9-day counterfactual — only 4 would-be-blocked entries, net −$15.78 (breaker would have SAVED money); agent recommended keep-as-is, operator chose 4 to tolerate one more correlated stop on 6-slot days (skip-reason stringsession_3_stop_breakerkept for analytics continuity). Monitor Jul-14 week: 6-slot nights, first-everexposure_capskips, AMC admissions on full-book mornings, breaker interplay on the correlated Tuesday bank stops.
Operator chose the outright relax (over half-size pilot / keep).
SIGNAL_LONG_MAX_THRESHOLD0.90 → 0.95 (config default + prod.env); lockstep per §M:conviction_calculator.is_high_conviction, simulatorDirectionPolicySpec(prob_threshold_70_30_with_95_skip),capital_manager._bmo_reservation_threshold(0.95 — preserves pre-#333 effective no-override behavior), dashboard Python + Jinja + JS gating (badges now✗95+/70-94%), Live Config Direction row, P&L-progression Jul-11 marker, STRATEGY.md ×8, Action Queue rows, 2 guard tests. ≥0.95 skip REMAINS.⚠️ Finding #334 (same day, operator-caught): the #333 rollout MISSED
priority.py, which independently zeroed ≥0.90 LONGs — the reopened band would have been silently dropped atpriority_filter. Fixed with the operator-specified re-tier: base 0-8 (Large 70-80/80-90/90-95 = 8/7/6 · Mid = 5/4/3 · Small 70-80 = 2, 90-95 lowest per mcap group, counterfactual-only evidence) + #313 volume bump → 0-10 scale (MAX_PRIORITY_SCORE=10). Small caps stay 70-80% LONGs only; SHORT miss-conf ≥90% stays SKIP. Dashboard legend/badges/tooltips all on /10. Lesson (§M, then-live): the LONG cap was encoded in BOTHConfig. SIGNAL_LONG_MAX_THRESHOLDANDpriority.py:LONG_MAX_CONVICTION— change together. (#399, Aug 22: priority.py now reads Config.SIGNAL_LONG_MAX_THRESHOLD lazily — the numeric twin is gone; changing the env/config is enough.) Monitor: first ~20 real fills in the reopened band vs the +$6.19/trade counterfactual; re-gauntlet on REAL fills at trade #150 or 20 band-fills. The pre-ship evaluation record follows.
Operator asked (Jul 10) whether the ≥0.90-skipped markets would have been winners — answered with a gap-aware 1m-bar replay (
scripts/ analyze_90_95_bucket.py) of all 112 #202-skipped markets instead of a live half-size pilot: scheduled entry/exit bars, per-tier 3/4/5% stops active 24/7 with gap-aware fills (#330 lesson), flat-25% sizing (#314.f), net of commissions.
Band n Net (Tiered) ex-top-2 WR stops Verdict 0.90-0.95 78 +$482.94 (+$6.19/tr) +$135.39 PASSES 42% 51% operator decision 0.95+ 34 −$6.03 −$228.48 32% 62% KEEP skipping Fragility (per §K, reported honestly): sub-slices mostly FAIL ex-top-2 (large −$157, mid −$55, pre-May −$95; only small-caps + the pooled band pass); ~2/3 of recorded convictions pre-date the #325/#327 estimator fixes; no slippage modeled; wrong-prediction instant-exit rescue NOT modeled (conservative). Contrary evidence #323.b (26 real pre-Mar-9 fills −$112) used the buggy estimator + old rule set. Options: (a) relax cap to 0.95, (b) relax at half-size until ~20 real fills, (c) keep #202, re-run at trade #150+. Mirror row:
relax-202-9095. Same finding also FIXED the exclusion-funnel coverage leaks (channel-window hole + gamma-live conviction fallback + end_time timing inference).
Jul 6, 2026: operator chose flat 25/25/25 (over 35/25/18 and KEEP) via AskQuestion — SHIPPED to production (
config.pyPOSITION_SIZE_PCT_LARGE/MID/SMALL0.30/0.22/0.15 → 0.25/0.25/0.25; simulatorrules.pysizing specjul6_flat25+production_strategy_jul6()factory in lockstep; dashboard Live Config + STRATEGY.md + memory.md updated). Monitor small-cap stop-outs (now sized 25% in the 5%-stop tier) over the next ~20 trades; re-validate at trade #150+. The pre-ship evaluation record follows.Jul 5, 2026 capacity-aware re-run of the parked #314.c sizing-up candidates (
replay_sizing_variants.py --exposure-cap 1.40, 578 signals = 134 live + 444 counterfactual, 39.0 weeks, June trades included). Then-baseline (since superseded) 30/22/15 = +$20.99/wk. Both raise/concentrate candidates gauntlet-PASS and STRENGTHENED vs May 31:
Variant Δ/wk Total WR maxDD 5p Gauntlet flat 25/25/25 +$7.40 (was +$4.18) +$1,107.04 44.0 % −$245.46 −$98.60 (unchanged) ✅ PASS 35/25/18 +$6.08 (was +$4.63) +$1,055.71 44.4 % −$236.88 −$113.65 (worse) ✅ PASS 33/22/15 (Large only) +$0.10 — — — — ❌ FAIL-EX-TOP-2 all lower-sizing variants negative — — — — ❌ FAIL-SPILLOVER Caveats unchanged from #314.c: flat 25/25/25 raises Small 15 %→25 % (squeeze risk in the 5 %-stop tier); 35/25/18 raises Small only to 18 % but has the worse 5p tail. Operator decision pending: ship flat 25/25/25 / ship 35/25/18 / KEEP the then-live 30/22/15 (since superseded by flat-25 #314.f, then S2c #366; re-check at trade #150+). Mirror row:
build_action_queue()idsizing-up-2026-07.
Finding #311 SHIPPED gate_uniform_$1000 to production (May 30, 2026 LATE evening). First real-money strategy ship since Mar 9. After full correctness audit caught + fixed 6 errors in earlier simulator outputs, the corrected per-tier empirical scaling showed
gate_uniform_$1000is Pareto-optimal: Δ E[wk] +$21/wk (~+$1,092/yr at $2,450 capital), Δ max DD -$46 (within -$735 target = 30% capital), outlier alarm fixed. Production code:src/earnings/config.pySIGNAL_MIN_VOLUME_TOTALdefault2000.0→1000.0.production_strategy_may30()factory captures new state. The other 2 PR 2 ship-eligible variants (gate_quarterly_$2000peak_$1000other,gate_quarterly_$1000peak_$500other) RETRACTED-IN-FAVOR-OF gate_uniform_$1000 — operator picked simplest single-axis change.gate_uniform_$250(more aggressive) DEFERRED to monitor uniform_$1000 effects first.
| # | Rule | Outcome | Date |
|---|---|---|---|
| ~~5~~ | ~~PR 2 — gate_uniform_$1000~~ | ✅ SHIPPED (Finding #311) | May 30, 2026 |
| ~~6~~ | ~~PR 2 — gate_quarterly_$2000peak_$1000other~~ | 🛑 RETRACTED-IN-FAVOR-OF gate_uniform_$1000 | May 30, 2026 |
| ~~7~~ | ~~PR 2 — gate_quarterly_$1000peak_$500other~~ | 🛑 RETRACTED-IN-FAVOR-OF gate_uniform_$1000 | May 30, 2026 |
Jul 5, 2026 (Finding #330): the RuleB dependency on both rows below is REMOVED — RuleB failed the gap-aware gauntlet and its Phase-2 active flip is CANCELLED, so the stop bleed these rules were waiting on has NO shippable stop-side remedy. Both re-evaluate as PURE selection rules.
| ID | Rule | Blocker | Re-evaluation criterion |
|---|---|---|---|
| v3 D | Skip Mid-cap LONGs at conviction ≥ 80 % | Folded into B-4 (#360/#366; superseded as a standalone row — the deployed B-4 table already ranks 80–85 mid/large LONGs and C-1 closes ≥0.90): reopen only if the K-B4 live re-check surfaces new evidence (was: ~~RuleB Phase-2~~ removed per #330 — trade #150+ audit or ~15 fresh post-#327 trades in the 0.80-0.90 band) | Re-run the capacity-aware simulator on the skip candidate as a PURE selection rule — likely with WIDENED scope to "Skip ALL LONGs ≥ 0.85" per the Jul 5 review (LONG 0.85-0.90 across ALL mcaps: n=31, −$92 net-of-commissions, ex-top-2 −$210, ex-repeat −$77, 52 % stop rate — §K-robust negative; but 2 of its June losers were the #327 conviction bug, now fixed). Operator ship decision required. |
| v3 E | Skip SHORTs in non-downtrend regimes | Re-keyed to the D-5 SHORT re-test (#360; ≥40 live CF cases, ~25 today): reopen only if D-5 surfaces new evidence (was: ~~RuleB Phase-2~~ removed per #330 — total SHORT count ≥ 30 or trade #150+ audit) | Re-evaluate as a PURE selection rule. If downtrend SHORT alpha is still GPRO+STUB-dominated at n ≥ 6 → keep ON-HOLD permanently. |
| Date | Rule | Category | Findings | Files (LIVE) |
|---|---|---|---|---|
| May 31, 2026 | Simplify daily exposure tiering → single uniform 140% cap (operator-CONFIRMED; collapsed OPPORTUNITY_EXPOSURE_LIMITS rare 60%→140%; #316 showed the rare discount near-inert; "more opps ≠ more ROI" — ROI lever is concentration not looser caps) |
risk | #317 | src/earnings/risk_manager.py (OPPORTUNITY_EXPOSURE_LIMITS uniform + docstring) + tests/unit/test_risk_manager.py (+1 test) |
| May 30, 2026 LATE LATE evening | PR 3.a — Volume-tier priority bump (+1 at $2k, +2 at $5k → scale 0-8) + ~~capital cap 1.40→2.00~~ (cap-raise REVERTED — see #315) + NYSE dead-code cleanup — third real-money strategy ship of the day | selection / risk | #313 (cap part re-scoped by #315) | src/earnings/priority.py (full rewrite, 0-6 → 0-8 with volume bump) + src/earnings/config.py (MAX_TOTAL_EXPOSURE_PCT re-aligned 2.00→1.40 per #315 — it was unwired, no live effect) + src/earnings/signal_generator.py (pass volume_total to priority) + src/earnings/order_executor.py (drop is_nyse dead branch) + earnings_dashboard/app.py + earnings_dashboard/templates/dashboard.html (legend + clamp + Live Config) + 3 unit-test updates / additions |
| May 30, 2026 LATE evening | Daily 3-stop session breaker (v2 #6) + DirectionPolicySpec doc-bug fix — second real-money strategy ship of the day | behavioral / selection | #312 | src/earnings/session_stop_breaker.py (NEW pure-decision module ~155 lines) + src/earnings/signal_generator.py (_count_todays_stops helper + skip block in _build_trading_signal after Queue Rule #1) + src/earnings/config.py (SESSION_STOP_BREAKER_ENABLED + SESSION_STOP_BREAKER_THRESHOLD env vars) + scripts/phase3_simulator/rules.py (DirectionPolicySpec defaults 0.55/0.45 → 0.70/0.30 + long_max_threshold=0.90 + conviction_fn="raw_prob") + 30 NEW unit tests (test_session_stop_breaker.py 22 + test_signal_session_stop_breaker.py 8) |
| May 30, 2026 | Lower volume gate from $2,000 → $1,000 (first real-money strategy ship since Mar 9 — first ship from the Phase 3 unified-strategy framework) | selection | #311 | src/earnings/config.py:239 (SIGNAL_MIN_VOLUME_TOTAL default 2000.0 → 1000.0) + scripts/strategy_performance_analysis.py (BOT_VOLUME_GATE_USD lock-step) + scripts/phase3_simulator/rules.py (production_strategy_may30 factory + baseline_ruleset gate updated) + tests updated (38/38 PASS) |
| May 28, 2026 (Phase 1 DRY-RUN) | RuleB — ±90 min no-stop window around earnings release — Phase 1 DRY-RUN ship; 🛑 Phase 2 active flip CANCELLED Jul 5, 2026 (Finding #330 — gap-aware simulator flipped RuleB to −$194/100 ex-top-2, FAILED-GAUNTLET); dry-run apparatus was REMOVED Aug 21, 2026 (#380; was logging-only) | stop-loss | #305 (reversed by #330; deleted #380) | src/earnings/ruleb_window_gate.py (DELETED #380; was the May 28 pure-decision module) + src/earnings/trading_orchestrator.py (dispatcher deleted #380) + src/earnings/config.py (RULEB_* env vars deleted #380) + tests/unit/test_ruleb_window_gate.py (deleted #380) |
| May 28, 2026 | Skip LONGs in downtrend regime (Queue Rule #1 ship; first Phase-3 strategy rule shipped after the May-26 un-gate) | selection | #304 | signal_generator.py (_safe_get_regime helper + skip block in _build_trading_signal after small_cap_long_above_80) + tests/unit/test_signal_regime_gate.py (7 unit tests) |
| Mar 9, 2026 | Skip all LONGs at conviction ≥ 90 % | selection | #202 | signal_generator.py |
| Mar 9, 2026 | Stop sizes widened to Large 3 % / Mid 4 % / Small 5 % | stop-loss | #202 | risk_manager.py / order_executor.py |
| Feb 10, 2026 | All stop-loss orders use STOP-LIMIT with 2 % buffer | stop-loss | #179 | order_executor.py (THIS is why Finding A could not work as soft-gate-only) |
| Feb 5, 2026 | BMO exit moved 09:32 → 10:32 AM ET | exit | (Feb timing analysis) | config.py |
| Mar 31, 2026 | earnings_markets.market_cap_category populated DB-first |
data | #219 | caching.py + app.py + earnings_sync.py |
| Apr 16, 2026 | ~~Effective cumulative-volume gate at $2K~~ (SUPERSEDED May 30, 2026 by #311 $1k ship; original was max(DB, Gamma) — Apr 30 fix Finding #282; previously "DB else Gamma") | selection | #222 / #223 / #224 / #225 / #226 / #282 / #311 | volume_policy.py + signal_generator.py + app.py |
| Apr 22, 2026 | Outcome resolver + counterfactual + regime/VIX capture | data | #227 | outcome_resolver.py + 3 migrations |
| ID | Rule | Why retracted |
|---|---|---|
| 🛑 RuleB Phase 2 | ±90 min no-stop window (active mode) | Finding #330 (Jul 5, 2026). The simulator arm filled window-blocked stops at the stop price after the price had gapped through — unobtainable under the as-shipped cancel-and-rearm mechanism. Gap-aware: headline −$209/100, ex-top-2 −$194/100, ex-repeat −$227/100 (n=129) — FAIL on every §K check. Same rearm_gap_open mechanism that killed FA_hard. Do NOT re-propose stop-silencing windows without a gap-aware TRUE simulator run. Phase-1 dry-run code was REMOVED Aug 21, 2026 (#380). |
| 🛑 v3 A | Block all stop-loss execution outside RTH | Finding #228 simulator: FA_soft = $0 (inert; hardware STP-LMT keeps outsideRth=True per Finding #179). FA_hard = −$418 / 100. 22 trades gap-through stops at RTH open (−$417); 9 recoveries (+$204) outweighed 2-to-1. Pre-EPS-trigger only also −$92. |
| 🛑 v3 C | Skip LONGs with drift ≥ 2 % | Apr 25 evening operator decision (option 3 of 3). Universe view at 5-day baseline weakened the bias check (skip bucket is +$3,289 net at $10K notional — would remove winners). Live n=13 in skip bucket at the gauntlet floor — too small to override. Drop the rule and rely on B + E + selection. Re-test at trade #150+ if drift signal re-appears with a tighter (1-day) drift definition. |
| 🛑 v3 F | BMO + VIX-bucket sizing (1.2× / 0.6× / 1.0×) | Apr 25 LATE evening (Finding #232). Deep bias-gauntlet split verdict: 0.6× scale-DOWN arm (BMO+VIX 18-22, n=30, −$54) PASSES robustly (ex-top-2 = −$135, more negative); but 1.2× scale-UP arm (BMO+VIX <18, n=20, +$100) FAILS bias #2 — ex-top-3 collapses to −$1.58 across 17 trades (the +$100 is concentrated in STT +$37 / VZ +$33 / ALLY +$32). Direct multiplier-on-realized-pnl modeling shows total per-100 lift is +$36 (NOT the docs' +$60), and that's optimistic (assumes linear scaling, ignores capital constraints + fixed costs). Operator dropped both arms — scale-down-only ~$20/100 not worth implementation + variance + capital-constraint risk at current ~$2.4k capital. Re-test at trade #150+. |
| ⚠️ v3 D-stop / G-stop | ATR k=2.0 stop / window + ATR | Finding #228 simulator: headline +$195/+$201 → ex-top-2 collapses to −$109/−$103. Outlier-driven (KSS/GME/BBY recovery cluster). |
| 🛑 v2 #4 | VIX 22+ is the best bucket | v3 audit Apr 22 §2: 64 % of bucket P&L from GPRO + SWBI. Ex-them +$36 across 12 trades. Replaced by Finding F (BMO + VIX <18). |
| 🛑 v2 #6 | L 70-80 % is the only profitable LONG band | v3 audit Apr 22: 82 % of bucket P&L from SWBI. Ex-SWBI +$15. Kept only as "don't penalize" baseline. |
| 🛑 v2 H-rule | ATR > 5 % pre-screen | v3 audit Apr 22 §1: headline +$329 on 49-trade subset → −$148 across 109. The smoking gun that made the 4-check gauntlet mandatory. |
| 🛑 Old rec — "Do Not Filter SHORT Signals" | Pre-v3 dashboard recommendation | Based on AMC-aggregate without regime split. Superseded by queue #4 (v3 Finding E: skip SHORT in non-downtrend). |
| Item | Source | Note |
|---|---|---|
| Exit timing is near-optimal | Q3 2025 cohort backtest (winsorized) | BMO winsorized: 4h (+1.23 % EV) ≈ day_close (+1.19 %). AMC: ~0 % EV at all horizons. Current 10:32 AM BMO / 15:57 next-day AMC remain operative. |
For each rule, the documentation pattern is: mechanism (why it should work) → evidence (the table) → bias check (4-check gauntlet result).
Ship status (May 28, 2026): SHIPPED as first Phase-3 strategy rule after the May-26 un-gate. Commit lives at
src/earnings/signal_generator.py(new private_safe_get_regime()helper + skip block inserted in_build_trading_signal()after thesmall_cap_long_above_80check). 7 new unit tests intests/unit/test_signal_regime_gate.py(LONG×downtrend skip, plus 6 fail-soft / direction-asymmetry / regime-variation negative-controls). Live acceptance test: monitorpolymarket_opportunity_log.skip_reason='long_downtrend'rows over the next downtrend regime. Note: at current PM volume-gate pass rate of 1.9 % (Finding #279 amendment), natural firing rate is ~0.4 % of all earnings markets — live "≥30 trades" gauntlet trigger may take years; rule's immediate value is in bias-gauntlet-locking the policy + correct behavior in the eventual next high-volume regime, NOT in fast live-evidence accumulation.
Mechanism: Earnings beats matter less when the broader market is selling. Even high-conviction LONGs get caught in macro flows; the stop fires on the macro move, not the earnings reaction.
Evidence (refreshed Apr 25 evening, 116 closed trades):
| Bucket | n | Wins | Stop rate (corrected) | Total $ |
|---|---|---|---|---|
| LONG in downtrend | 22 | 5 (23 %) | 68.2 % | −$136 |
| LONG in uptrend | 36 | 15 (42 %) | 38.9 % | +$71 |
| LONG in sideways | 37 | 12 (32 %) | 51.4 % | +$1 |
| LONG NULL regime | 3 | 2 | 33 % | +$88 |
Bias check (4 checks) — STRONGER after Apr 25 re-validation: - ✅ n=22 (≥12 minimum); 22/22 distinct tickers (no repeats — bias #3 trivially passes) - ✅ Ex-top-2 by |pnl| = −$175 (more negative than headline! The top-2 by |pnl| are SWBI +$70 winner + a smaller loser; SWBI was masking how bad the bucket really is) - ✅ Top losers across 8+ distinct tickers (BABA, GME, KSS, NKE, PDD, ASAN, VSCO, BBY) - ✅ Full-population spillover positive (uptrend +$71, sideways flat)
Stop rates corrected via exit_reason ILIKE '%stop%'; the old
stop_triggered boolean undercounted at 1.7 % across all trades and is
broken (Finding #233).
Implementation: Skip rule on signal_generator using
MarketRegimeProvider.get_snapshot().regime. ~10 lines.
Mechanism: Stocks that have already drifted into our LONG direction overnight have priced in the EPS expectation. The small additional move on the announcement isn't enough to cover commission + slippage + stop risk.
Evidence:
| Drift bucket | n | Wins | Total $ |
|---|---|---|---|
| LONG drift <2 % | 75 | 31 (41 %) | +$107 |
| LONG drift 2–5 % | 13 | 1 | −$120 |
| LONG drift ≥5 % | 2 | 0 | −$25 |
Bias check: - ✅ n=15 in the skip bucket (combined 2-5 % + ≥5 %) - ✅ 14/15 are losers; ex-best-1 (EBAY +$5.64) still −$150 across 14 - ✅ Monotonic — more drift, worse outcome (no cliff edge) - ✅ Full-population: skipping 15 of 90 LONGs preserves the +$107 winners
Implementation: Use earnings_markets.stock_price_day_before_close
(populated by Finding #227 resolver on 713/715 past markets); compute
drift = (current − stock_price_day_before_close) / stock_price_day_before_close
at signal time. ~15 lines.
Mechanism: High-conviction Mid-caps run the most into earnings (smart money front-running) so the move is most pre-priced. Large caps have deeper books and less front-running pressure. Apr 25 alternate mechanism (vindicated): stops eat winners on Mid-cap (Mid 80-90 % has 51.6 % stop rate, Mid 90-95 % has 86.7 % stop rate) — RuleB likely fixes.
Evidence (refreshed Apr 25 evening with corrected stop classification):
| Mcap × conviction | n | Wins | Stop rate | Total $ |
|---|---|---|---|---|
| Mid LONG 80–90 % | 31 | 11 (35 %) | 52 % | −$56 |
| Mid LONG 90–95 % | 15 | 1 (7 %) | 87 % | −$55 |
| Large LONG 80–90 % | 10 | 4 (40 %) | 50 % | −$3 (DEGRADED from prior +$22 KEEP) |
| Large LONG 90–95 % | 8 | 3 (38 %) | 63 % | −$18 |
Bias check: - ✅ Both Mid sub-buckets independently negative across n ≥ 15 - ✅ Mid is 70 % of trade count — high-leverage rule - ⚠️ Large 80-90 % degraded from +$22 to −$3 — the "Mid-only" framing is weakening; potential future widening to "Skip ALL LONGs ≥ 80 %" - ⚠️ Universe view at $2K gate shows Mid 80-90 % is POSITIVE without stops (Finding #228 stops-eat-winners hypothesis) — RuleB resolution highly likely
Mechanism: SHORTs are a different bet entirely — they need market weakness to amplify the bad-earnings move. In uptrend / sideways the recovery rally bounces our short out. Apr 25 alternate mechanism (vindicated): sideways SHORT 83.3 % stop rate (corrected from 67 %) strongly supports the stops-eat-winners hypothesis — RuleB likely fixes.
Evidence (refreshed Apr 25 evening with corrected stop classification):
| Regime × direction | n | Wins | Stop rate | Total $ |
|---|---|---|---|---|
| SHORT in downtrend | 3 | 3 (100 %) | 0 % | +$173 (KEEP set is 2-of-3 outliers: GPRO +$111, STUB +$58, GIS +$3.64) |
| SHORT in uptrend | 7 | 1 | 28.6 % | −$2 |
| SHORT in sideways | 6 | 0 | 83.3 % | −$46 |
Bias check: - ✅ 13/13 negative on the skip side — perfect direction signal - ⚠️ Downtrend-positive KEEP set is 2-of-3 outliers per the 5-outlier rule (GPRO + STUB; ex-them just GIS +$3.64) - ⚠️ Total SHORT n=18 below the n≥30 commit threshold
Mechanism: Tail-risk cap. After 3 stops in a single trading session, something systemically bad is happening (regime shift, earnings-day flash). Bot pauses entries until next session.
Evidence: 9 historical sessions with ≥3 stops per the May-30 #312
production query (2026-02-03 → 2026-04-29). The Apr-25 re-validation found 8 —
including Feb 19 (5 stops, −$35), Mar 2 (4 stops, −$59), and six 3-stop days;
total stops on those 8 days: 27, costing −$266. Was
previously believed to be tail-hedge only with no historical fire — that
claim was an artifact of the broken stop_triggered field (Finding #233).
Implementation (AS SHIPPED, #312): pure-decision module
src/earnings/session_stop_breaker.py + _count_todays_stops() helper +
skip block in signal_generator._build_trading_signal (after Queue Rule #1
long_downtrend); counts session stops via trade_audit_log (using
exit_reason ILIKE '%stop%', NOT stop_triggered); if ≥threshold today
(SESSION_STOP_BREAKER_ENABLED=True) → log
skip_reason='session_3_stop_breaker' and skip.
Threshold raised 3 → 4 Jul 11, 2026 (Finding #335.b, operator choice for
the busy week) — the skip-reason string is unchanged for analytics
continuity.
Moved to §4. Apr 25 LATE evening (Finding #232) bias gauntlet split verdict: scale-DOWN arm passes (BMO+VIX 18-22, n=30, −$54 robust); scale-UP arm fails ex-top-3 (BMO+VIX <18 +$100 collapses to −$1.58 across 17 ex STT/VZ/ALLY). Direct modeling shows total per-100 lift is +$36 (NOT +$60), and that's optimistic. Operator dropped both arms. Re-test only the scale-DOWN arm at trade #150+ with fresh data.
🛑 Jul 5, 2026 REVERSAL (Finding #330): the evidence below was an artifact of the simulator's gap-fill optimism —
simulate_window_onlyfilled window-blocked stops at the STOP PRICE even when the price was still beyond the stop at rearm. Gap-aware (rearm fills at the first post-window bar OPEN, matching the as-shipped cancel-and-rearm order semantics), RuleB is −$209/100 headline / −$194/100 ex-top-2 / −$227/100 ex-repeat (n=129) — FAILED-GAUNTLET. Phase-2 active flip CANCELLED. The section below is preserved as the historical record of the pre-#330 reasoning.Ship status (May 28, 2026; history): Phase 1 SHIPPED in DRY-RUN mode. Code lived (was deleted #380) in
src/earnings/ruleb_window_gate.py(pure decision function + RuleBAction enum + RuleBDecisionContext dataclass) plus dispatcher methods_process_ruleb_window_gate/_ruleb_fire_cancel/_ruleb_fire_rearmontrading_orchestrator. Hardware cancel-and-rearm pattern (NOT soft-gate per Finding #228 lesson — the simulator'ssimulate_window_onlyrequires hardware-level silencing; soft-gate would deliver $0 EV like FA_soft did). Phase 1 RULEB_MODE='dry_run' default = logs cancel/rearm actions WITHOUT IBKR side effects. Phase 2 (separate later session) flips RULEB_MODE='active' after operator reviews dry-run logs. Phase 1 known limitation: restored positions (signal=None perposition_manager.load_persisted_positions:1155) cannot deriveearnings_release_dt→ graceful SKIP_NO_EARNINGS_DT log; Phase 2 may add restart-safe lookup if dry-run shows this happens in practice. 25 unit tests intests/unit/test_ruleb_window_gate.pycover all 8 RuleBAction return values + sanity-gate skips + late-entry edge case + hard-fallback safety boundary; 36/36 PASS pre-commit (25 RuleB + 11 prior signal-test regression).
Mechanism: Earnings release momentarily widens spreads and triggers stops on volatility, not on direction. The ±90 min window covers the legitimate volatility spike.
Evidence (Apr 25 simulator): +$62.97 vs A_base across 51 stops
(+$123 / 100 trades). 4 better / 1 worse / 46 unchanged → 96 % no-effect.
Apr 25 evening re-validation confirmed live stop frequency matches
simulator population: 57 of 116 trades = 49 % stop rate, costing −$676
(corrected via exit_reason; old stop_triggered field reported only
1.7 % — Finding #233). Stops are the strategy's biggest leak; non-stops
contribute +$843.
Bias check: - ✅ n=51 - ✅ Robust to ex-top-2 (still positive at smaller magnitude) - ✅ Survives ex-repeat-tickers (no name dominance) - ✅ Full-population spillover: 96 % unchanged trades, no spillover risk
Implementation: Software gate in order_executor.py on stop-fill
event handler: if (now - earnings_release_dt).abs() < 90 min, log
"stop blocked: in earnings window" and don't act on the fill (let the
hardware order fill, then immediately re-enter at scheduled exit if
position is still flat). ~25 lines.
PROMOTED rank 4 → 2 on Apr 25 evening because the corrected stop classification revealed live stop bleed dominates the negative contribution. Rule #1 SHIPPED May 28, 2026 (#304); RuleB shipped right after it the same day as Phase-1 DRY-RUN (#305).
Documented here so future audit passes don't re-discover them.
Original claim: +$300–$400 / 100 trades, LOW risk, NO selection change. Implement first.
Why retracted: Comprehensive simulator (scripts/analyze_finding_a_full.py):
outsideRth=True per Finding #179, so a software-only gate is
literally inert — the broker still fills regardless of bot bookkeeping.Audit error: Used Rule B (±90 min window) as a proxy and treated the per-session observational table as counterfactual evidence. Rule B is narrower than Finding A and the per-session table just measures where stops fired (tautologically negative because stops cause losing exits).
Mechanism failure: The audit's "stocks fill at bad prices then revert during RTH" assumption isn't supported. For 22 of 51 stopped trades the stock kept falling past the stop into RTH open. Pre-EPS-trigger only (the audit's strongest claimed scenario) is also net-negative at −$92.
Original claim (v3 audit Apr 22): +$60 / 100 trades by scaling 1.2× / 0.6× / 1.0× across BMO + VIX <18 / 18-22 / ≥22 buckets. Robust on both ends per audit's ex-top-3 check.
Why retracted (deep bias gauntlet on Apr 25 evening with fresh data):
| Arm | Bucket | n | Headline | Ex-top-2 | Ex-top-3 | Verdict |
|---|---|---|---|---|---|---|
| 0.6× scale-DOWN | BMO+VIX 18-22 | 30 | −$54 | −$135 (more negative — top-2 are WING+BLK winners masking the loser bucket) | n/a | ✅ PASS — robust |
| 1.2× scale-UP | BMO+VIX <18 | 20 | +$100 | n/a | −$1.58 (concentrated in STT +$37 / VZ +$33 / ALLY +$32 = +$102) | ❌ FAIL bias #2 — fragile |
Direct multiplier-on-realized-pnl modeling: Baseline BMO total +$39.72 → After F (full 1.2/0.6/1.0): +$81.24 → delta +$36 / 100 trades, not the docs' +$60. And that's optimistic (assumes linear scaling, ignores commission/slippage fixed costs and capital constraints at ~$2.4k).
Operator decision Apr 25 LATE evening: Drop both arms. Scale-DOWN arm alone is only ~$20/100 lift — not worth the implementation + variance + capital-constraint risk at current capital. The scale-UP arm is fragile and adds risk for marginal gain.
Re-test trigger: Trade #150+ with fresh data. Only re-introduce the scale-DOWN arm if ex-top-2 stays robustly negative. Skip the scale-UP arm entirely until the BMO+VIX <18 winner bucket survives ex-top-3.
| Rule | Headline | Ex-top-2 |
|---|---|---|
| RuleD (ATR k=2.0) | +$195/100 | −$109/100 |
| RuleG (window + ATR k=2.0) | +$201/100 | −$103/100 |
Both collapse to net-negative when the top-2 outliers (KSS / GME / BBY recovery cluster) are removed. Bias-check #2 fails. Could be revisited when the 3-outlier dominance dilutes (n ≥ 100 stops).
64 % of bucket P&L from GPRO + SWBI. Ex-them: +$36 across 12 trades. Replaced by Finding F (BMO + VIX <18) which is bias-robust.
82 % of bucket P&L from SWBI. Ex-SWBI: +$15. Ex-SWBI+DAL: −$17. Kept only as "don't penalize" baseline (i.e. don't add a skip rule on this band — it isn't actually a sell signal).
The "smoking gun" for full-population spillover: headline +$329 on the 49-trade stopped+correct subset → −$148 net across 109 trades when applied to the full population. Skip rules in particular need the full- population check because they remove WINNERS as well as losers.
Every new finding / rule MUST pass all four checks below before being
added to the queue. Source: docs/STRATEGY_AUDIT_v3.md §1 + §6 +
.cursor/memory.md §K.
Plus the 5-outlier rule (renamed Apr 25 evening from 3-outlier — Finding #232): GPRO + DELL + SWBI + TXN (added Apr 22, +$92, LONG large NULL-regime) + STUB (added Mar 4, +$58, SHORT mid downtrend) together carry ~$430 of the strategy's ~+$212 net P&L on ~117 closed trades; ex-top-5 the strategy is −$263 across 111 trades. ANY slice that includes them looks great; ANY slice that excludes them is structurally negative. ALWAYS report numbers ex-top-2 alongside the headline; for any slice containing 2+ of the named 5 outliers, also report ex-them.
Plus the date-drift rule (added Aug 18, 2026 from Finding #362): any
analysis that joins historical trades to earnings_markets.earnings_date
(entry-day correctness, wrong-date-entry counts, release-window studies)
must treat pre-#349-era rows (before Jul 29, 2026) as unverified at trade
time — sync writers moved earnings_date AFTER events, so today's stored
date is not the date the trade decision saw. Known false positives: ON
(Feb-9) and NET (Feb-10) LOOK wrong-dated in today's DB but entered on the
correct day (the DB date drifted later post-event). Before classifying any
historical entry as wrong-dated, cross-check trade_audit_log entry dates
against earnings_date_audit history. The historical rows are deliberately
NOT repaired (repairing would falsify the as-traded record). The genuine
wrong-date class (4 of 193: CRSP, SBUX ×2, VIK) is closed forward by the
Plus the true-simulator rule (added Apr 25 from Finding #228): every counterfactual rule needs a TRUE simulator that replays the proposed rule end-to-end on the actual data. Proxies (e.g. "Rule B is close enough to Finding A") and observational tables (e.g. "stops fire pre-market AND pre-market trades have negative P&L → blocking pre-market stops would have helped") are NOT counterfactual evidence — they conflate selection with causation.
When implementing each rule, follow memory §B (5-step verification) and §H (commit + push + deploy). Each rule below has a pre-baked 5-step trace to copy into the implementation PR.
Implementation notes preserved for historical context + future reference. Actual code matches the spec below with minor refinements (insertion after
small_cap_long_above_80instead of "before volume gate" per operator AskQuestion choice; added_safe_get_regimeprivate helper rather than inlining). Seedocs/FINDINGS.mdFinding #304 for the canonical narrative.
File: src/earnings/signal_generator.py (helper _safe_get_regime ~17 lines + skip block ~22 lines) + tests/unit/test_signal_regime_gate.py (7 unit tests).
Step 1 — Trace path (AS SHIPPED): _build_trading_signal() → conviction direction classification → volume gate (may reject) → get_market_cap_for_symbol + classify_market_cap → small_cap_short skip (no-op for LONG) → small_cap_long_above_80 skip (no-op unless Small+≥80 %) → [Rule #1 here] if direction == LONG: current_regime = self._safe_get_regime(); if current_regime == "downtrend": return (None, "long_downtrend") → callers (BMO/AMC loops, line 1606 / 2052) see reject=="long_downtrend" → _emit_pm_opportunity_log({skip_stage: "generate_signal", skip_reason: "long_downtrend", ...}) → no entry order placed.
Step 2 — Simulate (AS SHIPPED): at signal time on a Mon BMO trade for AAPL when SPY is in downtrend (per MarketRegimeProvider._classify reading SPY MA20/MA50/MA200): bot calls _build_trading_signal() → conviction 0.82 (LONG) → volume_total $5,000 (passes $1k gate, #311) → mcap=Large → small_cap_short skipped (LONG, not SHORT) → small_cap_long_above_80 skipped (Large, not Small) → Rule #1 fires: _safe_get_regime() returns "downtrend" → logger.info("...Queue Rule #1...") → return (None, "long_downtrend") → caller emits opportunity_log row with skip_reason="long_downtrend" → continue (no order).
Step 3 — Line numbers (AS SHIPPED, source as of May 28, 2026):
- Helper: src/earnings/signal_generator.py:_safe_get_regime (immediately after _regime_fields_for_log at line ~1067).
- Skip block: src/earnings/signal_generator.py:_build_trading_signal (after small_cap_long_above_80 check at line ~1213, before calculate_entry_exit_times at line ~1234).
- Tests: tests/unit/test_signal_regime_gate.py (new file, 7 tests).
Step 4 — Failure modes (AS HANDLED):
- _regime_provider is None (test mocking bypasses init, OR production instance built before regime was wired in) → _safe_get_regime() returns None → no skip (preserved current behavior). Covered by test test_long_with_no_regime_provider_is_not_skipped.
- provider.get_snapshot() raises → caught at DEBUG (mirrors _regime_fields_for_log pattern) → returns None → no skip. Covered by test test_long_when_regime_provider_raises_is_not_skipped.
- snap.regime == "unknown" (classifier can't determine state, e.g., insufficient SPY MA history) → does not equal "downtrend" → no skip. Covered by test test_long_with_unknown_regime_is_not_skipped.
- snap.regime == None → does not equal "downtrend" → no skip (same code path as "unknown").
- Stale regime cache (≤ 60s per MarketRegimeProvider _CACHE_TTL_SECONDS) → at most 60s drift between actual SPY state and classifier output → acceptable; the rule is statistical not deterministic.
- SHORT direction with downtrend regime → rule does NOT fire (LONG-only) → preserves the historical +$172/3-trade downtrend-SHORT bucket. Covered by test test_short_in_downtrend_is_not_skipped_by_rule1.
Step 5 — Acceptance test (AS RUN):
- ✅ pytest tests/unit/test_signal_regime_gate.py -v — 7/7 PASS (verified pre-commit on prod's Python 3.12 venv).
- ✅ Broader signal-test regression: pytest tests/unit/test_signal_volume_threshold.py tests/unit/test_signal_reliability_gate.py tests/unit/test_signal_regime_gate.py — 11/11 PASS.
- Live post-deploy: journalctl -u earnings-trader --since "1 hour ago" | grep -E "(Queue Rule #1|long_downtrend)" should match for any LONG signal generated when SPY is in downtrend. May be zero matches at current volume regime (1.9 % gate-pass) — that's expected; the rule's value is policy-locking, not fast live evidence.
- Live post-deploy SQL: SELECT skip_reason, COUNT(*) FROM polymarket_opportunity_log WHERE evaluated_at > NOW() - INTERVAL '7 days' GROUP BY skip_reason ORDER BY 2 DESC — long_downtrend should appear if any LONG signal generated when SPY in downtrend during the window.
File: src/earnings/signal_generator.py (~15 lines).
Step 1 — Trace path: _build_trading_signal() → after volume gate
→ fetch earnings_markets.stock_price_day_before_close for this
condition_id → fetch current quote (use _pre_signal_quote() helper)
→ compute drift_pct = (current − prior_close) / prior_close → if
direction == "LONG" and drift_pct ≥ 0.02, skip with
skip_reason="pre_event_drift_long".
Step 2 — Simulate: at 15:58 ET prior-trading-day for a BMO trade on WDAY when prior close was $250 and current is $258: drift_pct = +0.032, direction LONG → skip.
Step 3 — Line numbers: insertion point = after volume gate, before final signal construction.
Step 4 — Failure modes:
- stock_price_day_before_close is NULL on this market → CONTINUE
(don't skip; the resolver covers 713/715 past markets but new markets
may be NULL until the daily 06:00 ET resolver runs).
- Quote fetch fails → CONTINUE.
- Drift exceeds threshold but direction is SHORT → unchanged (rule only
applies to LONG).
Step 5 — Acceptance test:
- Mock earnings_markets.stock_price_day_before_close = 100, current
quote = 103, direction LONG → expect skip.
- Same with direction SHORT → expect signal generated.
File: src/earnings/signal_generator.py (~5 lines, extension of
existing 90 %+ LONG skip).
Implementation: Find the existing skip on conviction >= 0.90 and
direction == LONG. Add a parallel branch: conviction >= 0.80 and
direction == LONG and mcap_tier == "mid" → skip with
skip_reason="mid_long_conviction_80".
File: src/earnings/signal_generator.py (~5 lines).
Implementation: Replace existing "max 2 SHORTs per session" rule
with if direction == SHORT and regime != "downtrend": skip with
reason="short_non_downtrend".
Files (AS SHIPPED, #312): src/earnings/signal_generator.py
(_count_todays_stops() helper + skip block in _build_trading_signal after
Queue Rule #1) + src/earnings/session_stop_breaker.py (NEW pure-decision
module) + src/earnings/config.py (SESSION_STOP_BREAKER_ENABLED /
SESSION_STOP_BREAKER_THRESHOLD).
Implementation: In _build_trading_signal (just before final signal
construction), query SELECT count(*) FROM trade_audit_log WHERE
exit_reason ILIKE '%stop%' AND DATE(exit_time AT TIME ZONE 'America/New_York') = CURRENT_DATE AT TIME ZONE 'America/New_York'.
If ≥3, log skip_reason="session_3_stop_breaker" and skip.
⚠️ Note: use
exit_reason ILIKE '%stop%', NOT the brokenstop_triggeredboolean (Finding #233). The latter undercounts badly (~1.7 %) vs the real stop frequency — see the live dashboard / FINDINGS for the current figure.
See §4 for the retraction narrative. Briefly: 1.2× scale-UP arm fails ex-top-3 (the +$100 winner bucket collapses to −$1.58 across 17 trades after dropping STT/VZ/ALLY); direct multiplier modeling shows total per-100 lift is +$36 not +$60; operator dropped both arms. Re-test the scale-DOWN arm only at trade #150+.
AS-SHIPPED implementation differs from the original spec below. Pre-coding investigation (May 28 afternoon) caught a structural inconsistency in the original spec: it described a "soft gate / bookkeeping defer" approach that would deliver $0 EV (same failure mode as FA_soft retracted in Finding #228). The simulator's
simulate_window_only(scripts/analyze_finding_a_full.py:443) requires the hardware stop to actually be SILENT during the ±90min window. Operator chose Path (A) hardware cancel-and-rearm viaAskQuestion. Seedocs/FINDINGS.mdFinding #305 for the full as-shipped narrative.
Files (AS SHIPPED):
- src/earnings/ruleb_window_gate.py — NEW module with pure decision function decide_ruleb_action() + RuleBAction enum + RuleBDecisionContext dataclass + derive_earnings_release_dt() helper (~180 lines including comprehensive module docstring).
- src/earnings/trading_orchestrator.py — _process_ruleb_window_gate() dispatcher + _ruleb_fire_cancel() + _ruleb_fire_rearm() + _ruleb_log_once() helper (~220 lines including detailed comments).
- src/earnings/config.py — 4 new env vars: RULEB_ENABLED (default False), RULEB_MODE ('dry_run' / 'active', default 'dry_run'), RULEB_WINDOW_MINUTES (default 90, matches simulator), RULEB_HARD_FALLBACK_MIN_BEFORE_EXIT (default 30, safety boundary).
- tests/unit/test_ruleb_window_gate.py — 25 unit tests covering all 8 RuleBAction return values + sanity-gate skips + late-entry edge case + hard-fallback boundary.
Mechanism (AS SHIPPED — hardware cancel-and-rearm, NOT soft-gate):
- At t = release_dt - 90min: cancel hardware STP-LMT via IBKRClient.cancel_order(stop_order_id). Stop now silent.
- At t = release_dt + 90min: re-place hardware STP-LMT via order_executor._place_stop_order(symbol, shares, side, stop_price, primary_exchange). Stop restored.
- Hard fallback: if cancelled state persists past scheduled_exit - 30min, force re-place (catches stuck-cancelled-past-rearm edge case).
- State is derived per-cycle from (now, hardware_stop_active, release_dt, scheduled_exit, entry_time) — no DB persistence (memory.md "IBKR is source of truth"). On bot restart, state re-derives from current world.
Failure modes (all handled fail-soft):
- IBKR disconnected during cancel/rearm → log error + return; next cycle retries.
- Cancel returns False → log warning + retry next cycle (stop still active = position protected; only EV opportunity lost).
- Rearm fails → HIGH-severity Telegram alert + retry every cycle (position unprotected until success).
- Bot crash between cancel and rearm → on restart, derived state shows "no stop active + past rearm" → re-place fires next cycle.
- Restored position with signal=None (Phase 1 limitation) → graceful SKIP_NO_EARNINGS_DT with once-per-position warning log.
- Late entry (entry ≥ cancel_target) → graceful SKIP_LATE_ENTRY (stop runs naturally; rule doesn't apply).
Phase 1 → Phase 2 rollout:
- Phase 1 (this commit): RULEB_ENABLED=false (production default — operator must explicitly enable). When enabled, RULEB_MODE='dry_run' logs every cancel/rearm action it WOULD take, without IBKR side effects. Operator reviews dry-run logs for ~few days. Phase 2 (separate later session) flips RULEB_MODE='active'. Phase 2 ship is a pure config-flip commit (~1 LOC); may also include the restart-safe earnings_release_dt lookup if Phase 1 logs show that's needed in practice.
Acceptance test (AS RUN):
- ✅ pytest tests/unit/test_ruleb_window_gate.py -v → 25/25 PASS pre-commit on prod's Python 3.12 venv.
- ✅ Broader regression: pytest tests/unit/test_ruleb_window_gate.py tests/unit/test_signal_regime_gate.py tests/unit/test_signal_volume_threshold.py tests/unit/test_signal_reliability_gate.py → 36/36 PASS, no regressions.
- Live post-deploy: enable via RULEB_ENABLED=true env var; monitor journalctl -u earnings-trader | grep "RuleB\[" for dry-run "would CANCEL" / "would RE-PLACE" entries on the next BMO/AMC trade.
The text below was the original spec WRITTEN ON APR 25 before the as-shipped investigation. It describes a soft-gate approach that would deliver $0 EV. Preserved here only as a historical reference for future agents debugging the "why is the as-shipped implementation different from the spec?" question.
File (ORIGINAL SPEC): src/earnings/order_executor.py + EventBus stop-fill handler
(~25 lines).
Implementation (ORIGINAL SPEC — DO NOT IMPLEMENT): On the orderStatusEvent callback for a stop fill,
check (now - position.earnings_release_dt).total_seconds() if the
release timestamp is known. If abs() < 90 * 60, log "stop blocked:
in earnings ±90min window" and DO NOT act on the fill in the bot's
state machine (the broker has already filled — this is a bookkeeping
defer; the position is reconciled at the next scheduled exit attempt
using existing position_manager reconciliation).
Caveat (CORRECTED MAY 28): The original spec claimed "This is the same 'soft gate' pattern as Finding A. It works for RuleB but only because the ±90 min window is narrow enough that the broker's hardware fill + bot's reconciliation-after gives a similar outcome to 'no stop in window.'" This claim was wrong: the broker's hardware fill closes the position at the stop-fired price regardless of window narrowness. The bot's reconciliation doesn't change the trade's P&L. The Finding #228 FA_soft retraction proved this — FA_soft delivered $0 EV because the hardware stop fired anyway. The as-shipped Finding #305 implementation uses hardware cancel-and-rearm to match the simulator's actual mechanism.
Tracked from docs/STRATEGY_AUDIT_v3.md §9. Re-test after another ~50
closed trades.
| ID | Hypothesis | Needs |
|---|---|---|
| H6 | Spread-at-entry filter | Wire spread_at_entry capture in _build_trading_signal (NULL on 110/110 today) |
| H7 | Conviction stability across 5 pre-event snapshots | 100+ resolved markets with full snapshot coverage |
| H8 | Conviction-at-exit drop signal | Wire conviction_at_exit capture in position_manager.persist_position_close (NULL on 106/110) |
| H9 | Volume / depth quality at entry | Need 50 more trades with pm_*_depth_at_entry populated |
| H10 | Same-ticker prior-trade history | Need 20+ repeated tickers (only 5 today) |
| H12 | Sector concentration of losses | Add GICS sector lookup at entry time |
| H14 | EPS surprise magnitude → stock move | Could run now (210 markets have eps_actual); deferred to keep audit scope bounded |
| H19 | Pre-event after-hours move (BMO entries) | Need IBKR pre-mkt SPY quote at signal time |
| H23 | Earnings-detector latency cost | Need 30 more wrong-prediction trades (have 7) |
| H24 | PM post-event yes_price as instant-exit accelerator | Re-test if earnings_detector latency degrades |
Possible re-test later: H4 (day-of-week / Thursday alpha) — was rejected because Thu's +$209 was the GPRO/DELL/SWBI cluster again. Re-test once the 3-outlier dominance dilutes.
May 28, 2026 LATE evening update — Phase 3 simulator PR 1 COMPLETE. See
docs/PHASE_3_SIMULATOR_DESIGN.md§12 for the 5-PR ship plan. Today's session shipped all 5 PR-1 commits:
Commit Finding Description 919c566#307 snapshot_schema='pm_v2' conditional-label fix (closes original Finding #273 Phase 1) de0d28e#308 Bug #6 hyp_pnl re-run + structural-ceiling discovery (deadband-conviction rows are un-simulatable) 615befa#306.a Phase 3 simulator foundation skeleton ( scripts/phase3_simulator/package + Trade/load_trades duplicated per Q1 HYBRID + RuleSet dataclasses + CLI stub)06cae0b#306.b cost_model.py (proxy-flat-1pct per Q2) + replay.py + reference_adapter.py + cross_check_baseline.py (operator-runnable §10.1 acceptance script) 62cb607#306.c gauntlet.py (5 checks per memory §K) + output.py (deterministic JSON schema) + runner.py --run-gauntlet + H-rule self-validation + reproducibility test All 4 PR 1 acceptance gates PASS (verified on prod): - §10.1 cross-check vs
analyze_finding_a_full.py: 100% match within $1 on all 7 rules (A_base/FA_soft/FA_hard/RuleB/RuleD/RuleG/RuleF), max drift $0.00 across 121 trades. - §10.2 reproducibility: 2 back-to-back runs ofrunner.py --run-gauntletproduced byte-identical JSON output (after maskinggenerated_at). - §10.3 H-rule self-validation: synthetic v2 H-rule shape returns FAIL-EX-TOP-2 pertest_h_rule_synthetic_returns_fail_ex_top_2(would emit DO-NOT-SHIP-PR-2 diagnostic if it ever flipped to PASS). - Phase 0 §0.6 Gate 1/4: corrected per #308 — thesignal_emitted100% subset is sufficient; ~69%/~28% on generate_signal/depth is structural deadband-conviction ceiling, not a coverage gap.Live gauntlet on prod (
runner.py --run-gauntlet --limit 200): RuleB verdict PASS, n=121, per-100 $+90.74 (headline) / $+39.93 (ex-top-2), ship recommendation SHIP. (Numbers are variant-vs-A_base-replay deltas; reference simulator's narrative numbers were variant-vs-LIVE deltas — both correct, see §1 verdict banner.) 🛑 SUPERSEDED Jul 5, 2026 (Finding #330): this PASS/SHIP was an artifact of the pre-#330 gap-fill optimism insimulate_window_only; gap-aware RuleB is FAILED-GAUNTLET (−$194/100 ex-top-2, n=129). Kept for traceability — the §10.1 cross-check itself remains valid (both sides used the same pre-#330 rule math).PR 2 — Volume-gate retune sweep — ✅ DONE;
gate_uniform_$1000SHIPPED (Finding #311, May 30). (Was "begins next session" — highest-leverage per May-28 PM volume-collapse evidence.) Addedgate_variants.py($2k → $1k → $500 → $250 → $100 → $0 sweep) +replay.pyextension for counterfactual admission onskip_reason='low_volume'rows + firstphase3_sim_gate_retunedashboard section instrategy_performance_analysis.py+ operator AskQuestion ship decisions per variant.
✅ May 31, 2026 status — PR 1-5 ALL COMPLETE + Phase 4 dashboard consolidation COMPLETE (#306-#322). (May 28 status, kept for context: PR 1 complete — foundation + replay + cost-model + cross-check + gauntlet + H-rule self-validation + reproducibility + JSON output across 5 commits — see §1 verdict banner.) Final outcomes of the PR 2-5 sequence per
docs/PHASE_3_SIMULATOR_DESIGN.md§12: - PR 2 — Volume-gate retune sweep — ✅ DONE; SHIPPEDgate_uniform_$1000(#311).gate_variants.pydeclarative thresholds +replay.pycounterfactual-admission extension forskip_reason='low_volume'rows + firstphase3_sim_gate_retunedashboard section. HIGHEST-LEVERAGE per May-28 PM volume-collapse evidence (Jan→May avg cumulative volume dropped ~109×; the then-$2k-gate pass rate had collapsed to 1.9%). Closed the volume-gate retune sub-item of thesizing-priority-v2row below. - PR 3 — Sizing + priority + exposure-cap variants — ✅ DONE.sizing_policies.pymcap-tier-pct sweep + tier-collapse + per-direction SKIP rule revalidation + position×regime interaction +capital_simulator.pyfor realistic overlapping-position capital reservation. Outcomes: priority 0-6→0-8 SHIPPED (#313); sizing 30/22/15 KEEP (#314.c — the then-live tiers, since superseded by #314.f/#366); per-cell SKIP rules analysis-only (#314.e); exposure cap — rare/normal/busy collapsed to a single uniform 140% cap (#317 SHIPPED, after #316 showed the rare discount near-inert). Closed the rest of thesizing-priority-v2row. - PR 4 — Regime classifier v2 candidates — ✅ DONE; KEEPcompound_v1(#318).regime_classifiers.pybaseline compound_v1 + EMA20 + MA50 + drawdown OR clause (VIX-term-structure / breadth / credit / FCI remain deferred to Phase 4 nice-to-have). Closed theregime-detection-v2row below. - PR 5 — Depth-gate v2 decomposition — ✅ DONE; KEEP gate (#319).depth_gate_variants.pydecomposed spread_gate + depth_gate variants + threshold sweep. Closed the depth-gate v2 row below.Each PR: ship code + integrate to runner.py + add
phase3_sim_*dashboard section + run on prod + operator AskQuestion ship decision per variant before any production rule change.Original framing (Apr 28, 2026 — kept for context): the bundle items were parked because doing them before the Phase 3 simulator landed would conflate rule-effects with infrastructure-effects and retroactively shrink the live-evidence buckets the rules are sized on. Mirror in dashboard 🎯 Action Queue under
status=DEFERRED-POST-PHASE-3(build_action_queue()entriesregime-detection-v2+sizing-priority-v2); these have now all flipped to CLOSED/IMPLEMENTED as PR 2-5 shipped (#311-#319) per design doc §12.
| Item | Canonical | Why deferred | Re-test trigger |
|---|---|---|---|
Market regime detection v2 — ✅ CLOSED May 31, 2026 (PR 4, Finding #318) — KEEP compound_v1 (no classifier swap). Built the 6-classifier sweep (scripts/phase3_simulator/regime_classifiers.py + replay_regime_v2.py) + ran on prod (568-signal universe, both universes). The fastest detector below_ema20 gains +$70.31 PASS on live-only but −$17.02 FAIL-EX-TOP-2 on the capacity-aware universe at the live 1.40 cap — the live-only win is selection luck that doesn't generalize (#315 "don't look in isolation"); it whipsaws ~40% of LONGs (vs compound's 17%). compound_or_dd5 (#278 option B) + below_ma50 inert; dd_3pct + compound_symmetric FAIL. Faster detection's only durable benefit is a better worst-week tail (5p −$98.60→−$57.08) at ~breakeven P&L — a downside trade-off, not a money-maker; Rule #1 optimizes for ROI → operator-confirmed KEEP. Methodology validated: PIT compound_v1 reproduces the live recorded regime 95.3%. VIX-term-structure / breadth / credit / FCI remain deferred to Phase 4 nice-to-have (design §15-Q5). Production market_regime_provider.py UNCHANGED. — current MarketRegimeProvider compound rule lags by median 31 trading days from SPY peak (vs 8d for close < EMA20, 12d for close < MA50, 28d for 5%-drawdown filter). Empirical lag table in scripts/analyze_regime_detection_lag.py output. Asymmetry to address: downtrend rule does NOT require close < MA200 (uptrend does). Industry-consensus faster alternatives: SMA→EMA, drawdown OR clause, VIX term structure (most-watched leading vol-regime indicator on institutional vol desks), breadth indicators, credit spreads, FCI composites. |
docs/FINDINGS.md Finding #278 |
Action Queue rule #1 was sized on 22 historical downtrend-LONG trades identified by exactly this lagging classifier. Switching detectors retroactively re-classifies those trades and may shrink the bucket below the n≥12 gauntlet floor (memory §K). Lag is opportunity-cost not damage-cost. | (1) Phase 3 simulator shipped. (2) Rule #1 live ≥30 trades AND lift within ±$30 of estimate. (3) THEN: build v2 candidate (likely compound OR dd_5pct OR (VIX>VIX3M for ≥3d)), re-run Action Queue analysis with v2 labels, apply 4-check gauntlet to every regime-using rule, ship only if ≥+30% improvement and survives gauntlet. |
Position sizing + priority tier system v2 + exposure-cap re-evaluation + $2k volume-gate retune (Finding #285 Phase B; May 28, 2026 — gate-retune scope folded in via the PM volume collapse evidence amendment) — 🟢 PARTIAL PROGRESS May 30-31, 2026: (a) volume-gate retune SHIPPED $2k→$1k (Finding #311); (b) priority-tier-v2 SHIPPED — base 0-6 re-validated on live data + extended to 0-8 with volume bump (Finding #313); (c) sizing v2 EVALUATED — lowering FAILS the gauntlet, but at the LIVE 1.40 cap (Finding #315) RAISING/concentrating (flat 25/25/25 +$4.18/wk, 35/25/18 +$4.63/wk) is gauntlet-PASS → ship-eligible candidate (Finding #314.c); (d) per-cell SKIP rules EVALUATED — 2 individual + combined gauntlet-PASS, ship deferred to operator + 30-trade monitoring (Finding #314.e). (e) exposure-cap re-evaluation DONE — gross cap KEEP 1.40 (#315; MAX_TOTAL_EXPOSURE_PCT was unwired, re-aligned 2.0→1.40) + daily tiering SIMPLIFIED to a single uniform 140% cap (#317 SHIPPED — collapsed rare/normal/busy after #316 showed the rare 60% discount was near-inert; "more opportunities ≠ more ROI" — the ROI lever is concentration not looser caps). REMAINING (deferred to after PR 4 per operator): SHORT-side ≤10%-conviction bucket validation + regime-conditioned sizing + position×regime interaction. — current POSITION_SIZE_PCT_LARGE=0.30 / MID=0.22 / SMALL=0.15 (config.py:141-143) and the priority tier system (priority.py, now 0-8 post #313) were set Mar 9, 2026 against a smaller dataset and a smaller capital base. Today's data (~117 closed trades, +$212 net per the May-28→31 refresh, stops are biggest leak) shows: Mid LONG 80-90% has 52% stop rate, Mid LONG 90-95% has 87% stop rate (the worst losers); LONG 95%+ universe-bucket is +$192/trade but currently SKIPPED (Finding #202); SHORT ≤ 10% bucket is also SKIPPED via symmetric application of #202 even though it was never validated on SHORTs (added May 6, 2026 — operator caught on COIN); the 0-6 tier system has dead values (tier 1 unused; tier 2 has n<5 production data) (DONE — base 0-6 re-validated + extended to 0-8 with volume bump, #313); Finding #218 quintile data exists but informs no rule. Sizing-by-mcap-tier currently treats different EV regimes as identical. May 9, 2026 (Finding #285 Phase B): the daily-opportunity rare/normal/busy exposure cap (risk_manager.OPPORTUNITY_EXPOSURE_LIMITS: 60% on rare days vs 140% normal/busy) needs re-evaluation (DONE — collapsed to a single uniform 140% cap, #317; #316 showed the rare 60% discount near-inert) — operator pushback May 7: "most days become rare days as our bottleneck is not no of markets is no of markets with volume above $2k usd that qualify as per our rules". Phase A (greedy-fill + opportunity_log emission) shipped May 9 — Phase B re-evaluation now bundled here. May 28, 2026 amendment (PM volume collapse evidence — was the chat-only "Finding #298 candidate", folded into #279 Phase B per operator AskQuestion option B): Jan→May earnings-market average cumulative volume dropped ~109× ($33,475 → $306), median ~1,847× ($24,730 → $13.39), $2k-gate pass rate 52× collapse (100.0 % → 1.9 % = 3 of 154 May markets). NO Mid-cap market crossed the gate in all of May (0/74); Small 1/59 (AMPL); Large 2/21 (NVDA + LOW). 21-day entry drought May 6 → May 27 (id=162 MCD → id=163 HPQ; HPQ only crossed via Finding #282 Gamma-cumulative fallback). Phase B must now also re-evaluate the $2k SIGNAL_MIN_VOLUME_TOTAL gate itself as a candidate retune (memory §K + §N: TRUE-simulator pass required before any threshold change — counterfactual P&L on currently-skipped markets at e.g. $1k / $500 / $250 / $0) (DONE — shipped uniform $1k, #311). Full evidence + per-month / per-mcap tables: docs/FINDINGS.md Finding #279 "Phase B framing premise — PM earnings-market volume collapse" subsection. |
docs/FINDINGS.md Finding #279 |
Action Queue selection rules #1 + #2 directly change which trades get sized and stopped. Their live impact must be measured at the CURRENT sizing first, otherwise we conflate rule-effect with sizing-effect. Phase 3 simulator (with equity_bars_1m from Finding #240) is needed to replay sizing-policy variants on the same trade history under realistic execution costs. SHORT-side specifically: zero historical SHORTs at conviction ≤ 10% means we have no live evidence for or against the symmetric skip. Volume-gate retune (May 28 amendment) requires the same simulator-first discipline — lowering $2k unilaterally is the NO-SHORTCUTS rule #9 antipattern. |
(1) Phase 3 simulator shipped. (2) Rule #1 + RuleB live ≥30 trades each, lift within ±$30 of estimate. (3) Trade #150+ audit gauntlet pass run. (4) THEN: comprehensive re-evaluation under unified simulator with (a) current sizing as baseline, (b) flat-equal sizing as null, (c) 4+ candidate redistributions; apply gauntlet to each; tighten/relax SKIP rules from #202/#207 against fresh data with explicit LONG vs SHORT separation (LONG ≥90% bucket vs SHORT ≤10% bucket = different mechanisms); re-evaluate POSITION_SIZE_FLEX_MAX (#74) against larger capital; explicit position×regime interaction. NEW (May 28): add SIGNAL_MIN_VOLUME_TOTAL retune sweep to the simulator's candidate-variant set; candidate threshold range $250 → $2,000 by half-decades; gauntlet each variant; report ex-top-5-outlier numbers per memory §K. Operator-decision required between simulator output and ship. |
Polymarket depth-quality gate v2 (decompose + re-tune) — ✅ CLOSED May 31, 2026 (PR 5, Finding #319) — KEEP gate. Widened reconstruction (n=22 binding kills vs ~4 logged; replayed the real conviction code over the full 915-market universe) answered "has it ever saved us from a bad trade?" → YES: 13 losers blocked (−$142.56), 9 winners killed (+$165.09), net removal +$22.54 over ~7 months (≈ noise). Mostly a snapshot_reliability filter (18/22: hollow book → sparse/unstable price-snapshot conviction), not the pure spread gate this row implied. Removal/carve-out adds variance for ~$0 EV → operator-confirmed KEEP. This was the LAST deferred-bundle item → Phase 3 simulator PR 1-5 COMPLETE. — current _calculate_depth_quality in conviction_calculator.py:588-628 collapses to a binary 0.30 (fail) / 0.75 (pass) in production; threshold 0.50 → hard skip at signal_generator.py:1568. 37 of 38 historical depth-skips were spread-dominated (bait orders at 1¢/99¢) — gate name is misleading (renamed WIDE SPREAD on dashboard Apr 30). 92% of kills (35/38) had conviction = 0.500 default → would have been skipped at conviction gate anyway → gate is redundant for those. Only 3 historical kills were real signals; 1 (ICE Apr 28 LONG 89.9%) had counterfactual P&L +$158.22; 1 (MPC Apr 29 LONG 74.5%) had counterfactual $0.00; 1 (MRNA today SHORT 18.5%, $4,210 cumulative volume) is the next pending kill. |
docs/FINDINGS.md Finding #283 |
Sample size of real-signal kills (n=3) is well below 4-check bias-gauntlet floor (n≥12, ideally ≥20) per memory §K. Cannot ship a gate-tuning rule change based on this evidence. Phase 3 unified simulator + counterfactual P&L on a wider universe of skipped depth-gate cases is needed to know whether the gate is helping or hurting. UX badge rename done now (Apr 30); behavior unchanged. | (1) Phase 3 simulator shipped. (2) ≥10 additional depth-skipped opportunities have computed counterfactual P&L (currently 2). (3) THEN: decompose the gate into min_depth_gate + spread_gate (named separately, tunable independently); evaluate "skip the gate when conviction is from last_trade_price / price_snapshots" hypothesis; re-tune the 0.50 threshold under counterfactual evidence; apply 4-check gauntlet; ship only if v2 candidate shows ≥+30% improvement on the gauntlet. |
Saved artifacts (per memory §J/§K/§N — both items have:
canonical Finding in docs/FINDINGS.md, forward entry here, AGENT_HANDOFF
§11 DEFER bullet, programmatic Action Queue row in
build_action_queue(), and dashboard render under
DEFERRED-POST-PHASE-3 status filter). Re-runnable analysis script for
the regime item is committed at scripts/analyze_regime_detection_lag.py.
| Script | Purpose | Output |
|---|---|---|
scripts/phase3_simulator/runner.py |
NEW May 28, 2026 (Finding #306.a/b/c) — Phase 3 unified simulator CLI. Loads trades + baseline RuleSet, optionally runs the baseline replay + 5-check bias gauntlet + emits deterministic JSON. Variant sweeps (volume-gate / sizing / regime / depth) land in PR 2+. | stdout + scripts/phase3_simulator_results.json (with --run-gauntlet) |
scripts/phase3_simulator/cross_check_baseline.py |
NEW May 28, 2026 (Finding #306.b) — design doc §10.1 acceptance gate. Load N trades, run replay_population, INNER JOIN against scripts/finding_a_full.csv, per-rule drift breakdown, PASS if match_pct >= 95% within $1 on every rule. |
stdout + scripts/phase3_simulator_baseline_cross_check.json |
scripts/strategy_performance_analysis.py |
Master report generator. Includes Finding-A simulator results, audit v3 status table, bias gauntlet doc, + phase3_simulator_status section (May 28, 2026). | scripts/strategy_analysis_report.json (consumed by dashboard Strategy Analysis tab) |
scripts/analyze_finding_a_full.py |
Comprehensive Finding-A counterfactual simulator. Read-only. Re-run before any future stop-loss rule proposal. Stop-loss math is the reference that Phase 3 simulator's reference_adapter delegates to per Q1 HYBRID (May 28, 2026, Finding #306.a). | scripts/finding_a_full.csv (121 rows × 41 cols as of May 28 prod regen) + stdout aggregate |
scripts/analyze_stop_counterfactual.py |
Original v3 Rule B/C/D/E/F/G/H simulator (kept for reference; superseded by analyze_finding_a_full.py). |
scripts/stop_counterfactual.csv |
scripts/analyze_atr_prescreen.py |
The script that killed the v2 H-rule. | scripts/atr_prescreen.csv |
scripts/analyze_regime_detection_lag.py |
Read-only baseline (Apr 28, 2026 — Finding #278). Replays MarketRegimeProvider._classify over SPY 2018-2026 and measures lag from peak to first downtrend flip vs faster alternatives (EMA20, MA50, drawdown filters). Will be consumed by Phase 3 simulator PR 4 (regime classifier v2 sweeps). |
stdout table + aggregate medians |
scripts/backfill_learning_loop.py |
Resolver backfill across earnings_markets / skipped_signals / opportunity_log. | DB writes |
scripts/backfill_regime_for_audit_log.py |
Regime/VIX backfill on closed trades. | DB writes |
| Doc | Purpose |
|---|---|
docs/PHASE_3_SIMULATOR_DESIGN.md |
Phase 3 unified simulator design (May 28, 2026) — concrete architecture, 5-PR ship plan, module layout, interface contracts, bias-gauntlet spec, Finding #273 lockstep, validation strategy, risk analysis, 8 open operator-decision points. Companion to STRATEGY_ANALYSIS_ARCHITECTURE.md Phase 0 baseline (Apr 26, 2026). |
docs/FINDINGS.md |
Canonical narrative for every finding (per memory §J). Finding #228 = Apr 25 retraction; Finding #227 = learning-loop infrastructure. |
docs/STRATEGY_AUDIT_v3.md |
v3 audit trail. §10 (Apr 25) = retraction with simulator data. §6 = audit-process learnings (now includes lesson #6 from Finding #228). |
docs/STRATEGY_PLAYBOOK.md |
This file. Forward-looking source of truth. |
docs/AGENT_HANDOFF.md §11 |
Outstanding-work table re-ranked Apr 25. |
docs/STRATEGY.md |
Long-form strategy rules (entry/exit timing, sizing, stops, exchanges). |
docs/OPERATIONS.md |
Server / service runbook. |
.cursor/memory.md |
Mandatory checklist (§A–§M). §K = strategy analysis consolidation rule. |
| Tab | Section | Source data |
|---|---|---|
| 📈 Strategy Analysis | 🛡️ Bias Gauntlet (mandatory reminder) | analysis.bias_gauntlet |
| 📈 Strategy Analysis | 📋 Audit v3 Status & Action Queue | analysis.audit_v3_status |
| 📈 Strategy Analysis | 🔬 Finding-A Simulator (Apr 25) | analysis.finding_a_simulator (loads scripts/finding_a_full.csv) |
| 📈 Strategy Analysis | 🔁 Learning Loop (Finding #227) | analysis.skipped_signal_cost, volume_gate_counterfactual, regime_vix_performance |
| 📈 Strategy Analysis | (existing) Direction × Timing, Stop Loss, Stop Reversal, etc. | (unchanged) |
URL: http://[hidden]:8080/#strategy
This playbook is the authoritative forward-looking reference. Update it when a rule ships (move from §2 queue → §3 verified), when a rule fails (move to §4 retracted), or when a deferred question becomes testable (move from §7 to §3 if validated).