Einführung in MQL5 (Teil 25): Aufbau eines EAs, der mit Chart-Objekten handelt (II)
Einführung
Willkommen zurück zu Teil 25 der Serie Einführung in MQL5! Im vorangegangenen Artikel haben wir untersucht, wie die Kombination von manueller Chart-Analyse und automatisierter Handelsausführung mithilfe von Chart-Objekten die Lücke zwischen diskretionärem und automatisiertem Handel schließen kann. Dieses Projekt konzentrierte sich auf Unterstützungs- und Widerstandszonen, die mit dem Werkzeug Rechteck gezeichnet wurden.
Dieser Artikel ist eine Fortsetzung dieses Konzepts, wobei wir dieses Mal Trendlinien verwenden werden. Trendlinien gehören zu den am häufigsten verwendeten Techniken in der technischen Analyse und helfen Ihnen, die Richtung des Marktes sowie mögliche Ausbruchs- oder Umkehrpunkte zu bestimmen. Wir werden einen EA erstellen, der Trendlinien auf dem Chart erkennen kann und je nach Marktlage automatisch Handelsgeschäfte einleitet, wenn der Kurs diese Linien über- oder unterschreitet.
Wie der EA funktioniert
Der Nutzer zeichnet manuell zwei Trendlinien in den Chart, die der EA verwendet. Eine Linie, die einen Abwärtstrend anzeigt, wird von einem höheren Punkt zu einem niedrigeren Punkt gezogen, während eine andere Linie, die einen Aufwärtstrend anzeigt, von einem niedrigeren Punkt zu einer höheren Position gezogen wird. Die EA verwenden ihre Namen, um die entsprechenden Objekte auf dem Chart zu identifizieren. Dies setzt voraus, dass der Nutzer die genauen Namen der Trendlinien in die Eingabeeinstellungen eingibt. Selbst wenn es mehrere Trendlinien im Chart gibt, gibt diese Methode dem EA einen klaren Hinweis darauf, was er im Auge behalten muss.
Darüber hinaus hat der Nutzer die Möglichkeit, den Zeitrahmen, den der EA verfolgen soll, die Losgröße, die er verwenden möchte, und den Handelsstil, den er verwenden möchte, festzulegen. Zu den verfügbaren Handelsmodi gehören sowohl „Reversal“ und die Bedingungen für „Breakout and Retest“, bei denen der EA je nach Kursverhalten um die Trendlinie herum sowohl Umkehr- als auch Ausbruch- und Retest verarbeitet, als auch die „Reversal“, bei dem der EA ein Handelsgeschäft eröffnet, wenn der Kurs die Trendlinie berührt und ein Umkehrsignal anzeigt. Der Modus „Breakout and Retest“ wartet darauf, dass der Kurs die Trendlinie durchbricht, bevor er ein Handelsgeschäft eröffnet.

Für das Handelsmanagement setzt der EA automatisch das Stop-Loss (SL) und Take-Profit (TP) auf Basis der letzten geschlossenen Kerze.
- Bei einem Kauf wird der SL auf das Tief der zuletzt geschlossenen Kerze gesetzt,
- bei einem Verkauf wird der SL auf das Hoch der zuletzt geschlossenen Kerze gesetzt.
- Der Take Profit (TP) wird auf 1:4 des Abstands zwischen dem Einstiegskurs und dem Stop-Loss festgelegt.


Erkennen von Trendlinien
Der nächste Schritt besteht darin, herauszufinden, wie der EA die Trendlinien auf dem Chart erkennt, nachdem Sie nun genau wissen, wie er funktioniert. Der EA benötigt eine einfache Methode, um zwischen den Linien zu unterscheiden, die den Aufwärtstrend und den Abwärtstrend anzeigen, da er von den vom Nutzer gezeichneten Trendlinien abhängig ist.
Zu diesem Zweck werden Trendliniennamen verwendet. Die Namen, die der Nutzer in den Eingabeeinstellungen eingibt, werden vom EA für die Suche nach Chart-Elementen verwendet. Durch den Namensabgleich kann der EA jede Trendlinie auf dem Chart genau lokalisieren und ihre Positionen in Echtzeit verfolgen. Der EA reagiert nur auf die bestimmten Trendlinien, die der Nutzer festgelegt hat, auch wenn der Chart andere Linien oder Abbildungen enthält.
Beispiel:input string down_trend = ""; // Down Trend Line input string up_trend = ""; // Up Trend Line ulong chart_id = ChartID(); //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- ObjectSetInteger(chart_id,down_trend,OBJPROP_RAY_RIGHT,true); ObjectSetInteger(chart_id,up_trend,OBJPROP_RAY_RIGHT,true); }
Erläuterung:
Die Trendlinien des Charts müssen vom EA verstanden werden, bevor er sie erkennen und manipulieren kann. Zu diesem Zweck entwerfen wir Eingabefelder, in die der Nutzer die Namen der beiden Trendlinien eingeben kann. Eine Linie zeigt den Abwärtstrend an, während die andere den Anstieg symbolisiert. Selbst bei Vorhandensein zahlreicher anderer Zeichnungen oder Zeichen hilft diese Benennungstechnik dem EA, genau zu erkennen, welche Objekte auf der Karte sein Eigentum sind.

Der Chart, auf dem der EA arbeitet, muss ihm ebenfalls bekannt sein. Jedes Chart in MetaTrader 5 enthält eine Chart-ID, die eine spezielle Identifikationsnummer ist. Durch den Erhalt dieser ID stellt der EA sicher, dass er sich nur mit dem entsprechenden Chart und seinen Elementen befasst.
Die Verlängerung der Trendlinien auf der rechten Seite des Charts ist ein wesentlicher Bestandteil dieser Anordnung. Aufgrund dieser Änderung können sich die Trendlinien in zukünftige Preisregionen erstrecken und über ihre Ankerpunkte hinaus fortsetzen. Dies ist ein entscheidender Schritt, da er es dem EA ermöglicht, Preisinteraktionen mit Trendlinien zu erkennen, selbst nachdem sich neue Kerzen gebildet haben. Ohne diese Verlängerung würden die Linien an ihren Ankerpunkten anhalten, was es dem EA unmöglich macht, bevorstehende Ausbrüche oder Umkehrungen zu erkennen. Wenn sich der Markt verändert, garantiert die Ausweitung über die Ankerpunkte hinaus eine zuverlässige Signalerkennung und laufende Überwachung.

