English
preview
Entwicklung des Price Action Analysis Toolkit (Teil 25): Dual EMA Fractal Breaker

Entwicklung des Price Action Analysis Toolkit (Teil 25): Dual EMA Fractal Breaker

MetaTrader 5Indikatoren |
25 3
Christian Benjamin
Christian Benjamin

Inhalt



Einführung

In diesem Artikel wird die Entwicklung eines Instruments vorgestellt, das bei der Preisaktionsanalyse helfen soll, indem es eine tiefere und aufschlussreichere Bewertung unter Verwendung des ursprünglich von Bill Williams entwickelten Fraktal-Indikators ermöglicht.

Bill M. Williams (1932–2019) war ein einflussreicher amerikanischer Händler und Autor, der für seine Beiträge zur Handelspsychologie, zur technischen Analyse und zur Chaostheorie auf den Finanzmärkten bekannt ist. Im Laufe seiner Karriere untersuchte Williams die Aktien-, Rohstoff- und Devisenmärkte und entwickelte eine Reihe innovativer technischer Analysetools, um Trends und potenzielle Umkehrpunkte zu erkennen. Zu seinen bekanntesten Indikatoren gehören der Accelerator/Decelerator Oszillator, der Alligator-Indikator, der Awesome Oszillator, der Fractals-Indikator, der Gator Oszillator und der Market Facilitation Index. Heute werden diese Indikatoren aufgrund ihrer Effektivität bei der Analyse des Marktverhaltens auf den Devisen-, Aktien- und anderen Finanzmärkten weithin eingesetzt.

Der Fractals-Indikator, eine Schlüsselkomponente der Williams-Methode, wird in unserem Ansatz mit den Exponential Moving Averages (EMAs) mit Periodenlängen von 14 und 200 kombiniert. Durch die Integration der fraktalen Muster mit diesen dynamischen Trendfiltern ist unser Expert Advisor (EA) in der Lage, potenzielle Marktumkehrungen genau zu erkennen und gleichzeitig die Ausrichtung auf die allgemeine Trendrichtung zu gewährleisten. Diese kombinierte Strategie verbessert die Entscheidungsfindung beim Handel, indem sie die frühzeitige Erkennung von Umkehrsignalen und die Bestätigung der Trendstärke ermöglicht, was letztlich zu zuverlässigeren und wahrscheinlicheren Einstiegspunkten führt. Die Synergie zwischen Fraktalanalyse und gleitenden Durchschnitten bietet Händlern ein leistungsfähiges Instrument zur tieferen Interpretation von Kursbewegungen und hilft, das Timing zu optimieren und die Handelsergebnisse zu verbessern.


Die Strategie verstehen

Unser Expert Advisor (EA) verwendet drei technische Schlüsselindikatoren: den Fractal-Indikator, den EMA 14 und den EMA 200. Der von Bill Williams entwickelte Fraktal-Indikator ist ein beliebtes Instrument der technischen Analyse, um potenzielle Trendumkehrungen zu erkennen. Es erkennt bestimmte Preismuster, so genannte Fraktale, die als lokale Höchst- oder Tiefststände erscheinen und mögliche Wendepunkte auf dem Markt signalisieren. Diese Fraktale dienen als Unterstützungs- oder Widerstandsniveaus und bieten Händlern visuelle Anhaltspunkte, um Ein- und Ausstiegszeitpunkte genauer zu bestimmen.

Der Exponentielle Gleitende Durchschnitt (EMA) unterscheidet sich grundlegend vom Einfachen Gleitenden Durchschnitt (SMA), da er den jüngsten Kursdaten ein größeres Gewicht beimisst, was zu einem reaktionsschnelleren Indikator führt. Diese Gewichtung wird durch einen Glättungsfaktor erreicht, der die jüngsten Kurse exponentiell hervorhebt, sodass der EMA rascher auf Marktveränderungen reagieren kann. Folglich sind EMAs sehr effektiv, um sich abzeichnende Trends zu erfassen und frühzeitige Signale für Trendwechsel zu liefern, insbesondere über kürzere Zeiträume.

Der EMA 14 spiegelt in unserem Setup die kurzfristige Marktdynamik wider und reagiert schnell auf die jüngsten Kursbewegungen, sodass er sich für einen rechtzeitigen Handelseinstieg eignet. Umgekehrt ist der EMA 200 ein langfristiger Trendindikator, der kurzfristiges Rauschen glättet und die allgemeine Marktrichtung erkennen lässt. Wenn der Kurs über dem EMA 200 notiert, deutet dies auf einen langfristigen Aufwärtstrend hin; liegt er darunter, wird ein Abwärtstrend angedeutet. Darüber hinaus fungiert der EMA 200 häufig als dynamisches Unterstützungs- oder Widerstandsniveau, das Händlern hilft, falsche Signale herauszufiltern und die Gültigkeit des Trends zu bestätigen.

Kaufsignal (Aufwärtsausbruch):

