Larry Williams’ Marktgeheimnisse (Teil 14): Erkennung versteckter Hidden-Smash-Day-Umkehrmuster mit einem benutzerdefinierten Indikator
Einführung
Verständnis der Hidden-Smash-Day-Umkehrmuster
Hidden-Smash-Day-Muster sind eine spezielle Variante der Smash-Day-Umkehrmuster von Larry Williams. Auf den ersten Blick unterstützen diese Bars die aktuelle Marktrichtung. Ein genauerer Blick auf ihre innere Struktur offenbart jedoch eher Schwäche als Stärke. Dieser Widerspruch zwischen Schein und Sein ist es, der dem Muster seinen Namen gibt.
Die Schlüsselidee hinter einem Hidden-Smash-Day ist das Scheitern. Der Markt versucht, sich während der Sitzung stark in eine Richtung zu bewegen, aber diese Bewegung wird vor Handelsschluss wieder zurückgewiesen. Obwohl der Kurs die Sitzung leicht höher oder niedriger beenden mag, erzählt die Lage des Schlusskurses innerhalb der Bar eine ganz andere Geschichte.
Das Hidden-Smash-Day-Kauf-Setup
Ein Setup für Hidden-Smash-Day-Buy beginnt mit einer Bar, die höher schließt als die vorherige Bar. Oberflächlich betrachtet sieht dies bullisch aus. Das wichtige Detail ist jedoch, wo dieser Schlusskurs innerhalb der eigenen Spanne der Bar liegt.

Für eine gültige Hidden-Smash-Day-Buy-Bar muss der Schlusskurs im unteren Bereich der Handelsspanne der Bar liegen. Bei den stärksten Versionen des Musters liegt der Schlusskurs zudem unter dem Eröffnungskurs. Dies bedeutet, dass die Käufer bis zum Sitzungsende den Großteil der zuvor erzielten Gewinne nicht halten konnten. Die Rallye stieß auf Verkaufsdruck, und die Kaufbemühungen wurden effektiv neutralisiert.
Dies erzeugt eine Falle. Trader, die sich nur auf den höheren Schlusskurs konzentrieren, könnten die Bar als Stärke interpretieren, während die interne Struktur Erschöpfung signalisiert. Das Muster ist mit dieser einzelnen Bar noch nicht vollständig. Eine Bestätigung ist erforderlich.
Ein bullisches Signal wird nur bestätigt, wenn die folgende Bar über dem Hoch der Hidden-Smash-Day-Bar schließt. Wenn dies geschieht, zeigt es, dass die gescheiterte Bewegung umgekehrt wurde und die Nachfrage mit genügend Stärke zurückgekehrt ist, um die vorherige Ablehnung zu überwinden. Diese Abfolge aus gescheitertem Ausbruchsversuch und unmittelbarer Erholung bildet die Grundlage für das bullische Hidden-Smash-Day-Umkehrmuster.
Das Setup für Hidden-Smash-Day-Sell
Das Setup für Hidden-Smash-Day-Sell ist das Spiegelbild des Kauf-Setups. In diesem Fall schließt die Bar niedriger als die vorherige Bar, was zunächst bärisch erscheint. Wieder einmal erzählt die interne Struktur die wahre Geschichte.

Für eine gültige Hidden-Smash-Day-Sell-Bar muss der Schlusskurs im oberen Teil der Spanne der Bar liegen. Bei den stärksten Mustern liegt der Schlusskurs zudem über dem Eröffnungskurs. Dies deutet darauf hin, dass Verkäufer die Kurse während der Sitzung nach unten drückten, aber die Kontrolle nicht behalten konnten. Der Kurs erholte sich vor Handelsschluss in Richtung des Hochs der Bar, was die Schwäche des Verkaufsdrucks offenbart.
Dies erzeugt eine weitere Falle. Trader könnten den Schlusskurs im Minus als Bestätigung der Schwäche interpretieren, während die Bar selbst eine Ablehnung niedrigerer Kurse zeigt.
Ein bärisches Signal wird nur bestätigt, wenn die folgende Bar unter dem Tief der Hidden-Smash-Day-Bar schließt. Dieser Durchbruch nach unten bestätigt, dass die versuchte Erholung gescheitert ist und der Verkaufsdruck mit Überzeugung zurückgekehrt ist. Das Muster folgt erneut demselben Thema von Scheitern und unmittelbarer Umkehr.
Anstatt Umkehrungen vorherzusagen, warten Hidden-Smash-Day-Muster darauf, dass der Markt seine eigene Schwäche offenbart, und bestätigen dann den Umschwung durch die Kursbewegung. Dies macht sie besonders nützlich innerhalb eines regelbasierten Handelsrahmens und zu einem starken Kandidaten für die systematische Automatisierung.
Wie der Hidden-Smash-Day-Indikator konzipiert ist
Bevor wir tiefer in die Implementierung eintauchen, ist es wichtig, klar zu verstehen, wie der Indikator konzipiert ist, um Informationen visuell und logisch zu kommunizieren. Ein guter technischer Indikator sollte zwei Dinge gut beherrschen. Er sollte das Muster präzise identifizieren und in einem leicht lesbaren Format darstellen. Dieser Indikator wurde mit beiden Zielen im Hinterkopf entwickelt.
Die visuelle Sprache des Indikators ist bewusst einfach gehalten. Ein meergrüner Aufwärtspfeil wird direkt unter einer Hidden-Smash-Day-Buy-Bar gezeichnet. Dieser Pfeil hebt Momente hervor, in denen der bullische Druck während der Sitzung nachließ, was die Grundlage für eine potenzielle Aufwärtsumkehr bildet. Im Gegensatz dazu wird ein schwarzer Abwärtspfeil über einer Hidden-Smash-Day-Sell-Bar gezeichnet. Dies markiert Situationen, in denen der Verkaufsdruck anfangs dominant erschien, letztendlich aber scheiterte, was oft einer Abwärtsumkehr vorausgeht. Indem die Pfeile direkt an der Bar platziert werden, an der sich das Muster bildet, macht es der Indikator einfach, diese Setups zu erkennen, ohne das Chart zu überladen.
Neben der visuellen Darstellung ist Flexibilität ein zentrales Designelement. Hidden-Smash-Day-Muster können je nach Handelsstil und Bestätigungspräferenzen auf verschiedene Weise interpretiert werden. Aus diesem Grund unterstützt der Indikator zwei Identifikationsmodi, die über Eingabeparameter ausgewählt werden können.
Im ersten Modus wird eine Hidden-Smash-Day-Bar sofort markiert, sobald sie sich bildet und die Kriterien von Larry Williams erfüllt. Dieser Modus ist nützlich für Trader, die frühzeitig auf potenzielle Umkehrungen aufmerksam gemacht werden und das Kursverhalten nach dem Erscheinen des Setups genau beobachten möchten.
Im zweiten Modus wartet der Indikator auf eine Bestätigung, bevor er das Muster markiert. Bei einem Hidden-Smash-Day-Kauf-Setup erfolgt die Bestätigung nur, wenn die nächste Bar über dem Hoch der Hidden-Smash-Day-Bar schließt. Bei einem Verkaufs-Setup erfordert die Bestätigung, dass die nächste Bar unter dem Tief der Hidden-Smash-Day-Bar schließt. Dieser Ansatz filtert schwächere Setups heraus und konzentriert sich nur auf Muster, bei denen die Kursbewegung eine gescheiterte Bewegung eindeutig bestätigt.
Indem diese Modi als konfigurierbare Eingaben bereitgestellt werden, passt sich der Indikator an verschiedene Arbeitsabläufe an, ohne eine einzige Interpretation zu erzwingen. Trader können je nach Strategie und Risikotoleranz zwischen früher Signalerkennung und bestätigten Signalen wählen.
Um zu veranschaulichen, wie all diese Designentscheidungen zusammenwirken, ist unten ein Screenshot des fertigen Indikators auf einem Live-Chart dargestellt.

