Auto-Signal abgeschaltet + B5-Abbruchregel fuer Auto-Squeeze fixiert

Auto-Signal AUS (auto_signal=false via Toggle -> runtime_state.json). Gruende
sind NICHT die Live-Bilanz (n=4 sagt nichts):
- gemessen in H1 durchgehend negativ (backtest_auto_signal.py, alle 8 Varianten)
- beide Auto-Pfade konkurrieren um den EINEN Positions-Slot -> solange beide
  laufen, ist die B5-Pruefung des Auto-Squeeze nicht sauber messbar

B4-Befund Auto-Squeeze (Anlass: negative Auto-Trades vom 31.07.):
  Mechanik (isolierter Einstieg): WR 46 %, OR +0,102, PF 1,15
  Live (n=31, 17.-31.07.)       : WR 45 %, OR -0,242, PF 0,49
Die Trefferquote stimmt ueberein - der Einstieg ist intakt. Die Luecke von
0,34 R/Trade entsteht im EXIT (O-Gewinn +11,02 vs O-Verlust -19,83). Alle drei
Ursachen wurden am 31.07. behoben (P(break) nachtrainiert, 15-Min-Regel aus,
Trail einheitlich 1,0), der Live-Zeitraum liegt also VOR den Reparaturen.
Deshalb kein Rueckbau, sondern vorab fixierte Latte:
  >=20 Squeeze-Trades ab 01.08., dann Verhaeltnis < 1,0 ODER PF < 1 -> aus.

measurement_reminder.py:
- neue Messung squeeze_b5 (loest autosig_b4 ab)
- CONFIG_DEPS um auto_signal (soll false) und auto_squeeze (soll true) ergaenzt
- ⚠ _cfg_now() liest jetzt AUCH runtime_state.json und bildet dessen Vorrang ab.
  Vorher verglich der Waechter nur die ini -> er meldete "alles auf dem
  gemessenen Stand", waehrend auto_signal per persistiertem UI-Toggle lief.
  Mit Szenario verifiziert (runtime true gegen validiert false -> gemeldet).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-01 17:52:51 +02:00
