Vom Neuling zum Experten: Synchronisieren der Zeitrahmen des Marktes
Inhalt
Einführung
Verstehen der visuellen Beschränkung der Standard-Zeitrahmen in MetaTrader 5
Bei der Analyse von Charts auf höheren Zeitskalen wie D1 oder H4 beobachten Händler oft Kerzenformationen, die eine große Bedeutung haben, wie z. B. die Muster Doji, Hammer oder Bullish Engulfing. Diese Kerzen mit höherem Zeitrahmen stellen jedoch die Zusammenfassung vieler kleinerer Kerzen dar und verschleiern daher die genaue interne Preisaktion, die in den niedrigeren Zeitrahmen stattgefunden hat.
Wenn Sie das Chart von einem höheren zu einem niedrigeren Zeitrahmen wechseln, bleibt die visuelle Zuordnung dieser größeren Zeiträume nicht erhalten. Infolgedessen verlieren Händler die Möglichkeit, leicht zu erkennen, wie sich der Preis innerhalb jeder Hauptkerze entwickelt hat – zum Beispiel, wo sich die Dynamik verschoben hat oder eine Konsolidierung innerhalb eines Balkens mit höherem Zeitrahmen stattgefunden hat.
Obwohl MetaTrader 5 eine eingebaute Option zur Anzeige von Punkttrennzeichen bietet, ist diese Funktion statisch und in ihrem Umfang begrenzt. Sie ist insbesondere dann unzureichend, wenn mit Zeitrahmen gearbeitet wird, die kürzer als ein Tag sind, oder wenn die Händler ein höheres Maß an Kontrolle über die Darstellung dieser Zeiträume benötigen.
Einführung in den Market Periods Synchronizer Indicator
Um diese Einschränkung zu überwinden, führen wir eine nutzerdefinierte Lösung mit dem Namen „Market Periods Synchronizer“ ein – ein in MQL5 entwickelter Indikator, der eine vollständige Anpassung der vertikalen Periodenmarker über mehrere Zeitrahmen hinweg ermöglicht. Das Tool synchronisiert visuell die Grenzen des höheren Zeitrahmens mit den Charts des niedrigeren Zeitrahmens und ermöglicht es Händlern, detaillierte Kursbewegungen innerhalb einer Periode zu studieren, während der Kontext des höheren Zeitrahmens erhalten bleibt.
Durch diesen Ansatz können die Nutzer:
- Darstellung und Farbcodierung von Markern für mehrere höhere Zeitrahmen gleichzeitig sehen.
- Untersuchen, wie kleinere Kerzen über Marktphasen hinweg größere Strukturen bilden.
- Die Markierungsintervalle, Sichtbarkeit und Farbschemata anpassen.
- Die Kerzenkörpern der höherem Zeitrahmen hervorheben und füllen.
- Markieren, öffnen und schließen der Kurshorizonte für jeden höheren Zeitrahmen.
- Das Zeichnen auf den sichtbaren Chart-Bereich (Leistungsoption) beschränken.
- Mehrere kleinere Intervalle, die sich nicht mit Dur-Intervallen überschneiden, verwenden.
Das folgende Bild zeigt die Standard-Visualisierung von MetaTrader 5 vor der Verbesserung – und hebt die Lücke hervor, die der Market Periods Synchronizer schließen soll.

