English 日本語
preview
Automatisieren von Handelsstrategien in MQL5 (Teil 32): Erstellung eines Price Action 5 Drives des harmonischen Mustersystems

Automatisieren von Handelsstrategien in MQL5 (Teil 32): Erstellung eines Price Action 5 Drives des harmonischen Mustersystems

MetaTrader 5Handel |
47 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Einführung

In unserem letzten Artikel (Teil 31) haben wir ein Muster-System aus 3 Drives in MetaQuotes Language 5 (MQL5) entwickelt, das die harmonische Muster aus steigenden und fallenden 3 Drives unter Verwendung von Fibonacci-Verhältnisse erkennt und Handelsgeschäfte mit anpassbaren Stop-Loss- und Take-Profit-Levels automatisiert, die durch Chartobjekte wie Dreiecke und Trendlinien visualisiert werden. In Teil 32 erstellen wir das Mustersystem mit 5 Drives, das die harmonischen Muster von steigenden und fallenden 5 Drives durch Umkehrpunkte und spezifische Fibonacci-Retracements und -Extensions identifiziert und Handelsgeschäfte mit flexiblen Einstiegs-, Stop-Loss- und Multi-Level-Take-Profit-Optionen ausführt, die durch visuelle Dreiecke, Trendlinien und Labels für eine klare Musterdarstellung ergänzt werden. Wir werden die folgenden Themen behandeln:

  1. Verstehen des harmonischen Musters 5 Drives
  2. Implementation in MQL5
  3. Backtests
  4. Schlussfolgerung

Am Ende haben Sie eine robuste MQL5-Strategie für den Handel mit harmonischen 5-Drives-Mustern, die Sie nur noch anpassen müssen – legen wir los!


Verstehen des harmonischen Musters 5 Drives

Das 5 Drives (5-0) Muster ist eine harmonische Handelsformation, die durch sechs wichtige Umkehrpunkte – A, B, C, D, E und F – definiert ist, die in aufsteigender und fallender Form existieren und dazu dienen, Umkehrzonen durch eine Sequenz von Drives (Kursbewegungen) und Retracements (Rücksetzer) mit spezifischen Fibonacci Retracement-Verhältnissen zu identifizieren. In einem steigenden 5-Drives-Muster bildet die Struktur eine Hoch-Tief-Hoch-Tief-Hoch-Tief-Sequenz, in der A ein hoher Umkehrpunkt, B ein tiefer, C ein hoher, D ein tiefer, E ein hoher und F ein tiefer Umkehrpunkt (über B) ist, wobei die Kanten AB und CD sich von 1.13 auf 1,618 der vorherigen Kanten, BC und DE verlängern 1,618 auf 2,24, und CD entspricht AB mit einem 0,5-Retracement; ein Abwärtsmuster kehrt diese Sequenz mit F unter B um:

Fallendes harmonisches 5 Drives Muster:

FALLENDES 5 DRIVES MUSTER

Steigendes harmonisches 5 Drives Muster:

STEIGENDES 5 DRIVES MUSTER

Unser Ansatz umfasst die Erkennung dieser Umkehrpunkte innerhalb eines bestimmten Balkenbereichs, die Validierung der Kanten des Musters anhand von Fibonacci-Kriterien, die Visualisierung der A-B-C-D-E-F-Struktur mit Chart-Objekten wie Dreiecken und Trendlinien und die Ausführung von Handelsgeschäften am F-Punkt mit anpassbaren Stop-Loss- (Fibonacci-basiert oder fest) und Take-Profit-Levels (ein Drittel, zwei Drittel oder E-Pivot), um von erwarteten Umkehrungen zu profitieren. Kommen wir nun zur Umsetzung!


Implementation in MQL5

Um das Programm in MQL5 zu erstellen, öffnen wir den MetaEditor, gehen zum Navigator, suchen den Ordner der Indikatoren, klicken auf die Registerkarte „Neu“ und folgen den Anweisungen, um die Datei zu erstellen. Sobald das erledigt ist, müssen wir in der Programmierumgebung einige globale Variablen deklarieren, die wir im gesamten Programm verwenden werden.

//+------------------------------------------------------------------+
//|                                          5 Drives Pattern EA.mq5 |
//|                        Copyright 2025, Forex Algo-Trader, Allan. |
//|                                 "https://t.me/Forex_Algo_Trader" |
//+------------------------------------------------------------------+
#property copyright "Forex Algo-Trader, Allan"
#property link "https://t.me/Forex_Algo_Trader"
#property version "1.00"
#property description "This EA trades based on 5 Drives Strategy"
#property strict

//--- Include the trading library for order functions
#include <Trade\Trade.mqh>   //--- Include Trade library
CTrade obj_Trade;            //--- Instantiate a obj_Trade object
//--- Enumeration for TP levels
enum ENUM_TAKE_PROFIT_LEVEL {
   TP1 = 1, // One-third of the move to E
   TP2 = 2, // Two-thirds of the move to E
   TP3 = 3  // Pivot E Price
};
//--- Enumeration for SL types
enum ENUM_STOP_LOSS_TYPE {
   SL_FIBO = 1, // Fibonacci Extension
   SL_FIXED = 2 // Fixed Points
};
//--- Input parameters for user configuration
input int PivotLeft = 5;                             // Number of bars to the left for pivot check
input int PivotRight = 5;                            // Number of bars to the right for pivot check
input double Tolerance = 0.10;                       // Allowed deviation (10% of move)
input double LotSize = 0.01;                         // Lot size for new orders
input bool AllowTrading = true;                      // Enable or disable trading
input ENUM_TAKE_PROFIT_LEVEL TakeProfitLevel = TP2;  // Take Profit Level
input ENUM_STOP_LOSS_TYPE StopLossType = SL_FIBO;    // Stop Loss Type
input double SL_FiboExtension = 1.618;               // Fibonacci Extension for SL
input double SL_FixedPoints = 50;                    // Fixed Points for SL (in points)

//---------------------------------------------------------------------------
//--- Structure for a pivot point
struct Pivot {
   datetime time; //--- Bar time of the pivot
   double price;  //--- Pivot price (High for swing high, low for swing low)
   bool isHigh;   //--- True if swing high; false if swing low
};
//--- Global dynamic array for storing pivots in chronological order
Pivot pivots[]; //--- Declare a dynamic array to hold identified pivot points
//--- Global variables to lock in a pattern (avoid trading on repaint)
int g_patternFormationBar = -1; //--- Bar index where the pattern was formed (-1 means none)
datetime g_lockedPatternA = 0; //--- The key A pivot time for the locked pattern
//--- Global array to track traded patterns (using A.time as identifier)
datetime tradedPatterns[];