Ein Kaufsignal wird ausgelöst, wenn mehrere Bedingungen gleichzeitig erfüllt sind, die auf eine starke Aufwärtsbewegung hindeuten. Zunächst überwacht der EA das jüngste fraktale Tief (das Unterstützungsniveau). Er sucht nach einem Szenario, in dem der aktuelle Marktpreis diese fraktale Unterstützungsebene überschreitet, was einen potenziellen Ausbruch signalisiert. Um zu bestätigen, dass sich der Markt in einem Aufwärtstrend befindet, prüft der EA, ob der aktuelle Kurs sowohl über dem EMA 14 als auch über dem EMA 200 liegt, wobei der EMA 14 über dem EMA 200 liegt, was auf einen Aufwärtstrend hinweist. Wenn diese Bedingungen zusammentreffen, wird ein Kaufsignal generiert. Visuelle Hinweise wie ein Aufwärtspfeil und eine Beschriftung werden auf dem Chart platziert, und ein Alarm kann ausgelöst werden, um den Händler zu benachrichtigen.

  • Der Kurs kreuzt über der letzten fraktalen Unterstützungsmarke.
  • Der aktuelle Kurs liegt über dem EMA 14 und dem EMA 200.
  • Der EMA 14 liegt über dem EMA 200, was einen Aufwärtstrend bestätigt.

Abb. 1. Aufwärtsausbruch

Verkaufssignal (Abwärtsausbruch):

Umgekehrt wird ein Verkaufssignal ausgelöst, wenn der Kurs ein signifikantes fraktales Hoch (Widerstandsniveau) unterschreitet, was auf eine mögliche Abwärtsbewegung hinweist. Der EA beobachtet das jüngste fraktale Hoch und wartet darauf, dass der Marktpreis unter dieses Niveau bricht. Um zu überprüfen, ob der Markt abwärts tendiert, wird bestätigt, dass der aktuelle Kurs unter beiden EMAs liegt, wobei der EMA 14 unter dem EMA 200 liegt, was auf einen Abwärtstrend hinweist. Wenn diese Kriterien erfüllt sind, d. h. wenn der Kurs unter das fraktale Widerstandsniveau fällt und der Trend weiterhin rückläufig ist, wird ein Verkaufssignal ausgegeben. Ähnliche visuelle Markierungen wie Abwärtspfeile und Beschriftungen werden eingezeichnet, und es können Warnmeldungen aktiviert werden.

  • Der Kurs kreuzt unter dem jüngsten fraktalen Widerstandsniveau.
  • Der aktuelle Kurs liegt unter dem EMA 14 und dem EMA 200.
  • Der EMA 14 liegt unter dem EMA 200, was einen Abwärtstrend bestätigt.

Abb. 2. Abwärtsausbruch


Aufschlüsselung der Code-Komponenten

Dieser EA integriert die Fraktalanalyse mit gleitenden Durchschnittstrendfiltern, um potenzielle Ausbruchspunkte im Markt zu identifizieren und zu visualisieren. Durch das Einzeichnen von horizontalen Ebenen an den jüngsten fraktalen Hochs und Tiefs werden kritische Unterstützungs- und Widerstandszonen markiert. Wenn der Kurs diese Niveaus in der durch den EMA-Trend bestätigten Richtung durchbricht, erzeugt der EA visuelle Signale (Pfeile und Etiketten) und akustische Warnungen, die den Entscheidungsprozess des Händlers vereinfachen. Der modulare Aufbau mit Funktionen für Zeichnung, Signalisierung und Datenverwaltung ermöglicht die Anpassung an verschiedene Handelsstile und -präferenzen. Darüber hinaus sorgt der Schwerpunkt auf Ressourcenmanagement und Sanierung für Stabilität und Klarheit während des Betriebs. Insgesamt bietet diese ausgeklügelte Kombination von Indikatoren und visuellen Hinweisen ein umfassendes Instrument für Händler, die fraktale Ausbruchschancen in einem Trendumfeld nutzen möchten.

Header und Metadaten

Der erste Abschnitt des Codes enthält Metadaten, die die Autorenschaft, die Version und die Lizenzinformationen des Skripts beschreiben. Die Kommentare innerhalb von //+------------------------------------------------------------------+ dienen dazu, den Zweck des Skripts zu kennzeichnen und eine Zuordnung vorzunehmen. Die Direktiven #property geben den Urheberrechtsinhaber, einen Hyperlink zum Profil des Autors in der MetaTrader-Community und die Versionsnummer an und setzen strenge Kompilierungsregeln durch. Die Direktive #property strict ist besonders wichtig, da sie den Compiler anweist, strengere Codierungsstandards einzuhalten und potenzielle Fehler wie nicht deklarierte Variablen oder Typinkongruenzen zu erkennen. Diese Metadaten und Direktiven haben keinen Einfluss auf die Laufzeitlogik, sondern dienen der Dokumentation und sichern die Codequalität während der Kompilierung.

//+------------------------------------------------------------------+
//|                              Fractal Breakout, EMA 14 and EMA 200|
//|                                   Copyright 2025, MetaQuotes Ltd.|
//|                           https://www.mql5.com/en/users/lynnchris|
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.0"
#property strict

Eingabe-Parameter

In diesem Abschnitt werden alle konfigurierbaren Parameter definiert, die ein Nutzer ändern kann, ohne den Kerncode zu verändern. Diese Eingaben umfassen den Zeitrahmen für die Analyse (InpTimeframe), die Anzahl der zu untersuchenden Balken (InpHistoryBars) und die Perioden für die beiden EMAs, die als Trendfilter dienen (InpEMA14Period und InpEMA200Period).

