User-Wunsch: das bestaetigte Muster in das jeweils passende Chart einzeichnen. CSV: neue Zeile `PT;<TF>;<name>;<dir>;<trigger>;<ziel>` je Zeitebene. INDIKATOR: zeichnet NUR die Zeile, deren <TF> zu SEINEM Chart passt (`TFName(PERIOD_CURRENT)`). Ohne diesen Filter laegen alle Zeitebenen uebereinander im selben Fenster und keine waere lesbar - so bekommt jedes Chartfenster (M1/M5/M15/M30/H1) sein eigenes Muster. Gezeichnet werden zwei waagerechte Linien: Trigger (Nackenlinie, durchgezogen, Breite 2) und Ziel (gestrichelt), gruen bei bullisch, rot bei baerisch, dazu ein Label an der Triggerlinie. ⚠⚠ NUR `confirmed`. "Bildet sich" ist genau der Zustand, in dem noch nichts gebrochen ist - ihn zu zeichnen waere eine Vorhersage. Live gegengeprueft: M30 "Tasse+Henkel" und H1 "Aufsteigendes Dreieck" stehen auf confirmed und sind in der CSV; der M5-"Steigende Keil" ist nur forming und wird korrekt NICHT exportiert. ⚠⚠ EHRLICHKEIT IM LABEL: die Muster-Klasse ist als SIGNAL gemessen und VERWORFEN - die Ziel-Trefferquote liegt bei nur 13-38 % (backtest_patterns.py). Deshalb steht "(trifft 13-38 %)" im Chart-Label. Eine gezeichnete Ziellinie ohne diesen Zusatz liest sich wie eine Prognose, und genau das ist sie nicht. Kein Verdict-Gewicht, kein Trade-Trigger. ⚠ Nur ZUSAMMENGESETZT aus `patterns_tf`, das der Snapshot ohnehin baut - kein zweiter Rechenweg (der Konsens-Pfeil-Fehler). ⚠ Der dokumentierte Fallstrick beachtet: kompiliert wurde ins RICHTIGE Terminal (D0E8209F..., das einzige mit sr_levels.csv), mit EIGENEM Logpfad, und geprueft wurde auf "Result: 0 errors, 0 warnings" PLUS frischen .ex5-Zeitstempel - nicht auf den Default-Log. Der erste Versuch lief ins Leere, weil der Editor-Pfad falsch war (Pepperstone-Ordner existiert nicht, es ist "MetaTrader 5"); das leere Log und die unveraenderte .ex5 haben es verraten. Quelle ins Repo gespiegelt (mql5/SR_Levels.mq5), Backup daneben. Abschaltbar: InpShowMuster=false; Farben ueber InpMusterBullColor/-BearColor. Pipeline A-G gruen, 97 Tests, deployt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1290 lines
72 KiB
Plaintext
1290 lines
72 KiB
Plaintext
//+------------------------------------------------------------------+
|
||
//| 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 <Terminal>\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.45"
|
||
// v1.42 (2026-08-19): Y-Stapel oben rechts GEMESSEN statt geschaetzt. Der
|
||
// Faktor 1,8 aus v1.41 war nur die naechste Schaetzung; jetzt liefert
|
||
// TextGetSize die TATSAECHLICHE Pixelhoehe (LabelH). Ausserdem wird Y bei
|
||
// JEDEM Redraw gesetzt, nicht nur beim Erzeugen -- ein bereits
|
||
// vorhandenes Label behielt sonst seine alte Position.
|
||
// v1.41 (2026-08-19): Y-STAPEL oben rechts korrigiert (User: "oben rechts die
|
||
// Texte ueberlagern sich"). Dieselbe Punkt-statt-Pixel-Rechnung wie
|
||
// gestern links: bei InpPriceSize=20 lag G/V auf y=44 mitten im Kurs
|
||
// (14..50) und HL auf y=56 mitten im G/V. Jetzt gestapelt mit Faktor
|
||
// 1,8 px je Punkt -> Kurs 14, G/V 50, HL 78.
|
||
// v1.40 (2026-08-19): MELDUNGEN ZENTRIERT statt oben links (User-Wunsch).
|
||
// MT5 kennt keine "Mitte"-Ecke: Bezug bleibt CORNER_LEFT_UPPER, aber der
|
||
// ANKER wird ANCHOR_UPPER (Oberkante mittig) und X = halbe Chartbreite.
|
||
// X wird bei JEDEM Redraw neu gesetzt, sonst haengt die Zentrierung nach
|
||
// einer Fenster-Groessenaenderung auf der alten Breite fest.
|
||
// Startabstand 40 -> 24, weil MT5s eigene Symbol-Zeile links steht und
|
||
// mittig nicht mehr stoert.
|
||
// v1.39 (2026-08-19): MELDUNGEN oben links neu positioniert (User: "die
|
||
// Anzeigetexte ueberlagern sich"). Zwei Fehler: der Start lag bei y=16
|
||
// und damit in MT5s EIGENER Symbol-/OHLC-Zeile, und der Zeilenabstand
|
||
// rechnete FONTSIZE wie Pixel -- es ist aber PUNKT (10 pt = 16-20 px je
|
||
// nach DPI). Jetzt Startabstand ueber InpMeldungY (40) und Abstand
|
||
// Faktor 2,0 der Schriftgroesse.
|
||
// v1.38 (2026-08-17): Beschriftung der KONSOLIDIERUNGS-BOX entfernt (User-Wunsch).
|
||
// Sie kam in v1.30 auf die Frage "was bedeutet die graue Box" und stand
|
||
// seither dauerhaft im Chart. Der erklaerende Text bleibt als TOOLTIP an
|
||
// der Box -- die Information geht nicht verloren, sie draengt sich nur
|
||
// nicht mehr auf. Ein Alt-Objekt wird beim ersten Redraw geloescht.
|
||
// v1.37 (2026-08-17): ZONEN (RZ/SZ) — S/R zusaetzlich als farbiges Band, wie im
|
||
// TradingView-Vorbild des Users. Die Breite ist die echte Spanne der
|
||
// M30-Pivots im Cluster; die Vorlage leitet ihre Zone aus Fibonacci ab,
|
||
// das ist hier gemessen und verworfen. Untere Zone heisst SUPPORT, nicht
|
||
// "Long Liquidation" -- echte Liquidationsdaten hat das Projekt nicht.
|
||
// v1.36 (2026-08-17): MELDUNGEN oben links (MS;<text>) — dieselben Zeilen wie
|
||
// die Dashboard-Karte "Meldungen" (Squeeze, Ueberdehnung, S/R-Ziel,
|
||
// Stop-Seite, News-Blackout). Der Bot setzt sie nur ZUSAMMEN aus bereits
|
||
// berechneten Snapshot-Teilen, er rechnet nichts neu -- die Lehre aus dem
|
||
// Konsens-Pfeil, der im 5-s-Takt ein zweites _verdict() zog.
|
||
// Abschaltbar per InpShowMeldungen oder [trading] export_meldungen=false.
|
||
// v1.35 (2026-08-13): S/R-LABEL WORTGLEICH ZUR M15-KARTE (User: „die Beschriftung
|
||
// fuer S/R im Chart stimmt nicht mit der Analyse in der M15-Karte ueberein").
|
||
// Das Label trug seit v1.27 die NACKTE Zahl = P(Durchbruch); die Karte klappt
|
||
// unter 45 % auf P(Abprall) um und nennt 45-55 % „unentschieden". Dasselbe
|
||
// Level stand damit im Chart als „33%" und in der Karte als „67 % Abprall" —
|
||
// beide Zahlen richtig, aber die Chart-Zahl sagte nicht, WAS sie ist.
|
||
// GEMESSEN in 88,1 % der Zeit verschieden (1.797 Vorhersagen/14 Tage).
|
||
// Jetzt: „69% Bruch" / „unentschieden" / „67% Abprall" — identisch zu app.js.
|
||
// v1.34 (2026-08-01): HYPERLIQUID-KURS (HL;...) unter Kurs und G/V oben rechts,
|
||
// bernstein. HL handelt 24/7, Pepperstone nicht - am Wochenende der einzige
|
||
// lebende Kurs; die Basis (~0,45 $ Kontrakt-Differenz) ist herausgerechnet,
|
||
// der Wert also direkt mit dem Broker-Kurs vergleichbar. InpShowHL/InpHLColor.
|
||
// v1.33 (2026-07-31): Konsens-Pfeil (K) per Default AUS + Pfeile kuerzer (8 statt
|
||
// 14 Bars). Grund: L und K starten am selben Punkt und zeigten oft in
|
||
// ENTGEGENGESETZTE Richtungen - zwei divergierende Linien aus einem Punkt
|
||
// sehen aus wie der Kegel, den sie ersetzen sollten. Jetzt normalerweise EIN
|
||
// Pfeil (L, der kalibrierte); S kommt nur beim Squeeze-Ausbruch dazu.
|
||
// InpShowConsensus=true holt den Konsens-Pfeil zurueck.
|
||
// v1.32 (2026-07-31): RICHTUNGS-PFEILE (AR;<art>;<von>;<nach>;<text>) statt des
|
||
// Kegels (User-Wunsch). DREI Arten mit UNTERSCHIEDLICHER Beleglage:
|
||
// L blau = am naechsten Level, aus dem kalibrierten P(break)
|
||
// (AUC 0,65 oos, live kalibriert) - BEDINGTE Aussage
|
||
// S neongruen = Squeeze-Ausbruch, das EINZIGE 2-Stichproben-validierte
|
||
// Richtungssignal - erscheint nur bei `active`
|
||
// K grau = Konsens der Verdict-Module - NICHT kalibriert, heisst
|
||
// deshalb "Konsens" und nicht "Prognose"
|
||
// ⚠ KEINER ist eine freie Kursprognose: die ist im Projekt gemessen ein
|
||
// Muenzwurf (analyze_reversal.py, AUC 0,499-0,509 oos, in-sample 0,52).
|
||
// Der Kegel bleibt im Code (InpShowCone), der Bot exportiert ihn aber per
|
||
// Default nicht mehr ([trading] export_cone).
|
||
// v1.31 (2026-07-31): WAHRSCHEINLICHKEITS-KEGEL (CN;<minuten>;<lo>;<hi>) — zwei sich
|
||
// oeffnende, gepunktete Pfade vom aktuellen Bar ueber 30/60/120 min.
|
||
// ⚠ KEINE Richtungsprognose, sondern STREUUNG: wie weit der Kurs plausibel
|
||
// gelaufen sein kann. Out-of-sample kalibriert (analyze_cone.py): das
|
||
// 80%-Band trifft real ~76%. Bewusst NEUTRAL grau (keine Richtungsfarbe).
|
||
// InpShowCone / InpConeColor.
|
||
// v1.30 (2026-07-30): Konsolidierungs-Box BESCHRIFTET (User-Frage „was bedeutet die
|
||
// graue Box") — sichtbares Label an der Oberkante, rechtsbuendig wie die
|
||
// uebrigen: „Konsolidierung (10-Bar-Spanne)" bzw. bei Kompression
|
||
// „Konsolidierung - komprimiert, Ausbruch steht bevor".
|
||
// 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
|
||
// Position schickt der Bot keine PL-Zeile -> Label verschwindet.
|
||
// v1.27 (2026-07-30): S/R-Label zeigt nur noch die Prozentzahl statt
|
||
// „Durchbruch 34%" (User-Wunsch) — der ausgeschriebene Text bleibt im Tooltip.
|
||
// v1.26 (2026-07-30): Beschriftungen + Pfeile stehen jetzt GANZ rechts am
|
||
// Chartrand — auf Hoehe des Kurs-Labels (User: „genau so angeordnet wie der
|
||
// aktuelle Kurs"). RightTime() rechnet dafuer das Ende des Shift-Bereichs
|
||
// aus (CHART_WIDTH_IN_BARS x InpShiftPct) statt fix 2 Kerzen hinter die
|
||
// letzte Bar. Gilt beim Erzeugen UND beim Nachfuehren.
|
||
// v1.25 (2026-07-30): S/R-Labels zeigen die DURCHBRUCHWAHRSCHEINLICHKEIT
|
||
// (User-Wunsch) — der Bot haengt sie als drittes CSV-Feld an (R;preis;pct).
|
||
// Quelle = dasselbe kalibrierte P(break)-Modell wie der S/R-Auto-Close, auf
|
||
// die M30-Level nachtrainiert (AUC 0,72 out-of-sample). Niedrig = Level
|
||
// haelt eher. Abschaltbar via InpShowPBreak.
|
||
// v1.24 (2026-07-30): Farb-Inputs UMBENANNT — MT5 speichert Input-Werte je
|
||
// Chart-Instanz und ueberschreibt damit NEUE Defaults, auch nach Recompile
|
||
// (deshalb blieben die Pfeile gold). Durch die Umbenennung findet MT5 keinen
|
||
// gespeicherten Wert mehr und nimmt den Default:
|
||
// InpWallBidColor -> InpArrowUpColor (neongruen #00FF7F)
|
||
// InpWallAskColor -> InpArrowDownColor (rot #FF4500)
|
||
// InpLiqTrendColor -> InpTrendLineColor (neongruen)
|
||
// InpLiqZoneColor/Alpha -> InpZoneColor/InpZoneAlpha
|
||
// v1.23 (2026-07-30): (a) Pfeile wieder NEONGRUEN/ROT statt Gold (User-Wunsch).
|
||
// (b) Liquiditaets-Trendlinie neongruen wie der Up-Pfeil (statt pink).
|
||
// (c) FIX „Beschriftungen nicht komplett rechtsbuendig": auf den Linien war
|
||
// OBJPROP_TEXT gesetzt — den zeichnet MT5 LINKS am Chartrand. Jetzt
|
||
// OBJPROP_TOOLTIP + CHART_SHOW_OBJECT_DESCR=false.
|
||
// (e) ALLE Beschriftungen weiss (InpLabelColor) — die Linien behalten
|
||
// ihre Farbe, nur der Text ist einheitlich weiss.
|
||
// (d) MT5-Positions-Labels ("sell 0.36") stehen systembedingt LINKS und
|
||
// koennen nicht verschoben werden -> nur ab-/anschaltbar via
|
||
// InpShowTradeLevels.
|
||
// v1.22 (2026-07-30): Aufraeumen nach User-Feedback „das Bild sieht komisch aus":
|
||
// (a) Trade-Umrandungen ENTFERNT (InpShowTrades=false, Export im Bot aus).
|
||
// (b) Liquiditaets-Trendlinie nicht mehr RAY_RIGHT — eine 60-min-Regression
|
||
// 100 Bars in die Zukunft zu ziehen riss die Linie ins Bodenlose.
|
||
// (c) CHART_SHIFT_SIZE begrenzt (InpShiftPct=12 %) — ohne Begrenzung stand
|
||
// der Kursverlauf ganz links gequetscht.
|
||
// ⚠ MT5 uebernimmt beim Neukompilieren NICHT die neuen Default-Inputs, wenn
|
||
// der Indikator schon auf dem Chart liegt: einmal ENTFERNEN und neu aufziehen.
|
||
// 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. InpZoneAlpha = 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;<H|L>;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;<O|C>;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 InpArrowUpColor = C'0,255,127'; // Liquiditaet Nachfrage (Bid) — NEONGRUEN
|
||
input color InpArrowDownColor = C'255,69,0'; // Liquiditaet Angebot (Ask) — ROT
|
||
input bool InpShowLiqTrend = true; // Liquiditäts-Trendlinie zeichnen
|
||
input color InpTrendLineColor = C'0,255,127'; // Liquiditaets-Trend — NEONGRUEN (wie Up-Pfeil)
|
||
input bool InpLiqTrendLabel = false; // Beschriftung der Trendlinie (aus per User-Wunsch)
|
||
input bool InpShowTrades = false; // Trade-Kerzen umranden (AUS per User-Wunsch)
|
||
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 InpZoneColor = C'245,158,11'; // Zonen-Grundfarbe (Gold #F59E0B)
|
||
input int InpZoneAlpha = 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 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 InpShowCone = true; // Wahrscheinlichkeits-Kegel (Streuung, NICHT Richtung)
|
||
input bool InpShowArrows = true; // Richtungs-Pfeile (Level / Squeeze / Konsens)
|
||
input color InpArrLevel = C'88,166,255'; // Pfeil am naechsten Level (P(break)) - blau
|
||
input color InpArrSqueeze = C'0,255,127'; // Squeeze-Ausbruch (validiert) - neongruen
|
||
input color InpArrConsensus = C'139,148,158'; // Konsens der Module (NICHT kalibriert) - grau
|
||
// ⚠ Konsens-Pfeil per DEFAULT AUS (2026-07-31): er startet am selben Punkt wie der
|
||
// Level-Pfeil und lief oft in die GEGENrichtung - zwei divergierende Linien aus einem
|
||
// Punkt sehen aus wie der Kegel, den er ersetzen sollte (User: "trichter anstatt
|
||
// pfeil wird angezeigt"). Der Konsens steht ohnehin im Dashboard (Bias-Nadel).
|
||
input bool InpShowConsensus = false; // Konsens-Pfeil zusaetzlich zeichnen
|
||
input int InpArrBars = 8; // Pfeil-Laenge in Bars (kuerzer = Spitze sichtbar)
|
||
input color InpConeColor = C'139,148,158'; // Kegel-Farbe (neutral grau - bewusst KEINE Richtungsfarbe)
|
||
input bool InpShowHL = true; // Hyperliquid-Kurs unter dem Broker-Kurs
|
||
input color InpHLColor = C'232,160,0'; // HL-Kurs (bernstein, klar unterscheidbar)
|
||
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)
|
||
// ── 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
|
||
input double InpShiftPct = 12.0; // Platz rechts fuer Pfeile/Labels (% der Chartbreite)
|
||
input bool InpShowTradeLevels = true; // MT5-Positionslinien+Labels (stehen immer LINKS)
|
||
// Meldungen oben links (User-Wunsch 2026-08-17) — dieselben Zeilen wie die
|
||
// Dashboard-Karte „Meldungen". Der Bot deckelt auf 5; abschaltbar per ini
|
||
// (`[trading] export_meldungen=false`) ODER hier.
|
||
input bool InpShowMeldungen = true; // Meldungen oben links einblenden
|
||
input int InpMeldungSize = 11; // Schriftgroesse der Meldungen (v1.43: 10 -> 11, User "eine Groesse zu klein")
|
||
input int InpMeldungY = 24; // Startabstand von oben (zentriert -> MT5s Symbol-Zeile stoert nicht)
|
||
input color InpMeldungColor = clrGainsboro; // Farbe der Meldungen
|
||
// Zonen statt nackter Linien (User-Wunsch 2026-08-17). Die BREITE ist die echte
|
||
// Spanne der Pivots im Cluster — NICHT Fibonacci (im Projekt gemessen und
|
||
// verworfen: haelt nicht besser als eine Zufallslinie gleicher Distanz).
|
||
input bool InpShowZonen = true; // S/R als ZONE (Band) zeichnen
|
||
input color InpZoneResColor = C'60,25,30'; // Widerstands-Zone (dunkelrot)
|
||
input color InpZoneSupColor = C'20,45,35'; // Support-Zone (dunkelgruen)
|
||
|
||
// Bestaetigtes Chartmuster je Zeitebene (User-Wunsch 2026-08-21).
|
||
// ⚠ Gezeichnet wird NUR das Muster, dessen Zeitebene zum EIGENEN Chart passt.
|
||
input bool InpShowMuster = true; // bestaetigtes Chartmuster zeichnen
|
||
input color InpMusterBullColor = C'70,180,100';// bullisch
|
||
input color InpMusterBearColor = C'220,90,80'; // baerisch
|
||
|
||
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)
|
||
// Kegel: Verkettung der Horizonte (30->60->120). Die CSV liefert sie aufsteigend;
|
||
// jeder Abschnitt startet dort, wo der vorherige endete -> ein sich oeffnender
|
||
// Faecher statt drei unverbundener Geraden. Wird je Redraw zurueckgesetzt.
|
||
datetime g_coneT = 0;
|
||
double g_coneLo = 0.0, g_coneHi = 0.0;
|
||
double g_conePx = 0.0; // aktueller Kurs (aus der PX-Zeile)
|
||
bool g_range_drawn = false; // hat DIESE Instanz die Range gezeichnet?
|
||
|
||
//+------------------------------------------------------------------+
|
||
|
||
//+------------------------------------------------------------------+
|
||
//| ECHTE Pixelhoehe eines Labels — gemessen, nicht geschaetzt. |
|
||
//| ⚠⚠ Die drei Labels oben rechts haben sich zweimal ueberlagert, |
|
||
//| weil OBJPROP_FONTSIZE in PUNKT angegeben wird und der Code mit |
|
||
//| Pixeln rechnete. Ein Korrekturfaktor (1,8) war nur die naechste|
|
||
//| Schaetzung — bei anderer DPI-Skalierung waere er wieder falsch.|
|
||
//| TextGetSize liefert die TATSAECHLICHE Hoehe in Pixeln. |
|
||
//| TextSetFont nimmt die Groesse in 1/10 Punkt, wenn sie NEGATIV |
|
||
//| ist — deshalb -size*10. |
|
||
//+------------------------------------------------------------------+
|
||
int LabelH(const string font, const int size)
|
||
{
|
||
TextSetFont(font, -size * 10);
|
||
uint w = 0, h = 0;
|
||
TextGetSize("0123456789.", w, h);
|
||
return (h > 0 ? (int)h + 6 : size * 2); // +6 px Luft; Rueckfall falls 0
|
||
}
|
||
|
||
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. |
|
||
//+------------------------------------------------------------------+
|
||
//| Zeitebene dieses Charts als Text ("M1","M5","M15","M30","H1" ...) |
|
||
//| ⚠ Muss zu den Schluesseln passen, die der Bot in `PT;` schreibt |
|
||
//| (`engine.patterns_tf`). Weicht die Schreibweise ab, wird still |
|
||
//| NICHTS gezeichnet — deshalb die Fallback-Zeile am Ende. |
|
||
//+------------------------------------------------------------------+
|
||
string TFName(ENUM_TIMEFRAMES tf)
|
||
{
|
||
switch(tf)
|
||
{
|
||
case PERIOD_M1: return "M1";
|
||
case PERIOD_M5: return "M5";
|
||
case PERIOD_M15: return "M15";
|
||
case PERIOD_M30: return "M30";
|
||
case PERIOD_H1: return "H1";
|
||
}
|
||
return EnumToString(tf);
|
||
}
|
||
|
||
//| ⚠ 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);
|
||
// Shift-Bereich klein halten: nur so viel Platz rechts, dass Pfeile und
|
||
// Beschriftungen hinpassen. Ohne Begrenzung stand der Kursverlauf ganz links
|
||
// gequetscht (User-Feedback „das Bild sieht komisch aus", 2026-07-30).
|
||
ChartSetDouble(0, CHART_SHIFT_SIZE, InpShiftPct);
|
||
// MT5 zeichnet Objekt-BESCHREIBUNGEN immer LINKS an den Chartrand — aus, damit
|
||
// nur die eigenen, rechtsbuendigen Labels sichtbar sind (User-Vorgabe).
|
||
ChartSetInteger(0, CHART_SHOW_OBJECT_DESCR, false);
|
||
// Positions-/Order-Beschriftungen ("sell 0.36 ...") stehen bei MT5 fest LINKS und
|
||
// lassen sich NICHT nach rechts holen — nur ganz aus- oder einschalten.
|
||
ChartSetInteger(0, CHART_SHOW_TRADE_LEVELS, InpShowTradeLevels);
|
||
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()
|
||
{
|
||
// Ganz an den RECHTEN Chartrand — also ans Ende des Shift-Bereichs, nicht nur
|
||
// 2 Kerzen hinter die letzte (User 2026-07-30: „genau so angeordnet wie der
|
||
// aktuelle Kurs"). Der Shift-Bereich ist InpShiftPct % der sichtbaren Breite;
|
||
// ein Balken Reserve, damit der Text nicht am Rand abgeschnitten wird.
|
||
long width = ChartGetInteger(0, CHART_WIDTH_IN_BARS);
|
||
int bars = (int)MathMax(2, (double)width * InpShiftPct / 100.0 - 1.0);
|
||
return iTime(_Symbol, PERIOD_CURRENT, 0) + (datetime)(PeriodSeconds() * bars);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| 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 = RightTime();
|
||
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;
|
||
int msg_idx = 0; // Meldungs-Stapel oben links
|
||
// ⚠⚠ ZEILENHOEHE MESSEN STATT SCHAETZEN (v1.44, User: „die zeilenabstaende
|
||
// sind immer noch zu gering"). Zweimal aus der Punktgroesse hochgerechnet
|
||
// (Faktor 2,0 dann 2,6) — beide Male zu knapp, weil der Zusammenhang
|
||
// Punkt->Pixel von der DPI-Skalierung abhaengt und NICHT vom Quelltext aus
|
||
// bekannt ist. `TextGetSize` liefert die TATSAECHLICHE Pixelhoehe.
|
||
// ⚠ NEGATIVE Groesse in `TextSetFont` = Angabe in 1/10 pt, und NUR diese
|
||
// Form wird von MT5 DPI-korrekt skaliert (positive Werte nicht).
|
||
int msg_h = 0;
|
||
{
|
||
uint _tw = 0, _th = 0; // ⚠ TextGetSize verlangt uint&, nicht int& (error 246)
|
||
TextSetFont("Arial", -InpMeldungSize * 10);
|
||
if(TextGetSize("Hg", _tw, _th) && _th > 0)
|
||
msg_h = (int)_th + 8; // + Luft, sonst kleben die Zeilen
|
||
}
|
||
if(msg_h < 20) msg_h = (int)(InpMeldungSize * 2.6); // Fallback wie v1.43
|
||
// Kegel-Verkettung je Redraw zuruecksetzen (sonst haengt der Faecher am Stand
|
||
// des vorherigen Durchlaufs)
|
||
g_coneT = 0; g_coneLo = 0.0; g_coneHi = 0.0; g_conePx = 0.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;<symbol> — 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;
|
||
// Feld 3 (optional) = P(Durchbruch) in % aus dem kalibrierten Modell des
|
||
// Bots. Niedrig = Level haelt eher, hoch = bricht eher.
|
||
// ⚠⚠ WORTGLEICH ZUR M15-KARTE (Fix 2026-08-13, v1.35, User: „die
|
||
// Beschriftung fuer S/R im Chart stimmt nicht mit der Analyse in der
|
||
// M15-Karte ueberein"). Hier stand bis dahin die NACKTE Zahl = P(Bruch).
|
||
// Die Karte (`app.js` lesart()/pTxt()) klappt unter 45 % aber auf den
|
||
// GEGENWERT P(Abprall) um und nennt 45–55 % „unentschieden" — dasselbe
|
||
// Level trug damit im Chart „33%" und in der Karte „67 % Abprall".
|
||
// Beide Zahlen waren richtig, aber die Chart-Zahl sagte nicht, WAS sie
|
||
// ist. GEMESSEN betraf das 88,1 % der Zeit (1.797 Vorhersagen/14 Tage:
|
||
// 66,3 % lagen unter 45 %, 21,9 % im unentschiedenen Band).
|
||
// ➜ Wer die Formulierung hier aendert, muss `lesart()` in app.js
|
||
// mitaendern — sonst laufen sie wieder auseinander.
|
||
string lbl = (typ=="R" ? "Widerstand " : "Unterstuetzung ")
|
||
+ DoubleToString(price, (int)_Digits);
|
||
if(InpShowPBreak && k > 2 && StringLen(p[2]) > 0)
|
||
{
|
||
int pb = (int)StringToInteger(p[2]);
|
||
if(pb >= 45 && pb <= 55) lbl += " · unentschieden";
|
||
else if(pb > 55) lbl += " · " + IntegerToString(pb) + "% Bruch";
|
||
else lbl += " · " + IntegerToString(100-pb) + "% Abprall";
|
||
}
|
||
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);
|
||
// ⚠ TOOLTIP, NICHT OBJPROP_TEXT: den TEXT zeichnet MT5 LINKS am
|
||
// Chartrand (Option „Objektbeschreibungen") — das war die
|
||
// linksbuendige Beschriftung. Als Tooltip stoert er nicht.
|
||
ObjectSetString (0, nm, OBJPROP_TOOLTIP, lbl);
|
||
}
|
||
// 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, InpLabelColor);
|
||
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;<U|M|L>;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_TOOLTIP, "Kanal " + kind);
|
||
}
|
||
continue;
|
||
}
|
||
// ECHTE Liquiditäts-Wände: LQ;<B|A>;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 ? InpArrowUpColor : InpArrowDownColor;
|
||
// ⚠ 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 = RightTime();
|
||
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;<H|L>;lo;hi;<broker_time> → 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(InpZoneColor, InpZoneAlpha);
|
||
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, InpZoneColor);
|
||
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;
|
||
}
|
||
// 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));
|
||
string ctip = (tight ? "Konsolidierung (komprimiert - Ausbruch steht bevor)"
|
||
: "aktuelle 10-Bar-Spanne")
|
||
+ " " + DoubleToString(clo, (int)_Digits) + " - "
|
||
+ DoubleToString(chi, (int)_Digits);
|
||
ObjectSetString (0, cn, OBJPROP_TOOLTIP, ctip);
|
||
// ⚠ SICHTBARE BESCHRIFTUNG ENTFERNT (User-Wunsch 2026-08-17). Sie kam
|
||
// in v1.30 auf die Frage „was bedeutet die graue Box" und war seither
|
||
// dauerhaft im Chart. Der erklaerende Text bleibt als TOOLTIP an der
|
||
// Box (`ctip`, Zeile darueber) — die Information geht also nicht
|
||
// verloren, sie draengt sich nur nicht mehr auf.
|
||
// ⚠ Ein evtl. noch vorhandenes Alt-Objekt aus v1.30-v1.37 wird hier
|
||
// geloescht: `ObjectsDeleteAll(0, PFX)` raeumt zwar bei jedem Redraw,
|
||
// aber nur solange der Indikator laeuft — nach einem Wechsel auf die
|
||
// neue Version ohne Redraw bliebe es sonst stehen.
|
||
ObjectDelete(0, PFX + "TCONSOL");
|
||
continue;
|
||
}
|
||
// WAHRSCHEINLICHKEITS-KEGEL: CN;<minuten>;<lo>;<hi>
|
||
// Zwei sich oeffnende Pfade vom aktuellen Bar aus. ⚠ Das ist KEINE Prognose
|
||
// der Richtung, sondern der STREUUNG: wie weit der Kurs in 30/60/120 min
|
||
// plausibel gelaufen sein kann. Out-of-sample kalibriert (analyze_cone.py):
|
||
// das 80%-Band trifft real ~76%. Bewusst NEUTRAL grau, kein gruen/rot.
|
||
if(typ == "CN")
|
||
{
|
||
if(k < 4) continue;
|
||
if(!InpShowCone) continue;
|
||
int mins = (int)StringToInteger(p[1]);
|
||
double clo = StringToDouble(p[2]);
|
||
double chi = StringToDouble(p[3]);
|
||
if(clo <= 0 || chi <= 0 || mins <= 0) continue;
|
||
// Anker: vom aktuellen Bar bis +mins Minuten (in Broker-Zeit)
|
||
datetime t0 = iTime(_Symbol, PERIOD_CURRENT, 0);
|
||
datetime t1 = t0 + (datetime)(mins * 60);
|
||
// Vorgaenger-Punkt: der naechstkleinere Horizont, sonst der aktuelle Kurs.
|
||
// g_coneT/g_coneLo/g_coneHi halten ihn zwischen den CSV-Zeilen fest; die
|
||
// Zeilen kommen aufsteigend sortiert vom Bot.
|
||
datetime pt = (g_coneT > 0 ? g_coneT : t0);
|
||
double plo = (g_coneT > 0 ? g_coneLo : g_conePx);
|
||
double phi = (g_coneT > 0 ? g_coneHi : g_conePx);
|
||
if(plo <= 0 || phi <= 0) { plo = clo; phi = chi; pt = t0; }
|
||
string ln = PFX + "CONE_L" + IntegerToString(mins);
|
||
string un = PFX + "CONE_U" + IntegerToString(mins);
|
||
string tip = "Streuung (keine Richtung): in " + IntegerToString(mins)
|
||
+ " min liegt der Kurs mit ~76% zwischen "
|
||
+ DoubleToString(clo, (int)_Digits) + " und "
|
||
+ DoubleToString(chi, (int)_Digits);
|
||
for(int s = 0; s < 2; s++)
|
||
{
|
||
string nm2 = (s == 0 ? ln : un);
|
||
double a2 = (s == 0 ? plo : phi);
|
||
double b2 = (s == 0 ? clo : chi);
|
||
if(ObjectCreate(0, nm2, OBJ_TREND, 0, pt, a2, t1, b2))
|
||
{
|
||
ObjectSetInteger(0, nm2, OBJPROP_COLOR, InpConeColor);
|
||
ObjectSetInteger(0, nm2, OBJPROP_STYLE, STYLE_DOT);
|
||
ObjectSetInteger(0, nm2, OBJPROP_WIDTH, 1);
|
||
ObjectSetInteger(0, nm2, OBJPROP_RAY_RIGHT, false);
|
||
ObjectSetInteger(0, nm2, OBJPROP_BACK, true);
|
||
ObjectSetInteger(0, nm2, OBJPROP_SELECTABLE, false);
|
||
}
|
||
else
|
||
{
|
||
ObjectMove(0, nm2, 0, pt, a2);
|
||
ObjectMove(0, nm2, 1, t1, b2);
|
||
}
|
||
ObjectSetString(0, nm2, OBJPROP_TOOLTIP, tip);
|
||
}
|
||
g_coneT = t1; g_coneLo = clo; g_coneHi = chi;
|
||
continue;
|
||
}
|
||
// RICHTUNGS-PFEILE: AR;<art>;<von>;<nach>;<text> art = L | S | K
|
||
// ⚠ KEINE freie Kursprognose (die ist gemessen ein Muenzwurf) - jede Art hat
|
||
// ihre eigene Beleglage, s. Versionshinweis oben.
|
||
if(typ == "AR")
|
||
{
|
||
if(k < 5) continue;
|
||
if(!InpShowArrows) continue;
|
||
string art = p[1];
|
||
if(art == "K" && !InpShowConsensus) continue; // Konsens-Pfeil optional
|
||
double a_from = StringToDouble(p[2]);
|
||
double a_to = StringToDouble(p[3]);
|
||
string a_txt = p[4];
|
||
if(a_from <= 0 || a_to <= 0) continue;
|
||
color ac = (art == "S") ? InpArrSqueeze
|
||
: (art == "K") ? InpArrConsensus : InpArrLevel;
|
||
int aw = (art == "S") ? 3 : 2; // der validierte Pfeil dicker
|
||
datetime at0 = iTime(_Symbol, PERIOD_CURRENT, 0);
|
||
datetime at1 = at0 + (datetime)(PeriodSeconds() * InpArrBars);
|
||
string an = PFX + "ARR_" + art;
|
||
if(ObjectCreate(0, an, OBJ_ARROWED_LINE, 0, at0, a_from, at1, a_to))
|
||
{
|
||
ObjectSetInteger(0, an, OBJPROP_COLOR, ac);
|
||
ObjectSetInteger(0, an, OBJPROP_WIDTH, aw);
|
||
ObjectSetInteger(0, an, OBJPROP_STYLE, STYLE_SOLID);
|
||
ObjectSetInteger(0, an, OBJPROP_RAY_RIGHT, false);
|
||
ObjectSetInteger(0, an, OBJPROP_BACK, false);
|
||
ObjectSetInteger(0, an, OBJPROP_SELECTABLE, false);
|
||
}
|
||
else
|
||
{
|
||
ObjectMove(0, an, 0, at0, a_from);
|
||
ObjectMove(0, an, 1, at1, a_to);
|
||
ObjectSetInteger(0, an, OBJPROP_COLOR, ac);
|
||
}
|
||
ObjectSetString(0, an, OBJPROP_TOOLTIP, a_txt);
|
||
// Beschriftung an der Pfeilspitze (rechtsbuendig wie alle anderen Labels)
|
||
string atn = PFX + "ALBL_" + art; // NICHT "T..." (s. RepositionLabels)
|
||
if(ObjectCreate(0, atn, OBJ_TEXT, 0, at1, a_to))
|
||
{
|
||
ObjectSetInteger(0, atn, OBJPROP_COLOR, ac);
|
||
ObjectSetInteger(0, atn, OBJPROP_FONTSIZE, InpLabelSize);
|
||
ObjectSetInteger(0, atn, OBJPROP_ANCHOR, ANCHOR_LEFT);
|
||
ObjectSetInteger(0, atn, OBJPROP_BACK, false);
|
||
ObjectSetInteger(0, atn, OBJPROP_SELECTABLE, false);
|
||
}
|
||
else
|
||
ObjectMove(0, atn, 0, at1, a_to);
|
||
ObjectSetString(0, atn, OBJPROP_TEXT, " " + a_txt);
|
||
continue;
|
||
}
|
||
// HYPERLIQUID-KURS unter dem Broker-Kurs: HL;<mt5_aequiv>;<alter_s>;<bid>;<ask>;<U|D|->
|
||
// HL (`xyz:CL`) handelt 24/7, Pepperstone nicht - am Wochenende der einzige
|
||
// lebende Kurs. Bereits basis-korrigiert, also direkt vergleichbar.
|
||
if(typ == "HL")
|
||
{
|
||
if(k < 6) continue;
|
||
if(!InpShowHL) continue;
|
||
double hlp = StringToDouble(p[1]);
|
||
if(hlp <= 0) continue;
|
||
int hage = (int)StringToInteger(p[2]);
|
||
string htr = p[5];
|
||
string hn = PFX + "HLPX";
|
||
if(ObjectFind(0, hn) < 0)
|
||
{
|
||
ObjectCreate(0, hn, OBJ_LABEL, 0, 0, 0);
|
||
ObjectSetInteger(0, hn, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
|
||
ObjectSetInteger(0, hn, OBJPROP_XDISTANCE, 12);
|
||
// unter Kurs (14) und G/V (14+PriceSize+6) einreihen
|
||
// Y wird unten jeden Redraw gesetzt
|
||
ObjectSetInteger(0, hn, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
|
||
ObjectSetInteger(0, hn, OBJPROP_SELECTABLE, false);
|
||
ObjectSetString (0, hn, OBJPROP_FONT, "Arial");
|
||
}
|
||
ObjectSetInteger(0, hn, OBJPROP_FONTSIZE, (int)MathMax(10, InpPriceSize - 7));
|
||
ObjectSetInteger(0, hn, OBJPROP_YDISTANCE,
|
||
14 + LabelH("Arial Black", InpPriceSize)
|
||
+ LabelH("Arial", (int)MathMax(8, InpPriceSize - 4)));
|
||
ObjectSetInteger(0, hn, OBJPROP_COLOR, InpHLColor);
|
||
ObjectSetString (0, hn, OBJPROP_TEXT,
|
||
"HL " + DoubleToString(hlp, (int)_Digits)
|
||
+ (htr == "U" ? " ^" : htr == "D" ? " v" : ""));
|
||
ObjectSetString (0, hn, OBJPROP_TOOLTIP,
|
||
"Hyperliquid xyz:CL, basis-korrigiert auf MT5-Niveau - "
|
||
+ IntegerToString(hage) + " s alt. Waende "
|
||
+ p[3] + " / " + p[4]);
|
||
continue;
|
||
}
|
||
// AKTUELLER KURS oben rechts, fett (User-Wunsch): PX;bid
|
||
if(typ == "PX")
|
||
{
|
||
if(k < 2) continue;
|
||
double pxv = StringToDouble(p[1]);
|
||
if(pxv <= 0) continue;
|
||
// Kegel-Startpunkt IMMER merken - auch wenn das Kurs-Label aus ist
|
||
// (sonst verliert der Faecher seinen Anker).
|
||
g_conePx = pxv;
|
||
if(!InpShowPrice) 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);
|
||
// ⚠ Y-STAPEL oben rechts (Fix 2026-08-19). Reihenfolge von oben:
|
||
// Kurs (20 pt) -> G/V (16 pt) -> HL (13 pt). Die Abstaende
|
||
// rechnen mit Faktor 1,8 px je PUNKT — FONTSIZE ist in Punkt,
|
||
// nicht Pixel. Die alte Formel behandelte sie wie Pixel, dadurch
|
||
// lag G/V (y=44) IM Kurs (14..50) und HL (y=56) IM G/V (44..73).
|
||
ObjectSetInteger(0, pn, OBJPROP_YDISTANCE, 14); // s. u. — jeden Redraw
|
||
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);
|
||
}
|
||
// ⚠ JEDEN Redraw setzen, nicht nur beim Erzeugen — sonst behaelt ein
|
||
// bereits vorhandenes Label seine ALTE Position fuer immer.
|
||
ObjectSetInteger(0, pn, OBJPROP_YDISTANCE, 14);
|
||
ObjectSetString (0, pn, OBJPROP_TEXT, DoubleToString(pxv, (int)_Digits));
|
||
ObjectSetInteger(0, pn, OBJPROP_COLOR, InpPriceColor);
|
||
continue;
|
||
}
|
||
// ZONEN (RZ;lo;hi = Widerstand · SZ;lo;hi = Support) — User-Wunsch
|
||
// 2026-08-17 nach einem TradingView-Bild. Farbiges Band statt nackter
|
||
// Linie; die BREITE ist die echte Spanne der Pivots, die den Cluster
|
||
// gebildet haben (nicht Fibonacci — das ist im Projekt gemessen und
|
||
// verworfen). Nach rechts verlaengert, damit es wie im Vorbild wirkt.
|
||
// BESTAETIGTES CHARTMUSTER je Zeitebene (PT;<TF>;<name>;<dir>;<trigger>;<ziel>)
|
||
// — User-Wunsch 2026-08-21.
|
||
// ⚠⚠ Es wird NUR die Zeile gezeichnet, deren <TF> zum EIGENEN Chart passt.
|
||
// Der Bot liefert alle Zeitebenen in derselben CSV; ohne diesen Filter
|
||
// laegen fuenf Musterpaare uebereinander und keines waere lesbar.
|
||
// So bekommt jedes Chartfenster (M1/M5/M15/H1) sein eigenes Muster.
|
||
// ⚠⚠ EHRLICHKEIT: die Ziel-Trefferquote dieser Muster-Klasse liegt gemessen
|
||
// bei nur 13-38 % (backtest_patterns.py). Sie steht im Label, weil eine
|
||
// gezeichnete Ziellinie sonst wie eine Prognose aussieht — und genau das
|
||
// ist sie nicht.
|
||
// ⚠ Nur `confirmed` kommt ueberhaupt an; "bildet sich" waere der Zustand, in
|
||
// dem noch nichts gebrochen ist.
|
||
if(typ == "PT")
|
||
{
|
||
if(!InpShowMuster || k < 6) continue;
|
||
if(p[1] != TFName(PERIOD_CURRENT)) continue; // fremde Zeitebene
|
||
double trg = StringToDouble(p[4]), zl = StringToDouble(p[5]);
|
||
if(trg <= 0 || zl <= 0) continue;
|
||
bool bull = (p[3] == "bull");
|
||
color pc = bull ? InpMusterBullColor : InpMusterBearColor;
|
||
datetime pt0 = iTime(_Symbol, PERIOD_CURRENT,
|
||
MathMin(80, Bars(_Symbol, PERIOD_CURRENT) - 1));
|
||
string ln1 = PFX + "MUST_TRG", ln2 = PFX + "MUST_ZIEL";
|
||
if(ObjectFind(0, ln1) < 0)
|
||
{
|
||
ObjectCreate(0, ln1, OBJ_TREND, 0, pt0, trg, RightTime(), trg);
|
||
ObjectSetInteger(0, ln1, OBJPROP_RAY_RIGHT, false);
|
||
ObjectSetInteger(0, ln1, OBJPROP_WIDTH, 2);
|
||
ObjectSetInteger(0, ln1, OBJPROP_SELECTABLE, false);
|
||
}
|
||
if(ObjectFind(0, ln2) < 0)
|
||
{
|
||
ObjectCreate(0, ln2, OBJ_TREND, 0, pt0, zl, RightTime(), zl);
|
||
ObjectSetInteger(0, ln2, OBJPROP_RAY_RIGHT, false);
|
||
ObjectSetInteger(0, ln2, OBJPROP_STYLE, STYLE_DOT);
|
||
ObjectSetInteger(0, ln2, OBJPROP_SELECTABLE, false);
|
||
}
|
||
ObjectSetInteger(0, ln1, OBJPROP_COLOR, pc);
|
||
ObjectMove(0, ln1, 0, pt0, trg); ObjectMove(0, ln1, 1, RightTime(), trg);
|
||
ObjectSetInteger(0, ln2, OBJPROP_COLOR, pc);
|
||
ObjectMove(0, ln2, 0, pt0, zl); ObjectMove(0, ln2, 1, RightTime(), zl);
|
||
string plb = PFX + "MUST_LBL";
|
||
if(ObjectFind(0, plb) < 0)
|
||
{
|
||
ObjectCreate(0, plb, OBJ_TEXT, 0, RightTime(), trg);
|
||
ObjectSetInteger(0, plb, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
|
||
ObjectSetInteger(0, plb, OBJPROP_FONTSIZE, InpLabelSize);
|
||
ObjectSetInteger(0, plb, OBJPROP_SELECTABLE, false);
|
||
}
|
||
ObjectSetString(0, plb, OBJPROP_TEXT,
|
||
(bull ? "^ " : "v ") + p[2] + " bestaetigt - Ziel "
|
||
+ DoubleToString(zl, (int)_Digits) + " (trifft 13-38 %)");
|
||
ObjectSetInteger(0, plb, OBJPROP_COLOR, pc);
|
||
ObjectMove(0, plb, 0, RightTime(), trg);
|
||
continue;
|
||
}
|
||
if(typ == "RZ" || typ == "SZ")
|
||
{
|
||
if(!InpShowZonen || k < 3) continue;
|
||
double zlo = StringToDouble(p[1]), zhi = StringToDouble(p[2]);
|
||
if(zlo <= 0 || zhi <= 0) continue;
|
||
string zn = PFX + "ZONE_" + typ;
|
||
color zc = (typ == "RZ" ? InpZoneResColor : InpZoneSupColor);
|
||
datetime t1 = iTime(_Symbol, PERIOD_CURRENT, MathMin(60, Bars(_Symbol, PERIOD_CURRENT) - 1));
|
||
if(ObjectFind(0, zn) < 0)
|
||
{
|
||
ObjectCreate(0, zn, OBJ_RECTANGLE, 0, t1, zlo, RightTime(), zhi);
|
||
ObjectSetInteger(0, zn, OBJPROP_FILL, true);
|
||
ObjectSetInteger(0, zn, OBJPROP_BACK, true);
|
||
ObjectSetInteger(0, zn, OBJPROP_SELECTABLE, false);
|
||
}
|
||
ObjectSetInteger(0, zn, OBJPROP_COLOR, zc);
|
||
ObjectMove(0, zn, 0, t1, zlo);
|
||
ObjectMove(0, zn, 1, RightTime(), zhi);
|
||
// Beschriftung an der Oberkante, rechtsbuendig wie die S/R-Labels
|
||
string zt = PFX + "TZONE_" + typ;
|
||
if(ObjectFind(0, zt) < 0)
|
||
{
|
||
ObjectCreate(0, zt, OBJ_TEXT, 0, RightTime(), zhi);
|
||
ObjectSetInteger(0, zt, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
|
||
ObjectSetInteger(0, zt, OBJPROP_FONTSIZE, InpLabelSize);
|
||
ObjectSetInteger(0, zt, OBJPROP_SELECTABLE, false);
|
||
}
|
||
ObjectSetString (0, zt, OBJPROP_TEXT,
|
||
(typ == "RZ" ? "Resistance Zone " : "Support Zone ")
|
||
+ DoubleToString(zlo, (int)_Digits) + " - "
|
||
+ DoubleToString(zhi, (int)_Digits));
|
||
ObjectSetInteger(0, zt, OBJPROP_COLOR, zc);
|
||
ObjectMove(0, zt, 0, RightTime(), zhi);
|
||
continue;
|
||
}
|
||
// MELDUNGEN oben LINKS (MS;<text>) — User-Wunsch 2026-08-17.
|
||
// Dieselben Zeilen wie die Dashboard-Karte „Meldungen"; der Bot setzt sie
|
||
// zusammen und deckelt auf 5. Hier nur gestapelt darstellen.
|
||
// ⚠ Eigener Praefix MSPFX, damit sie beim Redraw sauber verschwinden, wenn
|
||
// der Bot keine MS-Zeile mehr schickt (sonst blieben Alt-Meldungen
|
||
// stehen — genau der Fehler, den die HL-Pfeile schon einmal hatten).
|
||
if(typ == "MS")
|
||
{
|
||
if(!InpShowMeldungen || k < 2) continue;
|
||
string mn = PFX + "MSG_" + IntegerToString(msg_idx);
|
||
if(ObjectFind(0, mn) < 0)
|
||
{
|
||
ObjectCreate(0, mn, OBJ_LABEL, 0, 0, 0);
|
||
ObjectSetInteger(0, mn, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||
// ⚠ ZENTRIERT (User-Wunsch 2026-08-19). MT5 kennt keine „Mitte"-Ecke:
|
||
// der Bezugspunkt bleibt LINKS OBEN, aber der ANKER wird auf
|
||
// ANCHOR_UPPER (Text-Oberkante MITTIG) gesetzt und der X-Abstand
|
||
// auf die halbe Chartbreite gelegt. Damit waechst der Text nach
|
||
// beiden Seiten und bleibt bei jeder Fensterbreite zentriert.
|
||
ObjectSetInteger(0, mn, OBJPROP_ANCHOR, ANCHOR_UPPER);
|
||
ObjectSetString (0, mn, OBJPROP_FONT, "Arial");
|
||
ObjectSetInteger(0, mn, OBJPROP_FONTSIZE, InpMeldungSize);
|
||
ObjectSetInteger(0, mn, OBJPROP_SELECTABLE, false);
|
||
ObjectSetInteger(0, mn, OBJPROP_BACK, false);
|
||
}
|
||
// ⚠⚠ POSITION KORRIGIERT (User 2026-08-19: „die Anzeigetexte oben links
|
||
// ueberlagern sich"). ZWEI Fehler steckten im alten `16 + i*(size+6)`:
|
||
// (1) START zu hoch: MT5 zeichnet oben links SELBST die Symbol-/
|
||
// Zeitrahmen-Beschriftung ("SpotCrude,M5") und ggf. die
|
||
// OHLC-Zeile. y=16 landete mitten darin. Der Beleg war, dass sich
|
||
// etwas ueberlagerte, obwohl nur EINE MS-Zeile aktiv war — es
|
||
// konnten also gar nicht zwei Meldungen sein.
|
||
// (2) ABSTAND zu knapp: `OBJPROP_FONTSIZE` ist in PUNKT, nicht Pixel.
|
||
// 10 pt rendern je nach DPI-Skalierung 16-20 px hoch — bei 16 px
|
||
// Zeilenabstand ueberlappen mehrere Meldungen zwangslaeufig.
|
||
// Jetzt Faktor 2,0 (10 pt -> 20 px), das traegt auch 125 % DPI.
|
||
// ⚠ X JEDEN Redraw neu setzen, nicht nur beim Erzeugen: die Chartbreite
|
||
// aendert sich beim Groessenaendern des Fensters, sonst bliebe die
|
||
// Zentrierung auf der alten Breite haengen.
|
||
ObjectSetInteger(0, mn, OBJPROP_XDISTANCE,
|
||
(int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
|
||
ObjectSetInteger(0, mn, OBJPROP_YDISTANCE,
|
||
InpMeldungY + msg_idx * msg_h);
|
||
// ⚠⚠ FONTSIZE JEDEN Redraw setzen, nicht nur beim Erzeugen (v1.44).
|
||
// Genau daran scheiterte v1.43: ein bereits existierendes Label
|
||
// behaelt seine Schriftgroesse, die Erhoehung 10 -> 11 pt kam auf
|
||
// dem Chart also nie an. Gleiche Klasse wie die X-Position darueber.
|
||
ObjectSetInteger(0, mn, OBJPROP_FONTSIZE, InpMeldungSize);
|
||
ObjectSetString (0, mn, OBJPROP_TEXT, p[1]);
|
||
ObjectSetInteger(0, mn, OBJPROP_COLOR, InpMeldungColor);
|
||
msg_idx++;
|
||
continue;
|
||
}
|
||
// G/V der offenen Position — direkt UNTER dem Kurs (User-Wunsch 2026-07-30):
|
||
// PL;wert;waehrung. Wert ist NETTO (Bot rechnet die WHT-Quellensteuer schon
|
||
// raus, wie im Dashboard). Gruen im Plus, rot im Minus. Ohne offene Position
|
||
// schickt der Bot keine PL-Zeile -> das Label wird unten geloescht.
|
||
if(typ == "PL")
|
||
{
|
||
if(k < 2) continue;
|
||
if(!InpShowPnL) continue;
|
||
double plv = StringToDouble(p[1]);
|
||
string cur = (k > 2) ? p[2] : "";
|
||
string qn = PFX + "PNL";
|
||
if(ObjectFind(0, qn) < 0)
|
||
{
|
||
ObjectCreate(0, qn, OBJ_LABEL, 0, 0, 0);
|
||
ObjectSetInteger(0, qn, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
|
||
ObjectSetInteger(0, qn, OBJPROP_XDISTANCE, 12);
|
||
// direkt unter dem Kurs: dessen Y (14) + Schrifthoehe + kleiner Abstand
|
||
// Y wird unten jeden Redraw gesetzt
|
||
ObjectSetInteger(0, qn, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);
|
||
ObjectSetString (0, qn, OBJPROP_FONT, "Arial Black");
|
||
ObjectSetInteger(0, qn, OBJPROP_SELECTABLE, false);
|
||
}
|
||
ObjectSetInteger(0, qn, OBJPROP_FONTSIZE, (int)MathMax(8, InpPriceSize - 4));
|
||
ObjectSetInteger(0, qn, OBJPROP_YDISTANCE,
|
||
14 + LabelH("Arial Black", InpPriceSize));
|
||
ObjectSetString (0, qn, OBJPROP_TEXT,
|
||
(plv >= 0 ? "+" : "") + DoubleToString(plv, 2)
|
||
+ (StringLen(cur) > 0 ? " " + cur : ""));
|
||
ObjectSetInteger(0, qn, OBJPROP_COLOR,
|
||
(plv >= 0 ? InpPnLUpColor : InpPnLDownColor));
|
||
continue;
|
||
}
|
||
// TRADE-MARKER: TR;<O|C>;<broker_time> → 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;<U|D> (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, InpTrendLineColor);
|
||
ObjectSetInteger(0, nm, OBJPROP_STYLE, STYLE_SOLID);
|
||
ObjectSetInteger(0, nm, OBJPROP_WIDTH, 2);
|
||
// ⚠ KEIN RAY_RIGHT: eine 60-min-Regression 100 Bars in die Zukunft zu
|
||
// verlängern ergibt keinen Sinn und riss die Linie optisch ins
|
||
// Bodenlose (User-Feedback „das Bild sieht komisch aus", 2026-07-30).
|
||
// Die Linie endet jetzt am aktuellen Rand.
|
||
ObjectSetInteger(0, nm, OBJPROP_RAY_RIGHT, false);
|
||
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);
|
||
ObjectSetInteger(0, nm, OBJPROP_RAY_RIGHT, false);
|
||
}
|
||
// 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, InpLabelColor);
|
||
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();
|
||
}
|
||
//+------------------------------------------------------------------+
|