Um die Grundlage für das Muster5 Drives zu schaffen, binden wir zunächst die Bibliothek „<Trade\Trade.mqh>“ ein und instanziieren „obj_Trade“ als CTrade-Objekt, um Handelsoperationen wie die Ausführung von Kauf- und Verkaufsaufträgen zu verwalten. Dann definieren wir die Enumerationen „ENUM_TAKE_PROFIT_LEVEL“ (TP1 für ein Drittel, TP2 für zwei Drittel, TP3 für den Pivot-E-Preis) und „ENUM_STOP_LOSS_TYPE“ (SL_FIBO für die Fibonacci-Extension, SL_FIXED für Fixpunkte) für flexible Handelseinstellungen und setzen Eingabeparameter: „PivotLeft“ und „PivotRight“ bei 5 Balken für die Pivot-Erkennung, „Tolerance“ bei 0.10 für die Fibonacci-Abweichung, „LotSize“ bei 0.01, „AllowTrading“ auf true, „TakeProfitLevel“ auf TP2, „StopLossType“ auf SL_FIBO, „SL_FiboExtension“ auf 1.618, und „SL_FixedPoints“ auf 50. Sie sollten dies je nach dem Währungspaar, mit dem Sie handeln, optimieren.

Als Nächstes definieren wir die Struktur „Pivot“ mit „time“, „price“ und „isHigh“, um Umkehrpunkte zu speichern, deklarieren „pivots“ als dynamisches Array und initialisieren die globalen Variablen „g_patternFormationBar“ auf -1, um die Musterbildung zu verfolgen, „g_lockedPatternA“ auf 0, um die Pivot-Zeit von A zu sperren, und „tradedPatterns“ als Array, um gehandelte Muster unter Verwendung der Zeit von A zu verfolgen. Dieser Aufbau bildet das Grundgerüst für die Erkennung und den Handel mit 5 Drives-Mustern. Zur Visualisierung können wir Funktionen zum Zeichnen von Linien, Beschriftungen und Dreiecken verwenden.

//+------------------------------------------------------------------+
//| Helper: Draw a filled triangle                                   |
//+------------------------------------------------------------------+
void DrawTriangle(string name, datetime t1, double p1, datetime t2, double p2, datetime t3, double p3, color cl, int width, bool fill, bool back) {
   //--- Attempt to create a triangle object with three coordinate points
   if(ObjectCreate(0, name, OBJ_TRIANGLE, 0, t1, p1, t2, p2, t3, p3)) {
      //--- Set the triangle's color
      ObjectSetInteger(0, name, OBJPROP_COLOR, cl);
      //--- Set the triangle's line style to solid
      ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
      //--- Set the line width of the triangle
      ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
      //--- Determine if the triangle should be filled
      ObjectSetInteger(0, name, OBJPROP_FILL, fill);
      //--- Set whether the object is drawn in the background
      ObjectSetInteger(0, name, OBJPROP_BACK, back);
   }
}
//+------------------------------------------------------------------+
//| Helper: Draw a trend line                                        |
//+------------------------------------------------------------------+
void DrawTrendLine(string name, datetime t1, double p1, datetime t2, double p2, color cl, int width, int style) {
   //--- Create a trend line object connecting two points
   if(ObjectCreate(0, name, OBJ_TREND, 0, t1, p1, t2, p2)) {
      //--- Set the trend line's color
      ObjectSetInteger(0, name, OBJPROP_COLOR, cl);
      //--- Set the trend line's style (solid, dotted, etc.)
      ObjectSetInteger(0, name, OBJPROP_STYLE, style);
      //--- Set the width of the trend line
      ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
   }
}
//+------------------------------------------------------------------+
//| Helper: Draw a dotted trend line                                 |
//+------------------------------------------------------------------+
void DrawDottedLine(string name, datetime t1, double p, datetime t2, color lineColor) {
   //--- Create a horizontal trend line at a fixed price level with dotted style
   if(ObjectCreate(0, name, OBJ_TREND, 0, t1, p, t2, p)) {
      //--- Set the dotted line's color
      ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
      //--- Set the line style to dotted
      ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT);
      //--- Set the line width to 1
      ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
   }
}
//+------------------------------------------------------------------+
//| Helper: Draw anchored text label (for pivots)                    |
//| If isHigh is true, anchor at the bottom (label appears above);   |
//| if false, anchor at the top (label appears below).               |
//+------------------------------------------------------------------+
void DrawTextEx(string name, string text, datetime t, double p, color cl, int fontsize, bool isHigh) {
   //--- Create a text label object at the specified time and price
   if(ObjectCreate(0, name, OBJ_TEXT, 0, t, p)) {
      //--- Set the text of the label
      ObjectSetString(0, name, OBJPROP_TEXT, text);
      //--- Set the color of the text
      ObjectSetInteger(0, name, OBJPROP_COLOR, cl);
      //--- Set the font size for the text
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontsize);
      //--- Set the font type and style
      ObjectSetString(0, name, OBJPROP_FONT, "Arial Bold");
      //--- Anchor the text depending on whether it's a swing high or low
      if(isHigh)
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
      else
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
      //--- Center-align the text
      ObjectSetInteger(0, name, OBJPROP_ALIGN, ALIGN_CENTER);
   }
}

Wir fahren fort mit der Implementierung von Visualisierungsfunktionen, um klare Chartdarstellungen des harmonischen Musters der 5 Drives und seiner Handelsstufen zu erstellen. Zunächst entwickeln wir die Funktion „DrawTriangle“, die ObjectCreate verwendet, um ein gefülltes Dreieck (OBJ_TRIANGLE) zu zeichnen, das durch drei Punkte mit Zeiten („t1“, „t2“, „t3“) und Preisen („p1“, „p2“, „p3“), wobei OBJPROP_COLOR auf die angegebene Farbe, „OBJPROP_STYLE“ auf „STYLE_SOLID“, „OBJPROP_WIDTH“ auf die angegebene Breite, „OBJPROP_FILL“ zum Aktivieren oder Deaktivieren des Füllens und „OBJPROP_BACK“ zum Festlegen der Hintergrund- oder Vordergrundplatzierung mit der Funktion ObjectSetInteger gesetzt werden.