Die Farbparameter (InpBullColor und InpBearColor) ermöglichen die visuelle Anpassung der Pfeile und Linien, die Ausbrüche anzeigen. Textbeschriftungen (InpBullText und InpBearText) liefern beschreibende Anmerkungen zu den Signalen und verbessern die Übersichtlichkeit des Charts. Der Pfeilabstand (InpArrowOffset) und die Schriftgröße (InpArrowFontSize) ermöglichen eine weitere Kontrolle über die visuelle Darstellung, sodass der Händler die Beschriftungen bequem positionieren kann.

Das Warnsystem wird durch InpAlertsEnabled, das Pop-up-Benachrichtigungen ein- und ausschaltet, und InpAlertSoundFile, das die bei Erkennung abgespielte Sounddatei angibt, gesteuert. Diese Parameter machen den EA flexibel und anpassungsfähig an verschiedene Handelsstile und visuelle Vorlieben, sodass die Nutzer ihn an ihre spezifischen Bedürfnisse anpassen können.

input ENUM_TIMEFRAMES InpTimeframe      = PERIOD_CURRENT;  // chart TF
input int             InpHistoryBars    = 200;             // bars back to scan
input int             InpEMA14Period    = 14;              // fast EMA
input int             InpEMA200Period   = 200;             // slow EMA
input color           InpBullColor      = clrLime;         // bullish arrow color
input color           InpBearColor      = clrRed;          // bearish arrow color
input string          InpBullText       = "BULL Break";    // bullish label
input string          InpBearText       = "BEAR Break";    // bearish label
input int             InpArrowOffset    = 20;              // offset in points for label
input int             InpArrowFontSize  = 12;              // size of the arrow glyph
input bool            InpAlertsEnabled  = true;            // show pop-up alerts
input string          InpAlertSoundFile = "alert.wav";     // sound file in /Sounds/

Globale Variablen und Indikatorhandles

Die außerhalb von Funktionen deklarierten Variablen dienen als Speicher für Indikator-Handles und fraktale Datenarrays. Die Handles (hFractals, hEMA14, hEMA200) sind Verweise auf die Indikatorinstanzen, die während der Initialisierung erstellt wurden. Sie sind unverzichtbar, da sie es dem EA ermöglichen, mit den Puffern der Indikatoren zu interagieren, indem er Echtzeit- und historische Daten abruft. Die Arrays fractalUp[] und fractalDown[] sind dynamisch zugewiesene Puffer, die die Hoch- bzw. Tiefpunkte des Fraktals enthalten. Die Verwaltung dieser Variablen als globale Variablen stellt sicher, dass im gesamten Skript auf sie zugegriffen werden kann, insbesondere während der Verarbeitung in OnTick, bei der eine Echtzeitanalyse erfolgt.

int  hFractals, hEMA14, hEMA200;
double fractalUp[], fractalDown[];

Initialisierung (OnInit)

Während des Starts wird die Funktion OnInit aufgerufen, um die erforderlichen Ressourcen einzurichten. Es erstellt Indikator-Handles für Fraktale und EMAs mit Funktionen wie iFractals und iMA unter Angabe von Symbol und Zeitrahmen. Die erfolgreiche Erstellung dieser Handles ist von entscheidender Bedeutung; wenn ein Handle ungültig ist (z. B. aufgrund falscher Parameter oder nicht verfügbarer Daten), schlägt die Initialisierung fehl, wodurch der EA nicht ordnungsgemäß ausgeführt werden kann.

Der Code konfiguriert dann die fraktalen Datenfelder so, dass sie als Serien funktionieren, was bedeutet, dass die neuesten Daten bei Index 0 stehen, was die Rückwärtsanalyse vereinfacht. Durch die Anpassung der Größe dieser Arrays an die angegebene Anzahl der Balken wird sichergestellt, dass die Datenpuffer für eine effiziente Verarbeitung angemessen dimensioniert sind. Insgesamt schafft dieser Schritt die Grundlage für einen zuverlässigen Datenabruf, der für eine genaue Ausbruchserkennung unerlässlich ist.

int OnInit()
  {
   hFractals = iFractals(_Symbol, InpTimeframe);
   hEMA14    = iMA(_Symbol, InpTimeframe, InpEMA14Period, 0, MODE_EMA, PRICE_CLOSE);
   hEMA200   = iMA(_Symbol, InpTimeframe, InpEMA200Period,0, MODE_EMA, PRICE_CLOSE);
   if(hFractals==INVALID_HANDLE || hEMA14==INVALID_HANDLE || hEMA200==INVALID_HANDLE)
      return(INIT_FAILED);

   ArraySetAsSeries(fractalUp,   true);
   ArraySetAsSeries(fractalDown, true);
   ArrayResize(fractalUp,   InpHistoryBars);
   ArrayResize(fractalDown, InpHistoryBars);
   return(INIT_SUCCEEDED);
  }

Deinitialisierung (OnDeinit)

Wenn der EA aus dem Chart entfernt oder das Terminal geschlossen wird, wird OnDeinit ausgeführt, um die Ressourcen aufzuräumen. Es gibt die Indikator-Handles mit IndicatorRelease frei, gibt den zugehörigen Speicher frei und verhindert Lecks. Außerdem werden alle Objekte im Chart durchlaufen, identifiziert und die Objekte mit dem Präfix „FB_“, d. h. die visuellen Signale (Pfeile, Beschriftungen, Linien) gelöscht, die während der Ausführung erzeugt werden. Durch diese Bereinigung wird sichergestellt, dass nach der Deaktivierung des EA keine Objekte im Chart verbleiben, sodass eine saubere Chartumgebung erhalten bleibt und mögliche Konflikte oder Verwirrung bei nachfolgenden Analysen vermieden werden.