Abrufen von Kerzen- und Abwärtstrendlinien-Objektdaten
Damit der EA untersuchen kann, wie sich der Preis um die Trendlinien herum bewegt, müssen im nächsten Schritt sowohl Kerzen- als auch Trendliniendaten abgerufen werden. Die Kerzendaten für die letzten fünf Kerzen des Charts werden vom EA zuerst kopiert. Sie können allein anhand dieser jüngsten Kerzen erkennen, ob ein Ausbruch oder eine Umkehrung möglich ist.
Der EA sammelt die Trendliniendaten innerhalb des gleichen Fünf-Kerzen-Bereichs, nachdem er die Kerzendaten erhalten hat. Dabei werden nur die Trendlinienkurse berücksichtigt, die mit den jüngsten Kerzen übereinstimmen, und nicht die Ankerpunkte. Auf diese Weise kann der EA die aktuellen Kerzenbewegungen mit den genauen Preisniveaus der Trendlinien für denselben Zeitrahmen vergleichen.
Der EA kann erkennen, wann ein Kurs eine Trendlinie über- oder unterschreitet oder von ihr abweicht, indem er die Korrelation zwischen den Preisen der Trendlinie und den letzten fünf Kerzen untersucht. Diese Technik garantiert, dass der EA nur auf die jüngsten und relevantesten Marktbewegungen reagiert und verbessert die Genauigkeit des Erkennungsprozesses.
Analogie
Betrachten Sie den EA als aufmerksamen Wachhund auf dem Markt, ähnlich wie ein Detektiv, der einen Tatort untersucht. Jede Kerze stellt dar, was zu einem bestimmten Zeitpunkt preislich passiert ist, ähnlich wie ein Foto. Im Gegensatz dazu ähnelt die Trendlinie, die signifikante Grenzen anzeigt, einem Seil, das über das Chart gespannt ist.
Der EA prüft jede Kerze einzeln und achtet dabei besonders auf die letzten fünf. Es untersucht die Eigenschaften jeder Kerze sowie die genaue Position der Trendlinie zu diesem bestimmten Zeitpunkt. Dieses Verfahren ist so, als würde man zwei Fotos gleichzeitig betrachten, von denen eines die Bewegung der Kerze und das andere die Position der Trendlinie während dieser Bewegung zeigt.
Die EA beginnt mit ihrer Analyse, nachdem sie diese Daten gesammelt hat. Es stellen sich Fragen wie: Hat das Hoch oder Tief der Kerze die Trendlinie berührt? War sie darüber oder darunter, als die Fackel durchging? Gab es eine Auf- oder eine Abwärtskerze?
Ähnlich wie ein Händler einen Chart visuell inspizieren würde, um zu sehen, wann der Preis eine Linie berührt oder durchbricht, kann der EA nachvollziehen, wie die Kerze mit der Trendlinie interagiert hat, indem er diese beiden Informationen nebeneinander vergleicht.
Beispiel:input string down_trend = ""; // Down Trend Line input string up_trend = ""; // Up Trend Line input ENUM_TIMEFRAMES time_frame = PERIOD_CURRENT; // TIME FRAME ulong chart_id = ChartID(); double close_price[]; double open_price[]; double low_price[]; double high_price[]; datetime time_price[]; double td_line_value; double td1_line_value; double td2_line_value; double td3_line_value; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArraySetAsSeries(close_price, true); ArraySetAsSeries(open_price, true); ArraySetAsSeries(low_price, true); ArraySetAsSeries(high_price, true); ArraySetAsSeries(time_price, true); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- ObjectSetInteger(chart_id,down_trend,OBJPROP_RAY_RIGHT,true); ObjectSetInteger(chart_id,up_trend,OBJPROP_RAY_RIGHT,true); CopyOpen(_Symbol, time_frame, 1, 5, open_price); CopyClose(_Symbol, time_frame, 1, 5, close_price); CopyLow(_Symbol, time_frame, 1, 5, low_price); CopyHigh(_Symbol, time_frame, 1, 5, high_price); CopyTime(_Symbol, time_frame, 1, 5, time_price); //DOWN TREND td_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[0],0); td1_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[1],0); td2_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[2],0); td3_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[3],0); }
Erläuterung:
In diesem ersten Schritt legt das Programm den Zeitbereich fest, in dem es laufen soll, und bereitet sich darauf vor, Kerzeninformationen in leeren Containern zu speichern. Die Eröffnungs-, Schluss-, Höchst- und Tiefstkurse jeder Kerze sowie der genaue Zeitpunkt, zu dem die Kerze auf dem Chart erschienen ist, werden anschließend in diesen Containern gespeichert. Mit dieser Konfiguration wird vor Beginn der Analyse sichergestellt, dass das Programm umfassende und gut strukturierte Preisdaten vom Markt erhalten kann.
double td_line_value; double td1_line_value; double td2_line_value; double td3_line_value;
In dieser Phase werden Speicherplätze für numerische Daten eingerichtet, die die Lage der Trendlinie zu bestimmten Zeitpunkten anzeigen. Anhand dieser Zahlen vergleicht der Computer die Entwicklung des Marktpreises mit der Abwärtslinie im Chart. Die Container werden dann so angeordnet, dass die neuesten Informationen zuerst erscheinen. Der Computer kann nun die jüngsten Marktaktivitäten leichter analysieren, da er sofort auf die neuesten Kerzen zugreifen kann und nicht erst ältere Daten durchsuchen muss. Außerdem wird sichergestellt, dass deshalb alle Container vor der Entgegennahme der Marktwerte ordnungsgemäß geordnet werden.
Das Programm sammelt dann Informationen über die letzten fünf Kerzen. Es werden sowohl die Preise als auch die Zeiten, zu denen sie in der Tabelle angezeigt wurden, erfasst. Das Programm kann die Kursbewegungen um die Trendlinie überwachen und anhand dieser kurzen Kerzenserie feststellen, ob sich ein Ausbruchs- oder Umkehrmuster entwickelt.
td_line_value = ObjectGetValueByTime(chart_id, down_trend, time_price[0], 0); td1_line_value = ObjectGetValueByTime(chart_id, down_trend, time_price[1], 0); td2_line_value = ObjectGetValueByTime(chart_id, down_trend, time_price[2], 0); td3_line_value = ObjectGetValueByTime(chart_id, down_trend, time_price[3], 0);
Jede Linie erhält den Kurswert der Trendlinie zu einer bestimmten Kerzenzeit. Mit dem ersten Parameter wird der Funktion mitgeteilt, welches Chart untersucht werden soll. Der zweite Parameter gibt außerdem den Namen des Objekts (in diesem Fall die Abwärtstrendlinie), den genauen Zeitpunkt der Untersuchung (entsprechend der Bildung jeder Kerze) und das Chart-Fenster (wobei 0 das HauptpreisChart bezeichnet) an.
Vereinfacht ausgedrückt, prüft diese Funktion, wo die Trendlinie genau zum Zeitpunkt des Erscheinens jeder Kerze lag. Der EA kann dann den Höchst-, Tiefst- oder Schlussstand der Kerze mit der Position der Linie vergleichen, da er das Kursniveau der Linie zu diesem Zeitpunkt zurückgibt. Dies hilft bei der Identifizierung von Ausbruchs- oder Umkehrsituationen, da man so feststellen kann, ob die Kerze die Trendlinie berührt oder überschritten hat.
Erkennen von Umkehrungen in einen Abwärtstrend
Der nächste Schritt ist das Aufspüren einer Trendwende nach unten, die auf eine Verkaufsmöglichkeit hinweist. In diesem Fall wird der EA die Interaktion zwischen der Abwärtstrendlinie und den jüngsten Kerzen im Auge behalten. Der EA stellt fest, ob eine Kerze unterhalb der Linie schließt und damit eine potenzielle Umkehr signalisiert, wenn sich der Kurs dieser Linie nähert oder sie berührt. Dieses Verhalten ist ein mögliches Zeichen für eine Verkaufstransaktion, da es darauf hindeutet, dass die Verkäufer wieder die Kontrolle über den Markt übernehmen.
Aber es ist wichtig, dass Sie nicht zu viel handeln oder Indikationen duplizieren. Der EA prüft zunächst, ob es in den letzten paar Balken kein neues Handelssignal gegeben hat, bevor er dies tut. Dies stellt sicher, dass das Programm nur auf neue Setups reagiert und verhindert, dass es in derselben kurzen Zeitspanne redundante oder unnötige Handelsgeschäfte eröffnet.
Beispiel:
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- ObjectSetInteger(chart_id,down_trend,OBJPROP_RAY_RIGHT,true); ObjectSetInteger(chart_id,up_trend,OBJPROP_RAY_RIGHT,true); CopyOpen(_Symbol, time_frame, 1, 5, open_price); CopyClose(_Symbol, time_frame, 1, 5, close_price); CopyLow(_Symbol, time_frame, 1, 5, low_price); CopyHigh(_Symbol, time_frame, 1, 5, high_price); CopyTime(_Symbol, time_frame, 1, 5, time_price); //DOWN TREND td_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[0],0); td1_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[1],0); td2_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[2],0); td3_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[3],0); bool prev_touch_down = false; if((high_price[1] > td1_line_value && close_price[1] < open_price[1]) || (high_price[2] > td2_line_value && close_price[2] < open_price[2]) ) { prev_touch_down = true; } int no_bars_down = 0; for(int i = 0; i <= 3; i++) { if(high_price[i] > ObjectGetValueByTime(chart_id,down_trend,time_price[i],0) && open_price[i] < ObjectGetValueByTime(chart_id,down_trend,time_price[i],0)) { for(int j = i; j >= 0; j--) { if(close_price[j] < open_price[j] && close_price[j] < ObjectGetValueByTime(chart_id,down_trend,time_price[j],0)) { no_bars_down = Bars(_Symbol,time_frame,time_price[j],TimeCurrent()); break; } } break; } } }
Erläuterung:
bool prev_touch_down = false; if((high_price[1] > td1_line_value && close_price[1] < open_price[1]) || (high_price[2] > td2_line_value && close_price[2] < open_price[2]) ) { prev_touch_down = true; }
In der ersten Zeile wird eine Variable als false initialisiert. Diese Variable dient als Marker, der anzeigt, ob eine rückläufige Kerze kürzlich auf eine gültige Berührung der Abwärtstrendlinie gefolgt ist. Da zu Beginn keine solche Bedingung gefunden wurde, ist das Kennzeichen immer noch falsch. Das Konzept besteht darin, dass diese Variable auf true aktualisiert wird, wenn das System eine rückläufige Reaktion auf die Trendlinie bestätigt. Diese Variable kann dann verwendet werden, um weitere Handelsaktionen zu steuern, einschließlich der Vermeidung mehrerer oder wiederholter Verkaufssignale innerhalb eines kurzen Zeitraums.
Die Bedingung der if-Anweisung prüft zwei aktuelle Kerzen, um zu sehen, ob eine von ihnen die Umkehrbedingungen erfüllt. (high_price[1] > td1_line_value && close_price[1] < open_price[1]) ist der erste Teil der Bedingung, der die Kerze betrachtet, die unmittelbar vor der aktuellen geschlossen wurde. Sie bestimmt, ob die Spitze der Kerze die Trendlinie zu diesem Zeitpunkt überquert hat, was bedeutet, dass der Kurs die Linie berührt oder geringfügig durchbrochen hat. Die Kerze wird dann als Abwärtskerze bestätigt, wenn sie tiefer schließt als sie eröffnet wurde. Um die Trendlinie zu testen, könnten die Käufer den Kurs nach oben getrieben haben, aber die Verkäufer übernahmen wieder die Kontrolle und drückten den Markt nach unten, sodass ein Ablehnungsdocht darüber zurückblieb.
Um frühere Ablehnungen zu erfassen, wird im zweiten Abschnitt die Kerze von vor zwei Takten untersucht. Sie gilt als rechtmäßig, wenn eine der beiden Kerzen die Ablehnungskriterien erfüllt.
Der in geschweiften Klammern eingeschlossene Code ändert den Wert des Flags auf true, wenn die Bedingung sich als zutreffend erweist. Diesem Bericht zufolge hat der Markt bereits negativ auf die Abwärtstrendlinie reagiert. Diese Markierung kann später im Programm als Schutzmaßnahme verwendet werden, um ein Überhandeln zu verhindern, indem sichergestellt wird, dass wiederholte Berührungen an derselben Stelle das System nicht dazu veranlassen, zusätzliche Verkaufssignale zu erzeugen.
Zusammenfassend lässt sich sagen, dass dieser Codeblock dabei hilft, ein legitimes Umkehrsignal für einen Abwärtstrend zu erkennen. Wenn sich eine Kerze der Trendlinie von unten nähert, sie berührt und als Abwärtskerze schließt, wird dies bestätigt. Das Programm legt den Grundstein für eine diszipliniertere Handelsausführung, indem es dieses Verhalten identifiziert und kennzeichnet. Auf diese Weise werden Abwärts-Umkehrungen nur dann bestätigt, wenn die Kursbewegung die Trendlinie eklatant verletzt, und überflüssige Doppelsignale werden vermieden.
int no_bars_down = 0; for(int i = 0; i <= 3; i++) { if(high_price[i] > ObjectGetValueByTime(chart_id,down_trend,time_price[i],0) && open_price[i] < ObjectGetValueByTime(chart_id,down_trend,time_price[i],0)) { for(int j = i; j >= 0; j--) { if(close_price[j] < open_price[j] && close_price[j] < ObjectGetValueByTime(chart_id,down_trend,time_price[j],0)) { no_bars_down = Bars(_Symbol,time_frame,time_price[j],TimeCurrent()); break; } } break; } }
int no_bars_down = 0; wird verwendet, um einen Zähler am Anfang des Codes auf Null zu initialisieren. Die Anzahl der Balken, die seit dem letzten rechtmäßigen Berühren und Verwerfen der Abwärtstrendlinie verstrichen sind, wird anschließend von diesem Zähler erfasst. Die Schleife betrachtet die letzten vier Kerzen, um zu sehen, ob der Eröffnungskurs noch unter der Trendlinie liegt und der Höchststand jeder Kerze diese überschritten hat. Dies erleichtert die Erkennung von Kerzen, die die Trendlinie von unten berührt haben, was ein erstes Anzeichen für eine mögliche Umkehr ist.
Nachdem das Programm eine solche Kerze entdeckt hat, sucht es nach der ersten Kerze, die unter der Trendlinie schließt und eine Abwärtskerze ist. In dieser Phase wird das Signal für eine mögliche Verkaufsgelegenheit validiert, indem bestätigt wird, dass der Markt die Trendlinie abgelehnt hat. Das Programm ermittelt die Anzahl der Balken, die seit der bestätigenden Kerze bis zum jetzigen Zeitpunkt verstrichen sind. Diese Zählung hilft dabei, wiederholte oder doppelte Ausschreibungen zu vermeiden. Der EA stellt sicher, dass er neue Handelsgelegenheiten erst dann in Betracht zieht, wenn eine ausreichende Marktbewegung stattgefunden hat, indem er die Anzahl der Balken seit der letzten gültigen Ablehnung verfolgt. Dadurch wird das Overtrading deutlich reduziert.
Hinzufügen der Eingabebedingungen
Der nächste Schritt ist das Hinzufügen der Einstiegsbedingung für den Verkaufshandel. Der EA kann nun die genauen Umstände festlegen, unter denen er eine Position erstellt, nachdem er überprüft hat, dass die Umkehrung des Abwärtstrends stattgefunden hat und sichergestellt hat, dass zuvor kein neues Signal ausgelöst wurde. Um sicherzustellen, dass nur legitime Setups den Handel einleiten, werden der Kontakt mit der Trendlinie, die Bestätigung der Abwärtskerze und die Anzahl der Balken seit dem letzten Signal kombiniert. Der EA kann methodisch in den Markt einsteigen und Overtrading verhindern, indem er diese Einstiegsregeln aufstellt, die garantieren, dass jeder Handel mit dem Umkehrmuster des Charts übereinstimmt.
Beispiel:
#include <Trade/Trade.mqh> CTrade trade; int MagicNumber = 53217;
datetime lastTradeBarTime = 0; double ask_price; double take_profit;
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- ArraySetAsSeries(close_price, true); ArraySetAsSeries(open_price, true); ArraySetAsSeries(low_price, true); ArraySetAsSeries(high_price, true); ArraySetAsSeries(time_price, true); trade.SetExpertMagicNumber(MagicNumber); //--- return(INIT_SUCCEEDED); }
ask_price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); datetime currentBarTime = iTime(_Symbol, time_frame, 0); if(((high_price[1] >= td1_line_value && open_price[1] < td1_line_value) || (high_price[2] >= td2_line_value && open_price[2] < td2_line_value) || (high_price[3] >= td3_line_value && open_price[3] < td3_line_value) || (high_price[0] >= td_line_value)) && (close_price[0] < td_line_value && close_price[0] < open_price[0] && open_price[1] < td1_line_value) && (no_bars_down < 3) && prev_touch_down == false && (currentBarTime != lastTradeBarTime) ) { take_profit = MathAbs(ask_price - ((high_price[0] - ask_price) * 4)); trade.Sell(lot_size,_Symbol,ask_price, high_price[0], take_profit); lastTradeBarTime = currentBarTime; }
Erläuterung:
Die Standard-Handelsbibliothek für MQL5 ist in der ersten Zeile enthalten, #include <Trade/Trade.mqh>. Die Funktionen und Klassen, die zur Durchführung von Handelsgeschäften, zur Änderung von Aufträgen und zur Aufrechterhaltung von Positionen erforderlich sind, werden dem EA durch diese Bibliothek zur Verfügung gestellt. Der EA verwendet die Instanz des Handelsobjekts, das von der CTrade-Linie erstellt wurde, um Aufträge auf methodische und sichere Weise zu platzieren.
int MagicNumber = 53217; definiert die magische Zahl. Dies ist eine spezielle Nummer, die mit jedem Handelsgeschäft verknüpft ist, das dieser EA eröffnet. Dank SetExpertMagicNumber (MagicNumber) kann der EA seine Handelsgeschäfte von manuellen Handelsgeschäften oder von Handelsgeschäften, die von anderen EAs eröffnet wurden, unterscheiden. Dies ist unerlässlich, um Positionen zu verwalten, sie zu ändern oder später zu schließen, ohne andere Geschäfte zu beeinflussen.
Die Eingabe double lot_size = 0.6; wird verwendet, um die Handelsgröße zu definieren. Dies ermöglicht es dem Nutzer, die Größe der einzelnen Handelsgeschäfte direkt von den Eingabeeinstellungen aus zu ändern. datetime currentBarTime = iTime(_Symbol, time_frame, 0); speichert den Zeitpunkt der letzten Kerze, und ask_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); ruft den aktuellen Briefkurs des Marktes ab. Mit diesen Werten können Sie den Einstiegskurs festlegen, den Take-Profit bestimmen und verhindern, dass mehrere Handelsgeschäfte während derselben Kerze erfolgen.
(high_price[1] >= td1_line_value && open_price[1] < td1_line_value) || (high_price[2] >= td2_line_value && open_price[2] < td2_line_value) || (high_price[3] >= td3_line_value && open_price[3] < td3_line_value) || (high_price[0] >= td_line_value)
Diese Linie bestimmt, ob eine der jüngsten Kerzen mit der Abwärtstrendlinie in Berührung gekommen ist oder sie auch nur geringfügig überschritten hat. (high_price[1] >= td1_line_value && open_price[1] < td1_line_value, zum Beispiel) bestätigt, dass der Höchststand der Kerze vor einem Balken über der Trendlinie lag, die Eröffnung aber darunter. Dies zeugt von der Annäherung des Kurses an die Trendlinie und der daraus resultierenden möglichen Umkehrsituation. Für die vorherigen zwei und drei Balken wie für die aktuelle Kerze gelten die gleichen Überlegungen. Durch die Verwendung des logischen ODER-Operators ist gewährleistet, dass die Bedingung erfüllt ist, wenn eine der Kerzen diese Bedingung erfüllt.
Die Bedingung, die eine endgültige Abwärts-Ablehnung bestätigt, wurde dann hinzugefügt, indem sowohl die aktuelle als auch die vorherige Kerze untersucht wurden. Er deutet darauf hin, dass die Verkäufer an Stärke gewonnen haben und die Dynamik nachlässt, und sorgt dafür, dass die jüngste Kerze unterhalb der Trendlinie schließt. Außerdem muss die Kerze tiefer schließen als sie begonnen hat, um als Abwärtskerze zu gelten. Damit die Preisstruktur stabil bleibt und das Umkehrsignal präziser wird, muss die vorherige Kerze ebenfalls unterhalb der Trendlinie eröffnet haben.
Diese Bedingung garantiert, dass eine Abwärts-Trendwende durch die jüngste Kerze bestätigt wird. Sie bestätigt, dass die Kerze unterhalb der Trendlinie geschlossen hat, was auf einen Rückgang des Momentums und die Übernahme durch die Verkäufer hinweist. Der Abwärtsdruck wird bestätigt, wenn die Kerze tiefer schließt als sie begonnen hat. Damit die vorherige Kerze ein stetiges Abwärtsmuster beibehalten hätte, hätte sie unterhalb der Trendlinie eröffnen müssen. In Kombination helfen diese Bedingungen dabei, Fehleinstiege durch vorübergehende Kursschwankungen zu verhindern und die Gültigkeit des Umkehrsignals zu erhöhen.
Die Bedingung (currentBarTime!= lastTradeBarTime) sorgt durch den Vergleich der aktuellen Kerzenzeit mit der Zeit des zuletzt durchgeführten Handels dafür, dass der EA nicht mehrere Handelsgeschäfte für dieselbe Kerze eröffnet und somit nur einen Einstieg pro Balken zulässt. Der EA bestimmt den Take-Profit, sobald alle Einstiegsbedingungen erfüllt sind, indem er die absolute Differenz zwischen dem aktuellen Briefkurs und dem Höchststand der Bestätigungskerze mit vier multipliziert, um ein positives Risiko-Ertrags-Verhältnis zu ermitteln.
Unter Verwendung der festgelegten Losgröße, des Symbols, des Einstiegskurses, des Stop-Loss auf dem Höchststand der Bestätigungskerze und des berechneten Take-Profits wird die Verkaufstransaktion ausgeführt. Um eine disziplinierte und methodische Handelsausführung zu gewährleisten, aktualisiert der EA die lastTradeBarTime auf den Zeitpunkt der aktuellen Kerze, sobald die Transaktion platziert wurde. Dadurch werden zahlreiche Abschlüsse auf demselben Balken verhindert.
Der EA muss dann entscheiden können, ob er einen Ausbruch mit Retest oder eine einfache Umkehrung handeln will. Obwohl wir uns bisher nur mit der Situation der Umkehrung des Abwärtstrends befasst haben, können Sie sehen, wie der EA ein legitimes Umkehrsignal bestimmt, indem Sie die Bedingungen durchgehen, die wir gerade überprüft haben. Sobald die Umkehrlogik vollständig etabliert ist, können diese identischen Ideen modifiziert werden, um eine Breakout-and-Retest-Technik zu handhaben.
Beispiel:
input string down_trend = ""; // Down Trend Line input string up_trend = ""; // Up Trend Line input ENUM_TIMEFRAMES time_frame = PERIOD_CURRENT; // TIME FRAME input double lot_size = 0.6; // LOT SIZE enum line_type { reversal = 0, //REVERSAL break_out = 1, //BREAK-OUT reverse_break = 2 // REVERSAL AND BREAK-OUT }; input line_type line_exe = reversal; // MODE
if(((high_price[1] >= td1_line_value && open_price[1] < td1_line_value) || (high_price[2] >= td2_line_value && open_price[2] < td2_line_value) || (high_price[3] >= td3_line_value && open_price[3] < td3_line_value) || (high_price[0] >= td_line_value)) && (close_price[0] < td_line_value && close_price[0] < open_price[0] && open_price[1] < td1_line_value) && (no_bars_down < 3) && prev_touch_down == false && (currentBarTime != lastTradeBarTime) && (line_exe == reversal || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price - ((high_price[0] - ask_price) * 4)); trade.Sell(lot_size,_Symbol,ask_price, high_price[0], take_profit); lastTradeBarTime = currentBarTime; }
Ausgabe:

Identifizierung von Abwärtstrendausbruch und Wiederholungstest
Der EA wartet zunächst darauf, dass eine Kerze oberhalb der Abwärtstrendlinie schließt, was darauf hindeutet, dass der vorherige Widerstand durchbrochen wurde, bevor er ein Ausbruchs- und Wiederholungs-Setup mit dem Ziel eines Kaufs ausführt. Der EA beginnt jedoch nicht sofort mit dem Handel. Er wartet auf einen erneuten Test, bei dem der Kurs die durchbrochene Trendlinie berührt und zu ihr zurückkehrt, was darauf hindeutet, dass der vorherige Widerstand nun als Unterstützung dient.
Nach der Bestätigung des Retests sucht der EA nach einer Aufwärtskerze, die auf die Berührung folgt. Diese Aufwärts-Bestätigung bestätigt den Einstiegspunkt und zeigt, dass die Käufer die Oberhand gewinnen. Der EA löst einen Kaufauftrag aus, wenn diese drei Kriterien erfüllt sind: ein Ausbruch, eine Berührung als Retest und eine bestätigende Aufwärtskerze. Indem sichergestellt wird, dass nur dann gehandelt wird, wenn der Ausbruch durch eine Kursbewegung bestätigt wird, trägt diese Strategie dazu bei, einen zu frühen Einstieg zu verhindern und die Wahrscheinlichkeit falscher Ausbrüche zu verringern.
Beispiel:
td_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[0],0); td1_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[1],0); td2_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[2],0); td3_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[3],0); bool prev_touch_down = false; if((high_price[1] > td1_line_value && close_price[1] < open_price[1]) || (high_price[2] > td2_line_value && close_price[2] < open_price[2]) ) { prev_touch_down = true; } int no_bars_down = 0; for(int i = 0; i <= 3; i++) { if(high_price[i] > ObjectGetValueByTime(chart_id,down_trend,time_price[i],0) && open_price[i] < ObjectGetValueByTime(chart_id,down_trend,time_price[i],0)) { for(int j = i; j >= 0; j--) { if(close_price[j] < open_price[j] && close_price[j] < ObjectGetValueByTime(chart_id,down_trend,time_price[j],0)) { no_bars_down = Bars(_Symbol,time_frame,time_price[j],TimeCurrent()); break; } } break; } } //DOWN TREND td_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[0],0); td1_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[1],0); td2_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[2],0); td3_line_value = ObjectGetValueByTime(chart_id,down_trend,time_price[3],0); bool prev_touch_down = false; if((high_price[1] > td1_line_value && close_price[1] < open_price[1]) || (high_price[2] > td2_line_value && close_price[2] < open_price[2]) ) { prev_touch_down = true; } int no_bars_down = 0; for(int i = 0; i <= 3; i++) { if(high_price[i] > ObjectGetValueByTime(chart_id,down_trend,time_price[i],0) && open_price[i] < ObjectGetValueByTime(chart_id,down_trend,time_price[i],0)) { for(int j = i; j >= 0; j--) { if(close_price[j] < open_price[j] && close_price[j] < ObjectGetValueByTime(chart_id,down_trend,time_price[j],0)) { no_bars_down = Bars(_Symbol,time_frame,time_price[j],TimeCurrent()); break; } } break; } ask_price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); datetime currentBarTime = iTime(_Symbol, time_frame, 0); if(((high_price[1] >= td1_line_value && open_price[1] < td1_line_value) || (high_price[2] >= td2_line_value && open_price[2] < td2_line_value) || (high_price[3] >= td3_line_value && open_price[3] < td3_line_value) || (high_price[0] >= td_line_value)) && (close_price[0] < td_line_value && close_price[0] < open_price[0] && open_price[1] < td1_line_value) && (no_bars_down < 3) && prev_touch_down == false && (currentBarTime != lastTradeBarTime) && (line_exe == reversal || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price - ((high_price[0] - ask_price) * 4)); trade.Sell(lot_size,_Symbol,ask_price, high_price[0], take_profit); lastTradeBarTime = currentBarTime; } // DOWNTREND BREAKOUT AMD RETEST bool prev_touch_break_out_down = false; if((low_price[1] < td1_line_value && close_price[1] > open_price[1]) || (low_price[2] < td2_line_value && close_price[2] > open_price[2] && open_price[2] > td2_line_value)) { prev_touch_break_out_down = true; } int no_bars_down_breakout = 0; for(int i = 0; i <= 3; i++) { if(low_price[i] < ObjectGetValueByTime(chart_id, down_trend, time_price[i], 0) && open_price[i] > ObjectGetValueByTime(chart_id, down_trend, time_price[i], 0)) { for(int j = i; j >= 0; j--) { if(close_price[j] > open_price[j] && close_price[j] > ObjectGetValueByTime(chart_id, down_trend, time_price[j], 0)) { no_bars_down_breakout = Bars(_Symbol, time_frame, time_price[j], TimeCurrent()); break; } } break; } } if( ((low_price[0] < td_line_value && open_price[0] > td_line_value) || (low_price[1] < td1_line_value && open_price[1] > td1_line_value) || (low_price[2] < td2_line_value && open_price[2] > td2_line_value) || (low_price[3] < td3_line_value && open_price[3] > td3_line_value)) && (close_price[0] > open_price[0]) && close_price[0] > td_line_value && (no_bars_down_breakout < 3) && (prev_touch_break_out_down == false) && (currentBarTime != lastTradeBarTime) && (line_exe == break_out || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price + ((ask_price - low_price[0]) * 4)); trade.Buy(lot_size, _Symbol, ask_price, low_price[0], take_profit); lastTradeBarTime = currentBarTime; }
Erläuterung:
Im ersten Abschnitt des Codes wird ein boolesches Flag definiert, um zu überwachen, ob bereits eine kürzliche Breakout-and-Retest-Interaktion auf dem Abwärtstrend stattgefunden hat. Mit diesem Flag kann der EA verhindern, dass das gleiche Setup weitere Handelsgeschäfte generiert. Bei der nächsten Anforderung wird anhand der letzten Kerzen festgestellt, ob ein Ausbruchsszenario bereits begonnen hat.
Außerdem wird geprüft, ob die Kerze oberhalb der Trendlinie eröffnet wurde, um zu bestätigen, dass der Kurs die Trendlinie durchbrochen und erneut getestet hat. Um zu verhindern, dass der EA zu häufig mehrere Handelsgeschäfte eröffnet, zählt ein Zähler die Anzahl der Balken seit dem letzten Ausbruch, und ein Flag wird gesetzt, um zu signalisieren, dass ein Ausbruchsversuch bereits stattgefunden hat.
Der Ausbruchspunkt wird dann durch Iteration der letzten Kerzen in der Hauptschleife bestimmt. Zunächst wird nach einer Kerze gesucht, bei der der Eröffnungskurs über und der Tiefstkurs unter der Trendlinie lag. Dies deutet auf die erste Durchdringung der Trendlinie hin, die die Vorstufe eines Ausbruchs darstellt. Nach der Entdeckung einer solchen Kerze sucht eine verschachtelte Schleife rückwärts nach einer nachfolgenden Kerze, die oberhalb der Trendlinie schließt und nach oben gerichtet ist. Dies zeigt, dass sich die Trendlinie tatsächlich vom Widerstand zur Unterstützung bewegt hat und dass der Ausbruch legitim ist. Beide Schleifen werden gestoppt, um unnötige zusätzliche Überprüfungen zu vermeiden, sobald diese Bestätigung erfolgt ist, und der Zähler wird so angepasst, dass er die Anzahl der Balken seit dem Durchbruch widerspiegelt.
Dieses Breakout-and-Retest-Muster unterscheidet sich erheblich von einer Umkehrung. Der EA sucht nach einer Abwärtskerze, die die Trendlinie von unten berührt, um eine Ablehnung während einer Umkehr anzuzeigen. Bei der Breakout-and-Retest-Strategie wartet der EA auf eine Kerze, die über die Abwärtstrendlinie bricht, gefolgt von einem Retest und einer Aufwärtskerze, die den Trend bestätigt. Das Breakout-Setup eignet sich für Handelsgeschäfte, die auf eine verifizierte Richtungsänderung des Marktes folgen, da der Schwerpunkt eher auf der Gewinnung von Momentum nach dem Durchbrechen der Trendlinie als auf dem Abfangen einer Preisablehnung liegt.
if( ((low_price[0] < td_line_value && open_price[0] > td_line_value) || (low_price[1] < td1_line_value && open_price[1] > td1_line_value) || (low_price[2] < td2_line_value && open_price[2] > td2_line_value) || (low_price[3] < td3_line_value && open_price[3] > td3_line_value)) && (close_price[0] > open_price[0]) && close_price[0] > td_line_value && (no_bars_down_breakout < 3) && (prev_touch_break_out_down == false) && (currentBarTime != lastTradeBarTime) && (line_exe == break_out || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price + ((ask_price - low_price[0]) * 4)); trade.Buy(lot_size, _Symbol, ask_price, low_price[0], take_profit); lastTradeBarTime = currentBarTime; }
Der erste Abschnitt der Bedingung bestimmt, ob die Abwärtstrendlinie durchbrochen wurde. Dabei werden die jüngsten Kerzen betrachtet, um festzustellen, ob eine von ihnen eine Eröffnung oberhalb der Trendlinie und ein Tief hatte, das unter diese fiel. Dies deutet auf einen möglichen Durchbruch hin, da die Kerze die Trendlinie von oben durchbrochen hat. Der Mechanismus ermöglicht verzögerte Bestätigungen, indem er sicherstellt, dass der EA zusätzlich zur aktuellen Kerze auch Ausbruchsberührungen an den drei vorangegangenen Kerzen erkennt.
Es folgt die Bedingung (close_price[0] > open_price[0]). Die aktuelle ist eine Aufwärtskerze und hat oberhalb der Trendlinie geschlossen if && close_price[0] > td_line_value. Die Tatsache, dass die Käufer das Sagen haben und die Trendlinie von Widerstand auf Unterstützung umgeschlagen ist, ist eine Bestätigung für den Ausbruch.
Indem es die Anzahl der Balken seit dem letzten bestätigten Setup verfolgt, stellt es sicher, dass die Handelsgeschäfte nicht zu nahe an einem früheren Ausbruch getätigt werden. Dies ermöglicht es dem EA, sich auf neue Möglichkeiten zu konzentrieren und von Overtrading Abstand zu nehmen. Indem überprüft wird, dass kein kürzlicher Ausbruchsversuch aufgezeichnet wurde, werden auch doppelte Transaktionen mit demselben Kursverlauf vermieden. Schließlich wird überprüft, ob nicht bereits ein Handelsgeschäft innerhalb desselben Balkens getätigt wurde, um sicherzustellen, dass nur ein Handelsgeschäft pro Kerze ausgeführt wird.
Es wird überprüft, ob sich der EA in einem Modus befindet, der Ausbruchsgeschäfte ermöglicht, entweder allein oder mit Umkehrungen. Unter Verwendung eines günstigen Risiko-Ertrags-Verhältnisses berechnet der EA den Take-Profit auf der Grundlage des Abstands zwischen dem aktuellen Kurs und dem Tiefpunkt der Bestätigungskerze, sobald alle Handelsanforderungen erfüllt sind. Danach führt es eine Kauftransaktion mit der angegebenen Lotgröße aus, weist den berechneten Take-Profit zu, setzt den Stop-Loss auf den Tiefpunkt der Ausbruchskerze und protokolliert die Handelszeit, um doppelte Eingaben bei derselben Kerze zu vermeiden.
Ausgabe:

Erkennen einer Trendwende nach oben
Das Auffinden von Umkehrmöglichkeiten auf einer aufsteigenden Trendlinie ist der nächste Schritt, nachdem man gelernt hat, wie man Breakout-and-Retest- und Umkehr-Setups auf einer absteigenden Trendlinie erkennt. Die Argumentation des Aufwärtstrends ist im Grunde das Gegenteil eines Abwärtstrends. Die Trendlinie zeigt an, dass es mehr Unterstützung als Ablehnung gibt. Wenn das Tief einer aktuellen Kerze die Aufwärtstrendlinie berührt oder sich ihr nähert und eine Aufwärtskerze oberhalb ihrer Eröffnung schließt, ist dies ein legitimes Umkehrsignal. Dies deutet auf eine mögliche Kaufgelegenheit hin, da es zeigt, dass der Preis die Unterstützung getestet hat und die Käufer beginnen, Boden zu gewinnen.
Um zu vermeiden, dass mehrere Handelsgeschäfte aus demselben Unterstützungs-Test heraus getätigt werden, stellt der EA sicher, dass keine neuen Signale generiert wurden, ähnlich wie bei der Umkehrung des Abwärtstrends. Durch den Vergleich des Zeitpunkts der aktuellen Kerze mit dem Zeitpunkt des letzten Handels stellt es außerdem sicher, dass nur ein Handel pro Kerze zulässig ist. Der EA ist in der Lage, ein konsistentes Risikomanagement zu betreiben und Overtrading zu vermeiden, während er methodisch Aufwärtstrendumkehrungen identifiziert, indem er die Logik der Abwärtstrendumkehrung repliziert.
Beispiel:
double t_line_value; double t1_line_value; double t2_line_value; double t3_line_value;
// UP TREND t_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[0],0); t1_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[1],0); t2_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[2],0); t3_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[3],0); int no_bars_up = 0; for(int i = 0; i <= 3; i++) { if(low_price[i] < ObjectGetValueByTime(chart_id, up_trend, time_price[i], 0) && open_price[i] > ObjectGetValueByTime(chart_id, up_trend, time_price[i], 0)) { for(int j = i; j >= 0; j--) { if(close_price[j] > open_price[j] && close_price[j] > ObjectGetValueByTime(chart_id, up_trend, time_price[j], 0)) { no_bars_up = Bars(_Symbol, time_frame, time_price[j], TimeCurrent()); break; } } break; } } bool prev_touch_up = false; if((low_price[1] < t1_line_value && close_price[1] > open_price[1]) || (low_price[2] < t2_line_value && close_price[2] > open_price[2])) { prev_touch_up = true; // Flag that a recent touch already occurred } if( ((low_price[0] < t_line_value && open_price[0] > t_line_value) || (low_price[1] < t1_line_value && open_price[1] > t1_line_value) || (low_price[2] < t2_line_value && open_price[2] > t2_line_value) || (low_price[3] < t3_line_value && open_price[3] > t3_line_value)) && (close_price[0] > open_price[0]) && close_price[0] > t_line_value && (no_bars_up < 3) && prev_touch_up == false && (currentBarTime != lastTradeBarTime) && (line_exe == reversal || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price + ((ask_price - low_price[0]) * 4)); trade.Buy(lot_size, _Symbol, ask_price, low_price[0],take_profit); lastTradeBarTime = currentBarTime; }
Erläuterung:
Der Wert der Aufwärtstrendlinie zum Zeitpunkt der letzten Kerzen wird in Variablen gespeichert, die im ersten Abschnitt initialisiert werden. Der EA kann die Preisaktivität gegenüber der Trendlinie zu verschiedenen Zeitpunkten bewerten, da jede Variable mit einer bestimmten Kerze verbunden ist. Dies garantiert, dass der EA die letzten vier Kerzen beobachten kann und ist entscheidend für die Identifizierung von Wechselwirkungen zwischen Preis und Trendlinie.
Die genauen Trendlinienwerte für die letzten paar Kerzen werden im folgenden Schritt ermittelt. Der EA kann genau feststellen, ob das Tief einer Kerze die Aufwärtstrendlinie berührt oder durchbrochen hat, was die anfängliche Voraussetzung für eine Umkehr des Aufwärtstrends ist, indem er den Preis der Linie zum Zeitpunkt jeder Kerze ermittelt.
Die Anzahl der Balken seit dem letzten verifizierten Umkehr-Setup wird dann durch einen initialisierten Zähler verfolgt. Bei der Identifizierung einer Kerze, die auf einen Unterstützungstest hindeuten könnte, iteriert der EA über die jüngsten Kerzen, bis das Tief unter die Trendlinie fällt und die Eröffnung über dieser liegt. Um zu überprüfen, ob die Käufer eingreifen, wird in einer verschachtelten Schleife nach einer nachfolgenden Aufwärtskerze gesucht, die oberhalb der Trendlinie schließt. Bei der Vermeidung wiederholter Alarme in kurzer Folge wird der Zähler aktualisiert, um die Anzahl der Balken seit der Bestätigung wiederzugeben.
Anschließend wird ein boolesches Flag gesetzt, das anzeigt, ob die Trendlinie bereits vor kurzem berührt wurde. Der EA betrachtet die letzten Kerzen, um festzustellen, ob eine von ihnen nach dem Unterschreiten der Trendlinie als Aufwärtskerze geschlossen hat. Um sicherzustellen, dass nicht mehrere Handelsgeschäfte bei der gleichen Preisinteraktion getätigt werden, wird das Flag auf true gesetzt, wenn eine solche Kerze vorhanden ist.
Bevor ein Kaufauftrag erteilt wird, berücksichtigt der EA eine Reihe von Faktoren. Es wird überprüft, ob die aktuelle eine Aufwärtskerze ist und oberhalb der Trendlinie schließt, ob keine der jüngsten Berührungen bereits einen Handel ausgelöst hat, ob der Handel nicht bereits auf der aktuellen Kerze ausgeführt wurde, ob der Ausführungsmodus Umkehrgeschäfte zulässt und ob eine der jüngsten Kerzen die Trendlinie berührt oder durchbrochen hat.
Der Abstand zwischen dem Briefkurs und dem Tiefpunkt der bestätigenden Kerze, erhöht um einen Multiplikator für ein positives Risiko-Ertrags-Verhältnis, ist die Art und Weise, wie der EA den Take Profit bestimmt, wenn alle diese Bedingungen erfüllt sind. Danach wendet es den Take Profit an, führt eine Kauftransaktion durch, ändert den Zeitpunkt des letzten Handels, um zu vermeiden, dass mehrere Geschäfte auf derselben Kerze getätigt werden, und setzt den Stop Loss auf das Tief der Umkehrkerze.
Identifizierung von Aufwärtstrendausbruch und Wiederholungstest
Nach dem Verständnis von Aufwärtstrendumkehrungen folgt die Identifizierung von Ausbruchs- und Wiederholungsmöglichkeiten auf einer aufsteigenden Trendlinie. Eine Kerze, die unter die Trendlinie fällt, bestätigt in diesem Fall den Ausbruch und zeigt an, dass die Unterstützung durchbrochen wurde. Der EA wartet auf einen erneuten Test nach diesem Ausbruch, der stattfindet, wenn der Höchststand einer nachfolgenden Kerze wieder auf die Trendlinie trifft. Dieser erneute Test zeigt, dass die durchbrochene Unterstützung nun als Widerstand wirkt. Nachdem dieser Retest bestätigt wurde, sucht der EA nach einer Abwärtskerze, um einen Verkaufseinstieg zu signalisieren, was bedeuten würde, dass die Verkäufer die Kontrolle übernommen haben.
Beispiel:// UP TREND t_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[0],0); t1_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[1],0); t2_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[2],0); t3_line_value = ObjectGetValueByTime(chart_id,up_trend,time_price[3],0); int no_bars_up = 0; for(int i = 0; i <= 3; i++) { if(low_price[i] < ObjectGetValueByTime(chart_id, up_trend, time_price[i], 0) && open_price[i] > ObjectGetValueByTime(chart_id, up_trend, time_price[i], 0)) { for(int j = i; j >= 0; j--) { if(close_price[j] > open_price[j] && close_price[j] > ObjectGetValueByTime(chart_id, up_trend, time_price[j], 0)) { no_bars_up = Bars(_Symbol, time_frame, time_price[j], TimeCurrent()); break; } } break; } } bool prev_touch_up = false; if((low_price[1] < t1_line_value && close_price[1] > open_price[1]) || (low_price[2] < t2_line_value && close_price[2] > open_price[2])) { prev_touch_up = true; // Flag that a recent touch already occurred } if( ((low_price[0] < t_line_value && open_price[0] > t_line_value) || (low_price[1] < t1_line_value && open_price[1] > t1_line_value) || (low_price[2] < t2_line_value && open_price[2] > t2_line_value) || (low_price[3] < t3_line_value && open_price[3] > t3_line_value)) && (close_price[0] > open_price[0]) && close_price[0] > t_line_value && (no_bars_up < 3) && prev_touch_up == false && (currentBarTime != lastTradeBarTime) && (line_exe == reversal || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price + ((ask_price - low_price[0]) * 4)); trade.Buy(lot_size, _Symbol, ask_price, low_price[0],take_profit); lastTradeBarTime = currentBarTime; // Update last trade bar time to avoid duplicate signals } // UPTREND BREAKOUT AMD RETEST bool prev_touch_break_out_up = false; if((high_price[1] > td1_line_value && close_price[1] < open_price[1]) || (high_price[2] > td2_line_value && close_price[2] < open_price[2]) ) { prev_touch_break_out_up = true; } int no_bars_up_break_out = 0; for(int i = 0; i <= 3; i++) { if(high_price[i] > ObjectGetValueByTime(chart_id,down_trend,time_price[i],0) && open_price[i] < ObjectGetValueByTime(chart_id,down_trend,time_price[i],0) ) { for(int j = i; j >= 0; j--) { if(close_price[j] < open_price[j] && close_price[j] < ObjectGetValueByTime(chart_id,down_trend,time_price[j],0)) { no_bars_up_break_out = Bars(_Symbol,time_frame,time_price[j],TimeCurrent()); break; } } break; } } if(((high_price[1] >= t1_line_value && open_price[1] < t1_line_value) || (high_price[2] >= t2_line_value && open_price[2] < t2_line_value) || (high_price[3] >= t3_line_value && open_price[3] < t3_line_value) || (high_price[0] >= t_line_value)) && (close_price[0] < t_line_value && close_price[0] < open_price[0] && open_price[1] < t1_line_value) && (no_bars_up_break_out < 3) && (no_bars_up_break_out == false) && (currentBarTime != lastTradeBarTime) && (line_exe == break_out || line_exe == reverse_break) ) { take_profit = MathAbs(ask_price - ((high_price[0] - ask_price) * 4)); trade.Sell(lot_size,_Symbol,ask_price,high_price[0], take_profit); lastTradeBarTime = currentBarTime; }
Erläuterung:
Um festzustellen, ob ein kürzlicher Ausbruch bereits stattgefunden hat, wird im ersten Abschnitt ein boolesches Flag gesetzt. Wenn die Kerze als Abwärtskerze schloss, untersuchte der EA die vorherigen Kerzen, um zu sehen, ob ihr Hoch die Trendlinie von unten berührte. Um zu verhindern, dass mehrere Signale von demselben Ausbruchsereignis stammen, wird das Flag auf true gesetzt, wenn eine solche Berührung festgestellt wird. Dadurch wird sichergestellt, dass der EA bei der gleichen Preisinteraktion nicht erneut Handelsgeschäfte initiiert.
Der EA ermittelt dann, wie viele Balken seit dem letzten verifizierten Ausbruch vergangen sind. Es durchsucht die jüngsten Kerzen, um diejenigen zu identifizieren, bei denen der Eröffnungswert unterhalb der Trendlinie und der Höchstwert oberhalb dieser Linie lag. Eine darin eingebettete Schleife sucht nach einer Folgekerze, die unter der Trendlinie in einer Abwärtsweise schließt. Um sicherzustellen, dass nicht zu nahe an einem früheren Ausbruch gehandelt wird, zählt der EA die Balken zwischen dieser Kerze und dem aktuellen Balken, nachdem dieser entdeckt wurde. Um ein Überhandeln zu verhindern und die Häufigkeit der Einstiege unter Kontrolle zu halten, wird dieser Balkenzähler verwendet.
Mehrere Prüfungen werden kombiniert, um das Hauptkriterium für die Ausführung eines Verkaufsgeschäfts zu liefern. Um den Retest zu validieren, muss zunächst bestätigt werden, dass eine der letzten Kerzen die Trendlinie berührt oder überschritten hat. Anschließend wird ermittelt, ob die aktuelle Kerze unter die Trendlinie fällt und eine Abwärtskerze ist, was darauf hindeutet, dass die Verkäufer auf dem Vormarsch sind. Durch den Vergleich der aktuellen Balkenzeit mit der letzten ausgeführten Transaktion wird außerdem sichergestellt, dass seit dem letzten Ausbruch nicht zu viele Balken vergangen sind, um einen neuen Handel zu ermöglichen, dass keine kürzliche Ausbruchsberührung bereits einen Handel ausgelöst hat und dass nur ein Handel pro Kerze ausgeführt wird. Schließlich wird bestätigt, dass Breakout-Handelsgeschäfte im EA-Modus erlaubt sind.
Wenn alle diese Voraussetzungen erfüllt sind, bestimmt der EA den Take Profit, indem er den Abstand zwischen dem aktuellen Briefkurs und dem Höchststand der Bestätigungskerze mit einem Faktor multipliziert, der ein gutes Risiko-Ertrags-Verhältnis ergibt. Danach wird der berechnete Take-Profit angewandt, der Stop-Loss auf den Höchststand der Ausbruchskerze gesetzt, ein Verkaufsauftrag mit der angegebenen Losgröße ausgeführt und der Zeitpunkt des letzten Handels aktualisiert. Durch die Eliminierung doppelter oder verfrühter Handelsgeschäfte garantiert diese Logik, dass der EA durchgängig Möglichkeiten zum Ausbruch aus dem Aufwärtstrend und zur Wiederholung erfasst.
Schlussfolgerung
In Fortsetzung der letzten Studie über Chart-Objekte haben wir uns auf Trendlinien und nicht auf Rechtecke konzentriert. Wenn der Kurs von Trendlinien abweicht oder diese durchbricht, lernen Sie, wie Sie einen EA erstellen, der diese erkennen und automatisch Handelsgeschäfte ausführen kann. Durch die Kombination von automatischem Handel und manueller Trendlinienanalyse verwandelt dieser Ansatz ein beliebtes technisches Werkzeug in nützliche Handelssignale in MQL5.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/19968
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.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
MetaTrader 5 Machine Learning Blueprint (Teil 3): Methoden der Kennzeichnung von Trend-Scanning
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Selbstoptimierende Expert Advisors in MQL5 (Teil 16): Überwachte lineare Systemidentifikation
- 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.