Anschließend erstellen wir die Funktion „DrawTrendLine“, die eine Trendlinie (OBJ_TREND) zwischen zwei Punkten zeichnet. Als Nächstes implementieren wir die Funktion „DrawDottedLine“, die eine horizontale gepunktete Linie („OBJ_TREND“) zu einem bestimmten Kurs erzeugt. Zuletzt entwickeln wir die Funktion „DrawTextEx“, die ein Textlabel (OBJ_TEXT) an den Koordinaten („t“, „p“) mit „ObjectCreate“ erstellt, wobei „OBJPROP_TEXT“ auf den angegebenen Text, „OBJPROP_COLOR“, „OBJPROP_FONTSIZE““OBJPROP_COLOR“, „OBJPROP_FONTSIZE“ und „OBJPROP_FONT“ mit „ObjectSetString“ und „ObjectSetInteger“ auf „Arial Bold“ setzen, mit „OBJPROP_ANCHOR“ für Hochs und Tiefs auf der Grundlage von „isHigh“ oberhalb bzw. unterhalb verankern und mit „OBJPROP_ALIGN“ zentrieren. Wir können nun mit OnTick fortfahren und versuchen, Umkehrpunkte zu identifizieren, die wir später für die Mustererkennung verwenden können. Hier ist die Logik, mit der wir das erreichen.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
   //--- Declare a static variable to store the time of the last processed bar
   static datetime lastBarTime = 0;
   //--- Get the time of the current confirmed bar
   datetime currentBarTime = iTime(_Symbol, _Period, 1);
   //--- If the current bar time is the same as the last processed, exit
   if(currentBarTime == lastBarTime)
      return;
   //--- Update the last processed bar time
   lastBarTime = currentBarTime;
  
   //--- Clear the pivot array for fresh analysis
   ArrayResize(pivots, 0);
   //--- Get the total number of bars available on the chart
   int barsCount = Bars(_Symbol, _Period);
   //--- Define the starting index for pivot detection (ensuring enough left bars)
   int start = PivotLeft;
   //--- Define the ending index for pivot detection (ensuring enough right bars)
   int end = barsCount - PivotRight;
  
   //--- Loop through bars from 'end-1' down to 'start' to find pivot points
   for(int i = end - 1; i >= start; i--) {
      //--- Assume current bar is both a potential swing high and swing low
      bool isPivotHigh = true;
      bool isPivotLow = true;
      //--- Get the high and low of the current bar
      double currentHigh = iHigh(_Symbol, _Period, i);
      double currentLow = iLow(_Symbol, _Period, i);
      //--- Loop through the window of bars around the current bar
      for(int j = i - PivotLeft; j <= i + PivotRight; j++) {
         //--- Skip if the index is out of bounds
         if(j < 0 || j >= barsCount)
            continue;
         //--- Skip comparing the bar with itself
         if(j == i)
            continue;
         //--- If any bar in the window has a higher high, it's not a swing high
         if(iHigh(_Symbol, _Period, j) > currentHigh)
            isPivotHigh = false;
         //--- If any bar in the window has a lower low, it's not a swing low
         if(iLow(_Symbol, _Period, j) < currentLow)
            isPivotLow = false;
      }
      //--- If the current bar qualifies as either a swing high or swing low
      if(isPivotHigh || isPivotLow) {
         //--- Create a new pivot structure
         Pivot p;
         //--- Set the pivot's time
         p.time = iTime(_Symbol, _Period, i);
         //--- Set the pivot's price depending on whether it is a high or low
         p.price = isPivotHigh ? currentHigh : currentLow;
         //--- Set the pivot type (true for swing high, false for swing low)
         p.isHigh = isPivotHigh;
         //--- Get the current size of the pivots array
         int size = ArraySize(pivots);
         //--- Increase the size of the pivots array by one
         ArrayResize(pivots, size + 1);
         //--- Add the new pivot to the array
         pivots[size] = p;
      }
   }
}

Hier implementieren wir die anfängliche Logik der Funktion OnTick, um Umkehrpunkte zu erkennen, die für die Identifizierung des Musters wesentlich sind. Zunächst deklarieren wir ein statische Variable „lastBarTime“, die auf 0 initialisiert wird, um den letzten verarbeiteten Balken zu verfolgen und ihn mit der „currentBarTime“ zu vergleichen, die von iTime bei Shift 1 für das aktuelle Symbol und die aktuelle Periode erhalten wird, wobei wir den Vorgang beenden, wenn er unverändert bleibt, um redundante Verarbeitung zu vermeiden, und die „lastBarTime“ aktualisieren, wenn ein neuer Balken entdeckt wird. Dann leeren wir das Array „pivots“ mit ArrayResize, um eine neue Analyse zu gewährleisten. Als Nächstes rufen wir die Gesamtzahl der Balken mit Bars ab, legen den Pivot-Erkennungsbereich mit „Start“ als „PivotLeft“ und „Ende“ als Gesamtbalken minus „PivotRight“ fest und iterieren durch die ausgewählten Balken.

Für jeden Balken nehmen wir an, dass es sich um einen hohen („isPivotHigh“ = true) und einen tiefen Umkehrpunkt („isPivotLow“ = true) handelt, wir ermitteln sein Hoch und Tief mit iHigh und iLow und validieren den Umkehrpunkt, indem wir die umliegenden Balken innerhalb von „PivotLeft“ und „PivotRight“ mit „iHigh“ und „iLow“ überprüfen und den Umkehrpunkt ungültig machen, wenn ein benachbarter Balken ein höheres Hoch oder ein niedrigeres Tief aufweist. Wenn sich der Balken als Umkehrpunkt qualifiziert, erstellen wir die Struktur „Pivot“, setzen „time“ mit „iTime“, den „price“ auf das Hoch oder Tief auf der Grundlage von „isPivotHigh“ und dem „isHigh“-Flag und fügen ihn dann mit ArrayResize an das Array „pivots“ an und speichern ihn. Wenn wir die Pivot-Struktur ausdrucken, erhalten wir das folgende Array von Daten.

PIVOTS DATENBEISPIEL

Aus den Daten können wir die Umkehrpunkte extrahieren, und wenn wir genügend Umkehrpunkte haben, können wir die Muster analysieren und erkennen. Hier ist die Logik, mit der wir das erreichen.

//--- Determine the total number of pivots found
int pivotCount = ArraySize(pivots);
//--- If fewer than six pivots are found, the pattern cannot be formed
if(pivotCount < 6) {
   //--- Reset pattern lock variables
   g_patternFormationBar = -1;
   g_lockedPatternA = 0;
   //--- Exit the OnTick function
   return;
}