void OnDeinit(const int reason)
  {
   if(hFractals!=INVALID_HANDLE)
      IndicatorRelease(hFractals);
   if(hEMA14   !=INVALID_HANDLE)
      IndicatorRelease(hEMA14);
   if(hEMA200  !=INVALID_HANDLE)
      IndicatorRelease(hEMA200);

   for(int i=ObjectsTotal(0)-1; i>=0; i--)
     {
      string n = ObjectName(0,i);
      if(StringFind(n,"FB_")>=0)
         ObjectDelete(0,n);
     }
  }

Hauptverarbeitung (OnTick)

Die Kernlogik befindet sich in der Funktion OnTick, die jedes Mal ausgeführt wird, wenn ein neuer Markttick eintrifft. Zunächst werden die letzten Werte der beiden EMAs mit CopyBuffer abgerufen. Diese EMA-Werte dienen als Trendfilter: Ihre relative Position zeigt an, ob sich der Markt in einem Aufwärts- oder Abwärtstrend befindet, was die Ausbruchsentscheidung erleichtert. Wenn der Abruf der EMA-Daten fehlschlägt, wird die Funktion vorzeitig beendet, um fehlerhafte Signale zu vermeiden. Als Nächstes ruft die Funktion Fraktaldatenpuffer für die jüngsten hohen und niedrigen Fraktale ab, wiederum mit Fehlerprüfung. Der Code sucht dann rückwärts durch diese Puffer, um die letzten gültigen Fraktale zu finden, wobei alle Platzhalter mit EMPTY_VALUEs ignoriert werden. Durch die Identifizierung der letzten signifikanten fraktalen Punkte bestimmt der EA die kritischen Unterstützungs- oder Widerstandsniveaus, die Ausbrüche auslösen könnten. Anschließend werden mit Hilfe einer Hilfsfunktion horizontale Linien auf diesen Ebenen als visuelle Referenz gezeichnet. Die Debugging-Ausgabe des Terminals bietet Echtzeiteinblicke in die Niveaus, Preise und EMA-Zustände und hilft Händlern, die Logik zu überprüfen.

Schließlich prüft der EA auf Ausbruchsbedingungen: Ein Ausbruch nach unten liegt vor, wenn der vorherige Schlusskurs über dem Abwärtsniveau lag, der aktuelle Schlusskurs darunter kreuzt und der Kurs unter beiden EMAs in einem Abwärtstrend liegt. Umgekehrt wird ein Aufwärtsausbruch erkannt, wenn der vorherige Schlusskurs unter dem Aufwärtsniveau lag, das aktuelle Kreuz darüber liegt und der Kurs über beiden EMAs in einem Aufwärtstrend steht. Die Erkennung dieser Bedingungen löst die Signalisierungsfunktion aus.

void OnTick()
  {
   // 1) Read current EMAs
   double ema14Arr[1], ema200Arr[1];
   if(CopyBuffer(hEMA14,0,0,1,ema14Arr)<=0 || CopyBuffer(hEMA200,0,0,1,ema200Arr)<=0)
      return;
   double ema14_now  = ema14Arr[0];
   double ema200_now = ema200Arr[0];

   // 2) Read fractal history (skip current bar)
   if(CopyBuffer(hFractals,0,1,InpHistoryBars,fractalUp)<=0 ||
      CopyBuffer(hFractals,1,1,InpHistoryBars,fractalDown)<=0)
      return;

   // 3) Find most recent valid fractals (ignore EMPTY_VALUE)
   int upShift=-1, downShift=-1;
   for(int i=1; i<InpHistoryBars; i++)
     {
      if(fractalUp[i]   != EMPTY_VALUE && upShift<0)
         upShift   = i+1;
      if(fractalDown[i] != EMPTY_VALUE && downShift<0)
         downShift = i+1;
      if(upShift>0 && downShift>0)
         break;
     }

   // 4) Levels
   double lvlUp   = (upShift>0)   ? fractalUp[upShift-1]     : 0.0;
   double lvlDown = (downShift>0) ? fractalDown[downShift-1] : 0.0;

   // 5) Draw level lines
   DrawHLine("FB_LevelUp",   lvlUp,   InpBullColor);
   DrawHLine("FB_LevelDown", lvlDown, InpBearColor);

   // 6) DEBUG print
   double prevC = iClose(_Symbol,InpTimeframe,1);
   double currC = iClose(_Symbol,InpTimeframe,0);
   PrintFormat(
      "DBG lvlUp=%.5f lvlDown=%.5f prevC=%.5f currC=%.5f EMA14=%.5f EMA200=%.5f",
      lvlUp, lvlDown, prevC, currC, ema14_now, ema200_now
   );

   // 7) Breakouts on the last closed candle (shift=1)

   // Bearish breakout detection
   if(lvlDown>0
      && prevC>=lvlDown && currC<lvlDown
      && currC<ema14_now && currC<ema200_now
      && ema200_now>ema14_now)
     {
      Print(">>> Bear breakout triggered");
      Signal(false, 1, lvlDown, ema14_now, ema200_now);
     }

   // Bullish breakout detection
   if(lvlUp>0
      && prevC<=lvlUp && currC>lvlUp
      && currC>ema14_now && currC>ema200_now
      && ema14_now>ema200_now)
     {
      Print(">>> Bull breakout triggered");
      Signal(true, 1, lvlUp, ema14_now, ema200_now);
     }
  }

