From 11e13cdb5a1c145e22b04a0967b2e027826bc996 Mon Sep 17 00:00:00 2001 From: Axel Hocks Date: Thu, 30 Jul 2026 20:14:11 +0200 Subject: [PATCH] MQL5 v1.29: Konsolidierungs-Box als Anzeige (CO;lo;hi;tight) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User: "schauen wir uns das mal an" (nach dem verworfenen Konsolidierungs-Backtest). Der Bot exportiert die Spanne der letzten 10 M5-Bars -- exakt die Box, aus der der validierte Squeeze-Ausbruch kommt (wave._squeeze_one liefert jetzt box_hi/box_lo in allen Rueckgaben). Der Indikator zeichnet sie als transparentes blaues Rechteck; ist sie KOMPRIMIERT (<=2.5xATR, also armed/active), wird sie mit doppelter Deckkraft gezeichnet -> "Ausbruch steht bevor" ist auf einen Blick sichtbar. Schalter: InpShowConsol / InpConsolColor / InpConsolAlpha / InpConsolBars. ⚠ REINE ANZEIGE. Alle Konsolidierungs-SETUPS sind gemessen verworfen (backtest_consolidation.py: False Breakout, Distribution, Accumulation, Retest -- inkl. Kontrolltest, der die Distribution-Hypothese kippte). Die Box zeigt WO gestaut wird, nicht WOHIN es geht. Validiert ist ausschliesslich der Ausbruch. Verifiziert: CO;84.105;84.815;0 (0.710$ = 2.68xATR = knapp ueber der Schwelle, daher korrekt als "nicht komprimiert" markiert). Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 2 +- core/engine.py | 15 +++++++++++++ core/wave_rec.py | 12 +++++++---- mql5/SR_Levels.mq5 | 52 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c60a0ca..537772a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1202,7 +1202,7 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: Daten älter als 60 s werden verworfen. **REINE ANZEIGE** — ob HL-Buch-Signale auf den CFD übertragbar sind, wird gerade gemessen (`analyze_bookflow.py` im HL-Projekt, Datensammlung seit 2026-07-30, Urteil in ~2 Wochen). Der Indikator - **`mql5/SR_Levels.mq5`** (**v1.28** — `LQ`-Handler zeichnet seit v1.14 **nur noch + **`mql5/SR_Levels.mq5`** (**v1.29** — `LQ`-Handler zeichnet seit v1.14 **nur noch den PFEIL**, rechtsbündig am aktuellen Rand (in `RepositionLabels()` nachgeführt, bleibt beim Scrollen rechts; Details im **Tooltip**) — Linie und Text-Label sind auf User-Wunsch raus („Chart zu voll"). **v1.15 = CHART-THEME** (User „Farben im diff --git a/core/engine.py b/core/engine.py index 9f22dd8..4f76aee 100644 --- a/core/engine.py +++ b/core/engine.py @@ -2024,6 +2024,21 @@ class TradingEngine: lines.append(f"EQ;{tag};{z['lo']};{z['hi']};{int(z['t'])}") except Exception: pass + # KONSOLIDIERUNGS-BOX (M5, dieselbe wie der validierte Squeeze): + # CO;lo;hi;<0|1> — letztes Feld 1 = komprimiert (≤2,5×ATR, Ausbruch steht + # bevor), 0 = nur die aktuelle 10-Bar-Spanne. ⚠ REINE ANZEIGE: die + # Konsolidierungs-SETUPS (False Breakout, Distribution, Accumulation, + # Retest) sind gemessen ALLE verworfen (`backtest_consolidation.py`); + # validiert ist nur der Squeeze-AUSBRUCH. Die Box zeigt also, WO gerade + # gestaut wird — nicht, wohin es geht. + try: + _sq = (self.wave.snapshot() or {}).get("squeeze") or {} + _lo, _hi = _sq.get("box_lo"), _sq.get("box_hi") + if _lo and _hi and _hi > _lo: + _tight = 1 if _sq.get("state") in ("armed", "active") else 0 + lines.append(f"CO;{_lo};{_hi};{_tight}") + except Exception: + pass # Aktueller Kurs für die fette Anzeige oben rechts (User-Wunsch): PX;bid try: _bid = (self.data.snapshot() or {}).get("bid") diff --git a/core/wave_rec.py b/core/wave_rec.py index c8fb73e..fb57d11 100644 --- a/core/wave_rec.py +++ b/core/wave_rec.py @@ -604,17 +604,21 @@ class WaveRecommender: return none box_hi = max(hb); box_lo = min(lb) box_atr = round((box_hi - box_lo) / atr, 2) + # Box-Grenzen immer mitgeben — der MT5-Chart zeichnet die Konsolidierung + # daraus (reine Anzeige; Konsolidierungs-SETUPS sind gemessen verworfen, + # `backtest_consolidation.py` — nur der Squeeze-Ausbruch ist validiert). + _box = {"box_hi": round(box_hi, 3), "box_lo": round(box_lo, 3)} if box_atr > _SQ_MULT: # keine Kompression - return {"state": None, "dir": None, "level": None, "box_atr": box_atr} + return {"state": None, "dir": None, "level": None, "box_atr": box_atr, **_box} px = closes[-1] up = box_hi + _SQ_K * atr; dn = box_lo - _SQ_K * atr if px >= up: - return {"state": "active", "dir": "LONG", "level": round(up, 3), "box_atr": box_atr} + return {"state": "active", "dir": "LONG", "level": round(up, 3), "box_atr": box_atr, **_box} if px <= dn: - return {"state": "active", "dir": "SHORT", "level": round(dn, 3), "box_atr": box_atr} + return {"state": "active", "dir": "SHORT", "level": round(dn, 3), "box_atr": box_atr, **_box} dir_ = "LONG" if (up - px) <= (px - dn) else "SHORT" # armed → nähere Grenze return {"state": "armed", "dir": dir_, - "level": round(up if dir_ == "LONG" else dn, 3), "box_atr": box_atr} + "level": round(up if dir_ == "LONG" else dn, 3), "box_atr": box_atr, **_box} @staticmethod def _bounce_one(closes, atr): diff --git a/mql5/SR_Levels.mq5 b/mql5/SR_Levels.mq5 index bca144e..fb92aa8 100644 --- a/mql5/SR_Levels.mq5 +++ b/mql5/SR_Levels.mq5 @@ -12,7 +12,12 @@ //| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). | //+------------------------------------------------------------------+ #property copyright "Oil Trading Bot" -#property version "1.28" +#property version "1.29" +// v1.29 (2026-07-30): KONSOLIDIERUNGS-BOX (CO;lo;hi;tight) — die Spanne der letzten +// 10 M5-Bars, aus der der validierte Squeeze-Ausbruch kommt. Komprimiert +// (<=2,5xATR) wird sie deutlicher gezeichnet. ⚠ REINE ANZEIGE: alle +// Konsolidierungs-SETUPS sind gemessen verworfen (backtest_consolidation.py) — +// die Box zeigt WO gestaut wird, nicht WOHIN es geht. // v1.28 (2026-07-30): G/V der offenen Position direkt UNTER dem Kurs oben rechts // (User-Wunsch) — PL;wert;waehrung, NETTO wie im Dashboard (WHT-Quellensteuer // bei Gewinn bereits abgezogen). Gruen im Plus, rot im Minus; ohne offene @@ -136,6 +141,10 @@ input int InpLabelSize = 12; // Schriftgroesse der Linien-Besc input bool InpShowPBreak = true; // Durchbruchwahrscheinlichkeit am S/R-Label input color InpLabelColor = clrWhite; // Farbe ALLER Linien-Beschriftungen (User-Wunsch: weiss) input color InpPriceColor = clrWhite; // Kurs oben rechts (weiss) +input bool InpShowConsol = true; // Konsolidierungs-Box (10 M5-Bars) zeichnen +input color InpConsolColor = C'88,166,255'; // Box-Farbe (blau) +input int InpConsolAlpha = 8; // Deckkraft in % (komprimiert: x2) +input int InpConsolBars = 10; // Box-Laenge in Bars (= _SQ_N im Bot) input bool InpShowPnL = true; // G/V der offenen Position unter dem Kurs input color InpPnLUpColor = C'0,255,127'; // G/V im Plus (neongruen) input color InpPnLDownColor = C'255,69,0'; // G/V im Minus (rot) @@ -578,6 +587,47 @@ void Redraw() } continue; } + // KONSOLIDIERUNGS-BOX: CO;lo;hi;<0|1> — die Spanne der letzten 10 M5-Bars + // (dieselbe Box, aus der der validierte Squeeze-Ausbruch kommt). Feld 3 = 1 + // bedeutet KOMPRIMIERT (≤2,5×ATR) → Ausbruch steht bevor, dann kräftiger. + // ⚠ REINE ANZEIGE: alle Konsolidierungs-SETUPS (False Breakout, Distribution, + // Accumulation, Retest) sind gemessen verworfen — die Box sagt WO gestaut + // wird, nicht WOHIN es geht. + if(typ == "CO") + { + if(k < 3) continue; + if(!InpShowConsol) continue; + double clo = StringToDouble(p[1]), chi = StringToDouble(p[2]); + bool tight = (k > 3 && p[3] == "1"); + if(clo <= 0 || chi <= clo) continue; + datetime ct0 = iTime(_Symbol, PERIOD_CURRENT, 0) + - (datetime)(PeriodSeconds() * InpConsolBars); + datetime ct1 = RightTime(); + string cn = PFX + "CONSOL"; + if(ObjectCreate(0, cn, OBJ_RECTANGLE, 0, ct0, clo, ct1, chi)) + { + ObjectSetInteger(0, cn, OBJPROP_STYLE, STYLE_SOLID); + ObjectSetInteger(0, cn, OBJPROP_WIDTH, 1); + ObjectSetInteger(0, cn, OBJPROP_FILL, true); + ObjectSetInteger(0, cn, OBJPROP_BACK, true); + ObjectSetInteger(0, cn, OBJPROP_SELECTABLE, false); + } + else + { + ObjectMove(0, cn, 0, ct0, clo); + ObjectMove(0, cn, 1, ct1, chi); + } + // komprimiert = deutlicher sichtbar (Ausbruch steht bevor) + ObjectSetInteger(0, cn, OBJPROP_COLOR, + BlendBg(InpConsolColor, tight ? InpConsolAlpha * 2 + : InpConsolAlpha)); + ObjectSetString (0, cn, OBJPROP_TOOLTIP, + (tight ? "Konsolidierung (komprimiert - Ausbruch steht bevor)" + : "aktuelle 10-Bar-Spanne") + + " " + DoubleToString(clo, (int)_Digits) + " - " + + DoubleToString(chi, (int)_Digits)); + continue; + } // AKTUELLER KURS oben rechts, fett (User-Wunsch): PX;bid if(typ == "PX") {