co-authored by Claude Opus 5
parent d0f3b78796
commit d18d8712db
2 changed files with 118 additions and 19 deletions
+63 -11
View File
@@ -94,17 +94,32 @@ CHECKS = [
"need": 25000, "unit": "geloggte Verdicts (~3 Wochen)",
"cmd": "analog analyze_verdict_calibration.py, aber auf verdict_votes",
},
# (ausgetragen 2026-08-01: „Auto-Signal-Entry B4" — der Pfad wurde ABGESCHALTET
# (`auto_signal=false`, Toggle + runtime_state). Gründe: gemessen H1 durchgehend
# negativ, und er konkurriert mit dem Auto-Squeeze um den EINEN Positions-Slot →
# solange beide laufen, ist die Squeeze-Erholung unten nicht sauber messbar.
# Wird er je reaktiviert, gilt wieder: ≥20 AUTOSIG-Trades, ØR gegen +0,14 halten.
# Der Zustand wird jetzt über CONFIG_DEPS['auto_signal'] überwacht.)
{
"key": "autosig_b4",
"title": "Auto-Signal-Entry: B4-Monitor (trägt er live?)",
"why": "Gemessen NICHT tragfähig (H1 0,05…−0,18, H2 positiv = Regime-Kippen), "
"auf ausdrücklichen Wunsch trotzdem gebaut. Erwartung: im aktuellen "
"Regime ~+0,14 R/Trade, im ungünstigen 0,05. Driftet es negativ weg → "
"`auto_signal=false` (B5-Rückbau).",
"have": lambda: _q("SELECT COUNT(*) FROM trades WHERE setup LIKE 'AUTOSIG%' "
"AND pnl IS NOT NULL"),
"need": 20, "unit": "AUTOSIG-Trades",
"cmd": "Statistik-Tab · setup LIKE 'AUTOSIG%' gegen ØR +0,14 halten",
# ⚠ VORAB festgelegte Abbruchregel (User-Zustimmung 2026-08-01) — bewusst VOR
# der Beobachtung fixiert, damit die Latte hinterher nicht verschoben wird.
"key": "squeeze_b5",
"title": "Auto-Squeeze: B5-Abbruchprüfung (Latte vorab fixiert)",
"why": "Live-Bilanz 17.31.07.: n=31, ΣEUR 162,99, PF 0,49, Verhältnis 0,56 — "
"während der B4-Monitor den EINSTIEG als intakt ausweist (Trefferquote "
"live 45 % vs. Mechanik 46 %, ØR Mechanik +0,102). Die Lücke von ~0,34 R "
"entstand also im EXIT, und alle drei Ursachen wurden am 31.07. behoben: "
"P(break)-Modell nachtrainiert (schloss vorher 91 % aller Level-"
"Berührungen = faktisch pauschaler S/R-Close), 15-Min-Regel aus, Trailing "
"einheitlich 1,0 statt 1,53,0 je TF. Deshalb NICHT sofort zurückgebaut, "
"sondern ein sauberes Fenster mit harter Latte.",
"have": lambda: _q("SELECT COUNT(*) FROM trades WHERE setup LIKE 'SQUEEZE%' "
"AND pnl IS NOT NULL AND entry_time >= "
"strftime('%s','2026-08-01')"),
"need": 20, "unit": "Squeeze-Trades seit 01.08.",
"cmd": "ABBRUCHREGEL: Verhältnis (ØGewinn/ØVerlust) < 1,0 ODER PF < 1 "
"→ `auto_squeeze=false` (B5-Rückbau, kein Ego). Sonst weiterlaufen "
"lassen. Zahlen: /api/squeeze_monitor bzw. Statistik-Tab.",
},
{
"key": "m30_levels",
@@ -209,6 +224,24 @@ CONFIG_DEPS = [
"why": "Empirisch bester Punkt (NICHT weil höhere Konfidenz besser wäre — "
"conf_pct ist unkalibriert). Nachbarwerte sind nicht besser.",
},
{
"key": "auto_signal", "test": "backtest_auto_signal.py",
"validated": "false",
"why": "ABGESCHALTET 2026-08-01. Gemessen in H1 durchgehend negativ (alle 8 "
"Varianten, n=7181167/Hälfte), H2 positiv = Regime-Kippen. Zusätzlich: "
"beide Auto-Pfade konkurrieren um den EINEN Positions-Slot — läuft er "
"mit, ist die B5-Abbruchprüfung des Auto-Squeeze nicht sauber messbar. "
"⚠ Dieser Schlüssel lebt AUCH in runtime_state.json (UI-Toggle) und wird "
"von dort überschrieben — genau so lief er am 31.07. unbemerkt weiter, "
"obwohl die ini 'false' sagte.",
},
{
"key": "auto_squeeze", "test": "backtest_breakout_squeeze.py",
"validated": "true",
"why": "Der EINZIGE 2-Stichproben-validierte Auto-Einstieg (ØR +0,14…+0,23). "
"Bleibt an, aber unter der vorab fixierten B5-Abbruchregel (s. Messung "
"'squeeze_b5'). Ebenfalls über runtime_state.json überschreibbar.",
},
{
"key": "dead_hours", "test": "backtest_hourly_split.py / backtest_realcosts.py",
"validated": "",
@@ -220,8 +253,18 @@ CONFIG_DEPS = [
def _cfg_now() -> dict:
"""Liest NUR die überwachten [trading]-Keys. ⚠ Die ini enthält Live-Secrets —
hier wird bewusst nichts anderes gelesen oder ausgegeben."""
hier wird bewusst nichts anderes gelesen oder ausgegeben.
⚠⚠ WICHTIG (Fix 2026-08-01): Die ini ist NICHT die Quelle der Wahrheit für die
UI-Schalter. `runtime_state.json` wird beim Start über die ini gelegt (engine
`_load_runtime_state`) — der Wächter muss denselben Vorrang abbilden, sonst meldet
er „alles auf dem gemessenen Stand", während live etwas anderes läuft.
Real passiert: `auto_signal` stand in der ini auf `false`, lief aber wochenlang,
weil ein Dashboard-Toggle `true` persistiert hatte — 4 der 7 Bot-Trades vom 31.07.
stammten aus diesem Pfad, der gemessen in H1 negativ ist.
"""
import configparser
import json
out: dict = {}
try:
c = configparser.ConfigParser(inline_comment_prefixes=("#", ";"))
@@ -231,6 +274,15 @@ def _cfg_now() -> dict:
out[d["key"]] = (t.get(d["key"], "") or "").strip()
except Exception:
pass
# runtime_state.json überschreibt — exakt wie im Engine-Start.
try:
with open(os.path.join(HERE, "runtime_state.json"), encoding="utf-8") as f:
rt = json.load(f) or {}
for k, v in rt.items():
if k in out:
out[k] = ("true" if v else "false") if isinstance(v, bool) else str(v)
except Exception:
pass
return out