Horizontale Linien zeichnen (DrawHLine)

Diese Utility-Funktion verwaltet die Erstellung und Aktualisierung von horizontalen Linien im Chart. Beim Aufruf wird geprüft, ob eine Linie mit dem angegebenen Namen existiert; falls nicht, wird eine neue gepunktete Linie auf dem angegebenen Preisniveau mit der angegebenen Farbe erstellt. Wenn die Zeile bereits existiert, wird ihre Position einfach aktualisiert. Dieser Ansatz verhindert, dass sich mehrere Linien überschneiden, und sorgt dafür, dass die visuellen Ebenen immer auf dem neuesten Stand der fraktalen Analyse sind. Der gepunktete Stil hilft, diese Linien von anderen Chartobjekten zu unterscheiden und ihre Rolle als Unterstützungs- oder Widerstandsniveaus zu betonen. Solche visuellen Anhaltspunkte sind für Händler von unschätzbarem Wert, da sie eine schnelle Erkennung von Ausbruchszonen ermöglichen und die manuelle oder automatische Entscheidungsfindung erleichtern.

void DrawHLine(string name, double price, color clr)
  {
   if(price<=0)
      return;
   if(ObjectFind(0,name)<0)
     {
      ObjectCreate(0,name,OBJ_HLINE,0,0,price);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
     }
   else
      ObjectSetDouble(0,name,OBJPROP_PRICE,price);
  }

Signalisierung und Visualisierung (Signal)

Die Funktion Signal kapselt alle Aktionen im Zusammenhang mit der Signalisierung eines Breakout-Ereignisses. Zunächst wird der Zeitstempel des Balkens abgerufen, an dem das Signal aufgetreten ist, um eine genaue Platzierung der visuellen Objekte zu gewährleisten. Anschließend wird am Ausbruchsniveau ein Pfeilobjekt erstellt, das nach oben oder unten zeigt, je nachdem, ob es sich um eine Hausse oder Baisse handelt, wobei die Farbkodierung dem Trend entspricht. Das Erscheinungsbild des Pfeils wird zur besseren Übersichtlichkeit mit Parametern für Breite und Größe angepasst. Neben dem Pfeil wird eine Textbeschriftung leicht vertikal versetzt hinzugefügt, die eine beschreibende Nachricht wie „BULL Break“ oder „BEAR Break“ enthält und den visuellen Hinweis verstärkt.

Die Funktion protokolliert eine ausführliche Meldung auf der Registerkarte Experten, einschließlich der genauen Zeit, des Levels, des Schlusskurses und der EMA-Werte, und bietet so eine umfassende Aufzeichnung der Signale. Wenn Warnungen aktiviert sind, wird eine Pop-up-Meldung angezeigt und eine Tondatei abgespielt, um den Händler sofort zu informieren. Diese Kombination aus visuellen, akustischen und protokollbasierten Signalen stellt sicher, dass Händler umgehend über potenzielle Ausbruchschancen informiert werden und rechtzeitig handeln können.

void Signal(bool isBull, int shift, double level, double ema14, double ema200)
  {
   datetime t     = iTime(_Symbol,InpTimeframe,shift);
   double   price = level;
   string   side  = isBull ? "Bull" : "Bear";

   // Arrow
   string arrowName = StringFormat("FB_%sArrow_%d", side, (int)t);
   ObjectCreate(0, arrowName, OBJ_ARROW, 0, t, price);
   ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE,    isBull?233:234);
   ObjectSetInteger(0, arrowName, OBJPROP_COLOR,        isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, arrowName, OBJPROP_WIDTH,        2);
   ObjectSetInteger(0, arrowName, OBJPROP_FONTSIZE,     InpArrowFontSize);

   // Label
   string lab = arrowName + "_L";
   double offset = (isBull ? InpArrowOffset : -InpArrowOffset) * _Point;
   ObjectCreate(0, lab, OBJ_TEXT, 0, t, price + offset);
   ObjectSetString(0, lab, OBJPROP_TEXT,    isBull?InpBullText:InpBearText);
   ObjectSetInteger(0, lab, OBJPROP_COLOR,  isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, lab, OBJPROP_FONTSIZE, 11);

   // Log message
   string msg = StringFormat(
                   "%s breakout at %s | Level=%.5f | Close=%.5f | EMA14=%.5f | EMA200=%.5f",
                   side, TimeToString(t, TIME_DATE|TIME_SECONDS),
                   level, iClose(_Symbol,InpTimeframe,shift),
                   ema14, ema200
                );
   Print(msg);

   // Alert and sound
   if(InpAlertsEnabled)
     {
      Alert(msg);
      if(StringLen(InpAlertSoundFile)>0)
         PlaySound(InpAlertSoundFile);
     }
  }

MQL5 Code

