//+------------------------------------------------------------------+ //| SR_Levels.mq5 | //| Zeichnet Support-/Resistance-Linien + Zonen (Ranges), die der | //| Python-Bot (Oil Trading Server) nach MQL5\Files\sr_levels.csv | //| schreibt. Das Python-MetaTrader5-Paket kann selbst KEINE Chart- | //| Objekte erzeugen — daher diese Datei-Bridge. | //| | //| Installation: | //| 1) Diese Datei nach \MQL5\Indicators\ kopieren. | //| 2) In MetaEditor öffnen und mit F7 kompilieren. | //| 3) Im Navigator auf den WTI-Chart (SpotCrude) ziehen. | //| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). | //+------------------------------------------------------------------+ #property copyright "Oil Trading Bot" #property version "1.21" // v1.21 (2026-07-30): Beschriftungen aller Linien RECHTSBUENDIG am rechten // Chart-Rand (vorher zentriert; ANCHOR_RIGHT_LOWER -> Text endet am Anker, // laeuft nach links, ragt nicht raus) + Schriftgroesse 8 -> 12 (+4 px, // User-Wunsch). Neu einstellbar via InpLabelSize. // v1.20 (2026-07-30): aktuelle KURSLINIE weiss (User-Vorgabe) — CHART_COLOR_BID/ // ASK/LAST auf InpThemeBidLine, Bid-Linie explizit eingeschaltet. // v1.19 (2026-07-30): Liquiditaetszone TRANSPARENT (User: „Transparenz der Zone // auf 10 %"). MT5 kann bei OBJ_RECTANGLE kein echtes Alpha -> BlendBg() // mischt die Fuellfarbe gegen den (bekannten, einfarbigen) Chart-Hintergrund; // das Ergebnis sieht identisch aus. InpLiqZoneAlpha = Deckkraft in %. // Die gestrichelte Kante bleibt in voller Farbe (wie im Referenzbild). // v1.18 (2026-07-30): NEU (User-Wuensche) — (a) LIQUIDITAETSZONEN: Equal Highs / // Equal Lows aus den M30-Pivots als goldenes Band + gestrichelte Kante, // nach rechts verlaengert (EQ;;lo;hi;zeit). REINE ANZEIGE, als Signal // gemessen verworfen. (b) AKTUELLER KURS oben rechts, fett (PX;bid). // v1.17 (2026-07-30): FIX „Liquiditaets-Pfeile werden nicht angezeigt" — zwei // Ursachen: (1) ANCHOR_LEFT ist fuer OBJ_ARROW UNGUELTIG (nur ANCHOR_TOP/ // ANCHOR_BOTTOM), (2) die Pfeile sitzen rechts NEBEN der letzten Kerze — // ohne CHART_SHIFT gibt es dort keinen sichtbaren Bereich. Beides behoben. // NEU: TRADE-MARKER (TR;;zeit) — die Kerze der Eroeffnung wird HELLGRUEN, // die des Close DUNKELGRUEN umrandet (InpShowTrades/InpTradeOpenColor/ // InpTradeCloseColor). // v1.16 (2026-07-30): Beschriftung der Liquiditäts-Trendlinie per Default AUS // (User: „die beschreibung der liquiditätslinie kann ausgeblendet werden") — // Text steht jetzt im Tooltip der Linie; `InpLiqTrendLabel=true` holt sie zurück. // v1.15 (2026-07-30): CHART-THEME (User: „Farben im MT5 wie im Bild") — setzt beim // Start Hintergrund/Gitter/Kerzenfarben auf die Dashboard-Palette // (Bull #3B82F6, Bear #EF4444, BG #0D1117, Gitter #10151C dezent). // Liquiditäts-Pfeile jetzt GOLD #F59E0B (= „Liquiditätszone" der Legende). // Abschaltbar via InpApplyTheme. ⚠ ändert das Chart dauerhaft. // v1.14 (2026-07-30): Liquiditäts-LINIEN + Text-Labels ENTFERNT (User: „blende die // liquiditätslinien aus, nur die Pfeile sollen rechtsbündig angezeigt werden"). // Es bleibt NUR der Pfeil auf dem Wand-Preis, RECHTSBÜNDIG am aktuellen Rand // (wird in RepositionLabels() nachgeführt, bleibt beim Scrollen rechts). // Details (Seite/Größe/Dominanz/Preis) jetzt im TOOLTIP statt im Chart. // Die pinke Liquiditäts-Trendlinie bleibt unverändert. // 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 // Linien im Chart, die nicht aus Pivots geschätzt sind, sondern tatsächlich // ruhende Orders zeigen (dick gestrichelt + Größen-Label). Reine Anzeige. // v1.11: Chartmuster-Linien (jetzt entfernt). // ⚠ nach dem Update den Indikator NEU mit F7 kompilieren. #property indicator_chart_window #property indicator_plots 0 input string InpFile = "sr_levels.csv"; // Datei in MQL5\Files input int InpRefreshS = 2; // Aktualisierung (Sekunden) input color InpResColor = clrDodgerBlue; // Widerstand (blau kräftig) input color InpSupColor = clrDeepSkyBlue; // Support (blau hell) input bool InpShowRange = false; // dynamische Handels-Range zeichnen (aus per User-Wunsch) input int InpRangeBars = 50; // Range = Hoch/Tief der letzten N Kerzen input color InpRangeColor = clrGoldenrod; // Range-Farbe input bool InpRangeFill = false; // Range füllen (aus = nur Umriss) input bool InpShowChannel = true; // Regressionskanal (M30) zeichnen input color InpChanColor = clrYellow; // Kanal-Farbe input bool InpShowWalls = true; // echte Liquiditäts-Wände (Hyperliquid-Orderbuch) input color InpWallBidColor = C'245,158,11'; // Liquidität Nachfrage (Bid) — Gold input color InpWallAskColor = C'245,158,11'; // Liquidität Angebot (Ask) — Gold input bool InpShowLiqTrend = true; // Liquiditäts-Trendlinie zeichnen input color InpLiqTrendColor = clrMagenta; // Liquiditäts-Trend (pink) input bool InpLiqTrendLabel = false; // Beschriftung der Trendlinie (aus per User-Wunsch) input bool InpShowTrades = true; // Trade-Kerzen umranden (Eroeffnung/Close) input color InpTradeOpenColor = C'134,239,172'; // Eroeffnung — hellgruen input color InpTradeCloseColor = C'21,128,61'; // Close — dunkelgruen input bool InpShowLiqZones = true; // Liquiditaetszonen (Equal Highs/Lows) input color InpLiqZoneColor = C'245,158,11'; // Zonen-Grundfarbe (Gold #F59E0B) input int InpLiqZoneAlpha = 10; // Deckkraft der Zonenfuellung in % (10 = sehr transparent) input bool InpShowPrice = true; // aktuellen Kurs oben rechts anzeigen input int InpPriceSize = 20; // Schriftgroesse des Kurses input int InpLabelSize = 12; // Schriftgroesse der Linien-Beschriftungen (+4 per User-Wunsch) input color InpPriceColor = C'230,237,243'; // Kurs-Farbe // ── Chart-THEME (User-Vorgabe 2026-07-30 „Farben im MT5 wie im Bild") ──────── // Setzt beim Start die Chart-Eigenschaften auf die Dashboard-Palette, damit MT5 // und die PWA gleich aussehen. Farben in MQL5-Notation C'R,G,B'. // Bullish #3B82F6 · Bearish #EF4444 · Liquidität #F59E0B · Entry/Target #22C55E // Hintergrund #0D1117 · Gitter #10151C (sehr dezent) · Text #8B949E // ⚠ Ändert das Chart dauerhaft (bleibt auch nach Entfernen des Indikators) — // deshalb per Schalter abschaltbar. input bool InpApplyTheme = true; // Chart-Farben setzen (Dashboard-Look) input color InpThemeBull = C'59,130,246'; // Bullish Candle (blau) input color InpThemeBear = C'239,68,68'; // Bearish Candle (rot) input color InpThemeBg = C'13,17,23'; // Hintergrund input color InpThemeGrid = C'16,21,28'; // Gitternetz (dezent) input color InpThemeText = C'139,148,158'; // Achsen/Text input color InpThemeBidLine = clrWhite; // aktuelle Kurslinie (Bid) — weiss const string PFX = "SRB_"; // Präfix S/R-Linien (aus Datei) const string RPFX = "SRR_"; // Präfix dynamische Range (aus Chart) string g_last = "\x01"; // letzter Datei-Inhalt (gegen Flackern) bool g_range_drawn = false; // hat DIESE Instanz die Range gezeichnet? //+------------------------------------------------------------------+ int OnInit() { if(InpApplyTheme) ApplyTheme(); EventSetTimer(MathMax(1, InpRefreshS)); Redraw(); DrawRange(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Chart-Farben auf die Dashboard-Palette setzen (User-Vorgabe). | //| Kerzen werden GEFÜLLT gezeichnet (Body in Bull-/Bear-Farbe), damit| //| es aussieht wie im Referenzbild. | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Farbe mit dem Chart-Hintergrund mischen — simuliert TRANSPARENZ. | //| ⚠ MT5 kann bei OBJ_RECTANGLE KEIN echtes Alpha (nur Canvas- | //| Objekte könnten das). Da der Hintergrund bekannt und einfarbig | //| ist, sieht die Mischung exakt aus wie eine transparente Füllung. | //| pct = Deckkraft in % (10 = sehr transparent, 100 = voll deckend). | //+------------------------------------------------------------------+ color BlendBg(color c, int pct) { if(pct >= 100) return c; if(pct < 0) pct = 0; color bg = (color)ChartGetInteger(0, CHART_COLOR_BACKGROUND); double a = pct / 100.0; int r = (int)((c & 0xFF) * a + (bg & 0xFF) * (1 - a)); int g = (int)(((c >> 8) & 0xFF) * a + ((bg >> 8) & 0xFF) * (1 - a)); int b = (int)(((c >> 16)& 0xFF) * a + ((bg >> 16)& 0xFF) * (1 - a)); return (color)(r | (g << 8) | (b << 16)); } //+------------------------------------------------------------------+ void ApplyTheme() { ChartSetInteger(0, CHART_MODE, CHART_CANDLES); ChartSetInteger(0, CHART_COLOR_BACKGROUND, InpThemeBg); ChartSetInteger(0, CHART_COLOR_FOREGROUND, InpThemeText); ChartSetInteger(0, CHART_SHOW_GRID, true); ChartSetInteger(0, CHART_COLOR_GRID, InpThemeGrid); // Body-Füllung ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, InpThemeBull); ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, InpThemeBear); // Umriss + Docht in derselben Farbe → klare, flächige Kerzen wie im Bild ChartSetInteger(0, CHART_COLOR_CHART_UP, InpThemeBull); ChartSetInteger(0, CHART_COLOR_CHART_DOWN, InpThemeBear); ChartSetInteger(0, CHART_COLOR_CHART_LINE, InpThemeText); // Aktuelle Kurslinie WEISS (User-Vorgabe 2026-07-30) — sie soll sich klar von // den blau/roten Kerzen und den farbigen Overlays abheben. ChartSetInteger(0, CHART_COLOR_BID, InpThemeBidLine); ChartSetInteger(0, CHART_COLOR_ASK, InpThemeBidLine); ChartSetInteger(0, CHART_COLOR_LAST, InpThemeBidLine); ChartSetInteger(0, CHART_SHOW_BID_LINE, true); ChartSetInteger(0, CHART_COLOR_STOP_LEVEL, C'239,68,68'); ChartSetInteger(0, CHART_SHOW_PERIOD_SEP, false); // ⚠ CHART_SHIFT MUSS an sein: die Liquiditäts-Pfeile sitzen rechts NEBEN der // letzten Kerze. Ohne Shift gibt es dort keinen sichtbaren Bereich → die Pfeile // wären unsichtbar (das war der zweite Grund für „Pfeile werden nicht angezeigt"). ChartSetInteger(0, CHART_SHIFT, true); ChartRedraw(); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); ObjectsDeleteAll(0, PFX); ObjectsDeleteAll(0, RPFX); ChartRedraw(); } //+------------------------------------------------------------------+ void OnTimer() { Redraw(); DrawRange(); RepositionLabels(); } //+------------------------------------------------------------------+ //| Zeitpunkt der horizontalen Chart-Mitte (sichtbarer Bereich) | //+------------------------------------------------------------------+ datetime CenterTime() { long first = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR); long width = ChartGetInteger(0, CHART_WIDTH_IN_BARS); int mid = (int)MathMax(0, first - width / 2); return iTime(_Symbol, PERIOD_CURRENT, mid); } //+------------------------------------------------------------------+ //| Zeitpunkt am RECHTEN Chart-Rand (im Shift-Bereich hinter der | //| letzten Kerze) — dort sitzen ALLE Beschriftungen (User-Vorgabe | //| 2026-07-30 „Beschriftung aller Linien bitte rechtsbündig"). | //+------------------------------------------------------------------+ datetime RightTime() { return iTime(_Symbol, PERIOD_CURRENT, 0) + (datetime)(PeriodSeconds() * 2); } //+------------------------------------------------------------------+ //| Hält die Beschriftungen beim Scrollen/Zoomen am rechten Rand | //+------------------------------------------------------------------+ void RepositionLabels() { datetime ct = RightTime(); int total = ObjectsTotal(0, 0, OBJ_TEXT); for(int i = 0; i < total; i++) { string nm = ObjectName(0, i, 0, OBJ_TEXT); if(StringFind(nm, PFX + "T") == 0) { double pr = ObjectGetDouble(0, nm, OBJPROP_PRICE); ObjectMove(0, nm, 0, ct, pr); // rechtsbündig = Text endet am Anker und läuft nach LINKS ObjectSetInteger(0, nm, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER); } } // Liquiditäts-PFEILE rechtsbündig halten: die CSV ändert sich nicht bei jedem // Tick, ohne Nachführung würden die Pfeile mit jeder neuen Kerze nach links // wandern. Preis bleibt, nur die Zeit wird an den rechten Rand gezogen. datetime rt = iTime(_Symbol, PERIOD_CURRENT, 0) + (datetime)(PeriodSeconds() * 2); int na = ObjectsTotal(0, 0, OBJ_ARROW); for(int i = 0; i < na; i++) { string nm = ObjectName(0, i, 0, OBJ_ARROW); if(StringFind(nm, PFX + "ALQ_") == 0) ObjectMove(0, nm, 0, rt, ObjectGetDouble(0, nm, OBJPROP_PRICE)); } ChartRedraw(); } //+------------------------------------------------------------------+ //| Dynamische Handels-Range = Hoch/Tief der letzten N Kerzen des | //| AKTUELLEN Charts (TF-genau). In-place via ObjectMove → kein | //| Flackern, passt sich an M1/M5/…/H1 automatisch an. | //+------------------------------------------------------------------+ void DrawRange() { string nm = RPFX + "BOX"; if(!InpShowRange) { // Nur löschen, was DIESE Instanz gezeichnet hat — sonst kämpfen zwei // Instanzen (eine an/eine aus) um die Box → Blinken im 2-s-Takt. if(g_range_drawn) { ObjectDelete(0, nm); g_range_drawn = false; ChartRedraw(); } return; } int total = Bars(_Symbol, PERIOD_CURRENT); if(total < 5) return; int n = InpRangeBars; if(n > total - 1) n = total - 1; int hi_i = iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, n, 0); int lo_i = iLowest (_Symbol, PERIOD_CURRENT, MODE_LOW, n, 0); if(hi_i < 0 || lo_i < 0) return; double hi = iHigh(_Symbol, PERIOD_CURRENT, hi_i); double lo = iLow (_Symbol, PERIOD_CURRENT, lo_i); datetime t0 = iTime(_Symbol, PERIOD_CURRENT, n - 1); datetime t1 = iTime(_Symbol, PERIOD_CURRENT, 0) + PeriodSeconds(); if(ObjectFind(0, nm) < 0) { ObjectCreate(0, nm, OBJ_RECTANGLE, 0, t0, lo, t1, hi); ObjectSetInteger(0, nm, OBJPROP_COLOR, InpRangeColor); ObjectSetInteger(0, nm, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, nm, OBJPROP_WIDTH, 1); ObjectSetInteger(0, nm, OBJPROP_FILL, InpRangeFill); ObjectSetInteger(0, nm, OBJPROP_BACK, true); ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false); ObjectSetString (0, nm, OBJPROP_TEXT, "Range " + IntegerToString(n)); } else { ObjectMove(0, nm, 0, t0, lo); // linke untere Ecke ObjectMove(0, nm, 1, t1, hi); // rechte obere Ecke } g_range_drawn = true; ChartRedraw(); } //+------------------------------------------------------------------+ //| Pflicht-Funktion jedes Indikators — hier No-op (wir zeichnen | //| über OnTimer aus der Datei, nicht aus den Kursreihen). | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { return(rates_total); } //+------------------------------------------------------------------+ void Redraw() { int h = FileOpen(InpFile, FILE_READ|FILE_TXT|FILE_ANSI|FILE_SHARE_READ|FILE_SHARE_WRITE); if(h == INVALID_HANDLE) return; // Datei (noch) nicht da → nächster Tick // Ganze Datei in einen String lesen und mit dem letzten Stand vergleichen — // nur bei ÄNDERUNG neu zeichnen (sonst flackert der delete/recreate alle 2 s). string content = ""; while(!FileIsEnding(h)) content += FileReadString(h) + "\n"; FileClose(h); if(content == g_last) return; // nichts geändert → nicht anfassen g_last = content; ObjectsDeleteAll(0, PFX); string rows[]; int nr = StringSplit(content, '\n', rows); int idx = 0; for(int r = 0; r < nr; r++) { string line = rows[r]; if(StringLen(line) < 2) continue; string p[]; int k = StringSplit(line, ';', p); if(k < 2) continue; string typ = p[0]; // 1. Zeile: SYM; — nur auf dem passenden Chart zeichnen if(typ == "SYM") { if(p[1] != _Symbol) { ObjectsDeleteAll(0, PFX); ChartRedraw(); return; } continue; } // Horizontale S/R-Linien + sichtbares Text-Label an der Linie if(typ == "R" || typ == "S") { double price = StringToDouble(p[1]); if(price <= 0) continue; string lbl = (typ=="R" ? "Widerstand " : "Unterstützung ") + DoubleToString(price, (int)_Digits); color col = (typ=="R" ? InpResColor : InpSupColor); string nm = PFX + typ + "_" + IntegerToString(idx); if(ObjectCreate(0, nm, OBJ_HLINE, 0, 0, price)) { ObjectSetInteger(0, nm, OBJPROP_COLOR, col); ObjectSetInteger(0, nm, OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(0, nm, OBJPROP_WIDTH, 1); ObjectSetInteger(0, nm, OBJPROP_BACK, true); ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false); ObjectSetString (0, nm, OBJPROP_TEXT, lbl); // Tooltip } // Beschriftung als eigenes Text-Objekt — RECHTSBÜNDIG am rechten Chart- // Rand (User-Vorgabe 2026-07-30; vorher horizontal zentriert). Bleibt via // RepositionLabels() beim Scrollen/Zoomen dort. ANCHOR_RIGHT_LOWER: der // Text ENDET am Anker und läuft nach links → ragt nicht aus dem Chart. string tn = PFX + "T" + typ + "_" + IntegerToString(idx); if(ObjectCreate(0, tn, OBJ_TEXT, 0, RightTime(), price)) { ObjectSetString (0, tn, OBJPROP_TEXT, lbl); ObjectSetInteger(0, tn, OBJPROP_COLOR, col); ObjectSetInteger(0, tn, OBJPROP_FONTSIZE, InpLabelSize); ObjectSetInteger(0, tn, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER); ObjectSetInteger(0, tn, OBJPROP_BACK, false); ObjectSetInteger(0, tn, OBJPROP_SELECTABLE, false); } idx++; } // Regressionskanal: CH;;t1;p1;t2;p2 → diagonale Trendlinie (OBJ_TREND), // nach rechts verlängert. Anker in Broker-Zeit (= Server-Zeit im Terminal). if(typ == "CH") { if(!InpShowChannel) continue; if(k < 6) continue; string kind = p[1]; datetime t1 = (datetime)StringToInteger(p[2]); double pr1 = StringToDouble(p[3]); datetime t2 = (datetime)StringToInteger(p[4]); double pr2 = StringToDouble(p[5]); if(pr1 <= 0 || pr2 <= 0 || t1 <= 0 || t2 <= 0) continue; string nm = PFX + "CH_" + kind; if(ObjectCreate(0, nm, OBJ_TREND, 0, t1, pr1, t2, pr2)) { ObjectSetInteger(0, nm, OBJPROP_COLOR, InpChanColor); ObjectSetInteger(0, nm, OBJPROP_STYLE, (kind == "M" ? STYLE_DOT : STYLE_DASH)); ObjectSetInteger(0, nm, OBJPROP_WIDTH, 1); ObjectSetInteger(0, nm, OBJPROP_RAY_RIGHT, true); // nach rechts verlängern ObjectSetInteger(0, nm, OBJPROP_RAY_LEFT, false); ObjectSetInteger(0, nm, OBJPROP_BACK, true); ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false); ObjectSetString (0, nm, OBJPROP_TEXT, "Kanal " + kind); } continue; } // ECHTE Liquiditäts-Wände: LQ;;preis;size (B = Nachfrage/Bid-Wand, // A = Angebot/Ask-Wand). Quelle = Hyperliquid-L2-Orderbuch, größtes Level je // Seite, im Bot BASIS-KORRIGIERT auf CFD-Niveau (HL notiert ~0,45 $ tiefer). // ⚠ Das ist die EINZIGE Linie im Chart, die nicht aus Pivots geschätzt ist, // sondern tatsächlich ruhende Orders zeigt. Dick + gestrichelt, damit sie sich // klar von den dünnen S/R-Linien abhebt. REINE ANZEIGE (kein Signal). // (Chartmuster-Linien „PT;…" wurden 2026-07-30 auf User-Wunsch entfernt.) if(typ == "LQ") { if(k < 3) continue; if(!InpShowWalls) continue; string side = p[1]; double lpx = StringToDouble(p[2]); double lsz = (k > 3) ? StringToDouble(p[3]) : 0.0; if(lpx <= 0) continue; bool isBid = (side == "B"); color lcol = isBid ? InpWallBidColor : InpWallAskColor; // ⚠ 2026-07-30 (User): KEINE waagerechte Linie und KEIN Text-Label mehr — // der Chart war zu voll. Es bleibt NUR der Pfeil, RECHTSBÜNDIG am aktuellen // Rand, auf dem Preisniveau der Wand. Die Details (Seite/Größe/Dominanz) // stehen im TOOLTIP (Maus drüber) statt fest im Chart. string dirc = (k > 4) ? p[4] : (isBid ? "U" : "D"); bool isDom = (k > 5 && p[5] == "1"); string an = PFX + "ALQ_" + side; // Rechter Rand = aktuelle (rechteste) Kerze + kleiner Versatz, damit der // Pfeil frei neben dem Kursverlauf steht und beim Scrollen rechts bleibt. datetime atime = iTime(_Symbol, PERIOD_CURRENT, 0) + (datetime)(PeriodSeconds() * 2); 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 ? 4 : 2)); // ⚠ KEIN ANCHOR_LEFT: OBJ_ARROW unterstützt NUR ANCHOR_TOP/ANCHOR_BOTTOM // — ein ungültiger Anker war (neben dem fehlenden Chart-Shift) der Grund, // warum die Pfeile nicht erschienen (Fix 2026-07-30). ObjectSetInteger(0, an, OBJPROP_ANCHOR, ANCHOR_TOP); ObjectSetInteger(0, an, OBJPROP_SELECTABLE, false); } else { ObjectMove(0, an, 0, atime, lpx); ObjectSetInteger(0, an, OBJPROP_WIDTH, (isDom ? 4 : 2)); ObjectSetInteger(0, an, OBJPROP_COLOR, lcol); ObjectSetInteger(0, an, OBJPROP_ARROWCODE, (dirc == "U" ? 233 : 234)); } ObjectSetString(0, an, OBJPROP_TOOLTIP, (isBid ? "Liquiditaet NACHFRAGE " : "Liquiditaet ANGEBOT ") + DoubleToString(lsz, 0) + (isDom ? " (dominant)" : "") + " @ " + DoubleToString(lpx, (int)_Digits)); // evtl. noch vorhandene Alt-Objekte (Linie/Label aus v1.13) entfernen ObjectDelete(0, PFX + "LQ_" + side); ObjectDelete(0, PFX + "TLQ_" + side); continue; } // LIQUIDITÄTSZONE: EQ;;lo;hi; → goldenes Band über die // Equal Highs / Equal Lows (M30), ab dem ersten Pivot nach rechts verlängert, // plus gestrichelte Kante — Darstellung wie im Referenzbild des Users. // ⚠ REINE ANZEIGE: als Signal gemessen und verworfen (backtest_liquidity_sweep.py). if(typ == "EQ") { if(k < 5) continue; if(!InpShowLiqZones) continue; string zs = p[1]; double zlo = StringToDouble(p[2]), zhi = StringToDouble(p[3]); datetime zt = (datetime)StringToInteger(p[4]); if(zlo <= 0 || zhi <= 0 || zt <= 0) continue; datetime zend = iTime(_Symbol, PERIOD_CURRENT, 0) + (datetime)(PeriodSeconds() * 3); string zn = PFX + "EQZ_" + zs; color zfill = BlendBg(InpLiqZoneColor, InpLiqZoneAlpha); if(ObjectCreate(0, zn, OBJ_RECTANGLE, 0, zt, zlo, zend, zhi)) { ObjectSetInteger(0, zn, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, zn, OBJPROP_WIDTH, 1); ObjectSetInteger(0, zn, OBJPROP_FILL, true); ObjectSetInteger(0, zn, OBJPROP_BACK, true); ObjectSetInteger(0, zn, OBJPROP_SELECTABLE, false); ObjectSetString (0, zn, OBJPROP_TOOLTIP, (zs == "H" ? "Equal Highs - Sell-Side Liquidity" : "Equal Lows - Buy-Side Liquidity")); } else { ObjectMove(0, zn, 0, zt, zlo); ObjectMove(0, zn, 1, zend, zhi); } // Farbe IMMER setzen (auch beim Bewegen) — sonst bliebe nach einer // Alpha-Änderung die alte Füllung stehen, bis das Objekt neu entsteht. ObjectSetInteger(0, zn, OBJPROP_COLOR, zfill); // gestrichelte Kante auf Höhe des Levels (wie im Bild) string zl = PFX + "EQL_" + zs; double edge = (zs == "H" ? zhi : zlo); if(ObjectCreate(0, zl, OBJ_TREND, 0, zt, edge, zend, edge)) { ObjectSetInteger(0, zl, OBJPROP_COLOR, InpLiqZoneColor); ObjectSetInteger(0, zl, OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(0, zl, OBJPROP_WIDTH, 1); ObjectSetInteger(0, zl, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(0, zl, OBJPROP_BACK, true); ObjectSetInteger(0, zl, OBJPROP_SELECTABLE, false); } else { ObjectMove(0, zl, 0, zt, edge); ObjectMove(0, zl, 1, zend, edge); } continue; } // AKTUELLER KURS oben rechts, fett (User-Wunsch): PX;bid if(typ == "PX") { if(k < 2) continue; if(!InpShowPrice) continue; double pxv = StringToDouble(p[1]); if(pxv <= 0) continue; string pn = PFX + "PRICE"; if(ObjectFind(0, pn) < 0) { ObjectCreate(0, pn, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, pn, OBJPROP_CORNER, CORNER_RIGHT_UPPER); ObjectSetInteger(0, pn, OBJPROP_XDISTANCE, 12); ObjectSetInteger(0, pn, OBJPROP_YDISTANCE, 14); ObjectSetInteger(0, pn, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER); ObjectSetString (0, pn, OBJPROP_FONT, "Arial Black"); ObjectSetInteger(0, pn, OBJPROP_FONTSIZE, InpPriceSize); ObjectSetInteger(0, pn, OBJPROP_SELECTABLE, false); } ObjectSetString (0, pn, OBJPROP_TEXT, DoubleToString(pxv, (int)_Digits)); ObjectSetInteger(0, pn, OBJPROP_COLOR, InpPriceColor); continue; } // TRADE-MARKER: TR;; → die Kerze, in der eröffnet bzw. // geschlossen wurde, wird umrandet (User-Vorgabe 2026-07-30): // O = Eröffnung → HELLGRÜN · C = Close → DUNKELGRÜN // Umrandung = OBJ_RECTANGLE über die Bar-Spanne (Zeit) und High/Low (Preis), // ungefüllt. Die Zeit wird auf den Bar-Beginn der aktuellen Chart-TF gerundet, // damit die Box exakt auf einer Kerze sitzt — egal auf welcher TF man schaut. if(typ == "TR") { if(k < 3) continue; if(!InpShowTrades) continue; string tkind = p[1]; datetime tts = (datetime)StringToInteger(p[2]); if(tts <= 0) continue; int bi = iBarShift(_Symbol, PERIOD_CURRENT, tts, false); if(bi < 0) continue; // Zeit liegt außerhalb der History datetime bt = iTime(_Symbol, PERIOD_CURRENT, bi); double bh = iHigh(_Symbol, PERIOD_CURRENT, bi); double bl = iLow (_Symbol, PERIOD_CURRENT, bi); if(bh <= 0 || bl <= 0) continue; double pad = (bh - bl) * 0.12; // etwas Luft um die Kerze if(pad <= 0) pad = _Point * 10; string tn2 = PFX + "TRD_" + tkind + "_" + IntegerToString((int)tts); if(ObjectCreate(0, tn2, OBJ_RECTANGLE, 0, bt, bl - pad, bt + PeriodSeconds(), bh + pad)) { ObjectSetInteger(0, tn2, OBJPROP_COLOR, (tkind == "O" ? InpTradeOpenColor : InpTradeCloseColor)); ObjectSetInteger(0, tn2, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, tn2, OBJPROP_WIDTH, 2); ObjectSetInteger(0, tn2, OBJPROP_FILL, false); ObjectSetInteger(0, tn2, OBJPROP_BACK, false); ObjectSetInteger(0, tn2, OBJPROP_SELECTABLE, false); ObjectSetString (0, tn2, OBJPROP_TOOLTIP, (tkind == "O" ? "Trade EROEFFNET" : "Trade GESCHLOSSEN")); } 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); } // Beschriftung der Liquiditäts-Trendlinie: auf User-Wunsch (2026-07-30) // per Default AUS — der Chart soll sauber bleiben. Die Richtung liest man // an der Linie selbst ab; Details stehen im Tooltip der Linie. string tl = PFX + "TLIQTREND"; string tt = "Liquiditaets-Trend " + (td == "U" ? CharToString(94) : CharToString(118)); ObjectSetString(0, nm, OBJPROP_TOOLTIP, tt); if(InpLiqTrendLabel) { 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, InpLabelSize); 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); } } else ObjectDelete(0, tl); // evtl. Alt-Label aus v1.13–1.15 entfernen continue; } // ("Z;"-Zonen-Zeilen schreibt der Bot nicht mehr — die dynamische Handels- // Range zeichnet DrawRange() selbst aus den Chart-Kerzen.) } ChartRedraw(); } //+------------------------------------------------------------------+