From 1a679448428e49e9112d9e171d6a4c116ea8a0d3 Mon Sep 17 00:00:00 2001 From: Axel Hocks Date: Tue, 4 Aug 2026 11:19:48 +0200 Subject: [PATCH] Reversal-Setup abgeschaltet (User-Entscheidung nach der Messung) backtest_reversal_angle.py hat den Trigger in JEDER Variante beidhaelftig negativ gemessen (IST -0,122/-0,031 - vorzeichenkorrigiert -0,173/-0,061 - ohne Winkelbedingung -0,099/-0,023). Ausschlag gab aber nicht nur die Zahl: das Setup hebelt ZWEI gemessen POSITIVE Schutzmechanismen aus - die Anti-Ueberdehnung und den M30-Gegen-Trend-Filter (Edge x2). Ein Setup ohne eigenen Edge, das validierte Filter umgeht, ist der unguenstigste Fall. Umsetzung: neuer Schalter [trading] reversal_enabled (Config-Default im Engine false). WICHTIG: der Modul-Default in wave_rec bleibt True - saemtliche Backtests rufen dasselbe _build, ein False-Default haette alle bestehenden Messungen still veraendert. Abgeschaltet wird ausschliesslich im Live-Pfad. Verhaltensaenderung nur im Band |stretch| 3,0-3,5: dort kam vorher ein antizyklisches REV-Signal, jetzt das normale Trendsignal; ab 3,5 greift wie gehabt die Anti-Ueberdehnung. Verifiziert: - 3 Szenarien: ueberkauft+steigend SHORT/WAVE_REV_SHORT -> LONG/WAVE_LONG, ueberverkauft+fallend LONG/WAVE_REV_LONG -> SHORT/WAVE_SHORT, normaler Trend unveraendert - Live nach Neustart: bei 3,18xATR Ueberdehnung jetzt WARTEN/setup=WAVE/ reversal=None statt REV_SHORT; Log "Reversal-Setup AUS" - measurement_reminder CONFIG_DEPS ergaenzt, 11 Werte alle korrekt Die Winkelbedingung wurde bewusst NICHT vorzeichenkorrigiert - die korrigierte Variante misst sich schlechter. Die irrefuehrenden Kommentare sind jetzt als solche markiert. Bounce-Anzeige bleibt unveraendert (nur Warn-Kontext). Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 23 ++++++++++++++++++---- core/engine.py | 8 ++++++++ core/wave_rec.py | 43 ++++++++++++++++++++++++++++++++++++++--- measurement_reminder.py | 11 +++++++++++ 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 97aaf18..4a250f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -470,10 +470,25 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: ⚠ Gemessen wurde der ROHE Trigger (ohne Konfidenz-/Raum-Gate); der Legacy-Recheck der gegateten Variante kam auf ~Breakeven (PF 0,93/1,06) — dieselbe Richtung. **Keine Messung stützt die dokumentierten „+0,185 / PF 1,35" mehr.** - ⚠ **Offene Entscheidung:** Das Setup hebelt zwei GEMESSEN POSITIVE Schutzmechanismen - aus (Anti-Überdehnung UND den M30-Gegen-Trend-Filter, Edge ×2). Ein Setup ohne eigenen - Edge, das validierte Filter umgeht, ist der schlechteste Fall — Abschalten liegt nahe, - ist aber eine Strategie-Entscheidung des Users. + ✅ **ABGESCHALTET (User-Entscheidung 2026-08-04, `[trading] reversal_enabled=false`).** + Ausschlag gab nicht nur die negative Zahl, sondern dass das Setup **zwei gemessen + POSITIVE Schutzmechanismen aushebelt** (Anti-Überdehnung UND den M30-Gegen-Trend- + Filter, Edge ×2) — ein Setup ohne eigenen Edge, das validierte Filter umgeht, ist der + ungünstigste Fall. + ⚠ **Wichtig für Backtests: der Modul-Default in `wave_rec` bleibt `True`.** Sämtliche + Backtests rufen dasselbe `_build`; ein False-Default hätte alle bestehenden Messungen + still verändert. Abgeschaltet wird ausschließlich im Live-Pfad + (`engine` → `wave.set_reversal_enabled(...)`, Config-Default dort `false`). + Verhaltensänderung nur im Band **|stretch| 3,0–3,5**: dort kam vorher ein + antizyklisches REV-Signal, jetzt das normale Trendsignal (und ab 3,5 greift wie + gehabt die Anti-Überdehnung). Mit 3 Szenarien getestet — überkauft+steigend: + `SHORT/WAVE_REV_SHORT` → **`LONG/WAVE_LONG`**; nicht-überdehnter Trend unverändert. + Live verifiziert: bei 3,18×ATR Überdehnung jetzt `WARTEN · setup=WAVE · + reversal=None` statt REV_SHORT; Log „Reversal-Setup AUS". + Überwacht via `measurement_reminder.py` (CONFIG_DEPS, 11 Werte). + **Zurückholen:** `reversal_enabled = true`. Die **Bounce-Anzeige** (`wave.bounce`, + Kachel „Überdehnung") bleibt unverändert — sie war ohnehin nur Warn-Kontext, kein + Trade-Trigger. ⚠⚠ **DIESE ZAHLEN GELTEN NICHT MEHR** (Legacy-Recheck 2026-07-31, hier eingetragen am 2026-08-02): `backtest_bounce.py` nutzt den **vereinfachten Exit OHNE Kosten** (`LEGACY_SIMPLE`: kein Breakeven, kein Lock, kein Time-Stop). Mit dem **echten** diff --git a/core/engine.py b/core/engine.py index bbfe8e0..641e657 100644 --- a/core/engine.py +++ b/core/engine.py @@ -195,6 +195,14 @@ class TradingEngine: self.wave.set_entry_room(float(self.cfg["trading"].get("entry_room_atr", "0.6"))) except (TypeError, ValueError): pass + # Reversal/Bounce-Setup — Default hier **false** (User-Entscheidung 2026-08-04 + # nach `backtest_reversal_angle.py`: in JEDER Variante beidhälftig negativ, und + # es hebelt Anti-Überdehnung + M30-Filter aus). Der Modul-Default in `wave_rec` + # bleibt True, damit die Backtests unverändert bleiben — abgeschaltet wird + # ausschließlich hier im Live-Pfad. `reversal_enabled=true` holt es zurück. + self.wave.set_reversal_enabled( + (self.cfg["trading"].get("reversal_enabled", "false") or "false") + .strip().lower() == "true") # Tageszeit-Gate aus Config (Komma-Liste von Stunden; leer = AUS). Fehlt der # Key → gemessener Default (im wave_rec-Konstanten-Set). User-Vorgabe 2026-07-22: # ini auf leer → Gate aus, obwohl 12/16 gemessen negativ sind. diff --git a/core/wave_rec.py b/core/wave_rec.py index 07845a7..8917fee 100644 --- a/core/wave_rec.py +++ b/core/wave_rec.py @@ -201,6 +201,27 @@ class WaveRecommender: # Ertrag ist durch den S/R-Auto-Close gedeckelt, Kosten fressen den Rest. # 0 = aus. Nur Live-Pfad (refresh_market); Backtests via _build bleiben frei. self._entry_room_atr = 0.0 + # Reversal/Bounce-Setup an/aus. ⚠ Modul-Default bewusst TRUE: sämtliche + # Backtests rufen dasselbe `_build` — ein False-Default würde alle + # bestehenden Messungen still verändern. Abgeschaltet wird über die + # Config (`[trading] reversal_enabled`, s. `engine`), nicht hier. + self._reversal_enabled = True + + def set_reversal_enabled(self, on: bool): + """Antizyklisches Reversal-Setup (WAVE_REV_*) an/aus. + + ⚠ GEMESSEN NEGATIV (`backtest_reversal_angle.py`, 2026-08-04, 80k M5, + kanonischer Exit, Echtkosten, 2 Halbjahre): ØR −0,122/−0,031, PF 0,79/0,94. + Auch die vorzeichenkorrigierte Variante (−0,173/−0,061) und die Kontrolle + ohne Winkelbedingung (−0,099/−0,023) sind beidhälftig negativ. Dazu hebt + das Setup ZWEI gemessen positive Schutzmechanismen aus (Anti-Überdehnung + und den M30-Gegen-Trend-Filter, Edge ×2). Deshalb live abgeschaltet. + `true` stellt das alte Verhalten wieder her. + """ + with self._lock: + self._reversal_enabled = bool(on) + log.info(f"Reversal-Setup {'AN' if on else 'AUS'}" + + ("" if on else " (gemessen negativ, backtest_reversal_angle.py)")) def set_entry_room(self, x: float): with self._lock: @@ -716,11 +737,27 @@ class WaveRecommender: # aber schwächer als Trend & regime-anfällig (blutet in starken Trends). # Hebt Anti-Überdehnung UND M30-Filter bewusst auf (per Definition gegen # die nachlaufende EMA/HTF). + # ⚠⚠ ABGESCHALTET über `[trading] reversal_enabled=false` (2026-08-04). + # Gemessen (`backtest_reversal_angle.py`, 80k M5, kanonischer Exit, + # Echtkosten, 2 Halbjahre) ist der Trigger in JEDER Variante beidhälftig + # negativ: IST −0,122/−0,031 · vorzeichenkorrigiert −0,173/−0,061 · + # ohne Winkelbedingung −0,099/−0,023. Der Modul-Default bleibt True, + # damit die Backtests unverändert weiterlaufen. + # ⚠ ZUR BEDINGUNG SELBST (nicht korrigiert, weil gemessen SCHLECHTER): + # `calc_trend_angle` liefert 0°=AUFWÄRTS … 180°=ABWÄRTS, also ist + # `ad = angle−90` NEGATIV bei STEIGENDEM Kurs. Die untenstehenden + # Kommentare („Winkel auf/ab") beschreiben damit das GEGENTEIL dessen, + # was der Code tut: SHORT feuert bei überkauft UND WEITER STEIGENDEM + # Winkel. Das Vorzeichen wurde bewusst NICHT gedreht — die korrigierte + # Variante misst sich schlechter, und alle Alt-Messungen beruhen auf + # diesem Verhalten. ad = angle - 90.0 - if stretch <= -_REVERSAL_STRETCH and ad >= _ANGLE_DEAD: - sig, reversal = "LONG", True # überverkauft + Winkel auf → Bounce + if not self._reversal_enabled: + pass # Setup aus → nur Trendsignal + elif stretch <= -_REVERSAL_STRETCH and ad >= _ANGLE_DEAD: + sig, reversal = "LONG", True # ⚠ faktisch: Winkel FÄLLT noch elif stretch >= _REVERSAL_STRETCH and ad <= -_ANGLE_DEAD: - sig, reversal = "SHORT", True # überkauft + Winkel ab → Bounce + sig, reversal = "SHORT", True # ⚠ faktisch: Winkel STEIGT noch d_sig = 1 if sig == "LONG" else -1 diff --git a/measurement_reminder.py b/measurement_reminder.py index 73aeea1..3e1f6ed 100644 --- a/measurement_reminder.py +++ b/measurement_reminder.py @@ -224,6 +224,17 @@ CONFIG_DEPS = [ "why": "Empirisch bester Punkt (NICHT weil höhere Konfidenz besser wäre — " "conf_pct ist unkalibriert). Nachbarwerte sind nicht besser.", }, + { + "key": "reversal_enabled", "test": "backtest_reversal_angle.py", + "validated": "false", + "why": "AUS seit 2026-08-04. Der Reversal-Trigger ist in JEDER Variante " + "beidhälftig negativ (IST −0,122/−0,031 · vorzeichenkorrigiert " + "−0,173/−0,061 · ohne Winkelbedingung −0,099/−0,023) und hebelt dabei " + "ZWEI gemessen positive Schutzmechanismen aus (Anti-Überdehnung und den " + "M30-Gegen-Trend-Filter, Edge ×2). ⚠ Der Modul-Default in `wave_rec` ist " + "bewusst True — die Backtests rufen dasselbe `_build`; abgeschaltet wird " + "nur im Live-Pfad über diese Config.", + }, { "key": "auto_signal", "test": "backtest_auto_signal.py", "validated": "false",