//+------------------------------------------------------------------+
//|                              Fractal Breakout, EMA 14 and EMA 200|
//|                                   Copyright 2025, MetaQuotes Ltd.|
//|                           https://www.mql5.com/en/users/lynnchris|
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.0"
#property strict

//---inputs
input ENUM_TIMEFRAMES InpTimeframe      = PERIOD_CURRENT;  // chart TF
input int             InpHistoryBars    = 200;             // bars back to scan
input int             InpEMA14Period    = 14;              // fast EMA
input int             InpEMA200Period   = 200;             // slow EMA
input color           InpBullColor      = clrLime;         // bullish arrow color
input color           InpBearColor      = clrRed;          // bearish arrow color
input string          InpBullText       = "BULL Break";    // bullish label
input string          InpBearText       = "BEAR Break";    // bearish label
input int             InpArrowOffset    = 20;              // offset in points for label
input int             InpArrowFontSize  = 12;              // size of the arrow glyph
input bool            InpAlertsEnabled  = true;            // show pop-up alerts
input string          InpAlertSoundFile = "alert.wav";     // sound file in /Sounds/

//---indicator handles & buffers
int  hFractals, hEMA14, hEMA200;
double fractalUp[], fractalDown[];

//+------------------------------------------------------------------+
//| Expert initialization                                            |
//+------------------------------------------------------------------+
int OnInit()
  {
   hFractals = iFractals(_Symbol, InpTimeframe);
   hEMA14    = iMA(_Symbol, InpTimeframe, InpEMA14Period, 0, MODE_EMA, PRICE_CLOSE);
   hEMA200   = iMA(_Symbol, InpTimeframe, InpEMA200Period,0, MODE_EMA, PRICE_CLOSE);
   if(hFractals==INVALID_HANDLE || hEMA14==INVALID_HANDLE || hEMA200==INVALID_HANDLE)
      return(INIT_FAILED);

   ArraySetAsSeries(fractalUp,   true);
   ArraySetAsSeries(fractalDown, true);
   ArrayResize(fractalUp,   InpHistoryBars);
   ArrayResize(fractalDown, InpHistoryBars);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(hFractals!=INVALID_HANDLE)
      IndicatorRelease(hFractals);
   if(hEMA14   !=INVALID_HANDLE)
      IndicatorRelease(hEMA14);
   if(hEMA200  !=INVALID_HANDLE)
      IndicatorRelease(hEMA200);

   for(int i=ObjectsTotal(0)-1; i>=0; i--)
     {
      string n = ObjectName(0,i);
      if(StringFind(n,"FB_")>=0)
         ObjectDelete(0,n);
     }
  }

//+------------------------------------------------------------------+
//| Tick handler                                                     |
//+------------------------------------------------------------------+
void OnTick()
  {
// 1) Read current EMAs
   double ema14Arr[1], ema200Arr[1];
   if(CopyBuffer(hEMA14,0,0,1,ema14Arr)<=0 || CopyBuffer(hEMA200,0,0,1,ema200Arr)<=0)
      return;
   double ema14_now  = ema14Arr[0];
   double ema200_now = ema200Arr[0];

// 2) Read fractal history (skip current bar)
   if(CopyBuffer(hFractals,0,1,InpHistoryBars,fractalUp)<=0 ||
      CopyBuffer(hFractals,1,1,InpHistoryBars,fractalDown)<=0)
      return;

// 3) Find most recent valid fractals (ignore EMPTY_VALUE)
   int upShift=-1, downShift=-1;
   for(int i=1; i<InpHistoryBars; i++)
     {
      if(fractalUp[i]   != EMPTY_VALUE && upShift<0)
         upShift   = i+1;
      if(fractalDown[i] != EMPTY_VALUE && downShift<0)
         downShift = i+1;
      if(upShift>0 && downShift>0)
         break;
     }

// 4) Levels
   double lvlUp   = (upShift>0)   ? fractalUp[upShift-1]     : 0.0;
   double lvlDown = (downShift>0) ? fractalDown[downShift-1] : 0.0;

// 5) Draw level lines
   DrawHLine("FB_LevelUp",   lvlUp,   InpBullColor);
   DrawHLine("FB_LevelDown", lvlDown, InpBearColor);

// 6) DEBUG print
   double prevC = iClose(_Symbol,InpTimeframe,1);
   double currC = iClose(_Symbol,InpTimeframe,0);
   PrintFormat(
      "DBG lvlUp=%.5f lvlDown=%.5f prevC=%.5f currC=%.5f EMA14=%.5f EMA200=%.5f",
      lvlUp, lvlDown, prevC, currC, ema14_now, ema200_now
   );

// 7) Breakouts on the last closed candle (shift=1)

// Bearish breakout
   if(lvlDown>0
      && prevC>=lvlDown && currC<lvlDown
      && currC<ema14_now && currC<ema200_now
      && ema200_now>ema14_now)
     {
      Print(">>> Bear breakout triggered");
      Signal(false, 1, lvlDown, ema14_now, ema200_now);
     }
// Bullish breakout
   if(lvlUp>0
      && prevC<=lvlUp && currC>lvlUp
      && currC>ema14_now && currC>ema200_now
      && ema14_now>ema200_now)
     {
      Print(">>> Bull breakout triggered");
      Signal(true, 1, lvlUp, ema14_now, ema200_now);
     }
  }