//--- Extract the last six pivots as A, B, C, D, E, F
Pivot A = pivots[pivotCount - 6];
Pivot B = pivots[pivotCount - 5];
Pivot C = pivots[pivotCount - 4];
Pivot D = pivots[pivotCount - 3];
Pivot E = pivots[pivotCount - 2];
Pivot F = pivots[pivotCount - 1];

//--- Initialize a flag to indicate if a valid 5 Drives pattern is found
bool patternFound = false;
//--- Initialize pattern type
string patternType = "";
//--- Check for the high-low-high-low-high-low (Bullish reversal) structure
if(A.isHigh && (!B.isHigh) && C.isHigh && (!D.isHigh) && E.isHigh && (!F.isHigh)) {
   //--- Calculate XA length
   double XA_length = C.price - B.price;
   //--- Calculate AB length
   double AB_length = C.price - D.price;
   //--- Check AB extension of XA
   if(AB_length >= 1.13 * XA_length && AB_length <= 1.618 * XA_length) {
      //--- Calculate BC length
      double BC_length = E.price - D.price;
      //--- Check BC extension of AB
      if(BC_length >= 1.618 * AB_length && BC_length <= 2.24 * AB_length) {
         //--- Calculate CD length
         double CD_length = E.price - F.price;
         //--- Check 50% retracement of BC
         double ideal_retrace = 0.5 * BC_length;
         if(MathAbs(CD_length - ideal_retrace) <= Tolerance * BC_length) {
            //--- Check reciprocal AB=CD
            if(MathAbs(CD_length - AB_length) <= Tolerance * AB_length) {
               //--- Additional conditions: higher high at E, D above B
               if(E.price > C.price && F.price > B.price) {
                  patternFound = true;
                  patternType = "Bullish";
               }
            }
         }
      }
   }
}
//--- Check for the low-high-low-high-low-high (Bearish reversal) structure
if((!A.isHigh) && B.isHigh && (!C.isHigh) && D.isHigh && (!E.isHigh) && F.isHigh) {
   //--- Calculate XA length
   double XA_length = B.price - C.price;
   //--- Calculate AB length
   double AB_length = D.price - C.price;
   //--- Check AB extension of XA
   if(AB_length >= 1.13 * XA_length && AB_length <= 1.618 * XA_length) {
      //--- Calculate BC length
      double BC_length = D.price - E.price;
      //--- Check BC extension of AB
      if(BC_length >= 1.618 * AB_length && BC_length <= 2.24 * AB_length) {
         //--- Calculate CD length
         double CD_length = F.price - E.price;
         //--- Check 50% retracement of BC
         double ideal_retrace = 0.5 * BC_length;
         if(MathAbs(CD_length - ideal_retrace) <= Tolerance * BC_length) {
            //--- Check reciprocal AB=CD
            if(MathAbs(CD_length - AB_length) <= Tolerance * AB_length) {
               //--- Additional conditions: lower low at E, D below B
               if(E.price < C.price && F.price < B.price) {
                  patternFound = true;
                  patternType = "Bearish";
               }
            }
         }
      }
   }
}

Zunächst wird die Gesamtzahl der Umkehrpunkte mit „ArraySize(pivots)“ ermittelt, die in „pivotCount“ gespeichert ist. Werden weniger als 6 Umkehrpunkte gefunden, werden „g_patternFormationBar“ und „g_lockedPatternA“ auf -1 und 0 zurückgesetzt, da für das 5-Drives-Muster die Punkte A, B, C, D, E und F erforderlich sind.

Dann extrahieren wir die letzten sechs Umkehrpunkte aus dem Array „pivots“ und ordnen sie „A“ (früheste), „B“, „C“, „D“, „E“ und „F“ (späteste) zu. Als Nächstes berechnen wir für ein Aufwärtsmuster (A hoch, B tief, C hoch, D tief, E hoch, F tief) die Länge XA („C.Preis – B.Preis“), die Länge AB („C.Preis – D.Preis“), um sicherzustellen, dass sie sich über 1,13 bis 1,618 von XA erstreckt, die Länge BC („E.Preis – D.Preis“), um sich über 1.618 bis 2,24 von AB, und CD Länge („E.price – F.price“), um 0,5 von BC zurückzugehen und AB innerhalb der „Toleranz“ zu entsprechen, wobei bestätigt wird, dass E ein höheres Hoch als C ist und F über B liegt, wobei „patternFound“ auf true und „patternType“ auf „Bullish“ gesetzt wird. Zuletzt wenden wir für ein Abwärtsmuster (A tief, B hoch, C tief, D hoch, E tief, F hoch) ähnliche Validierungen für XA („B.price – C.price“), AB („D.price – C.price“), BC („D.Preis – E.Preis“) und CD („F.Preis – E.Preis“) an, wobei wir sicherstellen, dass E ein niedrigeres Tief als C und F unter B liegt, und setzen „patternFound“ auf true und „patternType“ auf „Bearish“. Wenn das Muster gefunden wurde, können wir es im Chart visualisieren.

//--- If a valid 5 Drives pattern is detected
if(patternFound) {
   //--- Print a message indicating the pattern type and detection time
   Print(patternType, " 5 Drives pattern detected at ", TimeToString(F.time, TIME_DATE|TIME_MINUTES|TIME_SECONDS));
  
   //--- Create a unique prefix for all graphical objects related to this pattern
   string signalPrefix = "5D_" + IntegerToString(A.time);
  
   //--- Choose triangle color based on the pattern type
   color triangleColor = (patternType=="Bullish") ? clrBlue : clrRed;
  
   //--- Draw the first triangle connecting pivots B, C, D
   DrawTriangle(signalPrefix+"_Triangle1", B.time, B.price, C.time, C.price, D.time, D.price,
                triangleColor, 2, true, true);
   //--- Draw the second triangle connecting pivots D, E, F
   DrawTriangle(signalPrefix+"_Triangle2", D.time, D.price, E.time, E.price, F.time, F.price,
                triangleColor, 2, true, true);
}

Hier wird die Visualisierung der erkannten Muster im Chart eingeleitet. Wenn ein gültiges Muster erkannt wird („patternFound“ ist true), protokollieren wir zunächst die Erkennung mit Print und geben den „patternType“ („Bullish“ oder „Bearish“) und die mit TimeToString formatierte Zeit des F-Umkehrpunkts aus, einschließlich Datum, Minuten und Sekunden. Anschließend erstellen wir einen eindeutigen Bezeichner „signalPrefix“ durch Verkettung von „5D_“ mit „A.time“, der mit IntegerToString in eine Zeichenkette umgewandelt wird, um eine eindeutige Benennung der Chart-Objekte zu gewährleisten.