Abb. 1. Einstellen von Standard-Perioden-Trennzeichen auf MetaTrader 5
In der Umsetzungsphase ist es unser Ziel, den Market Periods Synchronizer Indikator so zu gestalten, dass er sowohl visuelle Klarheit als auch analytische Tiefe aufweist. Das Tool ermöglicht es Händlern, die Kursentwicklung innerhalb eines Balkens visuell zu untersuchen, z. B. wie sich M1- oder M5-Kerzen innerhalb eines H1- oder D1-Balkens bilden, und zeigt die Schwungverschiebungen, Ablehnungen und Mikrostrukturen auf, aus denen sich Muster in höheren Zeitrahmen zusammensetzen. Ein entscheidender Vorteil dieses Designs besteht darin, dass die Nutzer auch in der Lage sein werden, Docht-Kursbewegungen zu beobachten, die sich über Kerzenkörper mit höherem Zeitrahmen hinaus erstrecken und neue Einblicke in die Volatilität und das Ablehnungsverhalten bieten, die diese größeren Kerzen prägen.
Der Indikator zeigt sowohl die Grenzen des Hauptzeitrahmens als auch die optionalen Grenzen des Zwischenzeitrahmens (Nebenzeitrahmens) in einem einzigen Chart des unteren Zeitrahmens an, jeweils mit unabhängiger Farbe und Linienart für eine klare visuelle Trennung. Die Nutzer können wählen, welche Zeitrahmen angezeigt werden sollen, die Rückblick-Tiefe einstellen und einzelne Serien ein- oder ausschalten, während sie Farben, Breiten und Linienstile an ihre analytischen Vorlieben anpassen können.
Um die Interpretation zu verbessern, wird das System eine Option enthalten, um die Preisspanne jeder Kerze mit höherem Zeitrahmen (steigt, fällt oder neutral ist) auszufüllen und kurze horizontale Linien für Eröffnungs- und Schlussniveaus zu zeichnen, was Händlern hilft, intraperiodische Umkehrpunkte und Reaktionszonen zu untersuchen. Um eine reibungslose Leistung zu gewährleisten, optimiert der Indikator die Zeichenvorgänge, indem er nur die Marker darstellt, die sich innerhalb des aktuell sichtbaren Chartfensters befinden. Dies ist besonders wichtig, wenn große Rückblicke auf M1- oder M5-Charts analysiert werden. Schließlich wird durch die Implementierung gewährleistet, dass die Zwischenzeitmarken genau zwischen aufeinanderfolgenden Hauptgrenzen positioniert werden, um Überschneidungen oder Behinderungen der Hauptmarken zu vermeiden.
Umsetzung
Dieser Indikator verwendet einen minimalen Dummy-Plot-Puffer (um MetaTrader 5-Warnungen auszuschalten) und steuert alle Grafiken mit Chart-Objekten (OBJ_VLINE, OBJ_TEXT, etc.). Ein Timer aktualisiert die Objekte in regelmäßigen Abständen, sodass sich der Indikator auch bei Charts mit niedrigem Zeitrahmen anpasst. Die Kernroutine ist RefreshLines(), die Balkenzeiten höherer Zeitrahmen kopiert und Objekte entsprechend erstellt/entfernt. Hilfsprogramme verwalten die Objektbereinigung.
1. Dateikopf und Dummy-Plot (Metadaten)
Wir deklarieren die Indikator-Metadaten und einen Dummy-Plot-Puffer. In MQL5 muss ein Indikator OnCalculate() implementieren, und normalerweise erstellen Sie Plotpuffer, die das Terminal zeichnet. Unser Werkzeug zeichnet keine Preisseriendaten, sondern Chart-Objekte (vertikale Linien, Rechtecke und Text). Der Compiler und das Terminal erwarten jedoch immer noch mindestens eine Puffer-/Plotdefinition für einen Indikator. Der übliche Trick besteht darin, einen einzigen „Dummy“-Puffer zu deklarieren, seinen PLOT_EMPTY_VALUE auf EMPTY_VALUE zu setzen und ihm niemals sinnvolle Werte zuzuweisen. Auf diese Weise erscheint der Indikator auf dem Terminal als gültig, erzeugt aber keine sichtbare Pufferkurve. Dieses Muster verhindert Warnungen und ermöglicht es uns, das Bildmaterial ausschließlich mit Chart-Objekten zu verwalten.
Ein paar Feinheiten von MQL5, die Sie beachten sollten:
- #property indicator_chart_window weist MetaTrader 5 an, den Indikator an das Hauptchart anzuhängen (damit die Objekte mit der Preisachse übereinstimmen).
- Halten Sie den Dummy-Puffer einfach und markieren Sie ihn mit INDICATOR_DATA, wenn Sie SetIndexBuffer aufrufen.
- Rufen Sie immer ArraySetAsSeries() in OnCalculate() für Puffer auf, die wie Preisreihen indiziert sind (0 = neueste) – wir zeigen das später.
//+------------------------------------------------------------------+ //| MarketPeriodsSynchronizer.mq5 | //+------------------------------------------------------------------+ #property copyright "Clemence Benjamin" #property version "1.01" #property indicator_chart_window // Dummy buffer to satisfy MT5 (we draw with chart objects) #property indicator_buffers 1 #property indicator_plots 1 #property indicator_label1 "HiddenDummy" #property indicator_type1 DRAW_LINE #property indicator_width1 1 #property indicator_color1 clrSilver double PlotDummyBuffer[];
2. Eingabe-Parameter
Inputs sind die öffentliche API Ihres Indikators. Wenn Sie Eingabevariablen deklarieren, erstellt MetaTrader UI-Felder für sie (im Indikator-Dialog) und macht sie zur Laufzeit schreibgeschützt. Da die Eingabevariablen im Code konstant sind, kopieren wir alle Werte, die möglicherweise intern angepasst werden müssen, in veränderbare globale Variablen (z. B. g_lookback). Diese Trennung verhindert eine versehentliche Änderung der Eingabewerte, während die Laufzeitvariablen für die Optimierung flexibel bleiben.
Die wichtigsten Punkte für jede Art der Eingabe:
- ENUM_TIMEFRAMES – bequeme typisierte Konstanten der Zeitrahmen (PERIOD_M15, PERIOD_H1, etc.). Sie werden zu ganzen Zahlen kompiliert, sind aber besser lesbar.
- Colors – MQL5 akzeptiert benannte Farbkonstanten (z.B. clrRed) oder ganzzahlige ARGB-Werte; benannte Farben sind aus Gründen der Lesbarkeit sicherer.
- Linienstil – Konstanten wie STYLE_SOLID und STYLE_DASH sind Integer-Konstanten; deklarieren Sie die Eingabe als int, um ein stabiles Verhalten über verschiedene Terminals hinweg zu gewährleisten.
- Performance – InpLookback steuert, wie viele HTF-Balken wir kopieren. Ein großer Rückblick auf M1/M5 kann teuer sein, wählen Sie eine konservative Standardeinstellung (200) und fügen Sie später eine Optimierung für den sichtbaren Bereich hinzu.
- Boolesche Werte zum Aktivieren/Deaktivieren optionaler Funktionen (Füllungen, Minuszeichen, offene/geschlossene Linien) ermöglichen es dem Nutzer, visuellen Reichtum gegen Leistung einzutauschen.
//--- inputs (Major) input ENUM_TIMEFRAMES InpHigherTF = PERIOD_H1; // Major higher timeframe to mark input int InpLookback = 200; // How many higher-TF bars to draw input color InpColorMajor = clrRed; // Major line color input int InpWidthMajor = 2; // Major line width input int InpRefreshSec = 5; // Refresh interval in seconds //--- inputs (Open/Close horizontals for Major) input bool InpShowOpenClose = true; // Show open/close horizontal markers? input color InpColorOpen = clrGreen; // Open line color input color InpColorClose = clrLime; // Close line color input int InpWidthOC = 1; // Open/Close line width input int InpStyleOC = STYLE_DASH;// Open/Close line style (integer) input int InpHorizOffsetBars = 3; // Horizontal length in current TF bars //--- inputs (Body fill for Major) input bool InpShowFill = true; // Show body fill? input color InpFillBull = clrLime; // Bullish fill color input color InpFillBear = clrTomato; // Bearish fill color //--- inputs (Minor 1) input bool InpShowMinor1 = false; // Show intermediate Minor 1? input ENUM_TIMEFRAMES InpMinor1TF = PERIOD_M30; // Minor1 TF (default M30) input color InpColorMin1 = clrOrange; // Minor1 color input int InpWidthMin1 = 1; // Minor1 width //--- inputs (Minor 2) input bool InpShowMinor2 = false; // Show intermediate Minor 2? input ENUM_TIMEFRAMES InpMinor2TF = PERIOD_M15; // Minor2 TF (default M15) input color InpColorMin2 = clrYellow; // Minor2 color input int InpWidthMin2 = 1; // Minor2 width
3. Puffer, veränderbare Kopien und Benennungskonventionen
Eine gute Namensgebung und ein kontrollierter Zustand machen den Code wartbar und robust. Ein paar Grundsätze:
- Dummy-Puffer: Wir haben PlotDummyBuffer[] früher deklariert, er zeichnet nie etwas (wir werden ihn mit EMPTY_VALUE füllen).
- Veränderbare Kopien: g_lookback spiegelt InpLookback wider, kann aber intern angepasst werden (z. B. gekappt).
- Präfixe für Objekte: Die Verwendung einheitlicher Präfixe (z. B. HTF_MAJ_, HTF_MIN1_) verhindert Namenskollisionen mit anderen Chart-Objekten und erleichtert die Bereinigung (suchen Sie beim Löschen nach „HTF_“).
- Lebensdauer des Arrays: Verwenden Sie ArrayFree() vor CopyTime(), um sicherzustellen, dass die Arrays leer sind; verwenden Sie ArrayResize(), um die Größe der Arrays zu bestimmen, wenn Sie nach Index schreiben wollen. ArraySetAsSeries() wirkt sich auf die Indexreihenfolge aus (0 = das Neueste) – achten Sie beim Lesen/Schreiben von Arrays ausdrücklich auf die Ausrichtung.
//--- indicator buffer (dummy) double PlotDummyBuffer[]; // mutable working copy of input(s) int g_lookback = 200; // name prefixes static string PREFIX_MAJ = "HTF_MAJ_"; static string PREFIX_MIN1 = "HTF_MIN1_"; static string PREFIX_MIN2 = "HTF_MIN2_";
4. Initialisierung (OnInit) – Lebenszyklusmechanismus und Sicherheit
OnInit() ist der Ort zum Einrichten: Binden von Puffern, Setzen von PLOT_EMPTY_VALUE, Kopieren/Validieren von Eingaben, Setzen von Timern und Ausführen der ersten Zeichnung. Wichtige Details und Fallen:
- SetIndexBuffer(0, PlotDummyBuffer, INDICATOR_DATA) bindet den Puffer an den Index 0. INDICATOR_DATA ist das gemeinsame Kennzeichen für Indikatorpuffer.
- PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE) teilt dem Terminal mit, dass EMPTY_VALUE „kein Plot“ bedeutet – indem EMPTY_VALUE in den Puffer geschrieben wird, bleibt der Plot unsichtbar.
- EventSetTimer(MathMax(1, InpRefreshSec)) registriert einen periodischen Rückruf an OnTimer(). Wählen Sie ein vernünftiges Minimum (1 Sekunde), um die CPU nicht zu überlasten. Denken Sie daran, EventKillTimer() in OnDeinit() aufzurufen.
- Führen Sie einen ersten Aufruf von RefreshLines() durch, damit das Chart sofort nach der Initialisierung synchronisiert wird.
int OnInit() { SetIndexBuffer(0, PlotDummyBuffer, INDICATOR_DATA); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); // copy input to mutable g_lookback = (InpLookback <= 0 ? 200 : InpLookback); // set timer (minimum 1s) EventSetTimer(MathMax(1, InpRefreshSec)); // initial draw RefreshLines(); return(INIT_SUCCEEDED); }
5. Deinitialisierung und Timer – Sauberes Ende und kontrollierte Aktualisierung
Beenden Sie den Timer ordnungsgemäß in OnDeinit(), damit das Terminal keine verwaisten Timer hinterlässt, die weiterhin OnTimer() aufrufen können, nachdem der Indikator verschwunden ist. OnTimer() sollte leichtgewichtig sein – es ruft einfach RefreshLines() auf, um die Objekte aktuell zu halten. Wenn Sie später schwere Operationen (Datei-E/A, Netzwerk) hinzufügen, verpacken Sie sie in Prüfungen, damit OnTimer() billig bleibt.
void OnDeinit(const int reason) { EventKillTimer(); // Optionally remove objects: // DeleteAllHTFLines(); } void OnTimer() { RefreshLines(); }
6. Minimale Einhaltung des OnCalculate – Indikatormodells und Pufferausrichtung
MetaTrader 5 erwartet OnCalculate() für jeden Indikator. Auch wenn wir keine Puffer zum Zeichnen verwenden, müssen wir sie dennoch implementieren. Ein paar wichtige MQL5-Konzepte für die Leser:
- ArraySetAsSeries(array, true) legt die Ausrichtung der Serie fest, wobei Index 0 der neueste Balken ist. Dies ist wichtig, wenn Sie Arrays mit Balkenverschiebungen indizieren (Shift=0 aktueller Takt).
- prev_calculated gibt an, wie viele Balken zuvor berechnet wurden. Verwenden Sie es, um nur einmal zu initialisieren und um neu hinzugefügte Balken mit EMPTY_VALUE zu füllen, damit Dummy-Plot ruhig bleibt.
- Geben Sie am Ende immer rates_total (die Anzahl der verarbeiteten Balken) zurück; MetaTrader 5 verwendet den Rückgabewert, um prev_calculated beim nächsten Aufruf zu setzen.
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[]) { // make the dummy buffer a series (0 = newest) ArraySetAsSeries(PlotDummyBuffer, true); // initialize to EMPTY_VALUE so no visible plot appears if(prev_calculated < 1) ArrayInitialize(PlotDummyBuffer, EMPTY_VALUE); else { int to_fill = rates_total - prev_calculated; if(to_fill > 0) for(int i = 0; i < to_fill && i < rates_total; ++i) PlotDummyBuffer[i] = EMPTY_VALUE; } return(rates_total); }
7. Kernroutine – RefreshLines() mit Optimierung des sichtbaren Bereichs.
Dies ist die wichtigste Funktion. Ich erkläre die Schritte, typische MQL5-Probleme und zeige eine optimierte Implementierung, die Marker bleiben auf das sichtbare Chart-Fenster beschränkt (großer Leistungsgewinn auf M1/M5 mit großen Rückblicken).
Warum Optimierung des sichtbaren Bereichs?
Das Kopieren langer HTF-Historien und das Erstellen von Hunderten oder Tausenden von Chart-Objekten in einem kleinen Zeitrahmen ist teuer. Wenn der Nutzer nur einen kleinen Teil der Historie betrachtet, sollten Sie nur Objekte erstellen, die in das sichtbare Zeitfenster fallen. MetaTrader 5 bietet ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR) (Index des ersten sichtbaren Balkens) und ChartGetInteger(0, CHART_WIDTH_IN_BARS) (Anzahl der sichtbaren Balken) – damit können Sie time_from und time_to im aktuellen Chart-Zeitrahmen berechnen und dann HTF-Zeitstempel auf dieses Intervall filtern.
Wichtige verwendete MQL5-Funktionen:
- CopyTime(symbol, timeframe, start_shift, count, array) – kopiert Zeitstempel aus dem angegebenen Zeitrahmen. Sie gibt die Anzahl der kopierten Elemente zurück. Hinweis: Die Ergebnisse werden nach dem neuesten Stand sortiert (Verschiebung 0 = neuester Stand), sodass bei Intervallvergleichen in der Regel der älteste Stand verwendet wird.
- CopyOpen, CopyClose – ähnlich wie CopyTime, jedoch werden Öffnungs-/Schließungspreise kopiert.
- PeriodSeconds(tf) – gibt die Anzahl der Sekunden in einem bestimmten Zeitrahmen zurück (nützlich für die Berechnung von Periodenendzeiten).
- ObjectCreate(chart_id, name, type, sub_window, time1, price1, time2, price2) – unterschiedliche Objekte erfordern unterschiedliche Parameterlisten:
- OBJ_VLINE: time1 und price werden akzeptiert, aber nur time ist wichtig.
- OBJ_RECTANGLE: erfordert (time1, price1, time2, price2) – verwenden Sie low/high/ open/close entsprechend.
- OBJ_TREND benötigt zwei Punkte (Zeit1, Preis1, Zeit2, Preis2).
Fehlerbehandlung:
- Überprüfen Sie immer den Rückgabewert von ObjectCreate() und rufen Sie GetLastError() auf, um Erstellungsfehler zu protokollieren/diagnostizieren.
- Verwenden Sie ObjectFind() (gibt index oder -1 zurück), um das Vorhandensein vor dem Erstellen zu prüfen – das verhindert Duplikate.
Implementierung (Sichtbereich optimiert)
- Abfrage von CHART_FIRST_VISIBLE_BAR und CHART_WIDTH_IN_BARS zur Berechnung von t_from und t_to unter Verwendung von iTime() für den aktuellen Chart-Zeitrahmen.
- Kopieren von HTF-Zeiten unter Verwendung von CopyTime, aber immer noch begrenzt durch g_lookback – Sie können g_lookback optional auf den für den sichtbaren Bereich erforderlichen Betrag reduzieren.
- HTF-Zeiten filtern: nur Objekte für HTF-Zeitstempel erstellen, die sich mit [t_from – period_seconds, t_to + period_seconds] schneiden (einen kleinen Rand hinzufügen, um Objekte genau an der Grenze zu erfassen).
//--- helper: get visible chart time range (returns false if couldn't obtain) bool GetVisibleTimeRange(datetime &time_from, datetime &time_to) { // ChartGetInteger uses constants CHART_FIRST_VISIBLE_BAR and CHART_WIDTH_IN_BARS long first_visible = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR); long visible_bars = ChartGetInteger(0, CHART_WIDTH_IN_BARS); if(first_visible < 0 || visible_bars <= 0) return(false); // first_visible is index in the time series (0 = newest) // iTime(symbol,period,shift) expects shift as bar index time_from = iTime(_Symbol, _Period, (int)first_visible); // time of first visible bar (leftmost) int last_index = (int)(first_visible + visible_bars - 1); // index of rightmost visible bar time_to = iTime(_Symbol, _Period, last_index); // time of last visible bar (rightmost) // If iTime returns 0 or invalid, fail gracefully if(time_from == 0 || time_to == 0) return(false); return(true); } //--- RefreshLines with visible-range filter void RefreshLines() { // determine visible chart time window (optional optimization) datetime vis_from = 0, vis_to = 0; bool have_vis = GetVisibleTimeRange(vis_from, vis_to); // optional: expand the visible window by one HTF period on each side uint64 ht_period_secs = (uint64)PeriodSeconds(InpHigherTF); datetime vis_from_margin = (have_vis ? vis_from - (int)ht_period_secs : 0); datetime vis_to_margin = (have_vis ? vis_to + (int)ht_period_secs : 0); // copy HTF times (newest-first) datetime major_times[]; ArrayFree(major_times); int copiedMaj = CopyTime(_Symbol, InpHigherTF, 0, g_lookback, major_times); if(copiedMaj <= 0) return; // copy opens & closes (same count) double major_opens[], major_closes[]; if(CopyOpen(_Symbol, InpHigherTF, 0, copiedMaj, major_opens) != copiedMaj || CopyClose(_Symbol, InpHigherTF, 0, copiedMaj, major_closes) != copiedMaj) return; // reverse to ascending order (oldest-first) — easier for interval checks datetime sorted_times[]; ArrayResize(sorted_times, copiedMaj); double sorted_opens[]; ArrayResize(sorted_opens, copiedMaj); double sorted_closes[]; ArrayResize(sorted_closes, copiedMaj); for(int k = 0; k < copiedMaj; ++k) { sorted_times[k] = major_times[copiedMaj - 1 - k]; sorted_opens[k] = major_opens[copiedMaj - 1 - k]; sorted_closes[k] = major_closes[copiedMaj - 1 - k]; } // Build keep-list (only include HTF entries in the visible window when available) string keepNames[]; ArrayResize(keepNames, 0); for(int i = 0; i < ArraySize(sorted_times); ++i) { datetime t = sorted_times[i]; // If we have a visible window, skip majors outside it (margin added) if(have_vis && (t < vis_from_margin || t > vis_to_margin)) continue; // create/vet major VLINE string name = PREFIX_MAJ + EnumToString(InpHigherTF) + "_" + IntegerToString((int)t); if(ObjectFind(0, name) == -1) { double dummy_price = 0.0; if(!ObjectCreate(0, name, OBJ_VLINE, 0, t, dummy_price)) PrintFormat("Failed to create major %s error %d", name, GetLastError()); else { ObjectSetInteger(0, name, OBJPROP_COLOR, InpColorMajor); ObjectSetInteger(0, name, OBJPROP_WIDTH, InpWidthMajor); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); } } // push to keepNames int sz = ArraySize(keepNames); ArrayResize(keepNames, sz+1); keepNames[sz] = name; // (rest: fills, open/close trend lines, and adding their names to keepNames) // ... same logic as before, but guarded by have_vis if you want to only create their labels when visible. } // Cleanup: delete HTF_ objects not in keepNames[] int total = ObjectsTotal(0); for(int idx = total - 1; idx >= 0; --idx) { string oname = ObjectName(0, idx); if(StringFind(oname, "HTF_") != -1) { bool found = false; for(int k = 0; k < ArraySize(keepNames); ++k) if(oname == keepNames[k]) { found = true; break; } if(!found) ObjectDelete(0, oname); } } }
8. DrawMinorsBetweenIntervals
Die Aufgabe dieses Hilfsmittels besteht darin, Zwischenmarkierungen nur dort einzufügen, wo sie hingehören, d. h. genau zwischen aufeinander folgende Hauptzeitstempel. Einzelheiten der Umsetzung und Entscheidungen:
- Wir lesen alle kleineren TF-Zeiten über CopyTime() (neueste-erste) und kehren für die Intervalllogik zur ältesten-ersten zurück.
- Für jeden kleineren Zeitstempel mt wird zunächst geprüft, ob er mit einem Hauptzeitstempel übereinstimmt (genaue Überschneidungen werden übersprungen).
- Dann suchen wir das Intervall j, in dem major[j] < mt < major[j+1] ist. Weil Majors aufsteigend sind, ist ein linearer Scan einfach und zuverlässig.
- Wenn es viele Majors und Minors gibt, können Sie diesen Vorgang beschleunigen:
- Verwendung der binären Suche (ArrayBsearch), wenn major_times groß und sortiert ist (ist es),
- Oder die Erstellung eines einzigen Durchlaufs durch Haupt- und Nebenwerte gleichzeitig (Merge-Join), um O(n)-Komplexität anstelle von O(n*m) zu erreichen.
- Aktualisieren Sie die Namensliste, um sicherzustellen, dass die Bereinigung korrekt ist.
void DrawMinorsBetweenIntervals(const string prefix, const ENUM_TIMEFRAMES minorTF, const color c, const int width, const datetime &major_times[], string &keepNames[]) { datetime minor_times[]; int copiedMin = CopyTime(_Symbol, minorTF, 0, g_lookback, minor_times); if(copiedMin <= 0) return; // Reverse to ascending (oldest-first) datetime sorted_minor_times[]; ArrayResize(sorted_minor_times, copiedMin); for(int k = 0; k < copiedMin; ++k) sorted_minor_times[k] = minor_times[copiedMin - 1 - k]; // Merge-like linear pass (more efficient than nested loops) — optional improvement: // if you expect many entries, implement two-pointer merge; below is the simpler approach. for(int m = 0; m < copiedMin; ++m) { datetime mt = sorted_minor_times[m]; // skip if equals any major time (linear check) bool equals_major = false; for(int kk = 0; kk < ArraySize(major_times); ++kk) if(major_times[kk] == mt) { equals_major = true; break; } if(equals_major) continue; // find interval where mt belongs bool placed = false; for(int j = 0; j < ArraySize(major_times)-1; ++j) { if(major_times[j] < mt && mt < major_times[j+1]) { string name = prefix + EnumToString(minorTF) + "_" + IntegerToString((int)mt); if(ObjectFind(0, name) == -1) { if(ObjectCreate(0, name, OBJ_VLINE, 0, mt, 0.0)) { ObjectSetInteger(0, name, OBJPROP_COLOR, c); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); } } // add to keepNames int sz = ArraySize(keepNames); ArrayResize(keepNames, sz+1); keepNames[sz] = name; placed = true; break; } } if(!placed) continue; } }
9. Bereinigung und Objektverwaltung
Das Löschen nur von Objekten mit unserem Präfix verhindert das versehentliche Löschen von Objekten von Nutzern oder anderen Indikatoren. Ein paar zusätzliche Überlegungen:
- Bevorzugen Sie ObjectFind(0, name) vor dem Aufruf von ObjectCreate(), um Duplikate zu vermeiden.
- Verwenden Sie GetLastError() nach einem fehlgeschlagenen ObjectCreate() zur Fehlersuche.
- Wenn Ihr Indikator viele Objekte erzeugt, sollten Sie diese nach Präfixen gruppieren und optional ein einziges Master-„Indexobjekt“ (kleiner Text) speichern, das eine kommagetrennte Liste der erzeugten Namen enthält, um die Existenz schneller zu überprüfen – obwohl die hier gezeigte keepNames[]-Technik in der Regel ausreichend ist.
void DeleteAllHTFLines() { int total = ObjectsTotal(0); for(int idx = total - 1; idx >= 0; --idx) { string oname = ObjectName(0, idx); if(StringFind(oname, "HTF_") != -1) ObjectDelete(0, oname); } }
Tests
Nach dem Kompilieren ist das Testen des Tools ganz einfach: Suchen Sie den Market Periods Synchronizer im Ordner Indicators im MetaTrader 5 Navigator und fügen Sie ihn einem beliebigen Chart hinzu. Das gesamte Verhalten kann über die Eingaben des Indikators konfiguriert werden. So können Sie beispielsweise den für die Periodenmarkierungen verwendeten Hauptzeitrahmen auswählen, die Rückblick-Tiefe festlegen und die Farben und Breiten einstellen. Sie können auch optionale Zwischenmarkierungen aktivieren und deren Zeitrahmen so wählen, dass sie genau zwischen aufeinanderfolgenden Hauptgrenzen erscheinen.
Der Name Market Periods Synchronizer spiegelt den Zweck des Tools wider: Es verknüpft visuell die Struktur des höheren Zeitrahmens mit der Preisaktion im unteren Zeitrahmen. In der Praxis bedeutet dies, dass Sie Dochte auf höheren Zeitebenen genau den Kerzen auf niedrigeren Zeitebenen zuordnen können, die sie hervorgebracht haben, sodass Sie untersuchen können, wie diese Dochte entstanden sind (Ablehnungen, Schwänze, Intra-Balken-Spikes usw.). Die folgenden Abbildungen zeigen typische Ergebnisse und Beispiele für die bei unseren Tests verwendeten Eingabeeinstellungen.

Abbildung 2. Marktperioden Synchronizer-Eingangseinstellungen

Abbildung 3. Starten des Indikators „Market Periods Synchronizer“ zum Chart

Abb. 4. Trends, die sich aus den Füllungen des H1-Zeitraums ergeben
In Abbildung 4 kennzeichnet unser Market Periods Synchronizer die Eröffnungs- und Schlusszeiten der einzelnen Hauptperioden, sodass wir aufkommende Trends auf einer feineren Skala beobachten können. Innerhalb jedes markierten Intervalls wird die Preisbewegung im unteren Zeitrahmen deutlich sichtbar und zeigt, wie sich die Intra-Balken-Struktur innerhalb der Grenzen der Kerzen im oberen Zeitrahmen entwickelt.
Auf diese Weise entsteht eine doppelte Sichtweise – eine, in der Händler gleichzeitig sowohl den breiteren Trendkontext als auch die detaillierten Mikrobewegungen, die ihn bilden, analysieren können. Die farbigen Füllungen dienen als visuelle Abstraktion von Kerzen auf höheren Zeitebenen und verwandeln das Chart effektiv in eine vielschichtige Darstellung des Marktverhaltens.

Abb. 5. Beschriftung der Kerzenteile
Abbildung 5 veranschaulicht die Beschriftung eines durch rote Linien begrenzten Bereichs, der einen einzelnen Stundenzeitraum darstellt. Dieser Abschnitt funktioniert ähnlich wie eine vergrößerte Kerze – er enthält den Eröffnungs- und Schlusskurs, den Körper, den oberen Docht und den unteren Docht eines Balkens mit höherem Zeitrahmen. Innerhalb dieser eingegrenzten Zone können Händler die Kursbewegung auf dieselbe analytische Weise interpretieren wie bei traditionellen Kerzenkomponenten. Im Wesentlichen dient jede hervorgehobene Periode als visuelle Rekonstruktion einer Kerze in einem höheren Zeitrahmen, die eine genauere Untersuchung der Struktur ermöglicht, die durch Schwankungen in einem niedrigeren Zeitrahmen gebildet wurde.
Schlussfolgerung
Wir haben erfolgreich eine konzeptionelle Idee in ein voll funktionsfähiges Analysewerkzeug durch die Kraft der MQL5-Programmierung umgewandelt. Der Market Periods Synchronizer-Indikator verleiht der Chartanalyse eine neue Dimension, indem er es Händlern ermöglicht, Strukturen mit höherem und niedrigerem Zeitrahmen in einer nahtlosen Schnittstelle zu betrachten. Es synchronisiert visuell Marktperioden über mehrere Zeitrahmen hinweg und ermöglicht eine klare Identifizierung, wie kleinere Kerzen zur Bildung größerer Marktphasen und Trendstrukturen beitragen. Diese Innovation schließt eine seit langem bestehende Lücke in den Visualisierungsmöglichkeiten des MetaTrader 5, insbesondere für Analysten, die ein tieferes Verständnis der Preisentwicklung in einem breiteren zeitlichen Kontext suchen.
Eine der Hauptstärken dieses Tools liegt in der Visualisierung der Periodenkörper. Durch das Füllen von Kerzenkörpern in höheren Zeitrahmen mit unterschiedlichen Farben können Händler sofort erkennen, ob ein Zeitrahmen steigt, fällt oder neutral ist – und dann untersuchen, wie sich die Kerzen in niedrigeren Zeitrahmen innerhalb dieser Regionen verhalten haben. Dies offenbart auch die Geschichte hinter Dochtformationen, da die Nutzer die Volatilität im unteren Zeitrahmen, Liquiditätsbewegungen und Intra-Balken-Reaktionen beobachten können, die diese ausgedehnten Hochs oder Tiefs verursacht haben. Solche Einblicke sind von unschätzbarem Wert bei der Analyse von Umkehrungen, Fakeouts oder Fortsetzungsmustern, die sonst in größeren Kerzenkörpern verborgen sind.
Ebenso wichtig ist das hohe Maß an Anpassung und Optimierung, das in das Tool integriert ist. Die Nutzer können konfigurieren, welche Zeitrahmen angezeigt werden sollen, unabhängige Linienstile und Farben für jeden festlegen, die Rückblickstiefe definieren und die Sichtbarkeit von Serien umschalten, um ein übersichtliches und dennoch informatives Chart-Layout zu erhalten. Diese einstellbaren Funktionen machen den Indikator anpassungsfähig für verschiedene Handelsstile – von Intraday-Scalpers, die das M1/M5-Verhalten untersuchen, bis hin zu langfristigen Analysten, die die D1- und W1-Strukturen ausrichten. Durch seine Flexibilität ermöglicht der Market Periods Synchronizer den Nutzern, die Märkte auf eine Weise zu analysieren, die ihrem individuellen Handelsansatz und kognitiven Workflow entspricht.
Für angehende MQL5-Entwickler zeigt dieses Projekt, wie abstrakte Handelskonzepte durch strukturierte Kodierungspraktiken in visuelle und interaktive Tools umgesetzt werden können. Es hebt praktische Fertigkeiten wie die Handhabung von Ereignissen, die Verwaltung von Chart-Objekten und die Datensynchronisierung mit mehreren Zeitrahmen hervor – alles zentrale Themen für jeden, der die Sprache MQL5 beherrschen möchte. Für Händler fördert der Indikator die Gewohnheit der strukturierten Beobachtung und hilft ihnen, nicht nur zu verstehen, was der Markt tut, sondern auch, wie sich der Preis im Laufe der Zeit über verschachtelte Zeitrahmen entwickelt. Dieses disziplinübergreifende Verständnis zwischen Codierung und Marktanalyse fördert sowohl die technische Kompetenz als auch die analytische Tiefe und bildet eine solide Grundlage für künftige Innovationen bei der Entwicklung von Handelsinstrumenten.
Im Wesentlichen stellt der Market Periods Synchronizer sowohl einen funktionalen Fortschritt für die technische Analyse als auch eine Lernplattform für diejenigen dar, die in die MQL5-Entwicklung einsteigen. Es zeigt, wie kreative Problemlösungen, die sich an realen Handelsherausforderungen orientieren, zu sinnvollen Tools führen können, die die Klarheit, Präzision und den pädagogischen Wert der Chartanalyse in der MetaTrader 5-Umgebung verbessern.
In der nachstehenden Tabelle finden Sie die wichtigsten Erkenntnisse aus dem Entwicklungsprozess sowie die angehängte Quelldatei am Ende dieses Artikels.
Wichtige Lektionen
| Wichtige Lektion | Beschreibung |
|---|---|
| 1. Datenverarbeitung mehrerer Zeitrahmen: | Lernen Sie, wie Sie auf Daten in höheren Zeitrahmen zugreifen, diese vergleichen und ausrichten können, während Sie in einem Chart mit niedrigerem Zeitrahmen arbeiten. Das Projekt demonstriert die korrekte Verwendung der Funktionen iTime() , iOpen() und iClose() zur Synchronisierung von Daten aus verschiedenen Zeitrahmen. |
| 2. Erstellen von Objekten und Zeichnen von Charts: | Verstehen, wie man Chart-Objekte wie vertikale Linien, Rechtecke und Beschriftungen programmatisch mit ObjectCreate() und ObjectSetInteger() erstellt und verwaltet. Es wird Wert auf korrekte Namenskonventionen und Ressourcenbereinigung gelegt, um Unordnung und Speicherlecks zu vermeiden. |
| 3. Entwurf der Eingabeparameter: | Sammeln Sie Erfahrungen mit der Definition flexibler Eingabeparameter, die es den Nutzern ermöglichen, die Auswahl von Zeitrahmen, Farben, Linienbreiten und die Sichtbarkeit von Markierungen anzupassen. Der Indikator zeigt die praktische Verwendung von Eingabevariablen für maximale Konfigurierbarkeit. |
| 4. Algorithmus-Optimierung und CPU-Management: | Erfahren Sie, wie Sie die Leistung von Indikatoren optimieren können, indem Sie das Zeichnen von Objekten auf den sichtbaren Chartbereich beschränken. Dies zeigt, wie wichtig effiziente Schleifen, bedingte Überprüfungen und eine minimale Ressourcennutzung bei hochfrequenten Aktualisierungen auf M1- oder M5-Charts sind. |
| 5. Visuelle Synchronisierungskonzepte: | Verstehen, wie visuelle Elemente strukturelle Beziehungen zwischen Zeitrahmen vermitteln können. Durch die Markierung von Haupt- und Zwischenperioden hilft das Tool den Nutzern, die Preisentwicklung intuitiv abzubilden und zu beobachten, wie Kerzen im unteren Zeitrahmen Formationen im oberen Zeitrahmen bilden. |
| 6. Praktische Fehlersuche und Tests: | Lernen Sie den Prozess des Kompilierens, Anhängens und Testens von nutzerdefinierten Indikatoren in MetaTrader 5 kennen. Entwickler lernen, Compiler-Meldungen zu interpretieren, mit Fehlern wie „falsche Parameteranzahl“ umzugehen und die Logik während der Live-Chart-Ausführung Schritt für Schritt zu validieren. |
| 7. Modulare Code-Strukturierung: | Erfahren Sie, wie die Trennung der Logik in Initialisierungs-, Berechnungs- und Visualisierungssegmente zu sauberem und wartbarem Code führt. Dies entspricht den bewährten Praktiken von MQL5 für die Entwicklung wiederverwendbarer und erweiterbarer Indikatoren. |
| 8. Brückenschlag zwischen Analyse und Automatisierung: | Erkennen, wie analytische Konzepte, wie z. B. die Anpassung von Zeitrahmen und die Abbildung von Preis und Aktion, in automatisierte visuelle Tools umgewandelt werden können. Diese Verschmelzung von Kodierung und Handelslogik stärkt sowohl die Programmierfähigkeiten als auch das analytische Denken. |
| 9. Die Mikrostruktur des Marktes verstehen: | Durch die visuelle Synchronisierung können Händler Dochtbildung, Momentum-Übergänge und Intra-Balken-Reaktionen untersuchen und so interpretieren, wie Mikro-Kursbewegungen Kerzenkörper und Dochte in höheren Zeitrahmen zusammensetzen. |
| 10. Bildungswert für neue Entwickler: | Das Projekt zeigt einen vollständigen Entwicklungszyklus – von der Ideenfindung und Problemdefinition bis zur Programmierung, Fehlersuche und Veröffentlichung. Es dient als praktische Lernvorlage für angehende MQL5-Entwickler, die ihre eigenen professionellen Indikatoren erstellen möchten. |
Anlagen
| Dateiname | Version | Beschreibung |
|---|---|---|
| MarketPeriodsSynchronizer.mq5 | 1.01 | Dieser Indikator ist ein visuelles Synchronisationsinstrument, mit dem Sie beobachten können, wie Kursbewegungen in niedrigeren Zeitrahmen die Struktur von Perioden in höheren Zeitrahmen bilden. Es zeichnet vertikale Markierungen und optionale Beschriftungen, die ausgewählten höheren Zeitrahmen entsprechen, sodass Händler den Beginn und das Ende größerer Marktperioden direkt in Charts mit kleineren Zeitrahmen identifizieren können. Das Tool wird automatisch aktualisiert und unterstützt anpassbare Markerfarben, -breiten und -rückblicke. Es wurde unter Verwendung der Kernfunktionen von MQL5 entwickelt, darunter CopyTime(), ObjectCreate() und Timer-Ereignisse, was es zu einem praktischen Studienfall für die Kombination von Chart-Visualisierung und Datenverarbeitung mit mehreren Zeitrahmen macht. |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/19841
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Einführung in MQL5 (Teil 23): Automatisieren der Opening Range Breakout Strategie
Statistische Arbitrage durch kointegrierte Aktien (Teil 6): Bewertungssystem
Die Grenzen des maschinellen Lernens überwinden (Teil 6): Effektive Speichervalidierung
Selbstoptimierende Expert Advisors in MQL5 (Teil 15): Identifizierung linearer Systeme
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.