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 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-04 11:19:48 +02:00
co-authored by Claude Opus 5
parent d052905319
commit 1a67944842
4 changed files with 78 additions and 7 deletions
+19 -4
View File
@@ -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 ⚠ 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 gegateten Variante kam auf ~Breakeven (PF 0,93/1,06) — dieselbe Richtung. **Keine
Messung stützt die dokumentierten „+0,185 / PF 1,35" mehr.** Messung stützt die dokumentierten „+0,185 / PF 1,35" mehr.**
**Offene Entscheidung:** Das Setup hebelt zwei GEMESSEN POSITIVE Schutzmechanismen **ABGESCHALTET (User-Entscheidung 2026-08-04, `[trading] reversal_enabled=false`).**
aus (Anti-Überdehnung UND den M30-Gegen-Trend-Filter, Edge ×2). Ein Setup ohne eigenen Ausschlag gab nicht nur die negative Zahl, sondern dass das Setup **zwei gemessen
Edge, das validierte Filter umgeht, ist der schlechteste Fall — Abschalten liegt nahe, POSITIVE Schutzmechanismen aushebelt** (Anti-Überdehnung UND den M30-Gegen-Trend-
ist aber eine Strategie-Entscheidung des Users. 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,03,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 ⚠⚠ **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** 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** (`LEGACY_SIMPLE`: kein Breakeven, kein Lock, kein Time-Stop). Mit dem **echten**
+8
View File
@@ -195,6 +195,14 @@ class TradingEngine:
self.wave.set_entry_room(float(self.cfg["trading"].get("entry_room_atr", "0.6"))) self.wave.set_entry_room(float(self.cfg["trading"].get("entry_room_atr", "0.6")))
except (TypeError, ValueError): except (TypeError, ValueError):
pass 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 # 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: # Key → gemessener Default (im wave_rec-Konstanten-Set). User-Vorgabe 2026-07-22:
# ini auf leer → Gate aus, obwohl 12/16 gemessen negativ sind. # ini auf leer → Gate aus, obwohl 12/16 gemessen negativ sind.
+40 -3
View File
@@ -201,6 +201,27 @@ class WaveRecommender:
# Ertrag ist durch den S/R-Auto-Close gedeckelt, Kosten fressen den Rest. # 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. # 0 = aus. Nur Live-Pfad (refresh_market); Backtests via _build bleiben frei.
self._entry_room_atr = 0.0 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): def set_entry_room(self, x: float):
with self._lock: with self._lock:
@@ -716,11 +737,27 @@ class WaveRecommender:
# aber schwächer als Trend & regime-anfällig (blutet in starken Trends). # aber schwächer als Trend & regime-anfällig (blutet in starken Trends).
# Hebt Anti-Überdehnung UND M30-Filter bewusst auf (per Definition gegen # Hebt Anti-Überdehnung UND M30-Filter bewusst auf (per Definition gegen
# die nachlaufende EMA/HTF). # 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 = angle90` 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 ad = angle - 90.0
if stretch <= -_REVERSAL_STRETCH and ad >= _ANGLE_DEAD: if not self._reversal_enabled:
sig, reversal = "LONG", True # überverkauft + Winkel aufBounce pass # Setup ausnur 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: 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 d_sig = 1 if sig == "LONG" else -1
+11
View File
@@ -224,6 +224,17 @@ CONFIG_DEPS = [
"why": "Empirisch bester Punkt (NICHT weil höhere Konfidenz besser wäre — " "why": "Empirisch bester Punkt (NICHT weil höhere Konfidenz besser wäre — "
"conf_pct ist unkalibriert). Nachbarwerte sind nicht besser.", "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", "key": "auto_signal", "test": "backtest_auto_signal.py",
"validated": "false", "validated": "false",