Als Nächstes setzen wir „triangleColor“ auf blau für Aufwärtsmuster oder rot für Abwärtsmuster, um sie visuell zu unterscheiden. Zuletzt rufen wir „DrawTriangle“ zweimal auf, um das Muster zu visualisieren: zuerst, um das BCD-Dreieck zu zeichnen, das die Umkehrpunkte B, C und D verbindet, und dann, um das DEF-Dreieck zu zeichnen, das die Umkehrpunkte D, E und F verbindet, wobei „signalPrefix“ mit den Suffixen „_Triangle1“ und „_Triangle2“, den jeweiligen Zeiten der Umkehrpunkte und -preisen, „triangleColor“, einer Breite von 2 und der Aktivierung der Füll- und Hintergrundanzeige mit true-Flags verwendet wird. Wir kommen zu folgendem Ergebnis.

DREIECK-SET

Anhand des Bildes können wir sehen, dass wir das erkannte Muster korrekt abbilden und visualisieren können. Jetzt müssen wir die Trendlinien weiter kartieren, um sie innerhalb der Grenzen vollständig sichtbar zu machen und eine Beschriftung hinzuzufügen, damit die Ebenen leichter zu identifizieren sind.

//--- Draw boundary trend lines connecting the pivots for clarity
DrawTrendLine(signalPrefix+"_TL_AB", A.time, A.price, B.time, B.price, clrBlack, 2, STYLE_SOLID);
DrawTrendLine(signalPrefix+"_TL_BC", B.time, B.price, C.time, C.price, clrBlack, 2, STYLE_SOLID);
DrawTrendLine(signalPrefix+"_TL_CD", C.time, C.price, D.time, D.price, clrBlack, 2, STYLE_SOLID);
DrawTrendLine(signalPrefix+"_TL_DE", D.time, D.price, E.time, E.price, clrBlack, 2, STYLE_SOLID);
DrawTrendLine(signalPrefix+"_TL_EF", E.time, E.price, F.time, F.price, clrBlack, 2, STYLE_SOLID);

//--- Retrieve the symbol's point size to calculate offsets for text positioning
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
//--- Calculate an offset (15 points) for positioning text above or below pivots
double offset = 15 * point;

//--- Determine the Y coordinate for each pivot label based on its type
double textY_A = (A.isHigh ? A.price + offset : A.price - offset);
double textY_B = (B.isHigh ? B.price + offset : B.price - offset);
double textY_C = (C.isHigh ? C.price + offset : C.price - offset);
double textY_D = (D.isHigh ? D.price + offset : D.price - offset);
double textY_E = (E.isHigh ? E.price + offset : E.price - offset);
double textY_F = (F.isHigh ? F.price + offset : F.price - offset);

//--- Draw text labels for each pivot with appropriate anchoring
DrawTextEx(signalPrefix+"_Text_A", "A", A.time, textY_A, clrBlack, 11, A.isHigh);
DrawTextEx(signalPrefix+"_Text_B", "B", B.time, textY_B, clrBlack, 11, B.isHigh);
DrawTextEx(signalPrefix+"_Text_C", "C", C.time, textY_C, clrBlack, 11, C.isHigh);
DrawTextEx(signalPrefix+"_Text_D", "D", D.time, textY_D, clrBlack, 11, D.isHigh);
DrawTextEx(signalPrefix+"_Text_E", "E", E.time, textY_E, clrBlack, 11, E.isHigh);
DrawTextEx(signalPrefix+"_Text_F", "F", F.time, textY_F, clrBlack, 11, F.isHigh);

//--- Calculate the central label's time as the midpoint between pivots A and D
datetime centralTime = (A.time + D.time) / 2;
//--- Set the central label's price at pivot F's price
double centralPrice = F.price;
//--- Create the central text label indicating the pattern type
if(ObjectCreate(0, signalPrefix+"_Text_Center", OBJ_TEXT, 0, centralTime, centralPrice)) {
   ObjectSetString(0, signalPrefix+"_Text_Center", OBJPROP_TEXT,
      (patternType=="Bullish") ? "Bullish 5 Drives" : "Bearish 5 Drives");
   ObjectSetInteger(0, signalPrefix+"_Text_Center", OBJPROP_COLOR, clrBlack);
   ObjectSetInteger(0, signalPrefix+"_Text_Center", OBJPROP_FONTSIZE, 11);
   ObjectSetString(0, signalPrefix+"_Text_Center", OBJPROP_FONT, "Arial Bold");
   ObjectSetInteger(0, signalPrefix+"_Text_Center", OBJPROP_ALIGN, ALIGN_CENTER);
}

Wir verbessern die Visualisierung der erkannten Muster weiter, indem wir detaillierte Chart-Objekte hinzufügen, um die Struktur der Muster klar darzustellen. Zunächst zeichnen wir mit „DrawTrendLine“ fünf durchgezogene Trendlinien mit dem eindeutigen „signalPrefix“, um wichtige Umkehrpunkte zu verbinden: AB, BC, CD, DE und EF, unter Verwendung von Pivot-Zeiten und -Preisen (z. B., „A.time“, „A.price“), wobei OBJPROP_COLOR auf „clrBlack“, „OBJPROP_WIDTH“ auf 2 und „OBJPROP_STYLE“ auf „STYLE_SOLID“ mit ObjectSetInteger gesetzt wird, um die Kanten des Musters zu umreißen. Dann wird die Punktgröße des Symbols mit „SymbolInfoDouble(_Symbol, SYMBOL_POINT)“ abgerufen und ein 15-Punkte-Offset für die Positionierung des Etiketts berechnet, wobei die Y-Koordinaten („textY_A“, „textY_B“, „textY_C“, „textY_D“, „textY_E“, „textY_F“) durch Addieren oder Subtrahieren des Offsets, je nachdem, ob es sich bei dem jeweiligen Pivot um einen hohen („isHigh“ true) oder tiefen Umkehrpunkt handelt, um die Beschriftungen über den Hochs oder unter den Tiefs zu platzieren.