Dieses Beispiel verdeutlicht, wie klar die Pfeile hervorstechen und wie natürlich sich der Indikator in ein übersichtliches Chart integriert, ohne es zu überladen.
Implementierung des Hidden-Smash-Day-Indikators in MQL5
Nachdem die Grundidee der Hidden-Smash-Day-Umkehrmuster klar definiert ist, besteht der nächste Schritt darin, dieses Konzept in einen funktionierenden benutzerdefinierten Indikator umzusetzen. In diesem Abschnitt beginnen wir mit der praktischen Implementierung unter Verwendung von MQL5. Das Ziel ist hier nicht, voreilig Signale zu generieren, sondern eine saubere, zuverlässige Grundlage zu schaffen, die eine genaue Erkennung und visuelle Markierung von Hidden-Smash-Day-Mustern unterstützt.
Bevor Sie mit dem Schreiben der Logik beginnen, ist es wichtig, die Entwicklungsumgebung ordnungsgemäß vorzubereiten. Dies umfasst ein grundlegendes Verständnis der MQL5-Syntax, Vertrautheit mit dem MetaTrader 5-Terminal und Sicherheit bei der Arbeit im MetaEditor. Mit diesen Voraussetzungen können wir fortfahren und den Indikator Schritt für Schritt aufbauen.
Die vollständige Implementierung des Indikators ist diesem Artikel als lwHiddenSmashDayIndicator.mq5 beigefügt. Es wird dringend empfohlen, die Beispiele aus der Anleitung selbst nachzuschreiben. Das manuelle Schreiben des Codes und der Vergleich mit der beigefügten Version hilft dabei, das Verständnis zu festigen und erleichtert die Fehlersuche, falls Probleme auftreten sollten.
Erstellen des Indikator-Grundgerüsts
Wir beginnen damit, eine neue leere benutzerdefinierte Indikator-Datei in MetaEditor zu erstellen. Der Dateiname kann frei gewählt werden, wobei die Verwendung desselben Namens wie bei der beigefügten Quelle zur Konsistenz beiträgt. Sobald die Datei erstellt ist, wird der anfängliche Standardcode eingefügt.
//+------------------------------------------------------------------+ //| lwHiddenSmashDayIndicator.mq5 | //| Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian | //| https://www.mql5.com/en/users/chachaian | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian" #property link "https://www.mql5.com/en/users/chachaian" #property version "1.00" //+------------------------------------------------------------------+ //| Custom Indicator specific directives | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_plots 2 #property indicator_buffers 2 //+------------------------------------------------------------------+ //| Defines how Hidden Smash Day patterns are validated | //+------------------------------------------------------------------+ enum ENUM_HIDDEN_SMASH_VALIDATION_MODE { HIDDEN_SMASH_BAR_ONLY, HIDDEN_SMASH_CONFIRMED }; //+------------------------------------------------------------------+ //| Hidden Smash Detection Settings | //+------------------------------------------------------------------+ input ENUM_HIDDEN_SMASH_VALIDATION_MODE hiddenSmashValidationMode = HIDDEN_SMASH_CONFIRMED; //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; //+------------------------------------------------------------------+ //| Indicator buffers | //+------------------------------------------------------------------+ double buySmashArrowBuffer []; double sellSmashArrowBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ //--- To configure the chart's appearance if(!ConfigureChartAppearance()){ Print("Error while configuring chart appearance ", GetLastError()); return INIT_FAILED; } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t 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 int32_t &spread[]) { ArraySetAsSeries(open, false); ArraySetAsSeries(high, false); ArraySetAsSeries(low, false); ArraySetAsSeries(close, false); //--- Temporary buffers used to store price data for rendering custom colored candles double lwOpen []; double lwHigh []; double lwLow []; double lwClose[]; //--- Copy price data into local working buffers to safely manipulate candle values without altering the original price arrays ArrayCopy(lwOpen, open); ArrayCopy(lwHigh, high); ArrayCopy(lwLow, low); ArrayCopy(lwClose, close); //--- This block will be executed whenever the indicator is initially attached to a chart if(prev_calculated == 0){ //--- Start with clean arrays } //--- This block is executed on new bar open if(prev_calculated != rates_total && prev_calculated != 0){ //--- Update buffers on new bar open } //--- This block is executed on arrival of new price (tick) data if(prev_calculated == rates_total){ //--- Update buffers on new tick } return(rates_total); } //+------------------------------------------------------------------+ //| This function configures the chart's appearance. | //+------------------------------------------------------------------+ bool ConfigureChartAppearance() { if(!ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite)){ Print("Error while setting chart background, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_SHOW_GRID, false)){ Print("Error while setting chart grid, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_MODE, CHART_CANDLES)){ Print("Error while setting chart mode, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack)){ Print("Error while setting chart foreground, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrSeaGreen)){ Print("Error while setting bullish candles color, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrBlack)){ Print("Error while setting bearish candles color, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CHART_UP, clrSeaGreen)){ Print("Error while setting bullish candles color, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrBlack)){ Print("Error while setting bearish candles color, ", GetLastError()); return false; } return true; } //+------------------------------------------------------------------+
Dieser anfängliche Code definiert die Struktur des Indikators und bereitet alle wesentlichen Komponenten vor, die später erweitert werden. In diesem Stadium werden weder Handelslogik noch Mustererkennung ausgeführt. Der Fokus liegt auf Organisation, Klarheit und zukünftiger Erweiterbarkeit.
Indikatoreigenschaften und Metadaten
//+------------------------------------------------------------------+ //| lwHiddenSmashDayIndicator.mq5 | //| Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian | //| https://www.mql5.com/en/users/chachaian | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian" #property link "https://www.mql5.com/en/users/chachaian" #property version "1.00"
Der erste Abschnitt der Quelldatei definiert allgemeine Metadaten wie Urheberrechtsinformationen, Versionsnummer und Referenzlinks. Diese Deklarationen sind nicht nur Formalitäten. Sie sorgen für Klarheit über die Urheberschaft und helfen bei der Versionsverfolgung, während sich der Indikator weiterentwickelt.
Unmittelbar danach werden indikatorspezifische Anweisungen deklariert. Diese Anweisungen informieren das Terminal darüber, dass der Indikator direkt im Chartfenster gezeichnet wird und dass er zwei Plots und zwei Puffer verwendet. Diese Entscheidung spiegelt das Designziel wider, sowohl bullische als auch bärische Hidden-Smash-Day-Bars visuell mit Pfeilen zu markieren.
Konfiguration des Validierungsmodus
Hidden-Smash-Day-Muster können auf verschiedene Weise interpretiert werden. Einige Trader bevorzugen es, das Muster zu sehen, sobald sich die Bar bildet, während andere eine Bestätigung durch die folgende Bar benötigen. Um beide Ansätze zu unterstützen, wird eine benutzerdefinierte Enumeration definiert.
//+------------------------------------------------------------------+ //| Defines how Hidden Smash Day patterns are validated | //+------------------------------------------------------------------+ enum ENUM_HIDDEN_SMASH_VALIDATION_MODE { HIDDEN_SMASH_BAR_ONLY, HIDDEN_SMASH_CONFIRMED };
Die Enumeration für den Validierungsmodus führt zwei klare Optionen ein. Eine Option markiert die Hidden-Smash-Day-Bar sofort basierend auf seiner internen Struktur. Die andere Option markiert die Bar erst nach Bestätigung in der nächsten Sitzung. Diese Auswahl wird als Benutzereingabeparameter bereitgestellt, wodurch sich der Indikator an verschiedene Analysestile anpassen kann, ohne dass Codeänderungen erforderlich sind.
//+------------------------------------------------------------------+ //| Hidden Smash Detection Settings | //+------------------------------------------------------------------+ input ENUM_HIDDEN_SMASH_VALIDATION_MODE hiddenSmashValidationMode = HIDDEN_SMASH_CONFIRMED;
Durch die frühzeitige Einführung dieser Konfiguration bleibt die Indikatorlogik flexibel und vermeidet fest codierte Annahmen.
Globaler Gültigkeitsbereich und Zeitrahmenbehandlung
Eine globale Zeitrahmenvariable wird deklariert und auf den aktuellen Chart-Zeitrahmen gesetzt.
//+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT;
Dies stellt sicher, dass sich der Indikator automatisch an jeden Chart anpasst, an den er angehängt wird. Unabhängig davon, ob der Chart stündlich, vierstündlich oder täglich ist, gilt dieselbe Logik ohne Änderung.
Dieser Ansatz entspricht den Prinzipien von Larry Williams und ermöglicht es ihm gleichzeitig, über mehrere Zeitrahmen hinweg zu arbeiten.
Indikator-Puffer und visuelle Ausgabe
Es werden zwei Indikator-Puffer deklariert.
//+------------------------------------------------------------------+ //| Indicator buffers | //+------------------------------------------------------------------+ double buySmashArrowBuffer []; double sellSmashArrowBuffer[];
Ein Puffer ist für bullische Hidden-Smash-Day-Bars reserviert, der andere für bärische Hidden-Smash-Day-Bars. Diese Puffer speichern später Kurswerte, an denen Pfeile gezeichnet werden sollen.
In diesem Stadium sind die Puffer absichtlich leer. Der Indikator markiert nichts, bis gültige Bedingungen erkannt werden. Dies hält den Chart sauber und vermeidet irreführende Signale.
Die visuelle Absicht ist einfach und bewusst gewählt. Ein meergrüner Pfeil wird unter einem bullischen Hidden-Smash-Day-Bar gezeichnet, während ein schwarzer Pfeil über einem bärischen Hidden-Smash-Day-Bar gezeichnet wird. Diese Wahl von Farbe und Platzierung erzeugt einen unmittelbaren visuellen Kontrast und hilft Tradern, potenzielle Umkehrzonen schnell zu identifizieren.
Logik der Initialisierung
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ //--- To configure the chart's appearance if(!ConfigureChartAppearance()){ Print("Error while configuring chart appearance", GetLastError()); return INIT_FAILED; } return(INIT_SUCCEEDED); }
Innerhalb der Initialisierungsfunktion konfiguriert der Indikator das Erscheinungsbild des Charts. Der Hintergrund, die Barfarben und die Sichtbarkeit des Rasters werden angepasst, um die Klarheit und Lesbarkeit während der Analyse und des Tests zu verbessern.
Dieser Schritt hat keine Auswirkungen auf Kursdaten oder Indikatorberechnungen. Sein einziger Zweck ist es, eine saubere visuelle Umgebung zu schaffen, die die Mustererkennung erleichtert. Wenn die Chartkonfiguration aus irgendeinem Grund fehlschlägt, lädt der Indikator nicht weiter und meldet den Fehler. Dies schützt vor einer teilweisen oder irreführenden visuellen Ausgabe.
Berechnungs-Framework
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t 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 int32_t &spread[]) { ArraySetAsSeries(open, false); ArraySetAsSeries(high, false); ArraySetAsSeries(low, false); ArraySetAsSeries(close, false); //--- Temporary buffers used to store price data for rendering custom colored candles double lwOpen []; double lwHigh []; double lwLow []; double lwClose[]; //--- Copy price data into local working buffers to safely manipulate candle values without altering the original price arrays ArrayCopy(lwOpen, open); ArrayCopy(lwHigh, high); ArrayCopy(lwLow, low); ArrayCopy(lwClose, close); //--- This block will be executed whenever the indicator is initially attached on a chart if(prev_calculated == 0){ //--- Start with clean arrays } //--- This block is executed on new bar open if(prev_calculated != rates_total && prev_calculated != 0){ //--- Update buffers on new bar open } //--- This block is executed on arrival of new price (tick) data if(prev_calculated == rates_total){ //--- Update buffers on new tick } return(rates_total); }
Die Berechnungsfunktion ist der Ort, an dem letztendlich die gesamte Indikatorlogik angesiedelt sein wird. Vorerst etabliert sie einen strukturierten Arbeitsablauf, der verschiedene Ausführungsszenarien voneinander trennt.
Kurs-Arrays werden sorgfältig behandelt, indem sie in lokale Arbeitspuffer kopiert werden. Dies ermöglicht eine sichere Datenmanipulation, ohne die ursprüngliche, vom Terminal bereitgestellte Zeitreihe der Kurse zu verändern.
Drei Ausführungspfade sind klar voneinander getrennt. Ein Pfad behandelt den Fall, dass der Indikator zum ersten Mal an einen Chart angehängt wird. Ein weiterer behandelt das Eintreffen einer neuen Bar. Der letzte Pfad behandelt eingehende Tick-Daten, während sich die aktuelle Bar bildet.
Diese Trennung ist beabsichtigt. Hidden-Smash-Day-Muster hängen von abgeschlossenen Bars und einer Bestätigungslogik ab. Durch die frühzeitige Organisation des Ausführungsablaufs stellen wir sicher, dass die Mustererkennung zum richtigen Zeitpunkt erfolgt und keine Signale neu zeichnet oder instabile Signale erzeugt.
In diesem Stadium sind diese Blöcke Platzhalter. Ihr Vorhandensein signalisiert, wo später Logik hinzugefügt wird, und stellt sicher, dass der Indikator auf kontrollierte und vorhersehbare Weise wächst.
Mit dieser Grundlage ist der nächste Schritt, die eigentliche Erkennungslogik für Hidden-Smash-Day Kauf- und Verkaufs-Setups einzuführen und sie mit den Indikatorpuffern zu verbinden. Von hier an baut jede Ergänzung natürlich auf dem auf, was bereits definiert wurde.
Zuerst stellen wir sicher, dass die Chart-Umgebung sauber und lesbar ist. Zweitens definieren wir wiederverwendbare Funktionen, die Hidden-Smash-Day-Muster genau so identifizieren, wie sie von Larry Williams beschrieben wurden. Drittens verbinden wir diese Funktionen mit dem Indikator-Lebenszyklus, sodass Muster historisch, bei neuen Bars und in Echtzeit erkannt werden. Jeder Schritt baut direkt auf dem vorherigen auf, wodurch der Indikator strukturiert, vorhersehbar und leicht zu warten bleibt.
Vorbereitung des Charts für visuelle Klarheit
Bevor eine Erkennungslogik angewendet wird, passen wir die Darstellung des Charts an, um sicherzustellen, dass visuelle Signale sowohl während des Tests als auch im Live-Betrieb leicht zu interpretieren sind.
//+------------------------------------------------------------------+ //| This function configures the chart's appearance. | //+------------------------------------------------------------------+ bool ConfigureChartAppearance() { if(!ChartSetInteger(0, CHART_COLOR_BACKGROUND, clrWhite)){ Print("Error while setting chart background, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_SHOW_GRID, false)){ Print("Error while setting chart grid, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_MODE, CHART_CANDLES)){ Print("Error while setting chart mode, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_FOREGROUND, clrBlack)){ Print("Error while setting chart foreground, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, clrSeaGreen)){ Print("Error while setting bullish candles color, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, clrBlack)){ Print("Error while setting bearish candles color, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CHART_UP, clrSeaGreen)){ Print("Error while setting bullish candles color, ", GetLastError()); return false; } if(!ChartSetInteger(0, CHART_COLOR_CHART_DOWN, clrBlack)){ Print("Error while setting bearish candles color, ", GetLastError()); return false; } return true; }
Die Funktion ConfigureChartAppearance zentralisiert alle Regeln zur Chart-Gestaltung an einem einzigen Ort. Sie stellt einen hellen Hintergrund ein, entfernt unnötige Gitterlinien und wendet kontrastierende Farben auf bullische und bärische Bars an. Dies schafft eine neutrale visuelle Umgebung, in der die Pfeile des Indikators deutlich sichtbar bleiben.
Der Aufruf dieser Funktion innerhalb von OnInit stellt sicher, dass der Chart einmalig konfiguriert wird, unmittelbar nachdem der Indikator angehängt wurde, und beeinträchtigt nicht die Kursberechnungen oder Pufferaktualisierungen zu einem späteren Zeitpunkt.
Registrierung und Vorbereitung der Indikator-Puffer
Nachdem der Chart vorbereitet ist, besteht der nächste Schritt darin, die Indikator-Puffer zu initialisieren und zu registrieren. Der Indikator verwendet zwei Puffer:
- Ein Puffer speichert Werte für bullische Hidden-Smash-Day-Bars.
- Der zweite Puffer speichert Werte für bärische Hidden-Smash-Day-Bars.
Beide Puffer werden explizit auf Nicht-Zeitreihen-Indizierung gesetzt.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ ... //--- Set arrays as series ArraySetAsSeries(buySmashArrowBuffer, false); ArraySetAsSeries(sellSmashArrowBuffer, false); return(INIT_SUCCEEDED); }
Dies bedeutet, dass Index 0 die älteste Bar in der Historie darstellt und nicht den aktuellsten. Diese Entscheidung ist bewusst und entscheidend, da die gesamte Erkennungslogik beim Durchlaufen historischer Daten von vorwärts indizierten Arrays ausgeht.
Nachdem die Richtung des Index-Puffers festgelegt wurde, werden die Puffer mit SetIndexBuffer registriert.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ ... //--- Bind arrays to indicator buffers SetIndexBuffer(0, buySmashArrowBuffer, INDICATOR_DATA); SetIndexBuffer(1, sellSmashArrowBuffer, INDICATOR_DATA); return(INIT_SUCCEEDED); }
Von diesem Punkt an weiß MetaTrader genau, wo Daten gelesen werden müssen, wenn Pfeile im Chart dargestellt werden.
Definition der Erkennungslogik für Hidden-Smash-Day-Bars
Nachdem die Pufferinfrastruktur eingerichtet ist, können wir nun die Funktionen definieren, die Hidden-Smash-Day-Muster identifizieren. Es werden zwei Basisfunktionen erstellt, um die Basismuster zu erkennen:
Eine identifiziert bullische Hidden-Smash-Day-Bars.
//+------------------------------------------------------------------+ //| Identifies a Bullish Hidden Smash Bar at a specific index | //| Larry Williams definition applied to any timeframe | //+------------------------------------------------------------------+ bool IsHiddenSmashBuyBarAtIndex( const int i, const double &open[], const double &high[], const double &low[], const double &close[], const bool requireCloseBelowOpen = false ) { // We need a previous bar to confirm an up close if(i < 1) return false; // 1. Must close higher than the previous bar if(close[i] <= close[i - 1]) return false; // 2. Use the bar's own range double range = high[i] - low[i]; if(range <= 0.0) return false; // 3. Close must be in the lower 25 percent of the bar range double lowerQuarter = low[i] + (range * 0.25); if(close[i] > lowerQuarter) return false; // 4. Best patterns only if requested if(requireCloseBelowOpen && close[i] >= open[i]) return false; return true; }
Die andere identifiziert bärische Hidden-Smash-Day-Bars.
//+------------------------------------------------------------------+ //| Identifies a Bearish Hidden Smash Bar at a specific index | //| Larry Williams definition applied to any timeframe | //+------------------------------------------------------------------+ bool IsHiddenSmashSellBarAtIndex( const int i, const double &open[], const double &high[], const double &low[], const double &close[], const bool requireCloseAboveOpen = false ) { // We need a previous bar to confirm a down close if(i < 1) return false; // 1. Must close lower than the previous bar if(close[i] >= close[i - 1]) return false; // 2. Use the bar's own range double range = high[i] - low[i]; if(range <= 0.0) return false; // 3. Close must be in the upper 25 percent of the bar range double upperQuarter = high[i] - (range * 0.25); if(close[i] < upperQuarter) return false; // 4. Best patterns only if requested if(requireCloseAboveOpen && close[i] <= open[i]) return false; return true; }
Jede Funktion bewertet eine einzelne Bar an einem gegebenen Index und wendet die Regeln von Larry Williams präzise an. Für bullische Setups muss die Bar höher schließen als die vorherige Bar, während sie innerhalb des unteren Viertels ihrer eigenen Spanne endet. Für bärische Setups wird die Logik gespiegelt: Ein tieferer Schlusskurs und ein Ende innerhalb des oberen Viertels der Handelsspanne der Bar sind erforderlich.
Optionale Bedingungen ermöglichen die Durchsetzung der strengsten Versionen des Musters, wie etwa die Anforderung, dass der Schlusskurs für qualitativ besonders starke Setups unter oder über dem Eröffnungskurs liegen muss. Durch die Isolierung dieser Logik in dedizierte Funktionen bleibt der Indikator modular und später leicht erweiterbar.
Bestätigung von Hidden-Smash-Day-Mustern
Larry Williams betonte, dass das Verhalten der folgenden Bar die stärksten Hidden-Smash-Day-Muster bestätigt. Um dies zu unterstützen, werden zwei Bestätigungsfunktionen eingeführt. Ein bullisches Muster wird nur bestätigt, wenn die nächste Bar über dem Hoch der Hidden-Smash-Day-Bar schließt.
//+------------------------------------------------------------------+ //| Returns true if a Hidden Smash Day Buy pattern is confirmed | //| Confirmation requires next bar to close above smash bar high | //+------------------------------------------------------------------+ bool IsConfirmedHiddenSmashBuyAtIndex(const double &open[], const double &high[], const double &low[], const double &close[], int index ) { int confirmationIndex = index + 1; // Ensure confirmation bar exists if(confirmationIndex >= ArraySize(close)) return false; // Smash bar must be valid if(!IsHiddenSmashBuyBarAtIndex(index, open, high, low, close)) return false; // Confirmation close above smash bar high if(close[confirmationIndex] > high[index]) return true; return false; }
Ein bärisches Muster wird nur bestätigt, wenn die nächste Bar unter dem Tief der Hidden-Smash-Day-Bar schließt.
//+------------------------------------------------------------------+ //| Returns true if a Hidden Smash Day Sell pattern is confirmed | //| Confirmation requires next bar to close below smash bar low | //+------------------------------------------------------------------+ bool IsConfirmedHiddenSmashSellAtIndex(const double &open[], const double &high[], const double &low[], const double &close[], int index ) { int confirmationIndex = index + 1; // Ensure confirmation bar exists if(confirmationIndex >= ArraySize(close)) return false; // Smash bar must be valid if(!IsHiddenSmashSellBarAtIndex(index, open, high, low, close)) return false; // Confirmation close below smash bar low if(close[confirmationIndex] < low[index]) return true; return false; }
Diese Bestätigungsfunktionen verwenden die Erkennungslogik ohne Bestätigung wieder und fügen einen Validierungsschritt hinzu. Dieser Ansatz vermeidet Duplikate und stellt eine konsistente Musterbewertung im gesamten Indikator sicher.
Zuordnung der Muster bei der Initialisierung
Wenn der Indikator erstmals an einen Chart angehängt wird, wurden noch keine historischen Muster verarbeitet. Um dies zu handhaben, wird eine dedizierte Initialisierungs-Mapping-Funktion eingeführt.
//+------------------------------------------------------------------+ //| Scans historical bars and maps Hidden Smash patterns on load | //+------------------------------------------------------------------+ void MapHiddenSmashPatternsOnInitialization( const int rates_total, const double &open[], const double &high[], const double &low [], const double &close[], int hidden_SmashValidationMode, double closePercentThreshold = 25.0 ) { //--- Safety check if(rates_total <= 1) return; //--- Loop through all historical bars for(int i = 1; i <= rates_total - 1; i++) { //--- Default to empty buySmashArrowBuffer[i] = EMPTY_VALUE; sellSmashArrowBuffer[i] = EMPTY_VALUE; //--- Mode 1: Bar only identification if(hiddenSmashValidationMode == HIDDEN_SMASH_BAR_ONLY) { if(IsHiddenSmashBuyBarAtIndex(i, open, high, low, close)) { buySmashArrowBuffer[i] = low[i]; } if(IsHiddenSmashSellBarAtIndex(i, open, high, low, close)) { sellSmashArrowBuffer[i] = high[i]; } } //--- Mode 2: Confirmed pattern identification else if(hiddenSmashValidationMode == HIDDEN_SMASH_CONFIRMED) { if(IsConfirmedHiddenSmashBuyAtIndex(open, high, low, close, i)) { buySmashArrowBuffer[i] = low[i]; } if(IsConfirmedHiddenSmashSellAtIndex(open, high, low, close, i)) { sellSmashArrowBuffer[i] = high[i]; } } } }
Diese Funktion durchläuft alle verfügbaren historischen Bars und bewertet jeden einzelnen gemäß dem gewählten Validierungsmodus. Im ungefilterten Erkennungsmodus werden Bars einzeln bewertet. Wenn der Bestätigungsmodus ausgewählt ist, werden die Bars zusammen mit der bestätigenden Folge-Bar bewertet.
Jedes gültige Muster führt dazu, dass ein Pfeilwert in den entsprechenden Puffer geschrieben wird. Alle anderen Bars bleiben leer, wodurch sichergestellt wird, dass nur echte Hidden-Smash-Day-Muster angezeigt werden. Diese Logik wird einmal innerhalb des Blocks prev_calculated == 0 ausgeführt, um unnötige Neuberechnungen zu vermeiden.
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t 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 int32_t &spread[]) { ... //--- This block will be executed whenever the indicator is initially attached on a chart if(prev_calculated == 0){ //--- Start with clean arrays ArrayInitialize(buySmashArrowBuffer, EMPTY_VALUE); ArrayInitialize(sellSmashArrowBuffer, EMPTY_VALUE); //--- Map all hidden smash bar patterns MapHiddenSmashPatternsOnInitialization(rates_total, lwOpen, lwHigh, lwLow, lwClose, hiddenSmashValidationMode); } ... return(rates_total); }
Aktualisierung von Mustern bei Bildung neuer Bars
Märkte bleiben nicht statisch, daher muss der Indikator auf neue Bars reagieren, sobald sie sich bilden. Wenn eine neue Bar erscheint, wertet der Indikator die zuletzt abgeschlossene Bar aus und aktualisiert die Pufferwerte entsprechend.
//+------------------------------------------------------------------+ //| Evaluates hidden smash patterns on new bar formation | //| Updates indicator buffers for the recently completed bar | //+------------------------------------------------------------------+ void ProcessHiddenSmashOnNewBar( const double &open[], const double &high[], const double &low[], const double &close[], int rates_total ) { int completedBarIndex = rates_total - 2; int currentBarIndex = rates_total - 1; //--- Safety check if(completedBarIndex < 0) return; //--- Always clear buffers for involved bars buySmashArrowBuffer [completedBarIndex] = EMPTY_VALUE; sellSmashArrowBuffer[completedBarIndex] = EMPTY_VALUE; buySmashArrowBuffer [currentBarIndex] = EMPTY_VALUE; sellSmashArrowBuffer[currentBarIndex] = EMPTY_VALUE; //--- Mode 1: Detect bar only if(hiddenSmashValidationMode == HIDDEN_SMASH_BAR_ONLY) { if(IsHiddenSmashBuyBarAtIndex(completedBarIndex, open, high, low, close)) buySmashArrowBuffer[completedBarIndex] = low[completedBarIndex]; if(IsHiddenSmashSellBarAtIndex(completedBarIndex, open, high, low, close)) sellSmashArrowBuffer[completedBarIndex] = high[completedBarIndex]; return; } //--- Mode 2: Confirmed smash if(hiddenSmashValidationMode == HIDDEN_SMASH_CONFIRMED) { int smashBarIndex = completedBarIndex - 1; if(smashBarIndex < 0) return; if(IsHiddenSmashBuyBarAtIndex(smashBarIndex, open, high, low, close)) { if(close[completedBarIndex] > high[smashBarIndex]) buySmashArrowBuffer[smashBarIndex] = low[smashBarIndex]; } if(IsHiddenSmashSellBarAtIndex(smashBarIndex, open, high, low, close)) { if(close[completedBarIndex] < low[smashBarIndex]) sellSmashArrowBuffer[smashBarIndex] = high[smashBarIndex]; } } }
Dies stellt sicher, dass Muster zeitnah erkannt werden, ohne die gesamte Historie neu zu verarbeiten. Eine separate Logik handhabt die ungefilterte Erkennung und die bestätigte Erkennung, wodurch sichergestellt wird, dass Pfeile je nach gewähltem Modus am korrekten Barindex erscheinen.
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t 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 int32_t &spread[]) { ... //--- This block is executed on new bar open if(prev_calculated != rates_total && prev_calculated != 0){ //--- Update buffers on new bar open ProcessHiddenSmashOnNewBar(lwOpen, lwHigh, lwLow, lwClose, rates_total); } ... return(rates_total); }
Dieser Ansatz gleicht Leistung mit Genauigkeit aus und hält den Indikator auch auf niedrigeren Zeitrahmen reaktionsfähig.
Unterstützung von Echtzeit-Tick-Updates
Um den Indikator unter Live-Marktbedingungen nutzbar zu machen, ist auch eine Echtzeit-Tick-Verarbeitung implementiert.
//+------------------------------------------------------------------+ //| Evaluates hidden smash patterns on tick updates | //| Supports real-time detection and confirmation logic | //+------------------------------------------------------------------+ void ProcessHiddenSmashOnTick( const double &open[], const double &high[], const double &low[], const double &close[], int rates_total ) { int currentBarIndex = rates_total - 1; int completedBarIndex = rates_total - 2; if(currentBarIndex < 0) return; //--- Always reset current bar buffer values buySmashArrowBuffer [currentBarIndex] = EMPTY_VALUE; sellSmashArrowBuffer[currentBarIndex] = EMPTY_VALUE; //--- Mode 1: Bar-only detection in real time if(hiddenSmashValidationMode == HIDDEN_SMASH_BAR_ONLY) { if(IsHiddenSmashBuyBarAtIndex(currentBarIndex, open, high, low, close)) buySmashArrowBuffer[currentBarIndex] = low[currentBarIndex]; if(IsHiddenSmashSellBarAtIndex(currentBarIndex, open, high, low, close)) sellSmashArrowBuffer[currentBarIndex] = high[currentBarIndex]; return; } //--- Mode 2: Confirmed smash evaluated continuously if(hiddenSmashValidationMode == HIDDEN_SMASH_CONFIRMED) { int smashBarIndex = completedBarIndex; if(smashBarIndex < 0) return; if(IsHiddenSmashBuyBarAtIndex(smashBarIndex, open, high, low, close)) { if(close[currentBarIndex] > high[smashBarIndex]) buySmashArrowBuffer[smashBarIndex] = low[smashBarIndex]; } if(IsHiddenSmashSellBarAtIndex(smashBarIndex, open, high, low, close)) { if(close[currentBarIndex] < low[smashBarIndex]) sellSmashArrowBuffer[smashBarIndex] = high[smashBarIndex]; } } }
Bei jedem eingehenden Tick wertet der Indikator die aktuelle Bar aus und passt die Pufferwerte dynamisch an.
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int32_t rates_total, const int32_t 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 int32_t &spread[]) { ... //--- This block is executed on arrival of new price (tick) data if(prev_calculated == rates_total){ //--- Update buffers on new tick ProcessHiddenSmashOnTick(lwOpen, lwHigh, lwLow, lwClose, rates_total); } return(rates_total); }
Dies ermöglicht es, dass noch unbestätigte Hidden-Smash-Day-Bars sofort bei ihrer Entstehung erscheinen und bestätigte Muster aktualisiert werden, sobald die Bestätigungsbedingungen erfüllt sind. Diese Echtzeit-Reaktionsfähigkeit macht den Indikator zu einem praktischen Instrument für eine diskretionäre Marktanalyse und aktives Monitoring.
Konfiguration der visuellen Ausgabe mit Pfeil-Plots
Selbst mit korrekten Pufferwerten erscheint nichts im Chart, es sei denn, dem Indikator wird mitgeteilt, wie er seine Daten darstellen soll. Die pfeilbasierten Plots werden in OnInit über die Funktionen PlotIndexSetInteger, PlotIndexSetDouble und PlotIndexSetString konfiguriert.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit(){ ... //--- Configure Graphic Plots PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_ARROW); PlotIndexSetInteger(0, PLOT_ARROW, 233); PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrSeaGreen); PlotIndexSetInteger(0, PLOT_ARROW_SHIFT, +20); PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2); PlotIndexSetDouble (0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetString (0, PLOT_LABEL, "Hidden Smash Buy Bar"); PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_ARROW); PlotIndexSetInteger(1, PLOT_ARROW, 234); PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrBlack); PlotIndexSetInteger(1, PLOT_ARROW_SHIFT, -20); PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 2); PlotIndexSetDouble (1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetString (1, PLOT_LABEL, "Hidden Smash Sell bar"); //--- General indicator configurations IndicatorSetString(INDICATOR_SHORTNAME, "Larry Williams Market Structure Indicator"); return(INIT_SUCCEEDED); }
Bullische Hidden-Smash-Day-Bars werden mit Aufwärtspfeilen markiert, die unter dem Kurs platziert sind. Bärische Hidden-Smash-Day-Bars werden mit Abwärtspfeilen markiert, die über dem Kurs platziert sind. Farbe, Größe, Verschiebung und Beschriftungen werden explizit definiert, um eine konsistente Darstellung über Symbole und Zeitrahmen hinweg zu gewährleisten. Sobald diese Plots konfiguriert sind, ist der Indikator visuell vollständig.
In diesem Stadium ist der Indikator voll funktionsfähig. Er erkennt Hidden-Smash-Day-Muster nach den Regeln von Larry Williams, unterstützt mehrere Validierungsmodi, aktualisiert sich dynamisch bei Marktveränderungen und stellt klare visuelle Signale im Chart dar.
Die vollständige Implementierung ist in der beigefügten Quelldatei mit dem Namen lwHiddenSmashDayIndicator.mq5 enthalten. In der Praxis ist es vorzuziehen, auf die beigefügte Datei zu verweisen, anstatt den vollständigen Quellcode in den Artikel einzubetten.
Dieser Abschnitt schließt die vollständige Entwicklung des Hidden-Smash-Day-Indikators ab und bereitet die Grundlage für Tests, Interpretation und weitere Experimente.
Tests und visuelle Inspektion
Wir beginnen mit der Kompilierung des Indikator-Quellcodes in MetaEditor. Wenn alle Schritte sorgfältig befolgt wurden, sollte der Code ohne Fehler oder Warnungen kompilieren. Eine erfolgreiche Kompilierung bestätigt, dass alle Funktionen korrekt definiert, Puffer ordnungsgemäß registriert und die Indikatorlogik strukturell einwandfrei sind.
Sollten Kompilierungsfehler auftreten, ist der sicherste Ansatz, die aktuelle Arbeitsdatei mit dem beigefügten Quellcode namens lwHiddenSmashDayIndicator.mq5 zu vergleichen. Kleine Unterschiede in Funktionssignaturen oder Pufferhandhabung können leicht zu Problemen führen, und ein Abgleich mit der Referenzimplementierung hilft, diese schnell zu lösen.
Sobald die Kompilierung erfolgreich ist, kann der Indikator an ein Chart angehängt werden. Nach dem Laden sollten sofort Pfeile auf historischen Bars erscheinen, auf denen basierend auf dem gewählten Validierungsmodus gültige Hidden-Smash-Day-Muster identifiziert wurden. Bullische Muster werden mit meergrünen Pfeilen unter dem Kurs markiert, während bärische Muster mit schwarzen Pfeilen über dem Kurs markiert werden.
Hier ist ein Screenshot, der zeigt, wie der fertige Indikator auf einem Live-Chart aussieht.

Diese visuelle Bestätigung hilft dabei, sowohl die Erkennungslogik als auch die Darstellungskonfiguration zu validieren.
Von hier aus lohnt es sich, den Indikator über verschiedene Symbole und Zeitrahmen hinweg zu untersuchen. Da die Musterlogik auf die eigene Spanne jeder Bar angewendet wird, passt sie sich natürlich sowohl an Intraday-Charts als auch an höhere Zeitrahmen an. Die Beobachtung, wie sich Hidden-Smash-Day-Muster unter verschiedenen Marktbedingungen verhalten, kann neue Forschungsideen und praktische Anwendungen eröffnen.Schlussfolgerung
- Hidden-Smash-Day Kauf- und Verkauf-Setups objektiv auf einem Chart erkennen
- Das Umkehrmuster von Larry Williams direkt mithilfe eines benutzerdefinierten Indikators visualisieren
- Das Muster konsistent über verschiedene Instrumente und Zeitrahmen hinweg untersuchen
- Die Erkennungslogik für Forschungszwecke oder zur Integration in automatisierte Systeme erweitern
- Zusätzliche Kontextfilter bei der Analyse potenzieller Handelsmöglichkeiten anwenden
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/21392
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.
Der MQL5-Standardbibliotheks-Explorer (Teil 9): Verwendung von ALGLIB zur Filterung übermäßiger MA-Crossover-Signale
Vereinheitlichte Validierungspipeline gegen Backtest-Overfitting
Integration von MQL5 mit Datenverarbeitungspaketen (Teil 8): Einsatz von Graph Neural Networks zur Erkennung von Liquiditätszonen
Vom Einsteiger zum Experten: Optimierung von Liquiditätsstrategien durch strukturelle Bestätigung über mehrere Zeitrahmen in MQL5
- 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.
Danke dafür