Einführung in MQL5 (Teil 19): Automatisiertes Erkennen von Wolfe-Wellen
Einführung
Willkommen zurück zu Teil 19 der Serie Einführung in MQL5! In Teil 18 habe ich Ihnen das Muster der Wolfe-Wellen vorgestellt, eine einzigartige Fünf-Wellen-Struktur, mit der sich Kursumkehrungen präzise vorhersagen lassen. Wir haben die beiden Haupttypen von Wolfe-Wellen besprochen: das Abwärts-Setup, das einen potenziellen Kursrückgang signalisiert, und das Aufwärts-Setup, das auf eine bevorstehende Erholung hindeutet. Sie haben auch gelernt, wie man Kerzendaten abruft, die für die Analyse von Preis-Aktionen unerlässlich sind, und wir haben die Logik erläutert, mit der man auf der Grundlage dieses Musters gültige Handelsmöglichkeiten erkennt.
In diesem Teil gehen wir von der Theorie zur Umsetzung über. Wir werden untersuchen, wie man die Strukturen der Wolfe-Wellen programmatisch identifiziert und darauf basierenden Handel mit MQL5 ausführt. Dazu gehören die Erkennung wichtiger Umkehr-Punkte, die Validierung von Musterregeln und die Vorbereitung des EA, um auf die ermittelten Signale zu reagieren.
In diesem Artikel erfahren Sie mehr über Folgendes:
- Wie man die klassische Fünf-Wellen-Struktur der Wolfe-Wellen anhand historischer Kursdaten erkennt.
- Programmatische Identifizierung von hohen und tiefen Umkehrpunkten zur Bestimmung von Wellenpunkten.
- Verstehen, wie man die Fibonacci-Expansionsstufen anwendet und modifiziert, um die Wellenbildung zu validieren, insbesondere für die Wellen 3 und 5.
- Der Artikel zeigt, wie man drei wichtige Trendlinien (Welle 1-3, 2-4 und 1-4) zeichnet, die für die Bestätigung von Mustern und Handelsentscheidungen entscheidend sind.
- Überprüfung der Symmetrie und der proportionalen Beziehungen zwischen Welle 1-2 und Welle 3-4 zur Verbesserung der Zuverlässigkeit der Muster.
- Lernen Sie, wie Sie mit MQL5 Wellen beschriften und visuelle Objekte wie Text, Rechtecke und Trendlinien direkt im Chart zeichnen können.
- Implementierung einer Logik, die vor der Platzierung von Handelsgeschäften auf eine Bestätigung wartet, um Fehleingaben zu vermeiden.
- Wie man automatische Ausstiege programmiert, wenn der Markt die Trendlinie zwischen Welle 1 und 4 berührt, um das Risiko zu kontrollieren.
Identifizierung der Abwärtsmuster der Wolfe-Wellen
Im letzten Artikel haben wir bereits die Struktur und die Regeln des Abwärtsmusters der Wolfe-Wellen im Detail besprochen. In diesem Abschnitt werden wir uns nun darauf konzentrieren, wie diese Logik programmatisch umgesetzt werden kann. Wie bereits erwähnt, besteht die fallende Wolfe-Welle aus fünf Wellen, die eine bestimmte Reihenfolge einhalten und bestimmte strukturelle Anforderungen erfüllen müssen. Welle 2 muss ein Umkehr-Tief sein, das unter Welle 1 liegt, und Welle 1 muss ein Umkehr-Hoch sein. Ein weiteres Umkehr-Hoch, diesmal jedoch oberhalb von Welle 1 und innerhalb einer bestimmten Fibonacci-Ausdehnung der Schenkel von Welle 1 zu Welle 2, wird dann von Welle 3 gebildet. Welle 4, ein Umkehr-Tief, das unter Welle 3 fällt, aber über Welle 2 bleibt, wird dann erkannt. Welle 5 vervollständigt das Muster, indem sie ein Umkehr-Hoch über Welle 3 erreicht und innerhalb einer vorbestimmten Fibonacci-Erweiterung der Bewegungen von Welle 3 zu Welle 4 fällt.
Entscheidend ist auch, dass die Beine der ersten und zweiten Welle eine vergleichbare Größe wie die der dritten und vierten Welle haben müssen. Die Wellen 3-4 sollten idealerweise mindestens 70% so lang sein wie die Wellen 1-2. Die Struktur gewinnt durch diese Symmetrie an Glaubwürdigkeit, die auch dazu dient, die Gültigkeit des Musters zu bestätigen. In diesem Abschnitt werden die fünf Standorte mit Hilfe von Schwingungserkennungsfunktionen lokalisiert und es wird geprüft, ob ihre Abstände und Verbindungen den Anforderungen der Wolfe-Welle entsprechen.
Identifizierung von Welle Eins und Zwei
Die genaue Erkennung der Wellen 1 und 2 ist der erste Schritt, um ein Abwärtsmuster der Wolfe-Wellen zu erkennen. Ohne diese beiden Grundlagen ist es schwierig, die übrigen Wellen genau zu lokalisieren. Dieser Teil konzentriert sich auf die Suche nach legitimen Umkehr-Hochs und -Tiefs, die den Kriterien der Welle 1 und Welle 2 auf dem Chart entsprechen. Wir werden die beiden Wellen auf dem Chart deutlich kennzeichnen, um sie visuell zu verdeutlichen, sobald sie erkannt worden sind.
Zwischen den Wellen 1 und 2 werden wir auch ein Fibonacci-Erweiterungsobjekt bereitstellen. Durch die Festlegung geeigneter Kursniveaus auf der Grundlage der Musterregeln wird diese Erweiterung dazu beitragen, die Erkennung der Wellen drei und fünf zu steuern. Durch die frühzeitige Festlegung dieser Kriterien schaffen wir eine solide Grundlage für den weiteren Prozess der Wellenidentifizierung.
Beispiel:input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; int bars_check = 500; datetime time_bar; double total_symbol_bars; double open[]; double close[]; double low[]; double high[]; datetime time[]; double wv1; datetime wv1_time; string wv1_txt; double wv2; datetime wv2_time; string wv2_txt; string fib_ext_wv1_wv2; ulong chart_id = ChartID(); //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(chart_id); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { total_symbol_bars = Bars(_Symbol, timeframe); time_bar = iTime(_Symbol,timeframe,0); CopyOpen(_Symbol, timeframe, time_bar, bars_check, open); CopyClose(_Symbol, timeframe, time_bar, bars_check, close); CopyLow(_Symbol, timeframe, time_bar, bars_check, low); CopyHigh(_Symbol, timeframe, time_bar, bars_check, high); CopyTime(_Symbol, timeframe, time_bar, bars_check, time); if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } break; } } } } } } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING LOW | //+------------------------------------------------------------------+ bool IsSwingLow(const double &low_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(low_price[index] > low_price[index - i] || low_price[index] > low_price[index + i]) return false; } return true; } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING HIGH | //+------------------------------------------------------------------+ bool IsSwingHigh(const double &high_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(high_price[index] < high_price[index - i] || high_price[index] < high_price[index + i]) return false; } return true; }
Ausgabe:

Erläuterung:
Bestimmte Variablen werden deklariert, um wichtige Informationen über die ersten beiden Wellen zu erhalten, damit Muster wie die fallenden Wolfe-Wellen auf dem Chart effizient identifiziert und beschrieben werden können. Für die Welle 1 werden drei Variablen hinzugefügt: wv1, um das Preisniveau festzuhalten, wv1_time, um den genauen Zeitpunkt des Preisanstiegs festzuhalten, und wv1_txt, um als Textbeschriftung für die grafische Darstellung der Welle im Chart zu dienen. Die Variablen wv2, wv2_time und wv2_txt haben für Welle 2 die gleiche Funktion.
Diese Daten sind von entscheidender Bedeutung, da sie es dem Expert Advisor ermöglichen, die genauen Preispunkte und Zeitstempel, an denen bemerkenswerte Höchst- oder Tiefststände festgestellt wurden, zu speichern und später abzurufen. Der Händler kann dank der Textkennzeichnung, die für die visuelle Klarheit besonders hilfreich sind, leichter feststellen, welche Welle im Chart hervorgehoben wird.
Eine String-Variable namens fib_ext_wv1_wv2 wird deklariert, um den Namen des Fibonacci-Erweiterungsobjekts zusätzlich zu den Wellendaten zu speichern. Diese Variable stellt sicher, dass das Element, das die Erweiterung von Welle 1 auf Welle 2 darstellt, bei Bedarf entsprechend erstellt, geändert oder entfernt werden kann, da jedes Objekt im Chart eine eindeutige Kennung haben muss. Um jede Instanz eindeutig zu halten, wird der Wellenindex in der Regel in den Namen aufgenommen, insbesondere wenn der Expert Advisor bei der Durchsicht vergangener Balken mehrere Muster erstellt.
Der Code verwendet zusätzlich die Funktion ChartID(), um die eindeutige ID des aktuellen Charts zu erhalten und speichert sie in der Variablen chart_id, um alle Operationen zur Objekterstellung zu unterstützen. Da mit MetaTrader 5 viele Charts gleichzeitig geöffnet werden können, ist dies von großer Bedeutung. Um Konflikte oder Fehlplatzierungen zu vermeiden, stellt die Anwendung sicher, dass sie grafische Elemente auf dem vorgesehenen Chart erzeugt und ändert, indem sie ausdrücklich auf die entsprechende Chart-ID verweist.
Die Zeile ObjectsDeleteAll(chart_id); in der Funktion OnDeinit() dient dem Aufräumen. Diese Funktion entfernt alle zuvor vom Expert Advisor gezeichneten Objekte aus dem Chart, wenn der Expert Advisor entfernt oder der Chart geschlossen wird. Dies vermeidet Unordnung und garantiert, dass veraltete Zeichenelemente wie Wellenbeschriftungen oder Fibonacci-Linien nicht zurückbleiben, wenn der EA seine Arbeit beendet hat.
Der EA führt eine kritische Prüfung durch, um sicherzustellen, dass genügend Balken vorhanden sind, bevor die Mustererkennungslogik beginnt. Er vergleicht die Anzahl der zu überprüfenden Balken (bars_check) mit der Gesamtzahl der Balken auf dem Chart (total_symbol_bars). Das Programm beginnt mit dem Scannen der Kursdaten, um die ersten Anzeichen einer fallenden Wolfe-Welle zu finden, nachdem es bestätigt hat, dass genügend historische Balken auf der Anzeige geladen sind (if(total_symbol_bars >= bars_check)).
Der erste Schritt bei dieser Erkennung ist eine for-Schleife:
for(int i = 7; i < bars_check - 7; i++)
Um sicher nach Höchst- und Tiefstständen zu suchen, beginnt die Schleife bei Index 7 und nicht bei 0. Um festzustellen, ob es sich bei einem Kurs tatsächlich um einen Umkehr-Punkt handelt, untersuchen die Umkehr-Erkennungsfunktionen (die gleich beschrieben werden) sieben Balken vorwärts und sieben Balken rückwärts. Würde die Schleife bei Index 0 beginnen, gäbe es keine vorherigen Balken zum Vergleich, was zu einem Out-of-bounds-Fehler führen würde. In ähnlicher Weise garantiert das Anhalten der Schleife bei bars_check -7, dass genügend nachfolgende Balken für den Vergleich vorhanden sind.
Diese äußere Schleife sucht nach dem, was Welle 1 des Wolfe-Wellenmusters sein könnte, ein Umkehr-Hoch. Der Code bestimmt, ob der Höchstkurs bei Index i ein lokales Maximum ist, d. h. höher als die umliegenden Kerzen. Jeder Index i steht für eine historische Kerze.
if(IsSwingHigh(high, i, 7))
Der EA betrachtet diese Kerze als potenziellen Kandidaten für Welle 1, wenn die Funktion den Wert „true“ ergibt, was bedeutet, dass es sich um ein legitimes Umkehr-Hoch handelt. Es wird eine Beschriftungszeichenfolge (wv1_txt) erstellt, die später im Chart verwendet wird, und der zugehörige Höchstpreis und die Uhrzeit werden in den Variablen wv1 und wv1_time gespeichert.
Der Code leitet eine innere Schleife ein, um nach dem nächsten gültigen Tiefpunkt der Welle 2 zu suchen, sobald ein gültiges Hoch der Welle 1 (hoher Umkehrpunkt) gefunden wurde:
for(int j = i; j < bars_check - 7; j++)
Diese Schleife beginnt mit demselben Index wie die äußere Schleife (i) und bewegt sich vorwärts. Es wird nach einem Balken gesucht, der zwei Bedingungen erfüllt:
- Es handelt sich um ein tiefer Umkehrpunkt (ein lokales Minimum).
- Sein Preis ist niedriger als der Preis von Welle 1.
if(IsSwingLow(low, j, 7) && low[j] < wv1)
Wenn beide Anforderungen der Welle 2 erfüllt sind, erfasst der EA die Kosten, die Zeit und die Bezeichnung als wv2, wv2_time und wv2_txt. Sobald die Wellen 1 und 2 lokalisiert sind, wird die innere Schleife mit einer Break-Anweisung beendet, ein Fibonacci-Extension-Objekt dazwischen gezeichnet und dem Chart Textbeschriftungen für beide Positionen hinzugefügt. Dadurch wird der EA daran gehindert, eine passende Übereinstimmung für die aktuelle Welle 1 zu finden und dann nach weiteren Möglichkeiten für Welle 2 zu suchen.
Identifizierung der dritten und vierten Welle
Um das Wolfe-Wellenmuster zu konstruieren, ist es sinnvoll, die Wellen 3 und 4 zu identifizieren, nachdem die Wellen 1 und 2 korrekt identifiziert wurden. Der Ort und die Zusammensetzung der Wellen 1 und 2 haben jedoch einen erheblichen Einfluss auf diese späteren Wellen. Insbesondere die Welle 3 muss zwei wesentliche Voraussetzungen erfüllen: Sie muss sich oberhalb des Hochs der Welle 1 entwickeln und innerhalb eines vorbestimmten Fibonacci-Erweiterungsbereichs liegen, der aus den Wellen 1 und 2 berechnet wird.
Die Kursbewegung von Welle 1 zu Welle 2 wird verwendet, um eine Fibonacci-Erweiterung zur Identifizierung dieses Bereichs zu erstellen. Auf der Grundlage des Ausmaßes und der Dynamik der ersten Wellenstruktur hilft dieses Instrument bei der Vorhersage möglicher zukünftiger Kursniveaus. Der Bereich, den der Kurs voraussichtlich erreichen wird, bevor er sich umkehrt, liegt zwischen 127,2 % und 161,8 %, was normalerweise der akzeptable Bereich für Welle 3 ist. Es wird angenommen, dass der Preis ein guter Anwärter für die Welle 3 ist, wenn er innerhalb dieser Spanne sich nach oben bewegt.
Welle 3 muss neben dem Kursniveau auch die Symmetrie des Musters beachten. Die Struktur und der Umfang der Wellen 1 und 2 sollten in den Wellen 3 und 4 angemessen widergespiegelt oder aufgegriffen werden. Es ist dieses geometrische Gleichgewicht, das die legitimen Wolfe-Wellenformen auszeichnet. Für die Zwecke dieser Studie werden wir Symmetrie in einfachen, quantifizierbaren Begriffen definieren. Die Gesamtbewegung von Welle 1 zu Welle 2 sollte mindestens 70 % der Größe der Wellen 3 und 4 betragen. Bei der weiteren Entwicklung des Expert Advisors bietet dieser Prozentsatz einen soliden Rahmen für die Mustervalidierung und trägt dazu bei, die strukturelle und visuelle Integrität der Wolfe-Welle zu erhalten.
Bestimmung von 70 % des Abstands zwischen Welle 1 und Welle 2
Lassen Sie uns zunächst 70 % des Abstands zwischen Welle 1 und Welle 2 bestimmen.
Beispiel:
double wv1_wv2_size; double wv1_wv2_70p;
if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; string luh = StringFormat("bb 2 %d", j); ObjectCreate(chart_id, luh, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); break; } } } } }
Ausgabe:

Erläuterung:
Welle 3 muss neben dem Kursniveau auch die Symmetrie des Musters beachten. Die Struktur und der Umfang der Wellen 1 und 2 sollten in den Wellen 3 und 4 angemessen widergespiegelt oder aufgegriffen werden. Es ist dieses geometrische Gleichgewicht, das die legitimen Wolfe-Wellenformen auszeichnet. Für die Zwecke dieser Studie werden wir Symmetrie in einfachen, quantifizierbaren Begriffen definieren. Die Gesamtbewegung von Welle 1 zu Welle 2 sollte mindestens 70 % der Größe der Wellen 3 und 4 betragen. Bei der weiteren Entwicklung des Expert Advisors bietet dieser Prozentsatz einen soliden Rahmen für die Mustervalidierung und trägt dazu bei, die strukturelle und visuelle Integrität der Wolfe-Welle zu erhalten.
Zur Veranschaulichung dieses Kriteriums wird im Chart eine horizontale Trendlinie vom Zeitpunkt der Welle 1 bis zum Zeitpunkt der Welle 2 auf einem Kursniveau eingezeichnet, das 70 % unter dem Hoch der Welle 1 liegt. Diese Linie dient als Referenzpunkt, um zu gewährleisten, dass die nachfolgenden Wellen die Mindestgröße einhalten.
Unabhängig von der Reihenfolge der Wellen 1 und 2 wird hier die Funktion MathAbs verwendet, um zu gewährleisten, dass die berechnete Größe immer positiv ist. Die Verwendung von MathAbs ist eine vorbeugende Maßnahme, auch wenn sie in diesem speziellen Fall technisch nicht erforderlich ist, da Welle 1 voraussichtlich über Welle 2 in einem Abwärtsmuster liegen wird. Dies hilft, mögliche Fehler zu vermeiden, wenn die Wellen unterschätzt oder vertauscht werden.
Fibonacci-Ausdehnung von Welle 1 und Welle 2
Mit der Funktion IsSwingHigh findet der Algorithmus die Welle 3, indem er nach einem Umkehr-Hoch sucht, das nach Welle 2 kommt und zwischen der 127,2 %- und 161,8 %-Fibonacci-Ausdehnung der Wellen 1 und 2 liegt. Welle 3 wird gespeichert, wenn sie passt. Um sicherzugehen, dass wir es mit dem richtigen Muster zu tun haben, zeichnen wir nur die Fibonacci-Tools, die 70%-Linie und die Wellennamen in das Chart ein. Der Algorithmus sucht dann nach Welle 4, die ein Umkehr-Tief nach Welle 3 sein muss.
Beispiel:
input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; input double max_fib_ext_wv12 = 161.8; input double min_fib_ext_wv12 = 127.2; int bars_check = 500; datetime time_bar; double total_symbol_bars; double open[]; double close[]; double low[]; double high[]; datetime time[]; double wv1; datetime wv1_time; string wv1_txt; double wv2; datetime wv2_time; string wv2_txt; string fib_ext_wv1_wv2; ulong chart_id = ChartID(); double wv1_wv2_size; double wv1_wv2_70p; string perc_70; double fib_ext_1_2_161_8; double fib_ext_1_2_127_2; string fib_ext_range; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(chart_id); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { total_symbol_bars = Bars(_Symbol, timeframe); time_bar = iTime(_Symbol, timeframe, 0); CopyOpen(_Symbol, timeframe, time_bar, bars_check, open); CopyClose(_Symbol, timeframe, time_bar, bars_check, close); CopyLow(_Symbol, timeframe, time_bar, bars_check, low); CopyHigh(_Symbol, timeframe, time_bar, bars_check, high); CopyTime(_Symbol, timeframe, time_bar, bars_check, time); if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_1_2_127_2 = MathAbs((((wv1 - wv2) / 100) * (min_fib_ext_wv12 - 100)) + wv1); fib_ext_1_2_161_8 = MathAbs((((wv1 - wv2) / 100) * (max_fib_ext_wv12 - 100)) + wv1); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_time, fib_ext_1_2_161_8, wv2_time, fib_ext_1_2_127_2); break; } } } } } } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING LOW | //+------------------------------------------------------------------+ bool IsSwingLow(const double &low_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(low_price[index] > low_price[index - i] || low_price[index] > low_price[index + i]) return false; } return true; } //+------------------------------------------------------------------+ //| FUNCTION FOR SWING HIGH | //+------------------------------------------------------------------+ bool IsSwingHigh(const double &high_price[], int index, int lookback) { for(int i = 1; i <= lookback; i++) { if(high_price[index] < high_price[index - i] || high_price[index] < high_price[index + i]) return false; } return true; }
Ausgabe:

Identifizierung der Welle 3
Der Code geht von Welle 2 aus, um ein Umkehr-Hoch zu entdecken, das innerhalb der 127,2 %- bis 161,8 %-Ausdehnung der Wellen 1 und 2 liegt, um Welle 3 als eine fallende Wolfe-Welle zu identifizieren. Diese Zone wird als Welle 3 bezeichnet, wenn dort ein legitimer Swing entdeckt wird.
Beispiel:double wv3; datetime wv3_time; string wv3_txt;
if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1 - wv2) / 100) * (min_fib_ext_wv12 - 100)) + wv1); fib_ext_1_2_161_8 = MathAbs((((wv1 - wv2) / 100) * (max_fib_ext_wv12 - 100)) + wv1); for(int k = j; k < bars_check - 7; k++) { if(IsSwingHigh(high, k, 7) && time[k] > wv2_time) { wv3 = high[k]; wv3_time = time[k]; wv3_txt = StringFormat("WAVE 3 %d", k); if(wv3 >= fib_ext_1_2_127_2 && wv3 <= fib_ext_1_2_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_time, fib_ext_1_2_161_8, wv2_time, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_time, wv3); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); } break; } } break; } } } } }
Ausgabe:

Erläuterung:
Drei Variablen werden im Code verwendet, um die Welle 3 zu definieren: wv3 für das Preisniveau, wv3_time für den Zeitpunkt und wv3_txt für die Beschriftung. Durch den Einsatz der IsSwingHigh-Funktion, um gültige hohe Umkehrpunkte zu finden, die auf Welle 2 folgen, kann sie Welle 3 bestimmen, indem sie von der Position von Welle 2 aus nach vorne scannt. Zuvor wurden alle Objekte nach der Erkennung von wv2 gezeichnet. Jetzt werden diese Objekte nur angezeigt, wenn wv3 innerhalb der angegebenen Erweiterung von wv1 und wv2 liegt.
Identifizierung von Welle 4
Die Suche nach Welle 4, die ein Tief sein muss, der sich nach Welle 3 entwickelt, ist der nächste Schritt. Wir müssen überprüfen, ob die Kursbewegung von Welle 3 zu Welle 4 eine angemessene Symmetrie mit der Bewegung von Welle 1 zu Welle 2 beibehält, um zu bestätigen, dass das Muster noch gültig ist. Wir wenden in diesem Projekt ein einfaches Symmetriekriterium an, das besagt, dass die Wellen 3 bis 4 mindestens 70 % so groß sein müssen wie die Wellen 1 bis 2. Durch die Verhinderung unverhältnismäßiger oder flacher Rücksetzer trägt diese Anforderung zur Aufrechterhaltung des strukturellen Gleichgewichts des Wolfe-Wellenmusters bei. Im folgenden Teil werden wir diese Überlegungen in die Praxis umsetzen, indem wir nach einem legitimen Umkehr-Tief im Anschluss an Welle 3 suchen und bestätigen, dass es die Kriterien der Mindestgröße erfüllt.
Beispiel:double wv4; datetime wv4_time; string wv4_txt; double wv3_wv4_size;
if(total_symbol_bars >= bars_check) { for(int i = 7; i < bars_check - 7; i++) { if(IsSwingHigh(high, i, 7)) { wv1 = high[i]; wv1_time = time[i]; wv1_txt = StringFormat("WAVE 1 %d", i); for(int j = i; j < bars_check - 7; j++) { if(IsSwingLow(low, j, 7) && low[j] < wv1) { wv2 = low[j]; wv2_time = time[j]; wv2_txt = StringFormat("WAVE 2 %d", j); wv1_wv2_size = MathAbs(wv1 - wv2); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1 - wv2) / 100) * (min_fib_ext_wv12 - 100)) + wv1); fib_ext_1_2_161_8 = MathAbs((((wv1 - wv2) / 100) * (max_fib_ext_wv12 - 100)) + wv1); for(int k = j; k < bars_check - 7; k++) { if(IsSwingHigh(high, k, 7) && time[k] > wv2_time) { wv3 = high[k]; wv3_time = time[k]; wv3_txt = StringFormat("WAVE 3 %d", k); if(wv3 >= fib_ext_1_2_127_2 && wv3 <= fib_ext_1_2_161_8) { for(int l = k; l < bars_check - 7; l++) { if(IsSwingLow(low, l, 7) && time[l] > wv3_time) { wv4 = low[l]; wv4_time = time[l]; wv4_txt = StringFormat("WAVE 4 %d", l); wv3_wv4_size = MathAbs(wv3 - wv4); if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2 && wv4 < wv3) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_time, wv1); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_time, wv2); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_time, wv2, wv1_time, wv1, wv2_time, wv2); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_time, wv1 - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_time, fib_ext_1_2_161_8, wv2_time, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_time, wv3); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); } break; } } } break; } } break; } } } } }
Ausgabe:

Erläuterung:
Nachdem das Programm wv3 identifiziert hat, muss als Nächstes wv4 identifiziert werden. Gesucht wird der Abstand zwischen wv3 und wv4 und in wv3_wv4_size gespeichert. Nachdem das Programm ein Umkehr-Tief entdeckt hat, speichert es die Zeit und den Preis des Balkens als wv4_time und wv4. Das Programm stellt sicher, dass wv3 und wv4 ähnlich wie wv1 und wv2 sind, und sorgt dafür, dass Welle 4 über Welle 2 und unter Welle 3 bleibt, um die richtige Struktur zu erhalten. Das Programm prüft, ob wv3 in die angegebene Erweiterung fällt. Welle 4, die das Muster-Setup unter Verwendung der Umkehr-Logik, der Fibonacci-Filter und der Symmetriekriterien vervollständigt, wird im Chart gekennzeichnet, nachdem alle Prüfungen erfolgreich waren.


Wie Sie im ersten Bild (Abbildung 11) sehen können, ist Welle 3 nicht das höchste Hoch während des Übergangs von Welle 3 zu Welle 4. Welle 3 sollte der wichtigste Höhepunkt vor dem Eintauchen in Welle 4 sein, daher ist dies problematisch. Die richtige Struktur wurde von unserem Erkennungsmechanismus nicht erfasst, wenn ein höheres Hoch nach dem Punkt auftritt, den wir als Welle 3 bezeichnet haben. Das zweite Bild (Abbildung 12) zeigt auch, dass die Welle 1 im Bereich zwischen den Wellen 1 und 2 nicht die höchste ist.
Darüber hinaus verstößt dies gegen die Regeln des Musters, da Welle 1 das dominierende Umkehr-Hoch in diesem Abschnitt sein sollte. Wir werden keine zuverlässigen Ergebnisse für das Wolfe-Wellenmuster erhalten, wenn unser Algorithmus immer wieder grundlegend falsche Wellenpunkte wählt. Um die Zuverlässigkeit der Erkennungslogik zu erhöhen, muss dieses Problem gelöst werden.
Wir werden nun einen zusätzlichen Validierungsschritt für jede Welle hinzufügen, um die Probleme zu lösen, die wir in den früheren Beispielen gesehen haben. Um sicher zu sein, dass Welle 3 den Höchststand vor dem Rückgang korrekt wiedergibt, muss es sich um den Höchststand zwischen den Wellen 3 und 4 handeln. Welle 2 muss den tiefsten Stand zwischen den Wellen 2 und 3 erreichen, um wirklich den Boden vor dem nächsten Aufwärtstrend zu bilden. Welle 1 muss das höchste Hoch zwischen den Wellen 1 und 2 sein, um leicht als das signifikante Umkehr-Hoch in diesem Mustersegment erkannt zu werden.
Beispiel:
int wv3_wv4_bars; int wv3_highest_index; double wv3_hh; datetime wv3_hh_t; int wv2_wv3_bars; int wv2_lowest_index; double wv2_ll; datetime wv2_ll_t; int wv1_wv2_bars; int wv1_highest_index; double wv1_hh; datetime wv1_hh_t;
for(int l = k; l < bars_check - 7; l++) { if(IsSwingLow(low, l, 7) && time[l] > wv3_time) { wv4 = low[l]; wv4_time = time[l]; wv4_txt = StringFormat("WAVE 4 %d", l); wv3_wv4_bars = Bars(_Symbol, timeframe, wv3_time, wv4_time); wv3_highest_index = ArrayMaximum(high, k, wv3_wv4_bars); wv3_hh = high[wv3_highest_index]; wv3_hh_t = time[wv3_highest_index]; wv2_wv3_bars = Bars(_Symbol, timeframe, wv2_time, wv3_time); wv2_lowest_index = ArrayMinimum(low, j, wv2_wv3_bars); wv2_ll = low[wv2_lowest_index]; wv2_ll_t = time[wv2_lowest_index]; wv1_wv2_bars = Bars(_Symbol, timeframe, wv1_time, wv2_time); wv1_highest_index = ArrayMaximum(high, i, wv1_wv2_bars); wv1_hh = high[wv1_highest_index]; wv1_hh_t = time[wv1_highest_index]; wv1_wv2_size = MathAbs(wv1_hh - wv2_ll); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1_hh - wv2_ll) / 100) * (min_fib_ext_wv12 - 100)) + wv1_hh); fib_ext_1_2_161_8 = MathAbs((((wv1_hh - wv2_ll) / 100) * (max_fib_ext_wv12 - 100)) + wv1_hh); wv3_wv4_size = MathAbs(wv3_hh - wv4); if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); } break; } }
Ausgabe:

Erläuterung:
Wir schlagen eine neue Reihe von Berechnungen vor, um die Struktur der Wolfe-Welle zu überprüfen und sicherzustellen, dass jeder Wellenpunkt den wichtigsten Hoch- oder Tiefpunkt in seinem Segment genau abbildet. Um die extremen Preispunkte (höchstes Hoch oder tiefstes Tief) zwischen den einzelnen Wellensegmenten zu identifizieren, deklarieren wir zunächst eine Reihe von Variablen: Die Variable wv3_wv4_bars enthält die Anzahl der Balken, die die Wellen 3 und 4 trennen. Der Höchststand innerhalb dieses Bereichs wird dann mit ArrayMaximum ermittelt, indem die Anzahl der Balken von wv3_wv4_bars durchlaufen wird und bei Index k (wo sich Welle 3 befindet) begonnen wird. Der wv3_highest_index behält das Ergebnis bei. Dieser Index wird verwendet, um das wahre Hoch (wv3_hh) und seinen Zeitstempel (wv3_hh_t) zu extrahieren.
wv2_wv3_bars deckt den Bereich zwischen den Wellen 2 und 3 ab, obwohl die Funktionsweise ähnlich ist. Hier verwenden wir ArrayMinimum, das den Index des niedrigsten Preises liefert, um den niedrigsten Wert zu finden. Wir rufen den passenden niedrigen Preis (wv2_ll) und die Zeit (wv2_ll_t) ab, nachdem wir diesen Index in wv2_lowest_index gespeichert haben. Die Anzahl der Balken zwischen den Wellen 1 und 2 wird durch wv1_wv2_bars bestimmt. In diesem Fall sollte Welle 1 eine dominante Spitze sein; daher verwenden wir wieder ArrayMaximum, um den höchsten Wert in diesem Bereich zu ermitteln. Aus dem sich daraus ergebenden Index, der in wv1_highest_index gespeichert wird, werden der höchste Preis (wv1_hh) und das dazugehörige Datum (wv1_hh_t) extrahiert.
In wv3_wv4_bars wird die Anzahl der Balken zwischen den Wellen 3 und 4 erfasst. Um das höchste Hoch innerhalb dieses Bereichs zu finden, verwenden wir ArrayMaximum, um die Anzahl der Balken von wv3_wv4_bars zu überprüfen und bei Index k zu beginnen, wo sich die Welle 3 befindet. Das Ergebnis bleibt im wv3_highest_index. Dieser Index wird verwendet, um den Zeitstempel (wv3_hh_t) und das tatsächliche Hoch (wv3_hh) zu extrahieren. Wir erhöhen die Genauigkeit unserer Wolfe-Wellen-Erkennung und verringern die Wahrscheinlichkeit, schwache oder falsche Wellenmuster zu erkennen, indem wir diese Einschränkungen programmatisch durchsetzen. Die Einhaltung der technischen Konzepte und die Eignung des Musters für die reale Handelsanalyse werden durch diese zusätzliche Validierungsstufe gewährleistet.
Die validierten Hoch- oder Tiefpunkte werden nun für die Konstruktion von Objekten auf dem Chart verwendet und nicht mehr die ursprünglich gewählten Wellenpunkte. Für Welle 1 werden wir wv1_hh_t und wv1_hh durch wv1_time und wv1 ersetzen. Wir ersetzen wv2_ll_t und wv2_ll für wv2_time und wv2 für Wave 2. Zusätzlich werden wir für Welle 3 wv3_hh_t und wv3_hh durch wv3_time und wv3 ersetzen. Durch diese Anpassung können wir sicher sein, dass wir uns auf die tatsächlichen strukturellen Höchst- und Tiefstwerte der einzelnen Segmente beziehen und nicht nur auf die gefundenen, anfänglichen Umkehrpunkte. Wir erhöhen die Genauigkeit und Verlässlichkeit der Wolfe-Wellen-Visualisierung erheblich, indem wir Chart-Objekte in diesen validierten Bereichen einzeichnen und Händlern helfen, auf der Grundlage einer exakteren Musterstruktur fundiertere Entscheidungen zu treffen.
Nur wenn die folgenden Kriterien erfüllt sind, werden die Fibonacci-Erweiterung, die Chart-Elemente der Wellen 1-4 und andere grafische Komponenten generiert:
if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8)Diese Bedingung garantiert, dass alle preislichen und strukturellen Voraussetzungen für eine legitime fallende Wolfe-Welle erfüllt sind. Es bestätigt, dass die Wellen 3 und 4 vertikal mindestens so weit voneinander entfernt sind wie die Wellen 1 und 2, wobei die Symmetrie erhalten bleibt. Die Position der Welle 4 über dem Tief zwischen den Wellen 2 und 3 und unter dem Hoch zwischen den Wellen 3 und 4 wird hierdurch weiter bestätigt. Darüber hinaus muss sich die Welle 3 im Vergleich zu den Wellen 1 und 2 innerhalb des Fibonacci-Ausdehnungsbereichs von 127,2 % bis 200 % bewegen.
Die Software wird die Wellen nicht benennen, die Fibonacci-Projektion nicht erstellen und die erforderlichen Trendlinien auf dem Chart nicht anzeigen, bis alle diese Anforderungen erfüllt sind. Diese strenge Validierung garantiert eine höhere Genauigkeit bei der Erkennung von Wolfe-Wellen und hilft, das Zeichnen ungenauer oder unvollständiger Muster zu verhindern.
Identifizierung der fünften Welle
Die Suche nach Welle 5 ist der nächste Schritt in unserem Verfahren zur Erkennung von Wolfe-Wellen. Da sie den möglichen Umkehrpunkt des Musters anzeigt, ist diese Welle von entscheidender Bedeutung. Die Welle 5 ist ein nützlicher Indikator in der technischen Analyse, da die Händler häufig nach ihr suchen, um eine Richtungsänderung des Marktes vorherzusagen. Wir müssen jedoch zunächst drei entscheidende Trendlinien konstruieren, die die Bestätigung von Welle 5 leiten werden, bevor wir sie korrekt identifizieren können.
Die erste Trendlinie wird die Wellen 1 und 3 verbinden. Diese Linie stellt in der Regel die obere Grenze des Musters in einer fallende Wolfe-Welle dar. Er trägt dazu bei, die Struktur und die Richtung des Musters zu definieren und dient als Widerstandsniveau, innerhalb dessen der Kurs während des Aufbaus von Welle 4 und der Entwicklung von Welle 5 bleibt. Die zweite Trendlinie wird die Wellen zwei und vier verbinden. Diese Linie ist wichtig, weil sie die Kanalstruktur und Symmetrie der Wolfe-Welle verdeutlicht. Wenn sich der Kurs dem Umkehrpunkt nähert, gibt er einen allgemeinen Hinweis auf den erwarteten Verlauf von Welle 5.
Die dritte Trendlinie, die die Wellen 1 und 4 verbindet, hat eine andere Funktion als die ersten beiden. Normalerweise wird diese Zeile verwendet, um zu entscheiden, wann die Transaktion beendet werden soll. Die Linie zwischen Welle 1 und Welle 4 dient als Take-Profit-Ziel in einer fallende Wolfe-Welle, sobald Welle 5 entdeckt wurde und der Kurs beginnt, sich in die erwartete Richtung zu bewegen. Sobald der Markt diese Trendlinie überschreitet, wird der Handel geschlossen, da dies anzeigt, dass die erwartete Bewegung stattgefunden hat und das Muster abgeschlossen ist.
Beispiel:string tline_1_3; string tline_2_4; string tline_1_4;
if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); ObjectCreate(chart_id, tline_1_3, OBJ_TREND, 0, wv1_hh_t, wv1_hh, wv3_hh_t, wv3_hh); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); ObjectCreate(chart_id, tline_2_4, OBJ_TREND, 0, wv2_ll_t, wv2_ll, wv4_time, wv4); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); ObjectCreate(chart_id, tline_1_4, OBJ_TREND, 0, wv1_hh_t, wv1_hh, wv4_time, wv4); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); }
Ausgabe:

Erläuterung:
Der Zweck der anfänglichen Deklaration der String-Variablen tline_1_3, tline_2_4 und tline_1_4 besteht darin, Trendlinien im Chart eindeutig zu identifizieren. In tline_1_3 wird die obere Begrenzung des fallende Wolfe-Wellenmusters durch die Trendlinie dargestellt, die die Wellen 1 und 3 verbindet. ObjectCreate() wird verwendet, um es unter Verwendung der bestätigten höchsten Punkte der Wellen 1 und 3 zu erstellen, und es ist zur besseren Sichtbarkeit blau gefärbt. Die zweite Trendlinie, die die Wellen 2 und 4 verbindet, wird in tline_2_4 beibehalten. Der Tiefpunkt der Welle 2 (wv2_ll_t, wv2_ll) ist zwischen dem Punkt der Welle 4 (wv4_time, wv4) eingezeichnet, der ebenfalls in Blau dargestellt ist. Die Wellen 1 und 4 sind durch die dritte Trendlinie, tline_1_4, verbunden.
Die Trendlinien werden nur zwischen zwei vorher festgelegten Ankerpunkten erstellt, was bei dieser Methode ein Problem darstellt. Jede Linie in einem echten Muster der Wolfe-Wellen sollte über ihren zweiten Anker hinausreichen, um mögliche zukünftige Interaktionen zwischen dem Anker und dem Preis anzuzeigen. So ist beispielsweise die Trendlinie zwischen den Wellen 1 und 3 nicht nur ein kurzes Segment zwischen diesen beiden Punkten. Stattdessen wird erwartet, dass sich die Welle 3 fortsetzt, sofern der Markt nicht über diese Marke steigt und dann wieder darunter fällt. Dieser erweiterte Abschnitt vermittelt ein klareres Bild von der Verbindung zwischen dem Preis und der oberen Grenze des Musters im Zeitverlauf.
Die Einhaltung der Wolfe-Wellen-Symmetrie und die Vorhersage der wahrscheinlichen Position von Welle 5 setzt voraus, dass die Trendlinie zwischen den Wellen 2 und 4 die gleiche Länge und Richtung hat wie die Linie zwischen den Wellen 1 und 3. Wenn sich der Kurs auf die Trendlinie zubewegt, die als Ziel für den Ausstieg aus dem Handel dient und angibt, wann die Transaktion abgeschlossen werden soll, muss sie auch über die Welle 4 hinaus verlängert werden, um befolgt zu werden. Alle drei Trendlinien müssen also in angemessener Weise in die Zukunft verlängert werden, um eine genaue Musterbestätigung und Handelsvorbereitung zu ermöglichen.
Beispiel:
tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); ObjectCreate(chart_id,tline_1_3,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv3_hh_t,wv3_hh); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); ObjectCreate(chart_id,tline_2_4,OBJ_TREND,0,wv2_ll_t,wv2_ll,wv4_time,wv4); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); ObjectCreate(chart_id,tline_1_4,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv4_time,wv4); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true);