Als Nächstes erstellen wir mit „DrawTextEx“ Textbeschriftungen für die Umkehrpunkte A, B, C, D, E und F mit „signalPrefix“ und Suffixen wie „_Text_A“, die den jeweiligen Buchstaben anzeigen, an der Pivot-Zeit und der eingestellten Y-Koordinate positioniert sind und „clrBlack“, Schriftgröße 11 und den „isHigh“-Status des Umkehrpunkts zur Verankerung verwenden. Zuletzt berechnen wir die Position der zentralen Kennzeichnung mit „centralTime“ als Mittelwert von „A.time“ und „D.time“ und „centralPrice“ bei „F.price“, erstellen ein Textobjekt mit „ObjectCreate“ mit dem Namen „signalPrefix + '_Text_Center'“, setzen OBJPROP_TEXT auf „Bullish 5 Drives“ oder „Bearish 5 Drives“ basierend auf „patternType“ und konfigurieren „OBJPROP_COLOR“ auf „clrBlack“, „OBJPROP_FONTSIZE“ auf 11, OBJPROP_FONT auf „Arial Bold“ und „OBJPROP_ALIGN“ auf „ALIGN_CENTER“ mit den Funktionen ObjectSetString und „ObjectSetInteger“. Wenn wir das Programm ausführen, sehen Sie hier eine Visualisierung der Ausgabe, die wir erhalten.

MUSTER MIT ETIKETTEN UND RÄNDERN

Auf dem Bild können wir sehen, dass wir die Kanten und die Kennzeichnung zum Muster hinzugefügt haben, um es aufschlussreicher und anschaulicher zu machen. Als Nächstes müssen wir die Handelsniveaus für dieses Muster bestimmen.

//--- Define start and end times for drawing horizontal dotted lines for trade levels
datetime lineStart = F.time;
datetime lineEnd = F.time + PeriodSeconds(_Period)*2;

//--- Declare variables for entry price and take profit levels
double entryPriceLevel, TP1Level, TP2Level, TP3Level, tradeDiff;
//--- Calculate trade levels based on whether the pattern is Bullish or Bearish
if(patternType=="Bullish") { //--- Bullish → BUY signal
   //--- Use the current ASK price as the entry
   entryPriceLevel = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   //--- Set TP3 at pivot E's price
   TP3Level = E.price;
   //--- Calculate the total distance to be covered by the trade
   tradeDiff = TP3Level - entryPriceLevel;
   //--- Set TP1 at one-third of the total move
   TP1Level = entryPriceLevel + tradeDiff/3;
   //--- Set TP2 at two-thirds of the total move
   TP2Level = entryPriceLevel + 2*tradeDiff/3;
} else { //--- Bearish → SELL signal
   //--- Use the current BID price as the entry
   entryPriceLevel = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   //--- Set TP3 at pivot E's price
   TP3Level = E.price;
   //--- Calculate the total distance to be covered by the trade
   tradeDiff = entryPriceLevel - TP3Level;
   //--- Set TP1 at one-third of the total move
   TP1Level = entryPriceLevel - tradeDiff/3;
   //--- Set TP2 at two-thirds of the total move
   TP2Level = entryPriceLevel - 2*tradeDiff/3;
}

//--- Draw dotted horizontal lines to represent the entry and TP levels
DrawDottedLine(signalPrefix+"_EntryLine", lineStart, entryPriceLevel, lineEnd, clrMagenta);
DrawDottedLine(signalPrefix+"_TP1Line", lineStart, TP1Level, lineEnd, clrForestGreen);
DrawDottedLine(signalPrefix+"_TP2Line", lineStart, TP2Level, lineEnd, clrGreen);
DrawDottedLine(signalPrefix+"_TP3Line", lineStart, TP3Level, lineEnd, clrDarkGreen);

//--- Define a label time coordinate positioned just to the right of the dotted lines
datetime labelTime = lineEnd + PeriodSeconds(_Period)/2;

//--- Construct the entry label text with the price
string entryLabel = (patternType=="Bullish") ? "BUY (" : "SELL (";
entryLabel += DoubleToString(entryPriceLevel, _Digits) + ")";
//--- Draw the entry label on the chart
DrawTextEx(signalPrefix+"_EntryLabel", entryLabel, labelTime, entryPriceLevel, clrMagenta, 11, true);

//--- Construct and draw the TP1 label
string tp1Label = "TP1 (" + DoubleToString(TP1Level, _Digits) + ")";
DrawTextEx(signalPrefix+"_TP1Label", tp1Label, labelTime, TP1Level, clrForestGreen, 11, true);

//--- Construct and draw the TP2 label
string tp2Label = "TP2 (" + DoubleToString(TP2Level, _Digits) + ")";
DrawTextEx(signalPrefix+"_TP2Label", tp2Label, labelTime, TP2Level, clrGreen, 11, true);

//--- Construct and draw the TP3 label
string tp3Label = "TP3 (" + DoubleToString(TP3Level, _Digits) + ")";
DrawTextEx(signalPrefix+"_TP3Label", tp3Label, labelTime, TP3Level, clrDarkGreen, 11, true);

Um die Handelsniveaus für das erkannte Muster zu definieren und zu visualisieren, setzen wir „lineStart“ auf den Zeitpunkt des Umkehrpunkts F („F.time“) und „lineEnd“ auf zwei Perioden im Voraus mit „PeriodSeconds(_Period) * 2“ und deklarieren die Variablen „entryPriceLevel“, „TP1Level“, „TP2Level“, „TP3Level“ und „tradeDiff“ für die Handelsberechnungen. Dann, für ein Aufwärtsmuster („patternType == 'Bullish'“), setzen wir „entryPriceLevel“ auf den aktuellen Briefkurs (Ask) mit „SymbolInfoDouble“, „TP3Level“ auf den Preis des Umkehrpunkts E, berechnen „tradeDiff“ als „TP3Level – entryPriceLevel“ und berechnen „TP1Level“ und „TP2Level“ als ein Drittel und zwei Drittel von „tradeDiff“, addiert zu „entryPriceLevel“; für ein Abwärtsmuster verwenden wir den Geldkurs (Bid), setzen „TP3Level“ auf den Preis von E, berechnen „tradeDiff“ als „entryPriceLevel – TP3Level“ und berechnen „TP1Level“ und „TP2Level“ durch Subtraktion von einem Drittel und zwei Dritteln der Handelsdifferenz.

Als Nächstes zeichnen wir mit „DrawDottedLine“ vier gepunktete horizontale Linien: eine Einstiegslinie bei „entryPriceLevel“ in Magenta und Take-Profit-Linien bei „TP1Level“ (forest green), „TP2Level“ (green) und „TP3Level“ (dark green), die sich von „lineStart“ bis „lineEnd“ erstrecken. Zuletzt setzen wir „labelTime“ auf „lineEnd“ plus eine halbe Periode, erstellen Texte mit Preisen, die mit der Funktion DoubleToString formatiert werden (z.B., „BUY (price)“ oder „SELL (price)“ für den Einstieg, „TP1 (price)“ usw.), und verwenden „DrawTextEx“, um diese Kennzeichnungen zum „labelTime“ mit entsprechenden Farben, Schriftgröße 11 und verankert über den Kursniveaus zu zeichnen. Nach dem Kompilieren erhalten wir folgendes Ergebnis.

