diff --git a/CLAUDE.md b/CLAUDE.md index 24c842d..c338006 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1246,7 +1246,27 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: Squeeze (nur `active`), Elliott (nur mit Ziel), KI (nur mit Bias) haben sonst **Gewicht 0** (vorher dämpfte das fast immer neutrale Squeeze-w=2,0 die Nadel permanent ~×0,8); `agree/total` zählt nur noch die ANDEREN stimmberechtigten - Module (Welle zählte sich selbst mit). Formel/Details: `docs/gesamtempfehlung.md`. + Module (Welle zählte sich selbst mit). + ⚠ **Bias-Fix ZWEITER TEIL 2026-07-30 (Review „Gesamtempfehlung komplett prüfen"):** + Die Regel „ohne Aussage = Gewicht 0" galt bis dahin für Squeeze/Elliott/KI, **NICHT + für die Welle selbst** — sie stand mit w=3,0 permanent im Nenner, auch bei WARTEN. + Das wog schwer: **~91 % der letzten 2000 Empfehlungen sind WARTEN** (Range-Regime), + die Nadel war also fast immer künstlich zur Mitte gezogen (realer Fall: bias + **+0,312 statt +0,625**, Faktor ~2). Jetzt `weight=0` bei WARTEN. **Zweiter Fix:** + `agree` nutzte als Referenz immer die Wellen-Richtung → bei WARTEN stand dort + zwangsläufig „0/N", obwohl sich die anderen Module einig waren (real „0/4" bei + 2 einigen Modulen). Jetzt Referenz = Wellen-Richtung, ersatzweise die **Bias- + Richtung** (real: „2/3"). Beides REINE ANZEIGE — Order-Logik unberührt. Mit 6 + synthetischen Szenarien verifiziert (alle einig · Rest dagegen · alles neutral · + WARTEN+alle SHORT · Welle+Squeeze). ⚠ **Offen (dokumentiert, nicht geändert):** + (a) **Doppelzählung** — die Welle nutzt M30 als Gegen-Trend-Filter und H1 als + Konfluenz-Bonus; beide zählen zusätzlich als eigene Stimmen (je 1,5), dieselbe + Information also zweimal. (b) **Drei divergierende Level-Quellen** seit der + M30-Umstellung: `_draw_levels` (M30 → Chart/S/R-Close), `pb_levels` (M5 → Entry- + Raum-Gate), `_sr_levels` (Misch-Set → Wellen-Konfidenz); real wichen die Supports + um 0,65 $ ab. Bewusst so (jedes Gate ist auf seine Quelle kalibriert), aber eine + Stolperfalle. (c) `tu` wird noch als Parameter durchgereicht, seit 2026-07-06 ungenutzt. + Formel/Details: `docs/gesamtempfehlung.md`. Headline = **validierte Welle** (steuert Order) + **Zeitebene** (`verdict.tf`, z. B. „▲ LONG · M5" — TF, für die die Empfehlung gilt); Rest = nur Konsens-Anzeige. Backend `engine._verdict` → `verdict` im Snapshot; Render `renderVerdict` diff --git a/core/engine.py b/core/engine.py index ca1ac55..ad3d235 100644 --- a/core/engine.py +++ b/core/engine.py @@ -2082,10 +2082,16 @@ class TradingEngine: votes.append({"name": name, "vote": int(vote), "weight": weight, "detail": detail}) - # 1) Welle — primär (validierter Edge) + # 1) Welle — primär (validierter Edge). ⚠ Bei WARTEN hat sie KEINE Aussage + # → Gewicht 0 (Fix 2026-07-30). Vorher stand w=3,0 permanent im Nenner und + # zog die Bias-Nadel dauerhaft zur Mitte — derselbe Logikfehler, der am + # 2026-07-15 beim Squeeze behoben wurde, hier übersehen. Das wog schwer: + # gemessen sind ~91 % der letzten 2000 Empfehlungen WARTEN, die Nadel war + # also fast immer künstlich gedämpft (real: bias 0,312 statt 0,500). wsig = (wave_signal or {}).get("signal") wv = 1 if wsig == "LONG" else -1 if wsig == "SHORT" else 0 - add("Welle", wv, 3.0, f"{wsig or '—'} · {(wave_signal or {}).get('conf_pct', 0)}%") + add("Welle", wv, 3.0 if wv != 0 else 0.0, + f"{wsig or '—'} · {(wave_signal or {}).get('conf_pct', 0)}%") # 2/3) M30 / H1 — die EMA-Signale, die die Welle tatsächlich nutzt m30 = int((wave_snap or {}).get("htf_trend", 0) or 0) @@ -2131,7 +2137,12 @@ class TradingEngine: wsum = sum(v["weight"] for v in votes) or 1.0 bias = sum(v["weight"] * v["vote"] for v in votes) / wsum others = [v for v in votes if v["name"] != "Welle" and v["weight"] > 0] - agree = sum(1 for v in others if wv != 0 and v["vote"] == wv) + # Referenzrichtung für „agree": normal die Welle. Sagt sie WARTEN (91 % der + # Zeit), gibt es keine Wellen-Richtung — dann zählt die Übereinstimmung mit + # der BIAS-Richtung (Fix 2026-07-30). Vorher stand dort immer „0/N", obwohl + # sich die anderen Module durchaus einig waren. + ref = wv if wv != 0 else (1 if bias > 0 else -1 if bias < 0 else 0) + agree = sum(1 for v in others if ref != 0 and v["vote"] == ref) return { "headline": wsig, "conf": (wave_signal or {}).get("conf_pct", 0), "tf": (wave_snap or {}).get("tf"), # Zeitebene, für die die Empfehlung gilt