//+------------------------------------------------------------------+
//| Draw or update a dotted HLine                                    |
//+------------------------------------------------------------------+
void DrawHLine(string name, double price, color clr)
  {
   if(price<=0)
      return;
   if(ObjectFind(0,name)<0)
     {
      ObjectCreate(0,name,OBJ_HLINE,0,0,price);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
     }
   else
      ObjectSetDouble(0,name,OBJPROP_PRICE,price);
  }

//+------------------------------------------------------------------+
//| Plot arrow, label, log & alert                                   |
//+------------------------------------------------------------------+
void Signal(bool isBull, int shift, double level, double ema14, double ema200)
  {
   datetime t     = iTime(_Symbol,InpTimeframe,shift);
   double   price = level;
   string   side  = isBull ? "Bull" : "Bear";

// Arrow
   string arrowName = StringFormat("FB_%sArrow_%d", side, (int)t);
   ObjectCreate(0, arrowName, OBJ_ARROW, 0, t, price);
   ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE,    isBull?233:234);
   ObjectSetInteger(0, arrowName, OBJPROP_COLOR,        isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, arrowName, OBJPROP_WIDTH,        2);
   ObjectSetInteger(0, arrowName, OBJPROP_FONTSIZE,     InpArrowFontSize);

// Label
   string lab = arrowName + "_L";
   double offset = (isBull ? InpArrowOffset : -InpArrowOffset) * _Point;
   ObjectCreate(0, lab, OBJ_TEXT, 0, t, price + offset);
   ObjectSetString(0, lab, OBJPROP_TEXT,    isBull?InpBullText:InpBearText);
   ObjectSetInteger(0, lab, OBJPROP_COLOR,  isBull?InpBullColor:InpBearColor);
   ObjectSetInteger(0, lab, OBJPROP_FONTSIZE, 11);

// Expert log
   string msg = StringFormat(
                   "%s breakout at %s | Level=%.5f | Close=%.5f | EMA14=%.5f | EMA200=%.5f",
                   side, TimeToString(t, TIME_DATE|TIME_SECONDS),
                   level, iClose(_Symbol,InpTimeframe,shift),
                   ema14, ema200
                );
   Print(msg);

// Pop-up alert + optional sound
   if(InpAlertsEnabled)
     {
      Alert(msg);
      if(StringLen(InpAlertSoundFile)>0)
         PlaySound(InpAlertSoundFile);
     }
  }
//+------------------------------------------------------------------+


Ergebnisse

Um den EA zu testen, kompilieren Sie zunächst den Code mit MetaEditor. Nach der Kompilierung können Sie ihn auf einem Chart in MetaTrader 5 laufen lassen, um ihn live zu testen, oder ihn direkt mit dem Strategy Tester für Backtest-Zwecke ausführen. Ich habe diesen EA sowohl unter Live-Marktbedingungen als auch in historischen Backtests getestet. Dieser Prozess ist wichtig für die Feinabstimmung der EA-Parameter, um das gewünschte Handelsverhalten zu erreichen und die Leistung zu optimieren.

Der Chart in der Abbildung unten zeigt, wie der EA eine signifikante Marktumkehr anhand von Fraktalen und EMA-Indikatoren erkennt. Konkret erkennt der EA einen Abwärtsausbruch des Fraktals an einem wichtigen Unterstützungsniveau, das auf dem Chart visuell markiert ist. Die anschließende Kursbewegung bestätigt die Umkehr, denn der Markt setzt seine Abwärtsbewegung fort und passt sich dabei dem EMA-Trend an, wobei der EMA 14 unter den EMA 200 kreuzt, was auf einen Abwärtstrend hinweist. Die visuellen Hinweise, wie z.B. der „BEAR Break“-Marker, unterstützen disziplinierte Ein- und Ausstiegsentscheidungen. Dieses Ergebnis veranschaulicht die Fähigkeit des EA, frühe Anzeichen einer Trendumkehr zu erkennen, was es Händlern ermöglicht, Chancen mit hoher Wahrscheinlichkeit zu nutzen und gleichzeitig falsche Signale zu vermeiden.

Abb. 3. Bear Break auf Step Index

Das folgende GIF zeigt die Echtzeit-Erkennung und Bestätigung einer Trendumkehr durch den EA. Sie zeigt, wie das Indikatorsystem eine fraktale Unterstützungs- oder Widerstandsstufe identifiziert und einen potenziellen Ausbruch signalisiert, der den Händler dazu veranlasst, eine Position in Betracht zu ziehen. Wenn sich der Markt in die vorhergesagte Richtung bewegt, werden die Signale des EA durch die Ausrichtung der EMAs bestätigt; der EMA 14 kreuzt unter dem EMA 200, was den Abwärtstrend bestätigt. Die visuellen Hinweise, wie z. B. Pfeile und Warnmeldungen, zeigen, wie der EA eine rechtzeitige Entscheidungsfindung erleichtert. Dieses Beispiel unterstreicht die Bedeutung einer frühzeitigen Erkennung in Verbindung mit einer Trendbestätigung, die das Vertrauen in den Handel stärkt und die Wahrscheinlichkeit von Fehleinstiegen verringert.

Abb. 4. Backtest auf V75 (1s)


Schlussfolgerung