Abwärtsmuster:

ABWÄRTSMUSTER

Aufwärtsmuster:

AUFWÄRTSMUSTER

Anhand der Bilder können wir sehen, dass wir die Handelsstufen richtig zugeordnet haben. Was wir jetzt tun müssen, ist, die eigentlichen Handelspositionen zu initiieren, und das ist alles.

//--- Retrieve the index of the current bar
int currentBarIndex = Bars(_Symbol, _Period) - 1;
//--- If no pattern has been previously locked, lock the current pattern formation
if(g_patternFormationBar == -1) {
   g_patternFormationBar = currentBarIndex;
   g_lockedPatternA = A.time;
   //--- Print a message that the pattern is detected and waiting for confirmation
   Print("Pattern detected on bar ", currentBarIndex, ". Waiting for confirmation on next bar.");
   return;
}
//--- If still on the same formation bar, the pattern is considered to be repainting
if(currentBarIndex == g_patternFormationBar) {
   Print("Pattern is repainting; still on locked formation bar ", currentBarIndex, ". No trade yet.");
   return;
}
//--- If we are on a new bar compared to the locked formation
if(currentBarIndex > g_patternFormationBar) {
   //--- Check if the locked pattern still corresponds to the same A pivot
   if(g_lockedPatternA == A.time) {
      Print("Confirmed pattern (locked on bar ", g_patternFormationBar, "). Opening trade on bar ", currentBarIndex, ".");
      //--- Update the pattern formation bar to the current bar
      g_patternFormationBar = currentBarIndex;
      //--- Only proceed with trading if allowed and if there is no existing position
      if(AllowTrading && !PositionSelect(_Symbol)) {
         //--- Check if this pattern has already been traded
         bool alreadyTraded = false;
         for(int k = 0; k < ArraySize(tradedPatterns); k++) {
            if(tradedPatterns[k] == A.time) {
               alreadyTraded = true;
               break;
            }
         }
         if(alreadyTraded) {
            Print("This pattern has already been traded. No new trade executed.");
            return;
         }
         double entryPriceTrade = 0, stopLoss = 0, takeProfit = 0;
         point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
         bool tradeResult = false;
         //--- Select TP level based on user input
         switch(TakeProfitLevel) {
            case TP1:
               takeProfit = TP1Level;
               break;
            case TP2:
               takeProfit = TP2Level;
               break;
            case TP3:
               takeProfit = TP3Level;
               break;
            default:
               takeProfit = TP2Level; // Fallback to TP2
         }
         //--- Calculate SL based on user-selected method
         if(patternType=="Bullish") { //--- BUY signal
            entryPriceTrade = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            if(StopLossType == SL_FIBO) {
               double third_drive = E.price - F.price;
               stopLoss = F.price - (SL_FiboExtension - 1.0) * third_drive;
            } else { // SL_FIXED
               stopLoss = entryPriceTrade - SL_FixedPoints * point;
            }
            // Ensure SL is below entry for BUY
            if(stopLoss >= entryPriceTrade) {
               stopLoss = entryPriceTrade - 10 * point;
            }
            tradeResult = obj_Trade.Buy(LotSize, _Symbol, entryPriceTrade, stopLoss, takeProfit, "5 Drives Signal");
            if(tradeResult)
               Print("Buy order opened successfully.");
            else
               Print("Buy order failed: ", obj_Trade.ResultRetcodeDescription());
         }
         //--- For a Bearish pattern, execute a SELL trade
         else if(patternType=="Bearish") { //--- SELL signal
            entryPriceTrade = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            if(StopLossType == SL_FIBO) {
               double third_drive = F.price - E.price;
               stopLoss = F.price + (SL_FiboExtension - 1.0) * third_drive;
            } else { // SL_FIXED
               stopLoss = entryPriceTrade + SL_FixedPoints * point;
            }
            // Ensure SL is above entry for SELL
            if(stopLoss <= entryPriceTrade) {
               stopLoss = entryPriceTrade + 10 * point;
            }
            tradeResult = obj_Trade.Sell(LotSize, _Symbol, entryPriceTrade, stopLoss, takeProfit, "5 Drives Signal");
            if(tradeResult)
               Print("Sell order opened successfully.");
            else
               Print("Sell order failed: ", obj_Trade.ResultRetcodeDescription());
         }
         //--- If trade was successful, mark the pattern as traded
         if(tradeResult) {
            int size = ArraySize(tradedPatterns);
            ArrayResize(tradedPatterns, size + 1);
            tradedPatterns[size] = A.time;
         }
      }
      else {
         //--- If a position is already open, do not execute a new trade
         Print("A position is already open for ", _Symbol, ". No new trade executed.");
      }
   }
   else {
      //--- If the pattern has changed, update the lock with the new formation bar and A pivot
      g_patternFormationBar = currentBarIndex;
      g_lockedPatternA = A.time;
      Print("Pattern has changed; updating lock on bar ", currentBarIndex, ". Waiting for confirmation.");
      return;
   }

}
else {
   //--- If no valid 5 Drives pattern is detected, reset the pattern lock variables
   g_patternFormationBar = -1;
   g_lockedPatternA = 0;
}

Wir schließen die Implementierung ab, indem wir die Handelsausführung und die Musterbestätigung für das erkannte Muster verwalten. Zunächst wird der aktuelle Balken-Index mit „Bars(_Symbol, _Period) – 1“ ermittelt und in „currentBarIndex“ gespeichert. Wenn kein Muster gesperrt ist („g_patternformationbar == -1“), setzen wir „g_patternformationbar“ auf „currentbarindex“, sperren die a-Pivot-Zeit in „g_lockedpatterna“ mit „a.time“, protokollieren die Erkennung mit Print, warten auf Bestätigung und beenden den Vorgang.

