Ursache der P(break)-Live-Degradation gefunden: Merkmals-Diskrepanz
backtest_pbreak_touches.py (M30-Level wie live, Touch-Zahl als 5. Merkmal) plus Rekonstruktion der Live-Merkmale aus candles_m1. Beweiskette: 1) Der Backtest reproduziert die 0,71 (Fit H1 -> AUC oos H2 0,715). Modell und Pipeline sind in Ordnung. 2) Populations-Hypothese widerlegt: live ist ausgerechnet die 1. Beruehrung (die trainierte Situation) mit AUC 0,445 die SCHLECHTESTE Gruppe, die Chop-Faelle (5.+) mit 0,577 die beste. Der Versatz "Modell 23-25 %, real 40-42 %" ist in JEDER Teilmenge gleich gross. 3) Merkmale rekonstruiert (n=2275): mom3 live 0,149 vs Training 1,4523 (-1,303), mom6 0,181 vs 1,6565 (-1,476). Daraus z-Versatz -1,05 -> aus 39,4 % Basisrate werden ~19 %, beobachtet 23 %. Erklaert praktisch die gesamte Fehlkalibrierung. MECHANISMUS: Training fixiert das Level beim Entry (>=0,3xATR entfernt) und wartet auf den ersten Touch -> mom3 ~1,45xATR = ein Schub. Live waehlt _draw_levels das naechstgelegene Level jede Sekunde NEU -> der Kurs steht oft neben einem Level, das gerade erst zum naechsten wurde, ohne Anlauf -> mom3 ~0,15. Gleicher Code, andere Situation. Folge: das Modell liegt live immer unter der Schwelle 0,55 -> das Gate war seit Inbetriebnahme faktisch nie aktiv (91 % aller Beruehrungen geschlossen = der pauschale S/R-Close, der 2x verworfen wurde). Zwei Reparaturwege (beide ungemessen): (a) Ziel-Level beim Oeffnen fixieren statt laufend neu waehlen, oder (b) Modell auf live-spiegelnder Stichprobe neu trainieren. TOUCH-ZAHL (User-Idee): im Backtest AUC 0,715 -> 0,725, Gewicht +0,176 fuer die 2.-4. Beruehrung (Vorzeichen bestaetigt), aber R-Ertrag nicht robust (H1 +131, H2 -43). Im Trainings-Datensatz 76 % Erst-Beruehrungen und KEINE 5+-Faelle - das live beobachtete umgekehrte U ist dort nicht abbildbar. Kleine Verbesserung, nicht der Hebel. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
92995b08d7
commit
b137967a68
@@ -1449,6 +1449,44 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
|
||||
beiden Hälften schlechter = Gewinner-Kappen). **Das erklärt die kontrafaktische
|
||||
Live-Messung vom Vortag** (`analyze_srclose_live.py`: −8 €/Trade, 43 % klar zu früh
|
||||
geschlossen, nur 26 % klar richtig) — Symptom und Ursache passen zusammen.
|
||||
⚠⚠ **URSACHE GEFUNDEN (2026-07-31, `backtest_pbreak_touches.py` + Rekonstruktion aus
|
||||
`candles_m1`): das Modell ist NICHT verfallen — es bekommt live eine ANDERE
|
||||
Merkmalsverteilung, als es trainiert wurde.** Beweiskette in drei Schritten:
|
||||
(1) **Der Backtest reproduziert die 0,71** (M30-Level, 4 Merkmale, Fit H1 → **AUC
|
||||
out-of-sample H2 0,715**) → Modell und Pipeline sind in Ordnung.
|
||||
(2) **Die Populations-Hypothese ist widerlegt:** live nach Berührungszahl
|
||||
aufgeschlüsselt ist ausgerechnet die 1. Berührung (= die trainierte Situation) mit
|
||||
**AUC 0,445 die SCHLECHTESTE** Gruppe, die Chop-Fälle (5.+) mit 0,577 die beste.
|
||||
Der Versatz „Modell sagt 23–25 %, real 40–42 %" ist in JEDER Teilmenge gleich groß
|
||||
(~17 Pp) — Signatur eines Merkmals-Problems, nicht eines Edge-Verfalls.
|
||||
(3) **Merkmale aus `candles_m1` rekonstruiert (n=2275) — der Versatz ist messbar:**
|
||||
| Merkmal | Live-Mittel | Training-µ | Differenz |
|
||||
|---|---|---|---|
|
||||
| mom3 | 0,149 | 1,4523 | **−1,303** |
|
||||
| mom6 | 0,181 | 1,6565 | **−1,476** |
|
||||
Daraus rechnet sich der z-Versatz exakt: mom3 → 1,433×(−1,303)/2,418 = **−0,772**,
|
||||
mom6 → **−0,275**, zusammen **−1,05**. Aus der Trainings-Basisrate 39,4 % (z=−0,429)
|
||||
wird damit ~19 % — beobachtet werden 23 %. **Erklärt praktisch die gesamte
|
||||
Fehlkalibrierung.**
|
||||
⚠ **DER MECHANISMUS:** Im Training ist der Touch-Bar `jt` der Moment, in dem der Kurs
|
||||
nach einem ECHTEN ANLAUF (Level bei Entry ≥0,3×ATR entfernt fixiert) zum ersten Mal
|
||||
ans Level stößt → mom3 ≈ 1,45×ATR = ein Schub. **Live wählt `_draw_levels` das
|
||||
nächstgelegene Level JEDE SEKUNDE NEU** (mit Hysterese) — der Kurs steht also oft
|
||||
neben einem Level, das gerade erst zum nächstgelegenen WURDE, ohne je darauf
|
||||
zugelaufen zu sein → mom3 ≈ 0,15. Gleicher Code, gleiche Formeln, aber **Training =
|
||||
Level bei Entry fixiert, Live = Level wandert mit.** Konsequenz: das Modell antwortet
|
||||
live konsistent „kein Schub → kein Durchbruch → 23 %", liegt damit IMMER unter der
|
||||
Schwelle 0,55 → **das Gate war seit Inbetriebnahme faktisch nie aktiv.**
|
||||
**Zwei Reparaturwege (beide ungemessen, erst prüfen):** (a) Ziel-Level beim Öffnen
|
||||
der Position FIXIEREN statt laufend neu zu wählen (macht Live = Training), oder
|
||||
(b) das Modell auf einer live-spiegelnden Stichprobe NEU trainieren (bei jedem Bar
|
||||
im 0,15×ATR-Band um das dynamisch nächste Level sampeln, ohne Anlauf-Bedingung).
|
||||
**TOUCH-ZAHL im Backtest (2 Halbjahre, `backtest_pbreak_touches.py`):** hebt die AUC
|
||||
nur von **0,715 auf 0,725**, Gewicht +0,176 für die 2.–4. Berührung (User-Vorzeichen
|
||||
bestätigt), aber der **R-Ertrag ist nicht robust** (H1 +131, H2 −43). ⚠ Im Trainings-
|
||||
Datensatz sind **76 % Erst-Berührungen und es gibt KEINE 5+-Fälle** (live sind 63 %
|
||||
fünfte oder später) — das live beobachtete umgekehrte U lässt sich dort nicht einmal
|
||||
abbilden. Kleine Verbesserung, nicht der Hebel.
|
||||
✅ **Pipeline gegen das Training geprüft, KEIN Bug gefunden:** `dist` ist in beiden
|
||||
entry-basiert (`abs(level−entry)/atr`, `backtest_srclose_prob.py:86`), `mom6`/`mom3`
|
||||
in beiden am Touch-Bar `jt`, `confirm`/`reject` dieselbe ±0,5×ATR-Definition, Timeout
|
||||
|
||||
Reference in New Issue
Block a user