Status: SPEC — not built. Awaiting approval before any code changes. Author: Hermes (2026-08-22) Applies to: ~/projects/algoTraderBot (supervisor.py + a new edge_monitor.py)
The strategy's realized edge is not constant. Same config, same grader:
| Period | Win rate | avg R | sum R |
|---|---|---|---|
| Apr–Jul 2026 (backtest, all 5 sym) | 68.4% | +1.50R | +374.8R |
| Aug 2026 (backtest, same window) | 29.0% | −0.04R | −1.3R |
The bot went live in the 29% month and bled the whole eval (−$2,609). Three existing defenses all failed to stop it:
- Trailing-DD breaker ($1,400) — already blown before it could matter.
- Daily-loss breaker ($400) — too coarse: allows ~$400/day of bleed, resets each ET day, so a sustained weak period just leaks ~$400/day forever.
- Regime gate (calm/trending/panic) — TESTED AND REFUTED (2026-08-22): EMA edge is 68.5% in "calm" and 63.8% in "trending" — no collapse. The regime model does not see the August decay.
The collapse is temporal, not regime-based. Nothing currently watches the bot's own realized performance and pulls back when it degrades. That is the gap.
Point-in-time only. The gate looks at the bot's own completed trades and own signal log — never future data, never the inflated backtest as its expectation. It answers one question every time a trade closes:
"Is my recent realized edge statistically gone — am I losing money now?"
If yes → de-risk, then halt. If it recovers → resume.
Pre-registered, set from the bot's OWN long-run measurements, NOT the 68%:
- B_breakeven = 0.0R — the hard halt line (losing money).
- B_healthy = +0.50R mean / 47% WR — the doctrine's "selected engine" long-run (the 5-year measurement). Used only for the de-risk tier, not the halt.
- Reference: the honest verified OOS edge is PF ~1.12–1.18 ≈ 36% WR ≈ +0.1R (trading-edge-validation reference). The 68% April–July number is a good-month artifact and is explicitly NOT used as a target or baseline.
Tracks the clear-rate: fraction of signals with proba ≥ PROBA_FLOOR (0.35) over a trailing 3-ET-day window (or last 50 signals, whichever is larger).
- Rationale: the grader itself flags a low-edge market before losses accumulate. In August the clear-rate was 6% (29 of 481 signals) — the grader was already saying "this market is junk."
- Watch trigger: clear-rate < 50% of the measured normal baseline → half size
- raise floor +0.05, log + alert.
- The "normal baseline" clear-rate is measured during validation from the April–July signal history (not assumed). Pre-registered estimate ~25–35%.
Rolling window of the last N = 15 closed trades' R-multiples.
- Bootstrap: 10,000 draws, seed 42, resample with replacement.
- One-sided p-value:
P(meanR < 0)andP(meanR < B_healthy). - Watch trigger:
P(meanR < +0.50R) > 0.70→ half size. - Halt trigger:
P(meanR < 0) > 0.90OR (WR < 30%ANDmeanR < 0) → halt. (2R:1R breakeven WR = 33.3%, so 30% WR with negative mean R is "clearly losing.")
- Normal — edge healthy → full size, current floor.
- Watch (either tier trips) → half size, floor +0.05, log + alert.
- Halt (Tier 2 trips) → no new entries; close nothing (positions are managed to their own stops/targets as usual — never panic-close a live position).
- Halt = a fixed pause (COOLDOWN_H = 24h), then auto-resume to test recovery. The window is cleared on halt; the bot trades again after the cooldown and the fresh window is judged normally (re-halts if still losing).
- This replaced the original "resume only when a fresh window recovers" rule, which was wrong twice: (1) in enforce mode no trades close while halted, so a fresh window can never form → deadlock; (2) it blocks the recovery leg of a V-shaped month (Aug 2026 lost the first week then recovered — a sticky halt locks in the dip and misses the +7R recovery).
| Parameter | Value |
|---|---|
| Window N | 15 closed trades |
| Bootstrap draws / seed | 10,000 / 42 |
| Watch threshold (Tier 2) | P(meanR < +0.50R) > 0.70 |
| Halt threshold (Tier 2) | P(meanR < 0) > 0.90, or WR<30% & meanR<0 |
| Tier 1 clear-rate watch | < 50% of measured normal baseline |
| Resume | fresh window meanR ≥ 0 & WR ≥ 35%, ≥1 ET day cooldown |
These are fixed now. If validation fails, we return to this spec and change the SPEC — we do NOT tune the thresholds until the historical replay passes.
Replay the gate over the full history (backtest CSVs, Apr–Aug 2026, all 5 symbols) trade-by-trade, in time order, applying the gate's decisions only to trades it would have seen at that point.
Success criteria (pre-registered):
- Gate does NOT worsen August (with-gate P&L >= without-gate).
- April–July profit retained ≥ 90% (vs +374.8R).
- ≤ 2 false halts in April–July.
RESULT (2026-08-22, after the auto-resume correction): PASS all three.
- August: without gate −1.27R → with gate +3.73R (gate effect +5.00R).
- April–July retained: 100% (0 false halts).
- 1 halt total (Aug 13, during the losing streak), correctly auto-resumed. Note: with the ORIGINAL sticky-halt rule the gate FAILED (August −4.98R vs −1.27R — it blocked the recovery leg of the V-shaped month). The auto-resume fix was the difference; this is a semantic correction, not a threshold tune.
- Evolver (evolve.py): the edge-monitor is a coarser, faster cousin. When the monitor halts, the evolver freezes (no floor changes while halted). No conflict.
- Breakers (daily $400, trailing DD $1,400): unchanged — per-day layer.
- Profit target ($500/25h): unchanged.
- Regime gate (panic): unchanged — it's not the fix, but it's harmless.
- Veto LLM: unchanged — the monitor gates after signal+veto, by pulling exposure, never by overriding an individual trade's veto.
- New file
edge_monitor.py+ a hook insupervisor.pycalled on everyon_trade_closeand on each new signal (for Tier 1 clear-rate). State persists to~/.autotrade_edge_monitor.json(restart-safe). Advisory-first rollout:AUTOTRADE_EDGE_MONITOR=advisory(log + alert only) → validate live → then=enforce.
- NOT re-tuning the grader, floor, or veto to "fix" August (the skipped trades genuinely lost −60R; the grader was right).
- NOT using the 68% backtest as the baseline or target.
- NOT claiming this raises the win rate. It only stops the bleeding in 29%-months.
- NOT panic-closing open positions on a halt signal.
Approve to build? Options:
- Build now (write edge_monitor.py + supervisor hook, advisory-first, run the validation replay, report the three success criteria).
- Adjust thresholds first (tell me which numbers to change).
- Paper-only — validate on the paper book before wiring to the live eval.