From 06b37a1474ac1fefcaa373786ffd55ed97a46494 Mon Sep 17 00:00:00 2001 From: Axel Hocks Date: Thu, 30 Jul 2026 15:58:50 +0200 Subject: [PATCH] Liquiditaets-Waende: Richtungs-Pfeil + pinke Liquiditaets-Trendlinie (v1.13) User-Wunsch: "Kennzeiche die Liquiditaetslinie mit einem Pfeil in welche richtung die linie den Kurs treibt. Zeichne mir eine Trendlnie in pink im mt5 auf basis der liquiditaet ein". (a) Pfeil je Wand in Wirkrichtung (Lesart "die Wand haelt": Nachfrage stuetzt hoch, Angebot deckelt runter); groessere Wand dicker + "<<". CSV-Format erweitert: LQ;;preis;size;;<1|0>. WICHTIG: Pfeilrichtung ist INTERPRETATION, nicht gemessen -- die Gegenthese ("Liquidity Grab", Kurs laeuft ZUR Wand) ist genauso verbreitet. Klaert analyze_bookflow.py Frage 3. (b) Pinke Liquiditaets-Trendlinie LT;t1;p1;t2;p2;: Regression ueber den VOLUMENGEWICHTETEN Wand-Schwerpunkt der letzten 60 min. Zeigt, wohin das Gewicht der RUHENDEN Orders wandert -- nicht der gehandelte Kurs. Zeiten im Bot in Broker-Zeit umgerechnet, Preise basis-korrigiert. HL /api/walls liefert jetzt arrow_bid/arrow_ask/dominant/trend. Verifiziert: LQ;B;84.182;2441;U;1 / LQ;A;84.223;2441;D;0 / LT;1785427175;84.135;1785430664;83.978;D in sr_levels.csv. Indikator kompiliert. Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 21 ++++++++++-- core/engine.py | 18 ++++++++-- core/hl_walls.py | 12 ++++++- mql5/SR_Levels.mq5 | 84 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 127 insertions(+), 8 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f076ea4..b593ad6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1106,8 +1106,9 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: PWA-Chart. **Für das Desktop-Terminal: Datei-Bridge** — `engine._write_levels_file` (im `_run_analysis`, ~5 s, `[trading] export_mql5_levels=true`) schreibt atomar `\MQL5\Files\sr_levels.csv` (`SYM;…` / `R;preis` / `S;preis` / **`CH;; - t1;p1;t2;p2`** = Regressionskanal-Anker / **`LQ;;preis;size`** = ECHTE - Liquiditäts-Wand, s. u.); Quelle **`_draw_levels`** (S/R) + + t1;p1;t2;p2`** = Regressionskanal-Anker / **`LQ;;preis;size;;<1|0>`** = ECHTE + Liquiditäts-Wand + Pfeilrichtung + Dominanz / **`LT;t1;p1;t2;p2;`** = + Liquiditäts-Trendlinie, s. u.); Quelle **`_draw_levels`** (S/R) + **`structure.channel_line`** (Kanal) + **`self.hl_walls`** (Liquidität), Indikator-Farben blau DodgerBlue/DeepSkyBlue, Wände grün/orangerot. ⚠ **Chartmuster-Linien (`PT;…`) 2026-07-30 auf User-Wunsch ENTFERNT** („entferne die @@ -1124,6 +1125,22 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: `bid_mt5`/`ask_mt5` an; fehlt die Basis, wird NICHT gezeichnet. ⚠ **`127.0.0.1`, nicht `localhost`** (IPv6-Auflösung → 2066 ms statt 19–46 ms, lief in den 2-s-Timeout) und der HL-Endpoint liest **nur seine DB** (live-`fetch_l2_book` dauerte ~2 s = Timeout). + **Pfeil + Liquiditäts-Trendlinie (User-Wunsch 2026-07-30, Indikator v1.13):** + (a) Jede Wand bekommt einen **Pfeil in ihrer Wirkrichtung** (Wingdings 233/234) — + Lesart **„die Wand HÄLT"**: Nachfrage-Wand stützt von unten (▲), Angebots-Wand + deckelt (▼); die **größere** der beiden wird dicker gezeichnet + „<<" im Label + (`dominant` aus dem Endpoint). ⚠ **Die Pfeilrichtung ist INTERPRETATION, nicht + gemessen** — die Gegenthese („Liquidity Grab": der Kurs läuft ZUR Wand, um sie + abzuräumen) ist genauso verbreitet. Welche stimmt, beantwortet `analyze_bookflow.py` + (Frage 3) nach genug Daten; bis dahin ist der Pfeil eine Lese-Hilfe, kein Signal. + (b) **Pinke Liquiditäts-Trendlinie** (`OBJ_TREND`, nach rechts verlängert, + `InpShowLiqTrend`/`InpLiqTrendColor`): lineare Regression über den **volumen- + gewichteten Wand-Schwerpunkt** `(bid_px·bid_sz + ask_px·ask_sz)/(bid_sz+ask_sz)` + der letzten **60 min** (≥20 Punkte nötig). ⚠ Sie zeigt etwas ANDERES als eine + Kurs-Trendlinie: **wohin das Gewicht der RUHENDEN Orders wandert**, nicht wohin der + gehandelte Preis läuft — steigt sie, ziehen die Käufer ihre großen Gebote hoch. + Zeiten werden im Bot in **Broker-Zeit** umgerechnet (`trader._broker_offset_s()`), + weil MT5-Charts die brauchen; Preise sind bereits basis-korrigiert. Fail-safe: HL-Server aus → keine Linien, kein Fehler (Log 1×, dann still), Cache 10 s, 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, diff --git a/core/engine.py b/core/engine.py index 08b5ee0..58deeec 100644 --- a/core/engine.py +++ b/core/engine.py @@ -1940,11 +1940,25 @@ class TradingEngine: # basis-korrigiert auf CFD-Niveau) — Format LQ;;preis;size. # Anders als R/S NICHT aus Pivots geschätzt, sondern tatsächlich ruhende # Orders. REINE ANZEIGE (Übertragbarkeit auf den CFD wird gerade gemessen). + # Format: LQ;;preis;size;;<1|0> (Pfeil-Richtung = Wirkrichtung + # der Wand nach der Lesart „sie hält"; letztes Feld 1 = die GRÖSSERE der + # beiden Wände). Zusätzlich LT;t1;p1;t2;p2; = Liquiditäts-Trendlinie + # (Regression über den volumengewichteten Wand-Schwerpunkt) — Zeiten + # werden hier in BROKER-Zeit umgerechnet, weil MT5-Charts die brauchen. try: w = self.hl_walls.walls() if w: - lines.append(f"LQ;B;{w['bid']};{w['bid_sz']:.0f}") - lines.append(f"LQ;A;{w['ask']};{w['ask_sz']:.0f}") + dom = w.get("dominant") + ab = "U" if (w.get("arrow_bid") == "up") else "D" + aa = "D" if (w.get("arrow_ask") == "down") else "U" + lines.append(f"LQ;B;{w['bid']};{w['bid_sz']:.0f};{ab};{1 if dom=='B' else 0}") + lines.append(f"LQ;A;{w['ask']};{w['ask_sz']:.0f};{aa};{1 if dom=='A' else 0}") + tr = w.get("trend") + if tr and tr.get("t1") and tr.get("t2"): + boff = self.trader._broker_offset_s() + lines.append(f"LT;{int(tr['t1'])+boff};{tr['p1']};" + f"{int(tr['t2'])+boff};{tr['p2']};" + f"{'U' if tr.get('dir')=='up' else 'D'}") except Exception: pass # Zonen NICHT mehr aus der (statischen) [zones]-Config — die dynamische diff --git a/core/hl_walls.py b/core/hl_walls.py index 681d32a..afcd766 100644 --- a/core/hl_walls.py +++ b/core/hl_walls.py @@ -67,7 +67,17 @@ class HLWalls: data = {"bid": float(d["bid_mt5"]), "ask": float(d["ask_mt5"]), "bid_sz": float(d.get("bid_sz") or 0), "ask_sz": float(d.get("ask_sz") or 0), - "basis": d.get("basis"), "imb5": d.get("imb5")} + "basis": d.get("basis"), "imb5": d.get("imb5"), + # Wirkrichtung je Wand (Pfeil im Chart) + größere Wand. + # ⚠ Lesart „die Wand hält" — INTERPRETATION, nicht gemessen. + "arrow_bid": d.get("arrow_bid") or "up", + "arrow_ask": d.get("arrow_ask") or "down", + "dominant": d.get("dominant"), + # Liquiditäts-Trendlinie (Regression über den volumen- + # gewichteten Wand-Schwerpunkt): {t1,p1,t2,p2,dir,slope_per_h} + # — Zeiten sind LOKALE Epoch, der Aufrufer rechnet sie in + # Broker-Zeit um (MT5-Charts brauchen Broker-Zeit). + "trend": d.get("trend")} self._fail_logged = False except Exception as e: if not self._fail_logged: # nur 1× melden, nicht jeden Tick diff --git a/mql5/SR_Levels.mq5 b/mql5/SR_Levels.mq5 index 32f81c4..92f2bdf 100644 --- a/mql5/SR_Levels.mq5 +++ b/mql5/SR_Levels.mq5 @@ -12,7 +12,14 @@ //| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). | //+------------------------------------------------------------------+ #property copyright "Oil Trading Bot" -#property version "1.12" +#property version "1.13" +// v1.13 (2026-07-30): Liquiditäts-Wände bekommen einen PFEIL in ihrer Wirkrichtung +// (Lesart „die Wand hält" — Nachfrage stützt hoch, Angebot deckelt runter; +// die GRÖSSERE Wand wird dicker gezeichnet + "<<"). NEU: pinke +// LIQUIDITÄTS-TRENDLINIE (LT;…) = Regression über den volumengewichteten +// Wand-Schwerpunkt der letzten ~60 min — zeigt, wohin das Gewicht der +// RUHENDEN Orders wandert (nicht der gehandelte Kurs). +// ⚠ Pfeilrichtung ist INTERPRETATION, nicht gemessen (s. analyze_bookflow.py). // v1.12 (2026-07-30): Chartmuster-Linien (PT;…) ENTFERNT (User-Wunsch, Chart war zu // voll — Kachel/PWA-Anzeige bleibt). NEU: ECHTE Liquiditäts-Wände (LQ;…) aus // dem Hyperliquid-L2-Orderbuch, basis-korrigiert auf CFD-Niveau — die einzigen @@ -36,6 +43,8 @@ input color InpChanColor = clrYellow; // Kanal-Farbe input bool InpShowWalls = true; // echte Liquiditäts-Wände (Hyperliquid-Orderbuch) input color InpWallBidColor = clrMediumSpringGreen; // Nachfrage-Wand (Bid, Käufer) input color InpWallAskColor = clrOrangeRed; // Angebots-Wand (Ask, Verkäufer) +input bool InpShowLiqTrend = true; // Liquiditäts-Trendlinie zeichnen +input color InpLiqTrendColor = clrMagenta; // Liquiditäts-Trend (pink) const string PFX = "SRB_"; // Präfix S/R-Linien (aus Datei) const string RPFX = "SRR_"; // Präfix dynamische Range (aus Chart) @@ -279,8 +288,16 @@ void Redraw() } else ObjectMove(0, nm, 0, 0, lpx); - string llbl = (isBid ? "Liquidität NACHFRAGE " : "Liquidität ANGEBOT ") - + DoubleToString(lsz, 0); + // Pfeil = Wirkrichtung der Wand (Feld 4: U/D). Lesart „die Wand HÄLT": + // Nachfrage-Wand stützt von unten (hoch), Angebots-Wand deckelt (runter). + // Feld 5 = 1 bei der GRÖSSEREN der beiden Wände → dickere Linie + "<<". + string dirc = (k > 4) ? p[4] : (isBid ? "U" : "D"); + bool isDom = (k > 5 && p[5] == "1"); + string arrow = (dirc == "U" ? CharToString(94) : CharToString(118)); // ^ / v + if(isDom) + ObjectSetInteger(0, nm, OBJPROP_WIDTH, 3); + string llbl = arrow + " " + (isBid ? "Liquidität NACHFRAGE " : "Liquidität ANGEBOT ") + + DoubleToString(lsz, 0) + (isDom ? " <<" : ""); string ltn = PFX + "TLQ_" + side; if(ObjectCreate(0, ltn, OBJ_TEXT, 0, CenterTime(), lpx)) { @@ -295,6 +312,67 @@ void Redraw() ObjectMove(0, ltn, 0, CenterTime(), lpx); ObjectSetString(0, ltn, OBJPROP_TEXT, llbl); } + // Echtes Pfeil-Objekt am rechten Rand (Wingdings 233 hoch / 234 runter) — + // deutlicher sichtbar als das Textzeichen im Label. + string an = PFX + "ALQ_" + side; + datetime atime = CenterTime() + (datetime)(PeriodSeconds() * 6); + if(ObjectCreate(0, an, OBJ_ARROW, 0, atime, lpx)) + { + ObjectSetInteger(0, an, OBJPROP_ARROWCODE, (dirc == "U" ? 233 : 234)); + ObjectSetInteger(0, an, OBJPROP_COLOR, lcol); + ObjectSetInteger(0, an, OBJPROP_WIDTH, (isDom ? 3 : 2)); + ObjectSetInteger(0, an, OBJPROP_SELECTABLE, false); + } + else + ObjectMove(0, an, 0, atime, lpx); + continue; + } + // Liquiditäts-TRENDLINIE: LT;t1;p1;t2;p2; (pink, nach rechts verlängert). + // Regression über den VOLUMENGEWICHTETEN Schwerpunkt der beiden Wände über die + // letzten ~60 min: zeigt, wohin das Gewicht der RUHENDEN Orders wandert — + // NICHT wohin der gehandelte Kurs läuft. Steigt sie, ziehen die Käufer ihre + // großen Gebote hoch. Zeiten kommen bereits in Broker-Zeit aus dem Bot. + if(typ == "LT") + { + if(k < 5) continue; + if(!InpShowLiqTrend) continue; + datetime t1 = (datetime)StringToInteger(p[1]); + double q1 = StringToDouble(p[2]); + datetime t2 = (datetime)StringToInteger(p[3]); + double q2 = StringToDouble(p[4]); + string td = (k > 5) ? p[5] : ""; + if(t1 <= 0 || t2 <= 0 || q1 <= 0 || q2 <= 0) continue; + string nm = PFX + "LIQTREND"; + if(ObjectCreate(0, nm, OBJ_TREND, 0, t1, q1, t2, q2)) + { + ObjectSetInteger(0, nm, OBJPROP_COLOR, InpLiqTrendColor); + ObjectSetInteger(0, nm, OBJPROP_STYLE, STYLE_SOLID); + ObjectSetInteger(0, nm, OBJPROP_WIDTH, 2); + ObjectSetInteger(0, nm, OBJPROP_RAY_RIGHT, true); + ObjectSetInteger(0, nm, OBJPROP_RAY_LEFT, false); + ObjectSetInteger(0, nm, OBJPROP_BACK, true); + ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false); + } + else + { + ObjectMove(0, nm, 0, t1, q1); + ObjectMove(0, nm, 1, t2, q2); + } + string tl = PFX + "TLIQTREND"; + string tt = "Liquiditäts-Trend " + (td == "U" ? CharToString(94) : CharToString(118)); + if(ObjectCreate(0, tl, OBJ_TEXT, 0, t2, q2)) + { + ObjectSetString (0, tl, OBJPROP_TEXT, tt); + ObjectSetInteger(0, tl, OBJPROP_COLOR, InpLiqTrendColor); + ObjectSetInteger(0, tl, OBJPROP_FONTSIZE, 9); + ObjectSetInteger(0, tl, OBJPROP_ANCHOR, ANCHOR_LOWER); + ObjectSetInteger(0, tl, OBJPROP_SELECTABLE, false); + } + else + { + ObjectMove(0, tl, 0, t2, q2); + ObjectSetString(0, tl, OBJPROP_TEXT, tt); + } continue; } // ("Z;"-Zonen-Zeilen schreibt der Bot nicht mehr — die dynamische Handels-