Datum: 2026-06-05 Modus: PLAN-ONLY · 0× Code · 0× Push · 0× Orders · 0× Runtime-Apply Trigger: 180-d-Replay (MS-STRATEGY-REPLAY-20COIN-BACKTEST-1) zeigt RANGE +26 %, WEAK_TREND −30 %, BULL_STRONG −9 % Heutiger XLM-SL-Loss (−11.17 USDT in BEAR-Regime) ist ein Live-Beispiel des nicht-regulierten Risikos
Per-Regime-Verhalten der MS-Pipeline einführen, um die paradoxe Eigenschaft („trend_follow funktioniert nur in RANGE, verliert in Trends") strukturell zu reparieren — ohne Coin-Allowlist/Denylist, ohne Exit-Parameter-Touch.
Drei Phasen: - P1.A — Shadow-Logger (log-only) - P1.B — Hard-Gate (erst nach 2-4 Wochen Shadow-Daten) - P1.C — Per-Regime-Params (optional, nach P1.B-Pilot stabil)
Diese Plan-Phase deckt P1.A ab und bereitet die Regeln für P1.B vor.
Im Bot existieren bereits:
- MarketRegime Detector (5 Labels: STRONG_TREND, WEAK_TREND, RANGE, HIGH_VOLATILITY, CHOP)
- StrategyRouter Hard-Blocks (CHOP + HIGH_VOL ohne base bereits blockiert)
- Per-Regime-Strategy-Activation (STRONG_TREND→trend_follow, WEAK_TREND→breakout+trend+oversold, RANGE→mean+vwap+vol_sweep+oversold)
- Decision-Log Regime im decision_logs
→ Regime-Detection ist bereits vollständig. Was fehlt ist die regime-spezifische Edge-Filter-Schicht zwischen Router und Final-Decision.
| Regime | N | WR | Exp % | Total Net % | Verdict |
|---|---|---|---|---|---|
| STRONG_TREND | 23 | 35 % | −0.37 | −9 | TOXISCH |
| WEAK_TREND | 207 | 43 % | −0.15 | −30 | HOCH-TOXISCH |
| RANGE | 261 | 48 % | +0.10 | +26 | EDGE positiv |
| HIGH_VOLATILITY | klein | – | – | – | gedämpft via Router |
| CHOP | 0 | – | – | – | bereits blockiert |
Kern-Befund: Die MS-trend_follow-Strategie ist eigentlich ein RANGE-Breakout-Detektor.
| Changed Area | Direct Effect | Downstream | Follow-up |
|---|---|---|---|
multi_strategy_runner.py |
neue _compute_regime_gate_shadow() |
nur MS-Runner | Tests |
multi_strategy_runner.py |
metadata regime_gate |
decision_logs, JSONL | KEIN DB-Migration |
settings.py |
6 neue Settings | nur MS-Runner | safe Defaults |
position_manager.py, live_trade.py, trader_core.py |
0 | – | – |
| Strategy-Subklassen, Router, MarketRegime | 0 | – | – |
Mainnet/MS-Live: unverändert.
| Bot-Regime | base_regime | Class | Default Action |
|---|---|---|---|
| RANGE | – | range_safe | ALLOW |
| WEAK_TREND | – | weak_trend_toxic | HARD_REJECT (P1.B) |
| STRONG_TREND | – | strong_trend_caution | SOFT_REJECT (P1.B) |
| HIGH_VOL | RANGE | high_vol_range_caution | ALLOW |
| HIGH_VOL | trend | high_vol_trend_toxic | HARD_REJECT |
| CHOP | – | chop | bereits durch Router |
| Mode | Toxic | Caution | Safe |
|---|---|---|---|
| shadow (Default) | log, allow | log, allow | allow |
| soft | reject mit score-Penalty | reject mit score-Penalty | allow |
| hard | reject | reject (low conf) | allow |
MS_REGIME_GATE_ENABLED: bool = os.getenv('MS_REGIME_GATE_ENABLED', 'true').lower()=='true'
MS_REGIME_GATE_MODE: str = os.getenv('MS_REGIME_GATE_MODE', 'shadow')
MS_REGIME_GATE_BLOCK_WEAK_TREND: bool = os.getenv('MS_REGIME_GATE_BLOCK_WEAK_TREND', 'true').lower()=='true'
MS_REGIME_GATE_BLOCK_STRONG_TREND: bool = os.getenv('MS_REGIME_GATE_BLOCK_STRONG_TREND', 'false').lower()=='true'
MS_REGIME_GATE_BLOCK_HIGH_VOL_TREND:bool = os.getenv('MS_REGIME_GATE_BLOCK_HIGH_VOL_TREND', 'true').lower()=='true'
MS_REGIME_GATE_SOFT_SCORE_PENALTY: float = float(os.getenv('MS_REGIME_GATE_SOFT_SCORE_PENALTY', '1.5'))
Cutover-Default: enabled=true, mode=shadow (log-only).
multi_strategy_runner._compute_regime_gate_shadow(regime, decision)def _compute_regime_gate_shadow(self, regime, decision):
s = self.settings
if not s.MS_REGIME_GATE_ENABLED: return {'enabled': False}
rg = regime.get('regime'); bg = regime.get('base_regime')
if rg == 'RANGE': cls = 'range_safe'
elif rg == 'WEAK_TREND':
cls = 'weak_trend_toxic' if s.MS_REGIME_GATE_BLOCK_WEAK_TREND else 'weak_trend_caution'
elif rg == 'STRONG_TREND':
cls = 'strong_trend_toxic' if s.MS_REGIME_GATE_BLOCK_STRONG_TREND else 'strong_trend_caution'
elif rg == 'HIGH_VOLATILITY' and bg == 'RANGE':
cls = 'high_vol_range_caution'
elif rg == 'HIGH_VOLATILITY':
cls = 'high_vol_trend_toxic' if s.MS_REGIME_GATE_BLOCK_HIGH_VOL_TREND else 'high_vol_trend_caution'
else: cls = 'unknown_pass_through'
mode = s.MS_REGIME_GATE_MODE
if cls.endswith('_toxic'):
action = 'hard_reject' if mode=='hard' else ('soft_reject' if mode=='soft' else 'allow')
elif cls.endswith('_caution'):
action = 'soft_reject' if mode in ('soft','hard') else 'allow'
else: action = 'allow'
return {'enabled': True, 'regime': rg, 'base_regime': bg,
'regime_confidence': regime.get('confidence'),
'regime_class': cls, 'gate_mode': mode, 'gate_action': action,
'gate_reason': f"{cls}_in_{mode}_mode",
'would_have_blocked': action != 'allow'}
_evaluate_symbolregime_gate = self._compute_regime_gate_shadow(regime, decision)
if regime_gate.get('enabled') and regime_gate.get('gate_mode') != 'shadow':
if regime_gate['gate_action'] == 'hard_reject':
decision = build_REJECT(..., reject_reason='regime_gate_hard', metadata={..., 'regime_gate': regime_gate})
elif regime_gate['gate_action'] == 'soft_reject' and decision['decision'] == DECISION_TRADE_CANDIDATE:
new_score = (decision.get('final_score') or 0) - self.settings.MS_REGIME_GATE_SOFT_SCORE_PENALTY
if new_score < (decision.get('threshold') or 7.0):
decision = build_REJECT(..., reject_reason='regime_gate_soft', ...)
_log_decision JSONL und emit_decision metadata bekommen regime_gate-Key.
1-20: shadow/soft/hard × RANGE/WEAK/STRONG/HIGH_VOL × allow/reject/penalty + Kill-Switch + JSONL/DB-meta
Regression-Sweep: phase_n7/n8, ms_mtf, ms_dedup, ms_stablecoin, recon-1, sync_sanity, exit_reason_fix → ~250 grün.
| Item | Bleibt |
|---|---|
| MULTI_STRATEGY_DRY_RUN | true |
| Protected-Toolkit (BE/Partial/Trailing) | unverändert |
| 4h Hold | unverändert |
| Router Hard-Blocks (CHOP/HIGH_VOL ohne base) | unverändert |
| MarketRegime Detector | unverändert |
_is_4h_confirming |
unverändert |
| Strategy-Subklassen | unverändert |
| Live-Trade-Entscheidungen | unverändert |
/root/regime-gate-backup-{TS}/docker compose build clawbotdocker compose up -d --force-recreate clawbotPhase A (24h Smoke): 0 Tracebacks, regime_gate-Key in jeder Decision, gate_mode='shadow', gate_action='allow', would_have_blocked aggregierbar.
Phase B (4 Wochen Shadow): Total Decisions vs would_have_blocked, Verteilung über regime_class, Filter-Rate bei hypothetischem hard-Mode, BUY-Rate je Regime.
Phase C (Backtesting): 180d-Replay mit hard-mode auf Shadow-Daten, Vergleich Shadow vs hard, Akzeptanz-Check.
| Schwelle | Wert |
|---|---|
| Shadow-Daten ≥ 200 TRADE_CANDIDATEs | 200 |
| WEAK_TREND-Toxizität bestätigt | WR < 35 % |
| RANGE-Edge bestätigt | WR ≥ 50 % |
| Total Net bei WEAK_TREND-Block positiv | ≥ +5 % über Shadow-Period |
| Keine Coin-Allowlist/Denylist | (Boundary) |
| Operator-GO | ja |
| # | Risiko | Severity | Mitigation |
|---|---|---|---|
| 1 | Regime-Detector falsch klassifiziert | Mittel | seit Phase-N1 produktiv |
| 2 | RANGE-Edge im 180d-Sample war Markt-spezifisch | Hoch | Shadow > 4 Wochen |
| 3 | Toxic-Klassifikation blockiert echte Gewinner | Hoch | Shadow misst genau das |
| 4 | Doppel-Defense mit Router | Niedrig | Router-Blocks bleiben, Gate ist additive Schicht |
| 5 | Shadow-Period zu kurz | Mittel | 4–6 Wochen |
| 6 | env-flip shadow→hard vergessen | Niedrig | Roadmap-Pin |
| 7 | metadata_json wächst | Niedrig | ~300 Bytes/Row |
| 8 | Score-Penalty 1.5 heuristisch | Mittel | Sweep nach Shadow |
Soft: git revert + SOT-1d rebuild.
Hard: env MS_REGIME_GATE_ENABLED=false oder MS_REGIME_GATE_MODE=shadow, recreate.
Phase: env MS_REGIME_GATE_MODE=shadow, recreate, weiter Daten sammeln.
Backup: /root/regime-gate-backup-{TS}/.
| Q | Frage | Default |
|---|---|---|
| Q1 | Cutover im shadow-Mode? | A Ja, 4 Wochen log-only |
| Q2 | Block WEAK_TREND in P1.B? | A Ja (−30 %) |
| Q3 | Block STRONG_TREND in P1.B? | B Nein (Caution statt Toxic) |
| Q4 | Block HIGH_VOL mit base in Trends? | A Ja |
| Q5 | Soft-Score-Penalty? | A 1.5 |
| Q6 | Kill-Switch enabled? | A Ja, default true |
| Q7 | Shadow-Period? | B 4 Wochen |
| Q8 | Cutover-Zeitpunkt? | Wochenende |
| Q9 | Bundle mit MS-MTF-D-SHADOW-LOGGER-1? | A Empfohlen |
| Q10 | P1.B-Flip nach 2 Wochen erlaubt? | B Nein, mind. 4 Wochen |
~145 LoC + 39 Tests + Cutover-Prep = ~5.5 h.
0× Code-Touch (außer Plan-Phase) · 0× Trading-State · 0× Orders · 0× MS-Live · 0× Mainnet · 0× Env-Änderung (außer optional 6 safe-Default Settings) · 0× DB-Schema/Migration · 0× ConfigProfile-Apply · 0× Bot/Worker-Recreate · 0× Push · 0× Roadmap-Commit · 0× Coin-Allowlist · 0× Coin-Denylist · 0× Protected-Toolkit-Param-Change.
NICHT umsetzen wenn: Operator-GO fehlt, Bot/Worker unhealthy, State-Coherence-Conflicts aktiv, MS-Dry-Run-Anomalien letzte 24h, Bundle-Partner hat frische Tracebacks.
Plan abgeschlossen. Keine Umsetzung. Operator-Entscheidung zu Q1–Q10 + GO EXECUTE REGIME-AWARE-PARAMS-1-P1A-SHADOW erforderlich für Code-Phase.