Wenn wir uns dann immer noch auf dem Formationsbalken befinden („currentBarIndex == g_patternFormationBar“), protokollieren wir das Repainting und beenden die Funktion, um ein zu frühes Handelsgeschäft zu verhindern. Zuletzt, wenn sich ein neuer Balken gebildet hat („currentBarIndex > g_patternFormationBar“) und der A-Pivot mit „g_lockedPatternA“ übereinstimmt, bestätigen wir das Muster, protokollieren es, aktualisieren „g_patternFormationBar“ und prüfen, ob der Handel mit „AllowTrading“ zulässig ist und keine offenen Positionen über PositionSelect bestehen. Wir überprüfen, ob das Muster noch nicht gehandelt wurde, indem wir „tradedPatterns“ überprüfen, wählen das Take-Profit-Niveau („TP1Level“, „TP2Level“ oder „TP3Level“) basierend auf „TakeProfitLevel“ aus, berechnen den Stop-Loss mit „SL_FIBO“ („F.price ± (SL_FiboExtension - 1.0) * third_drive”) oder „SL_FIXED” („entryPriceTrade ± SL_FixedPoints * point”) berechnet, stellt sicher, dass der Stop-Loss gültig ist (unterhalb des Einstiegspreises für Kauf, oberhalb für Verkauf, bei Bedarf um 10 Punkte angepasst), führt einen Kauf oder Verkauf mit „obj_Trade. Buy” oder „obj_Trade.Sell” unter Verwendung von „LotSize” und „5 Drives Signal”, Protokollierung von Erfolg oder Misserfolg und Markierung des Musters als gehandelt in „tradedPatterns”; wenn der Handel nicht zulässig ist, eine Position besteht oder das Muster gehandelt wurde, protokollieren wir das Handelsverbot; wenn sich das Muster ändert, aktualisieren wir die Sperre und warten; wenn kein Muster gefunden wird, setzen wir die globalen Variablen zurück. Nach dem Kompilieren erhalten wir folgendes Ergebnis.

Abwärtssignal:

ABWÄRTSSIGNAL

Aufwärtssignal:

AUFWÄRTSSIGNAL

Aus dem Bild können wir ersehen, dass wir das harmonische Muster aufzeichnen und in der Lage sind, es entsprechend zu handeln, sobald es bestätigt ist. Damit haben wir unser Ziel erreicht, das Muster zu identifizieren, aufzuzeichnen und zu handeln. Bleiben nur noch die Backtests des Programms, und das wird im nächsten Abschnitt behandelt.


Backtests

Nach einem gründlichen Backtest erhalten wir folgende Ergebnisse.

Backtest-Grafik:

GRAPH

Backtest-Bericht:

BERICHT


Schlussfolgerung

Abschließend haben wir ein 5 Drives (5-0) Mustersystem in MQL5 entwickelt, das die Preisbewegung nutzt, um steigende und fallende harmonische 5 Drives Muster mit präzisen Fibonacci-Verhältnissen zu erkennen, den Handel mit anpassbaren Einstiegs-, Stop-Loss- und mehrstufigen Take-Profit-Punkten zu automatisieren und die Muster mit Chart-Objekten wie Dreiecken und Trendlinien zu visualisieren.

Haftungsausschluss: Dieser Artikel ist nur für Bildungszwecke gedacht. Der Handel ist mit erheblichen finanziellen Risiken verbunden, und die Volatilität der Märkte kann zu Verlusten führen. Gründliche Backtests und sorgfältiges Risikomanagement sind entscheidend, bevor Sie dieses Programm auf den Live-Märkten einsetzen.

Indem Sie die vorgestellten Konzepte und deren Umsetzung nutzen, können Sie dieses 5-Drives-Muster-System an Ihren Handelsstil anpassen und Ihre algorithmischen Strategien verbessern. Viel Spaß beim Handeln!

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/19463

Beigefügte Dateien |
Vom Neuling zum Experten: Implementierung von Fibonacci-Strategien im Post-NFP-Handel Vom Neuling zum Experten: Implementierung von Fibonacci-Strategien im Post-NFP-Handel
Auf den Finanzmärkten gehören die Gesetze des Retracement nach wie vor zu den unbestreitbaren Kräften. Als Faustregel gilt, dass die Kurse immer zurückgehen werden – sei es bei großen Bewegungen oder sogar innerhalb kleinster Tick-Muster, die oft als Zickzack erscheinen. Das Retracement-Muster selbst steht jedoch nie fest; es bleibt ungewiss und unterliegt der Antizipation. Diese Ungewissheit erklärt, warum sich Händler auf mehrere Fibonacci-Niveaus verlassen, von denen jedes eine bestimmte Wahrscheinlichkeit des Einflusses hat. In diesem Beitrag stellen wir eine verfeinerte Strategie vor, die Fibonacci-Techniken anwendet, um die Herausforderungen des Handels kurz nach der Ankündigung wichtiger wirtschaftlicher Ereignisse zu bewältigen. Durch die Kombination von Retracement-Prinzipien mit ereignisgesteuertem Marktverhalten wollen wir zuverlässigere Einstiegs- und Ausstiegsmöglichkeiten aufdecken. Nehmen Sie an der vollständigen Diskussion teil und erfahren Sie, wie Fibonacci für den Handel nach Ereignissen angepasst werden kann.
Den Marktstimmungsindikator automatisieren Den Marktstimmungsindikator automatisieren
In diesem Artikel entwickeln wir einen nutzerdefinierten Indikator für die Marktstimmung, um die Bedingungen in aufwärts, abwärts, mehr und weniger Risiko oder neutral zu klassifizieren. Der Expert Advisor liefert Echtzeit-Einblicke in die vorherrschende Stimmung und vereinfacht den Analyseprozess für aktuelle Markttrends oder -richtungen.
Einführung in MQL5 (Teil 21): Automatisiertes Erkennen von harmonischen Mustern Einführung in MQL5 (Teil 21): Automatisiertes Erkennen von harmonischen Mustern
Lernen Sie, wie Sie das harmonische Muster von Gartley im MetaTrader 5 mit MQL5 erkennen und anzeigen können. In diesem Artikel wird jeder Schritt des Prozesses erläutert, von der Identifizierung der Umkehrpunkte über die Anwendung der Fibonacci-Ratios bis hin zur Darstellung des gesamten Musters auf dem Chart zur eindeutigen visuellen Bestätigung.
Beherrschung der Fair Value Gaps: Bildung, Logik und automatisierter Handel von Ausbrüchen und Marktstrukturverschiebungen Beherrschung der Fair Value Gaps: Bildung, Logik und automatisierter Handel von Ausbrüchen und Marktstrukturverschiebungen
Dies ist ein Artikel, den ich geschrieben habe, um Fair Value Gaps, ihre Entstehungslogik und den automatisierten Handel von Ausbrüchen und Marktstrukturverschiebungen zu erläutern und zu erklären.