Das Attribut OBJPROP_RAY_RIGHT sorgt dafür, dass die Trendlinien über ihre Ankerpositionen hinausgehen, was ebenfalls ein Problem darstellt. Obwohl dies für die Aufrechterhaltung der Sichtbarkeit der Linie nützlich sein könnte, entspricht es nicht dem genauen Verhalten, nach dem wir in der Wolfe-Wellen-Analyse suchen. Wir wollen nicht, dass sich die Trendlinien in unserer Situation ewig fortsetzen. Vielmehr wollen wir, dass sie zu einem bestimmten Zeitpunkt anhalten, insbesondere wenn ein bestimmter Umstand erfüllt ist.
Die Trendlinie, die die Wellen 1 und 3 verbindet, sollte beispielsweise nur so weit gehen, wie der Markt sie überschreitet, bevor er wieder darunter fällt. Auf diese Weise bleibt die Genauigkeit erhalten, und das Chart wird von überflüssigen, möglicherweise irrelevanten Trendlinien freigehalten. Wir haben eine bessere Kontrolle, und die visuelle Struktur des Wolfe-Wellenmusters ist präziser und sauberer, wenn wir für jede Linie eine bestimmte Endzeit auf der Grundlage der tatsächlichen Preisinteraktion festlegen.
Beispiel:tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); if(ObjectCreate(chart_id,tline_1_3,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv3_hh_t,wv3_hh)) { ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); if(ObjectCreate(chart_id,tline_2_4,OBJ_TREND,0,wv2_ll_t,wv2_ll,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); if(ObjectCreate(chart_id,tline_1_4,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); }

Erläuterung:
Indem das Attribut so eingestellt wird, dass es in allen Zeitrahmen verborgen bleibt, erzeugt dieser Code eine unsichtbare Trendlinie, die intern verwendet werden kann, ohne dass sie auf dem Chart zu sehen ist. Anschließend achtet er auf signifikante Kursschwankungen, z. B. wenn eine Kerze über und dann unter dieser Trendlinie der Welle 1-3 schließt.
Beispiel:double t_1_3_values; double t_2_4_values; string tline_1_3_visible; string tline_2_4_visible;
for(int m = l; m < bars_check - 2; m++) { t_1_3_values = ObjectGetValueByTime(chart_id, tline_1_3, time[m], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[m], 0); if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[m],t_1_3_values); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[m],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); break; } }
Ausgabe:

Erläuterung:
Dieser Codeabschnitt erkennt, wenn der Kurs die Trendlinie, die die Wellen 1 und 3 verbindet, durchbricht, indem er die zukünftigen Balken ab der Welle 4 überprüft. Er verwendet Variablen, um das Preisniveau der Trendlinie zum Zeitpunkt jedes Balkens zu ermitteln, und sucht nach einer Aufwärtskerze, die unterhalb der Trendlinie eröffnet, aber oberhalb davon schließt, was einen Ausbruch signalisiert, der mindestens vier Balken nach Welle 4 erfolgen muss. Zwei zusätzliche sichtbare Trendlinien werden generiert und bei Erkennung des Ausbruchs dynamisch mit StringFormat benannt. Das Chart zeigt dann diese Trendlinien an, von denen eine die Welle 1 mit dem Ausbruchspunkt und die andere die Welle 2 mit der gleichen Position verbindet. Dies hilft Ihnen, die Entwicklung des Wolfe-Wellenmusters besser zu beobachten und zu bewerten, da sie einen klaren visuellen Hinweis auf den genauen Balken erhalten, an dem der Preis die Trendlinie der Welle 1-3 überschreitet.
Aber das ist nicht unser Ziel. Die sichtbaren Trendlinien, die beim Überschreiten der Trendlinie der Wellen 1 bis 3 entstehen, unterstreichen zwar den Ausbruch, beenden aber noch nicht die Wolfe-Wellenstruktur. Das eigentliche Ziel besteht darin, diese Linien so lange zu verlängern, bis der Markt die Trendlinie der Wellen 1-3 kreuzt und darunter schließt.
Beispiel:double t_1_3_values_2;for(int m = l; m < bars_check - 2; m++) { t_1_3_values = ObjectGetValueByTime(chart_id, tline_1_3, time[m], 0); if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { for(int n = m; n < bars_check - 1; n++) { t_1_3_values_2 = ObjectGetValueByTime(chart_id, tline_1_3, time[n], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[n], 0); if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2) { tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); break; } } break; } }
Ausgabe:

Erläuterung:
Aber das ist nicht unser Ziel. Die sichtbaren Trendlinien, die beim Überschreiten der Trendlinie der Wellen 1 bis 3 entstehen, unterstreichen zwar den Ausbruch, beenden aber noch nicht die Wolfe-Wellenstruktur. Das eigentliche Ziel besteht darin, diese Linien so lange zu verlängern, bis der Markt die Trendlinie der Wellen 1-3 kreuzt und darunter schließt. Insbesondere verwendet die innere for-Schleife die Variable t_1_3_values_2, um das Kursniveau der Trendlinie der Welle 1-3 zu einem späteren Zeitpunkt zu halten. Diese Schleife beginnt ab dem Balken, an dem der Durchbruch über die Trendlinie beobachtet wurde (m). Es verwendet ObjectGetValueByTime, um den Trendlinienwert zu diesem Zeitpunkt für jeden Balken n abzurufen und speichert ihn in t_1_3_values_2.
Eine Abwärtskerze, die oberhalb der Trendlinie eröffnet und unterhalb der Trendlinie geschlossen wurde, wird durch den Ausdruck if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2) überprüft, der anzeigt, dass der Kurs nun wieder unter die Trendlinie zurückgefallen ist. Bemerkenswert ist die Tatsache, dass dieser Punkt häufig den Abschluss von Welle 5 und den Beginn der erwarteten Kursumkehr markiert. Sobald dieses zweite Kreuzen gefunden wird, entstehen zwei erkennbare Trendlinien, von denen die eine die Welle 1 mit dieser neuen Position auf dem Chart verbindet, während die andere die Welle 2 mit derselben Stelle verbindet. Dies vermittelt ein umfassenderes und genaueres Bild der Wolfe-Welle vom Beginn über den Ausbruch bis zur Umkehrung und ersetzt die bisherigen Trendlinien. Nun erstrecken sich die Trendlinien von ihren Ausgangspositionen bis zu dem Punkt, an dem die Preisbewegung das gesamte Muster bestätigt.
Der nächste Schritt besteht darin, das Preisniveau von Welle 5 zu ermitteln. Um dies zu erreichen, müssen wir den höchsten Stand zwischen zwei signifikanten Punkten bestimmen: das erste Mal, wenn der Markt die Trendlinie der Wellen 1 bis 3 kreuzt und darüber schließt, und das zweite Mal, wenn er sich umkehrt und unter dieselbe Trendlinie fällt. Normalerweise bezeichnet dieser Bereich die Abschlussphase des Wolfe-Wellenmusters. Bevor die erwartete Umkehr einsetzt, macht der Kurs in diesem Bereich häufig noch einen weiteren Vorstoß nach oben. Wenn wir den höchsten Stand in diesem Fenster finden, können wir den Höhepunkt von Welle 5 genau bestimmen.
Beispiel:int cross_bars; int cross_bars_highest; string wv5_txt;
if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { for(int n = m; n < bars_check - 1; n++) { t_1_3_values_2 = ObjectGetValueByTime(chart_id, tline_1_3, time[n], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[n], 0); if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2) { tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); cross_bars = Bars(_Symbol,timeframe,time[n], time[m]); cross_bars_highest = ArrayMaximum(high,m,cross_bars); wv5_txt = StringFormat("WAVE 5 %d", i); ObjectCreate(chart_id, wv5_txt, OBJ_TEXT, 0, time[cross_bars_highest], high[cross_bars_highest]); ObjectSetString(chart_id, wv5_txt, OBJPROP_TEXT, "WV5"); ObjectSetInteger(chart_id, wv5_txt, OBJPROP_COLOR, clrBlue); break; } }
Erläuterung:
Welle 5 des Wolfe-Wellenmusters wird in diesem Codesegment identifiziert und gekennzeichnet. Der Algorithmus bestimmt die Anzahl der Balken zwischen dem Ausbruchs- und dem Umkehrpunkt, um den voraussichtlichen Zeitpunkt für das Auftreten von Welle 5 zu ermitteln, sobald der Kurs über die Trendlinie von Welle 1-3 bricht und dann wieder unter diese zurückkehrt. Der Code beginnt dann bei Index m und durchläuft die Anzahl der Balken in cross_bars mit Hilfe der Funktion ArrayMaximum(), um das Preis-Array high[] zu durchsuchen. Der Index des höchsten Hochs in diesem Bereich, der den Spitzenwert von Welle 5 bezeichnet, wird von dieser Funktion zurückgegeben. In der Variablen cross_bars_highest wird dieser Index gespeichert.
Um dieses erkannte Hoch als „WV5“ zu bezeichnen, erzeugt der Code schließlich ein Textobjekt im Chart. Die Beschriftung wird anhand des Datums und des Preises beim Index cross_bars_highest positioniert, und ihre Farbe wird auf blau gesetzt, um den Beschriftungen der vorangegangenen Wellen zu ähneln. Dies vervollständigt die Wolfe-Wellenstruktur grafisch auf dem Chart, indem es garantiert, dass die Welle 5 am höchsten Punkt zwischen dem Ausbruch und der Umkehrung angemessen markiert ist.
Fibonacci Erweiterung
Wie Sie sich vielleicht erinnern, haben wir bereits festgestellt, dass Welle 5 innerhalb eines bestimmten Bereichs der durch die Wellen 3 und 4 erzeugten Expansion liegen muss. Zwischen den Wellen 3 und 4 liegt diese Spanne in der Regel zwischen 127,2 % und 161,8 % der Kursveränderung.
Beispiel:input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; // TIMEFRAME input double max_fib_ext_wv12 = 161.8; // WAVE 1 AND 2 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv12 = 127.2; // WAVE 1 AND 2 FIBO EXTENSION MIN LEVEL input double max_fib_ext_wv34 = 120.0; // WAVE 3 AND 4 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv34 = 200.0; // WAVE 3 AND 4 FIBO EXTENSION MIN LEVEL string fib_ext_3_4; double fib_ext_3_4_161_8; double fib_ext_3_4_127_2; string fib_ext_3_4_168_127; string fib_ext_range_3_4; int no_bars;
for(int l = k; l < bars_check - 7; l++) { if(IsSwingLow(low, l, 7) && time[l] > wv3_time) { wv4 = low[l]; wv4_time = time[l]; wv4_txt = StringFormat("WAVE 4 %d", l); wv3_wv4_bars = Bars(_Symbol, timeframe, wv3_time, wv4_time); wv3_highest_index = ArrayMaximum(high, k, wv3_wv4_bars); wv3_hh = high[wv3_highest_index]; wv3_hh_t = time[wv3_highest_index]; wv2_wv3_bars = Bars(_Symbol, timeframe, wv2_time, wv3_time); wv2_lowest_index = ArrayMinimum(low, j, wv2_wv3_bars); wv2_ll = low[wv2_lowest_index]; wv2_ll_t = time[wv2_lowest_index]; wv1_wv2_bars = Bars(_Symbol, timeframe, wv1_time, wv2_time); wv1_highest_index = ArrayMaximum(high, i, wv1_wv2_bars); wv1_hh = high[wv1_highest_index]; wv1_hh_t = time[wv1_highest_index]; wv1_wv2_size = MathAbs(wv1_hh - wv2_ll); wv1_wv2_70p = (wv1_wv2_size / 100) * 70; fib_ext_1_2_127_2 = MathAbs((((wv1_hh - wv2_ll) / 100) * (min_fib_ext_wv12 - 100)) + wv1_hh); fib_ext_1_2_161_8 = MathAbs((((wv1_hh - wv2_ll) / 100) * (max_fib_ext_wv12 - 100)) + wv1_hh); wv3_wv4_size = MathAbs(wv3_hh - wv4); if(wv3_wv4_size >= wv1_wv2_size && wv4 > wv2_ll && wv4 < wv3_hh && wv3_hh >= fib_ext_1_2_127_2 && wv3_hh <= fib_ext_1_2_161_8) { tline_1_3 = StringFormat("TREND LINE WAVE 1 AND 3 %d", i); if(ObjectCreate(chart_id,tline_1_3,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv3_hh_t,wv3_hh)) { ObjectSetInteger(chart_id, tline_1_3, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_3, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_2_4 = StringFormat("TREND LINE WAVE 2 AND 4 %d", i); if(ObjectCreate(chart_id,tline_2_4,OBJ_TREND,0,wv2_ll_t,wv2_ll,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_2_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_2_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } tline_1_4 = StringFormat("TREND LINE WAVE 1 AND 4 %d", i); if(ObjectCreate(chart_id,tline_1_4,OBJ_TREND,0,wv1_hh_t,wv1_hh,wv4_time,wv4)) { ObjectSetInteger(chart_id, tline_1_4, OBJPROP_COLOR, clrBlue); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_RAY_RIGHT, true); ObjectSetInteger(chart_id, tline_1_4, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } fib_ext_3_4 = StringFormat("FIB EXTENSION WAVE 3 AND 4 %d", i); fib_ext_3_4_127_2 = MathAbs((((wv3_hh - wv4) / 100) * (min_fib_ext_wv34 - 100)) + wv3_hh); fib_ext_3_4_161_8 = MathAbs((((wv3_hh - wv4) / 100) * (max_fib_ext_wv34 - 100)) + wv3_hh); fib_ext_3_4_168_127 = StringFormat("FIB EXTENSION wv3 wv4 %d", i); for(int m = l; m < bars_check - 2; m++) { t_1_3_values = ObjectGetValueByTime(chart_id, tline_1_3, time[m], 0); if(close[m] > open[m] && open[m] < t_1_3_values && close[m] > t_1_3_values && time[m] > time[l+4]) { for(int n = m; n < bars_check - 1; n++) { t_1_3_values_2 = ObjectGetValueByTime(chart_id, tline_1_3, time[n], 0); t_2_4_values = ObjectGetValueByTime(chart_id, tline_2_4, time[n], 0); no_bars = Bars(_Symbol, timeframe, wv3_hh_t, time[n]); cross_bars = Bars(_Symbol,timeframe,time[n], time[m]); cross_bars_highest = ArrayMaximum(high,m,cross_bars); if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2 && no_bars < 100 && time[n] > time[m] && high[cross_bars_highest] >= fib_ext_3_4_127_2 && high[cross_bars_highest] <= fib_ext_3_4_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); wv5_txt = StringFormat("WAVE 5 %d", i); ObjectCreate(chart_id, wv5_txt, OBJ_TEXT, 0, time[cross_bars_highest], high[cross_bars_highest]); ObjectSetString(chart_id, wv5_txt, OBJPROP_TEXT, "WV5"); ObjectSetInteger(chart_id, wv5_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, fib_ext_3_4,OBJ_EXPANSION, 0,wv4_time, wv4,wv3_hh_t,wv3_hh,wv4_time,wv4); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_LEVELCOLOR,i,clrBlue); ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_COLOR,clrBlue); } fib_ext_range_3_4 = StringFormat("Fibo EXPENSION RANGE WV3 WV4 %d", i); ObjectCreate(chart_id,fib_ext_range_3_4,OBJ_RECTANGLE,0,wv3_hh_t,fib_ext_3_4_127_2,time[cross_bars_highest],fib_ext_3_4_161_8); break; } } break; } } } break; } }
Ausgabe:

Erläuterung:
Er verwendet die Fibonacci-Expansion der Wellen 3 und 4. Durch die Berechnung der Fibonacci-Levels und das Zählen der Balken zwischen Welle 3 und dem Kurs, der unter der Trendlinie von Welle 1-3 schließt, wird sichergestellt, dass das Muster strukturell solide und kompakt ist. Der EA sucht nach einer bestimmten Abwärtskerze innerhalb des Konditionsblocks, die über die Trendlinie der Welle 1 bis 3 ausbricht, bevor sie wieder unter dieser schließt. Die Umkehrung muss innerhalb einer angemessenen Anzahl von Balken (weniger als 100) erfolgen, und der höchste Kurs zwischen dem Ausbruch und der Umkehrung muss nach weiteren Parametern innerhalb des zulässigen Fibonacci-Ausdehnungsbereichs liegen. Welle 5 könnte legitim sein, wenn jede dieser Voraussetzungen erfüllt ist.
Die Wellen 3 und 4 werden dann als Basisbeine verwendet, um ein Objekt der Fibonacci-Expansion zu zeichnen. Zur besseren Sichtbarkeit sind alle drei Expansionsstufen – 0, 127,2 und 161,8 – blau dargestellt. Um die Fibonacci-Torzone visuell hervorzuheben, wird ebenfalls ein Rechteck gemalt. Entscheidend ist, dass dieser Bedingungsblock der einzige ist, mit dem alle relevanten Chart-Objekte, wie Expansionszonen, Beschriftungen und Trendlinien, erzeugt werden. Dies verringert Fehlsignale und erhöht die Zuverlässigkeit der Wolfe-Wellen-Erkennungslogik, da garantiert wird, dass das vollständige Muster nur dann markiert wird, wenn alle Regeln erfüllt sind.
Zeichnung der Trendlinie von Welle 1 bis Welle 4
Bevor wir fortfahren, den EA Handelsgeschäfte ausführen zu lassen, müssen wir die Trendlinie zeichnen, die Welle 1 mit Welle 4 verbindet. Diese Trendlinie spielt im Muster der Wolfe-Wellen eine entscheidende Rolle, insbesondere für die Ausstiegsplanung.int no_wv1_n_bars; int no_n_c_bars; string tline_1_4_visible; double t_1_4_values; string tline_1_4_visible_2; if(close[n] < open[n] && open[n] > t_1_3_values_2 && close[n] < t_1_3_values_2 && no_bars < 100 && time[n] > time[m] && high[cross_bars_highest] >= fib_ext_3_4_127_2 && high[cross_bars_highest] <= fib_ext_3_4_161_8) { ObjectCreate(chart_id, wv1_txt, OBJ_TEXT, 0, wv1_hh_t, wv1_hh); ObjectSetString(chart_id, wv1_txt, OBJPROP_TEXT, "WV1"); ObjectSetInteger(chart_id, wv1_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv2_txt, OBJ_TEXT, 0, wv2_ll_t, wv2_ll); ObjectSetString(chart_id, wv2_txt, OBJPROP_TEXT, "WV2"); ObjectSetInteger(chart_id, wv2_txt, OBJPROP_COLOR, clrBlue); fib_ext_wv1_wv2 = StringFormat("FIBO EXTENSION WAVE 1 AND 2 %d", i); ObjectCreate(chart_id, fib_ext_wv1_wv2, OBJ_EXPANSION, 0, wv2_ll_t, wv2_ll, wv1_hh_t, wv1_hh, wv2_ll_t, wv2_ll); ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_COLOR, clrBlue); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id, fib_ext_wv1_wv2, OBJPROP_LEVELCOLOR, i, clrBlue); } perc_70 = StringFormat("70 PERCENT %d", j); ObjectCreate(chart_id, perc_70, OBJ_TREND, 0, wv1_hh_t, wv1_hh - wv1_wv2_70p, wv2_time, wv1 - wv1_wv2_70p); fib_ext_range = StringFormat("Fibo EXPENSION RANGE%d", j); ObjectCreate(chart_id, fib_ext_range, OBJ_RECTANGLE, 0, wv1_hh_t, fib_ext_1_2_161_8, wv2_ll_t, fib_ext_1_2_127_2); ObjectCreate(chart_id, wv3_txt, OBJ_TEXT, 0, wv3_hh_t, wv3_hh); ObjectSetString(chart_id, wv3_txt, OBJPROP_TEXT, "WV3"); ObjectSetInteger(chart_id, wv3_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, wv4_txt, OBJ_TEXT, 0, wv4_time, wv4); ObjectSetString(chart_id, wv4_txt, OBJPROP_TEXT, "WV4"); ObjectSetInteger(chart_id, wv4_txt, OBJPROP_COLOR, clrBlue); tline_1_3_visible = StringFormat("TREND LINE WAVE 1 AND 3 V %d", i); ObjectCreate(chart_id,tline_1_3_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n],t_1_3_values_2); ObjectSetInteger(chart_id, tline_1_3_visible, OBJPROP_COLOR, clrBlue); tline_2_4_visible = StringFormat("TREND LINE WAVE 2 AND 4 V %d", i); ObjectCreate(chart_id,tline_2_4_visible,OBJ_TREND,0,wv2_ll_t,wv2_ll,time[n],t_2_4_values); ObjectSetInteger(chart_id, tline_2_4_visible, OBJPROP_COLOR, clrBlue); wv5_txt = StringFormat("WAVE 5 %d", i); ObjectCreate(chart_id, wv5_txt, OBJ_TEXT, 0, time[cross_bars_highest], high[cross_bars_highest]); ObjectSetString(chart_id, wv5_txt, OBJPROP_TEXT, "WV5"); ObjectSetInteger(chart_id, wv5_txt, OBJPROP_COLOR, clrBlue); ObjectCreate(chart_id, fib_ext_3_4,OBJ_EXPANSION, 0,wv4_time, wv4,wv3_hh_t,wv3_hh,wv4_time,wv4); for(int i = 0; i <= 2; i++) { ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_LEVELCOLOR,i,clrBlue); ObjectSetInteger(chart_id,fib_ext_3_4,OBJPROP_COLOR,clrBlue); } fib_ext_range_3_4 = StringFormat("Fibo EXPENSION RANGE WV3 WV4 %d", i); ObjectCreate(chart_id,fib_ext_range_3_4,OBJ_RECTANGLE,0,wv3_hh_t,fib_ext_3_4_127_2,time[cross_bars_highest],fib_ext_3_4_161_8); no_wv1_n_bars = Bars(_Symbol, timeframe, wv1_hh_t, time[n]); no_n_c_bars = Bars(_Symbol, timeframe, time[n], TimeCurrent()); if(no_n_c_bars <= no_wv1_n_bars) { t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, TimeCurrent(), 0); tline_1_4_visible = "TL WAVE 1 AND 4 Visible"; ObjectCreate(chart_id,tline_1_4_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,TimeCurrent(),t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_COLOR,clrBlue); } if(no_n_c_bars > no_wv1_n_bars) { ObjectDelete(chart_id,tline_1_4_visible); t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, time[n + no_wv1_n_bars], 0); tline_1_4_visible_2 = StringFormat("TL WAVE 1 AND 4 DISPLAY %d", i); ObjectCreate(chart_id,tline_1_4_visible_2,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n+no_wv1_n_bars],t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_COLOR,clrBlue); } break; }
Erläuterung:
Die Anzahl der Balken zwischen zwei wichtigen Stellen wird mit den Variablen no_wv1_n_bars und no_n_c_bars ermittelt. Die Anzahl der Balken zwischen dem Zeitstempel der Welle 1 und dem Zeitstempel, an dem der Markt eine Umkehr vollzog, als er wieder unter die Trendlinie fiel, wird speziell durch die Funktion no_wv1_n_bars bestimmt. Umgekehrt zählt no_n_c_bars die Anzahl der Balken, die den aktuellen Balken im Chart vom Umkehrpunkt trennen (Welle 5). Dieser Vergleich hilft bei der Entscheidung, ob die Trendlinie der Wellen 1 bis 4 einen festen zukünftigen Balken oder den aktuellen Markt erreichen sollte.
Eine Trendlinie mit der Beschriftung „TL WAVE 1 AND 4 Visible“ wird zwischen Welle 1 und dem aktuellen Marktzeitpunkt gebildet, wenn der aktuelle Balken noch innerhalb des Bereichs liegt, den Welle 1 und der Umkehrpunkt (no_n_c_bars <= no_wv1_n_bars) definieren. ObjectGetValueByTime wird verwendet, um den aktuellen Wert der Trendlinie abzurufen, und für die Sichtbarkeit wird die Linie blau und gestrichelt dargestellt.
Die zuvor gezeichnete Linie wird jedoch mit ObjectDelete entfernt, wenn die Anzahl der Balken nach dem Umkehrpunkt größer ist als der Bereich zwischen Welle 1 und der Umkehrung. Um sicherzustellen, dass sie die gleiche Strecke wie die ursprüngliche Projektion zurücklegt, wird in diesem Fall eine neue Trendlinie konstruiert, die sich von Welle 1 bis zu einem bestimmten Punkt in der Zukunft (time[n + no_wv1_n_bars]) erstreckt. Diese neue Linie hat ein dynamisches Etikett und ist in Blau und mit einer gestrichelten Linie gestaltet. Dieser Algorithmus passt sich zwar sichtbar an die Echtzeit-Aktualisierungen des Charts an, garantiert aber, dass die Trendlinie von Welle 1 bis Welle 4 konstant und beabsichtigt bleibt.
Ausführen des Handels
Zum jetzigen Zeitpunkt haben wir alle fünf Wellen des Wolfe-Wellenmusters, die Wellen 1 bis 5, sowie die drei wichtigsten Trendlinien, die Welle 1 mit Welle 3, Welle 2 mit Welle 4 und Welle 1 mit Welle 4 verbinden, erfolgreich erkannt. Diese Trendlinien bieten nicht nur eine visuelle Bestätigung des Musters, sondern dienen auch als Referenz für unsere Handelsausführungsentscheidungen.
Als Nächstes folgt die Durchführung des Handelsgeschäfts gemäß der vorgegebenen Struktur. Die Einstiegsbedingung für ein fallendes Wolfe-Wellen-Muster ist eng damit verbunden, wie sich der Kurs um die Trendlinie zwischen Welle 1 und Welle 3 bewegt. Insbesondere muss die Kerze zunächst über diese Trendlinie kreuzen, was darauf hindeutet, dass der Aufwärtstrend zu Ende geht, und dann wieder unter diese Linie kreuzen. Diese zweite Bewegung ist ein guter Zeitpunkt, um eine Verkaufsposition zu eröffnen, da sie bestätigt, dass der Markt beginnen könnte, nach unten zu drehen. Der EA sollte keine Transaktion einleiten, bevor diese zweistufige Bestätigung abgeschlossen ist.
Beispiel:
#include <Trade/Trade.mqh> CTrade trade; input int MagicNumber = 6160; input double lot_size = 0.01; input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT; // TIMEFRAME input double max_fib_ext_wv12 = 161.8; // WAVE 1 AND 2 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv12 = 127.2; // WAVE 1 AND 2 FIBO EXTENSION MIN LEVEL input double max_fib_ext_wv34 = 200.0; // WAVE 3 AND 4 FIBO EXTENSION MAX LEVEL input double min_fib_ext_wv34 = 120.0; // WAVE 3 AND 4 FIBO EXTENSION MIN LEVEL
datetime time_exe[]; datetime lastTradeBarTime = 0; double ask_price; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- trade.SetExpertMagicNumber(MagicNumber); ArraySetAsSeries(time_exe,true); //--- return(INIT_SUCCEEDED); }
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- total_symbol_bars = Bars(_Symbol, timeframe); time_bar = iTime(_Symbol,timeframe,0); CopyOpen(_Symbol, timeframe, time_bar, bars_check, open); CopyClose(_Symbol, timeframe, time_bar, bars_check, close); CopyLow(_Symbol, timeframe, time_bar, bars_check, low); CopyHigh(_Symbol, timeframe, time_bar, bars_check, high); CopyTime(_Symbol, timeframe, time_bar, bars_check, time); CopyTime(_Symbol, timeframe, 0, 2, time_exe); datetime currentBarTime = iTime(_Symbol, timeframe, 0); ask_price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
if(time[n] == time_exe[1] && currentBarTime != lastTradeBarTime) { trade.Sell(lot_size,_Symbol,ask_price, high[cross_bars_highest],wv2_ll); lastTradeBarTime = currentBarTime; }
Ausgabe:

Erläuterung:
Die eingebaute MQL5-Handelsbibliothek wird in der ersten Zeile #include importiert, wodurch die Klasse CTrade Zugang zu den Handelsmanagementfunktionen erhält. Nach Einbindung dieser Bibliothek wird eine Instanz von CTrade mit dem Namen trade erzeugt. Handelsbefehle wie Kauf, Verkauf, Festlegung von Take-Profit und Stop-Loss sowie die Aufrechterhaltung von Aufträgen werden von diesem Objekt ausgeführt. MagicNumber und lot_size sind die nächsten beiden definierten Eingabevariablen. Die Transaktionen dieses EAs werden durch ihre MagicNumber eindeutig identifiziert, was es einfach macht, sie von anderen Handelsgeschäften zu unterscheiden, die auf demselben Konto getätigt werden könnten. Die Losgröße, die in diesem Fall 0,01 Lots beträgt, gibt das Volumen oder die Größe des Handels an, der durchgeführt werden soll.
Dann werden einige Variablen deklariert: time_exe[], lastTradeBarTime und ask_price. Das Array time_exe speichert die Zeitdaten der letzten Balken. lastTradeBarTime ist mit Null initialisiert und wird verwendet, um zu verhindern, dass der EA mehrere Handelsgeschäfte auf demselben Balken ausführt. ask_price wird verwendet, um den aktuellen Briefkurs des Symbols zu speichern, d.h. den Preis, zu dem ein Verkauf ausgeführt werden kann. Die Zeile trade.SetExpertMagicNumber(MagicNumber); weist dem Handelsobjekt die Magic Number zu, sodass jeder von ihm platzierte Handel später identifiziert werden kann. ArraySetAsSeries(time_exe, true); stellt das Array time_exe so ein, dass es als Zeitreihe behandelt wird, d. h. Index 0 entspricht dem jüngsten Balken.
Anschließend wird CopyTime(_Symbol, timeframe, 0, 2, time_exe); verwendet, um die Zeitwerte der letzten beiden Balken in das Array time_exe zu kopieren. Dann erhält datetime currentBarTime = iTime(_Symbol, timeframe, 0); die Eröffnungszeit des sich gerade bildenden Balkens. Die Zeile ask_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); holt den aktuellen Briefkurs des Handelsinstruments, der für die Erteilung eines Verkaufsauftrags erforderlich ist.
Die Bedingung if (time[n] == time_exe[1] && currentBarTime != lastTradeBarTime) prüft nun, ob die in time[n] gespeicherte Zeit mit der Eröffnungszeit des zweitjüngsten Balkens (time_exe[1]) übereinstimmt, und stellt durch den Vergleich mit lastTradeBarTime sicher, dass auf dem aktuellen Balken nicht bereits ein Handel ausgeführt wurde. Wenn diese Bedingung erfüllt ist, platziert der EA einen Verkauf mit trade.Sell(). Der Handel wird zum aktuellen Briefkurs eröffnet, wobei der Stop-Loss zu hoch angesetzt wird (was wahrscheinlich das obere Ende von Welle 5 darstellt) und der Take-Profit auf wv2_ll gesetzt wird (das untere Ende von Welle 2, möglicherweise das Zielniveau). Schließlich wird die lastTradeBarTime auf die aktuelle Balkenzeit aktualisiert, um Mehrfacheingaben innerhalb derselben Kerze zu verhindern.
Bitte beachten Sie den letzten wichtigen Punkt auf unserer Liste: die Gewährleistung eines ordnungsgemäßen Ausstiegs aus dem Handel. Nachdem wir einen Handel auf der Grundlage des Wolfe-Wellenmusters ausgeführt haben, müssen wir eine Logik implementieren, um den Handel automatisch zu schließen, wenn der Markt die Trendlinie berührt, die Welle 1 und Welle 4 verbindet. Diese Linie dient uns als Ausstiegsziel, da theoretisch eine Kursumkehr in diesem Bereich zu erwarten ist. Darüber hinaus müssen wir auch einen Schutz vor zu langem Halten von Geschäften einbauen. Wenn der Kurs die Trendlinie nicht innerhalb einer angemessenen Anzahl von Balken (Kerzen) erreicht, sollte der EA den Handel trotzdem schließen. Dies hilft uns, unnötige Risiken und Risiken in Situationen zu vermeiden, in denen das Muster nicht funktioniert oder sich die Marktbedingungen ändern.
Beispiel:double low_m[]; double high_m[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- trade.SetExpertMagicNumber(MagicNumber); ArraySetAsSeries(time_exe,true); ArraySetAsSeries(low_m,true); ArraySetAsSeries(high_m,true); //--- return(INIT_SUCCEEDED); }
CopyLow(_Symbol, timeframe, 0, 3, low_m); CopyHigh(_Symbol, timeframe, 0, 3, high_m);
if(no_n_c_bars <= no_wv1_n_bars) { t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, TimeCurrent(), 0); tline_1_4_visible = "TL WAVE 1 AND 4 Visible"; ObjectCreate(chart_id,tline_1_4_visible,OBJ_TREND,0,wv1_hh_t,wv1_hh,TimeCurrent(),t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible,OBJPROP_COLOR,clrBlue); if(time[n] == time_exe[1] && currentBarTime != lastTradeBarTime) { trade.Sell(lot_size,_Symbol,ask_price, high[cross_bars_highest],wv2_ll); lastTradeBarTime = currentBarTime; } for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); datetime positionTime = 0; if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(chart_id)) { positionTime = (datetime)PositionGetInteger(POSITION_TIME); if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { double pos_bars = Bars(_Symbol, timeframe, positionTime, TimeCurrent()); if((ask_price < t_1_4_values || low_m[1] < t_1_4_values || no_n_c_bars == no_wv1_n_bars) && no_n_c_bars == pos_bars+1) { trade.PositionClose(ticket); } } } } } } if(no_n_c_bars > no_wv1_n_bars) { ObjectDelete(chart_id,tline_1_4_visible); t_1_4_values = ObjectGetValueByTime(chart_id, tline_1_4, time[n + no_wv1_n_bars], 0); tline_1_4_visible_2 = StringFormat("TL WAVE 1 AND 4 DISPLAY %d", i); ObjectCreate(chart_id,tline_1_4_visible_2,OBJ_TREND,0,wv1_hh_t,wv1_hh,time[n+no_wv1_n_bars],t_1_4_values); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_STYLE,STYLE_DASH); ObjectSetInteger(chart_id,tline_1_4_visible_2,OBJPROP_COLOR,clrBlue); }
Ausgabe:

Erläuterung:
Im ersten Abschnitt des Codes werden zwei Arrays deklariert: double low_m[]; und double high_m[];. Die letzten Höchst- und Tiefstkurse des Charts werden in diesen Arrays gespeichert. Ähnlich dem typischen Chart-Verhalten von MetaTrader 5 kehren die Zeilen ArraySetAsSeries(low_m, true); und ArraySetAsSeries(high_m, true); die Indexierung der Arrays um, sodass sich Index 0 immer auf den jüngsten Balken bezieht. Dies ist erforderlich, um die jüngsten oder gegenwärtigen Preisniveaus mit wichtigen Trendlinienwerten zu vergleichen.
Die letzten drei Tiefst- und Höchstkurse aus dem Chart werden dann mit den Methoden CopyLow(_Symbol, timeframe, 0, 3, low_m); und CopyHigh(_Symbol, timeframe, 0, 3, high_m); zu den Arrays low_m bzw. high_m hinzugefügt. An diesen Punkten wird der Kurs dann analysiert, um festzustellen, ob er eine bestimmte Trendlinie berührt oder unterschritten hat, z. B. die Trendlinie der Welle 1 bis 4.
Wenn es sich bei der Position um einen Verkauf handelt, wie es das Muster der Wolfe-Wellen in einem Abwärts-Setup verlangt, berechnet der Code mit Bars(_Symbol, timeframe, positionTime, TimeCurrent()), wie viele Balken seit der Eröffnung des Handels vergangen sind. Schließlich wird durch eine Bedingung geprüft, ob der Markt den Ausstiegspunkt erreicht hat. Konkret wird ausgewertet, ob:
- der aktuelle Briefkurs unter der Trendlinie der Wellen 1 bis 4 (t_1_4_values) liegt oder
- das Tief der vorherigen Kerze (low_m[1]) diese Trendlinie durchstoßen hat oder
- die Anzahl der Balken seit dem Einstieg der Anzahl der Balken entspricht, die nötig wären, um die Trendlinie der Welle 1 bis 4 zu erreichen (no_n_c_bars == no_wv1_n_bars) und
- die Position während genau so viele Balken offen war (no_n_c_bars == pos_bars + 1).
Der EA verwendet das, um die Position zu schließen, wenn alle diese Kriterien erfüllt sind, da das anzeigt, dass der Handel entweder seinen voraussichtlichen Ausstiegspunkt erreicht hat oder zu lange gehalten wurde. Ticket; PositionClose. Um sicherzustellen, dass der EA einen offenes Handelsgeschäft korrekt mit dem jüngsten Muster der Wolfe-Wellen verknüpft, wird die Bedingung no_n_c_bars == pos_bars + 1 verwendet. Der Bot sucht in der Logik dieses Expert Advisors nach mehreren Muster der Wolfe-Wellen über eine vorgegebene Anzahl von Balken. Es wird jedoch nur dann ein Handelsgeschäft abgeschlossen, wenn time[n] == time_exe[1] ist. Damit ist gewährleistet, dass der Handel im selben Moment stattfindet, in dem das letzte Muster verifiziert wurde.
Die Anzahl der Balken, die seit der Eröffnung des Geschäfts verstrichen sind, wird durch die Variable pos_bars dargestellt, die berechnet wird, um diese Ausrichtung zwischen Signal und Ausführung zu erhalten. Umgekehrt bestimmt no_n_c_bars die Anzahl der Balken, die zwischen dem aktuellen Zeitpunkt und dem Bestätigungspunkt der Wolfe-Welle (time[n]) verstrichen sind. Der EA wird darüber informiert, dass die Transaktion durch genau dieses Muster und nicht durch ein früheres Muster ausgelöst wurde, wenn diese beiden Werte übereinstimmen, da no_n_c_bars == pos_bars + 1.
Dies ist von entscheidender Bedeutung, denn auch wenn der EA mehrere Wolfe-Wellen auf dem Chart sehen kann, sollte er nur den Handel abwickeln und schließen, der der jüngsten Welle entspricht. Ist dies nicht der Fall, kann der Bot versehentlich den Handel mit früheren Signalen stoppen oder unterbrechen. Der EA garantiert eine genaue Transaktionsverarbeitung, verhindert Signalkonflikte und sorgt für ein konsistentes Verhalten bei der Ausführung und beim Risikomanagement, indem er diese Ausrichtung überprüft.
Identifizierung der Aufwärtsmuster der Wolfe-Wellen
Das Aufwärtsmuster der Wolfe-Wellen ist einfach das Gegenteil des Abwärtsmusters der Wolfe-Wellen, das wir zuvor besprochen haben. Da die Struktur und die Logik sehr ähnlich sind, werden wir nicht zu viel Wert darauf legen, jedes Detail noch einmal zu erläutern. Stattdessen werden wir nur die Teile hervorheben, die umgekehrt oder anders sind. In diesem Fall suchen wir nach einer Fünf-Wellen-Struktur, die eher auf eine potenzielle Kaufgelegenheit als auf eine Verkaufsgelegenheit hindeutet.
Welle 1, die die erste Basis in einer steigenden Wolfe-Welle bildet, muss ein Umkehr-Tief sein. Ohne Unterschreitung von Welle 1 dürfte Welle 3 nach Welle 2 ein weiteres Umkehr-Tief erzeugen, das ein Umkehr-Hoch sein muss. Das Aufwärts-Setup muss vervollständigt werden, indem Welle 5 ein endgültiges Umkehr-Tief bildet und Welle 4 ein Umkehr-Hoch, das in der Regel niedriger als Welle 2 ist.
Die Wellen 1 bis 3 müssen die niedrigsten oder höchsten Punkte zwischen ihren benachbarten Wellen sein, während Welle 5 zwischen den 127,2 % und 161,8 % Fibonacci-Ausdehnung der Wellen 3 und 4 liegen sollte. Die Empfindlichkeit der Mustererkennung kann vom Nutzer durch Variation dieser Bereiche verändert werden. Um die Einstiegssicherheit zu erhöhen, muss der Kurs zunächst unter die Trendlinie zwischen den Wellen 1 und 3 fallen und dann darüber steigen. Die Linie Wave 1-4 wird häufig als Take-Profit-Ziel verwendet. Wichtige Trendlinien, die die Wellen 1-3, 2-4 und 1-4 miteinander verbinden, werden automatisch eingezeichnet, um die Mustererkennung und die Planung des Ausstiegs zu unterstützen.

Schlussfolgerung
Dieser Artikel beschreibt, wie wir einen Expert Advisor in MQL5 erstellt haben, der sowohl Auf- als auch Abwärtsformation der Wolfe-Wellen erkennen kann. Wir haben besprochen, wie man Umkehr-Hochs und -Tiefs verwendet, um die Fünf-Wellen-Struktur zu identifizieren, Fibonacci-Expansionslevels anwendet, wichtige Trendlinien erstellt und nur dann in den Handel einsteigt, wenn alle Voraussetzungen erfüllt sind. Obwohl 127,2 % bis 161,8 % die typische Fibonacci-Spanne ist, kann der Einzelne diese Zahlen an seine eigenen Pläne anpassen. Dieses Projekt bietet eine solide Grundlage für die Entwicklung anspruchsvollerer, musterbasierter Handelssysteme sowie für die Automatisierung eines komplizierten Chartmusters.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/18884
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.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 78): Gator- und AD-Oszillator-Strategien für Marktresilienz
Aufbau eines Handelssystems (Teil 1): Ein quantitativer Ansatz
MQL5-Handelswerkzeuge (Teil 8): Verbessertes informatives Dashboard mit verschiebbaren und minimierbaren Funktionen
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 77): Verwendung des Gator-Oszillators und des Akkumulations-/Distributions-Oszillators
- 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.