Dieser Expert Advisor nutzt die Leistungsfähigkeit des Fraktal-Indikators von Bill Williams sowie kurz- und langfristige exponentielle gleitende Durchschnitte, um Einstiegspunkte mit hoher Wahrscheinlichkeit zu ermitteln. Durch die Kombination dieser Instrumente werden frühzeitige Umkehrsignale erfasst, die gegen den vorherrschenden Markttrend bestätigt werden, was die Präzision und Konsistenz der Handelsausführung verbessert. Rigorose Backtests und Live-Tests haben seine Flexibilität unter verschiedenen Marktbedingungen bewiesen, und bei einer Feinabstimmung können seine Parameter für eine optimale Performance angepasst werden. Mit intuitiven Pfeilen und Beschriftungen auf dem Chart sowie vollautomatischer Orderplatzierung bringt dieser EA Disziplin und Geschwindigkeit in Ihre Handelsroutine. Im Wesentlichen bietet es einen systematischen, regelbasierten Rahmen für die Preisaktionsanalyse, ideal für Händler, die technische Strenge mit Automatisierung verbinden möchten.

In der nachstehenden Tabelle finden Sie unsere vorgestellten Tools.





   
Chart Projector
Analytical Comment
Analytics Master
Analytics Forecaster 
Volatility Navigator
Der Mean Reversion Signal Reaper
Signal Pulse 
Metrics Board 
External Flow
VWAP
Heikin Ashi   FibVWAP  
RSI DIVERGENCE
Parabolic Stop and Reverse (PSAR) 
Quarters Drawer Script
Intrusion Detector
TrendLoom Tool  Quarters Board 
ZigZag Analyzer  Correlation Pathfinder  Market Structure Flip Detector Tool
Correlation Dashboard   Currency Strength Meter 
PAQ Analysis Tool 
Pin Bar, Engulfing und RSI-Divergenz
Dual EMA Fractal Breaker        

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

Beigefügte Dateien |
Letzte Kommentare | Zur Diskussion im Händlerforum (3)
Delly Kabongo
Delly Kabongo | 4 Juni 2025 in 09:17
Interessanter Artikel, und danke für den EA-Quellcode. Ich werde ihn ausprobieren und Feedback geben.
Christian Benjamin
Christian Benjamin | 9 Juni 2025 in 19:54
Delly Kabongo #:
Interessanter Artikel, und danke für den EA-Quellcode. Ich werde ihn ausprobieren und Feedback geben.
Danke, dass Sie sich gemeldet haben. Ihr Feedback wird sehr geschätzt und ist immer willkommen.
ABEL OLUFEMI FAMODU
ABEL OLUFEMI FAMODU | 11 Juni 2025 in 20:29
Sehr interessanter Artikel. Es wird ein langer Weg zur Vereinfachung der Handelsstrategie gehen.
Datenwissenschaft und ML (Teil 41): Mustererkennung mit YOLOv8 im Forex und den Aktienmärkten Datenwissenschaft und ML (Teil 41): Mustererkennung mit YOLOv8 im Forex und den Aktienmärkten
Die Erkennung von Mustern auf den Finanzmärkten ist eine Herausforderung, denn dazu muss man sehen, was auf dem Chart zu sehen ist, und das ist in MQL5 aufgrund der Bildbeschränkungen schwierig zu bewerkstelligen. In diesem Artikel werden wir ein anständiges Modell in Python besprechen, das uns hilft, mit minimalem Aufwand Muster im Chart zu erkennen.
MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel MQL5-Handelswerkzeuge (Teil 3): Aufbau eines Multi-Timeframe Scanner Dashboards für den strategischen Handel
In diesem Artikel bauen wir ein Multi-Timeframe-Scanner-Dashboard in MQL5, um Handelssignale in Echtzeit anzuzeigen. Wir planen eine interaktive Gitterschnittstelle, implementieren Signalberechnungen mit mehreren Indikatoren und fügen eine Schaltfläche zum Schließen hinzu. Der Artikel schließt mit Backtests und strategischen Handelsvorteilen
Umstellung auf MQL5 Algo Forge (Teil 1): Erstellen des Haupt-Repositorys Umstellung auf MQL5 Algo Forge (Teil 1): Erstellen des Haupt-Repositorys
Bei der Arbeit an Projekten in MetaEditor stehen Entwickler oft vor der Notwendigkeit, Codeversionen zu verwalten. MetaQuotes kündigte kürzlich die Migration zu GIT und die Einführung von MQL5 Algo Forge mit Codeversionierung und Kollaborationsfunktionen an. In diesem Artikel wird erörtert, wie die neuen und bereits vorhandenen Tools effizienter genutzt werden können.
Entwicklung des Price Action Analysis Toolkit (Teil 24): Analyse-Tool zur Quantifizierung von Preisaktionen Entwicklung des Price Action Analysis Toolkit (Teil 24): Analyse-Tool zur Quantifizierung von Preisaktionen
Kerzenmuster bieten wertvolle Einblicke in potenzielle Marktbewegungen. Einige einzelne Kerzen signalisieren die Fortsetzung des aktuellen Trends, während andere, je nach ihrer Position innerhalb der Kursbewegung, Umkehrungen vorhersagen. In diesem Artikel wird ein EA vorgestellt, der automatisch vier wichtige Kerzen-Formationen identifiziert. In den folgenden Abschnitten erfahren Sie, wie dieses Tool Ihre Preis-Aktions-Analyse verbessern kann.