
Aufbau des Kerzenmodells Trend Constraint (Teil 10): Strategisches Goldenes und Todeskreuz (EA)
Einführung
In diesem Artikel befassen wir uns mit der Integration des strategischen Goldenen Kreuzes (Golden Cross) und des Todeskreuzes (Death Cross) in den Expert Advisor Trend Constraint, um das Potenzial dieser bewährten gleitenden Durchschnitts-Crossover-Techniken zu erschließen. Unser Ziel ist es, die Trendfolgemöglichkeiten im algorithmischen Handel zu verbessern, indem wir diese Strategien automatisieren und so Präzision, Konsistenz und nahtlose Kompatibilität mit breiteren Handelssystemen gewährleisten.
Viele Händler sehen sich mit der Herausforderung konfrontiert, starke Aufwärts- und Abwärtstrends effektiv zu erkennen und zu nutzen. Während das Goldene Kreuz, das ein Aufwärtsmomentum signalisiert, und das Todeskreuz, das eine Abwärtsstimmung anzeigt, ihren Wert im manuellen Handel unter Beweis gestellt haben, führt ihre fehlende Automatisierung häufig zu verpassten Chancen und inkonsequenter Ausführung.
Durch die Integration der Golden und Todeskreuz Strategien in einen automatisierten Expert Advisor können Händler systematisch Umkehrsignale ausführen, ohne die Einschränkungen, die anderen Trendfolgestrategien auferlegt sind. Im Gegensatz zu eingeschränkten Strategien, die von der täglichen Marktstimmung abhängen, arbeiten diese Crossover-Strategien unabhängig, um Umkehrungen zu erkennen und darauf zu reagieren, sobald sie auftreten. Dadurch wird sichergestellt, dass potenzielle Wendepunkte früher erfasst werden, was die Reaktionsfähigkeit und die allgemeine Handelsleistung verbessert und gleichzeitig die Ausrichtung auf breitere Trendstrategien beibehält.
Hauptinhalt:
- Die Strategie des Goldenen und des Totenkreuzes verstehen
- Analyse ihrer Bedeutung im breiteren Kontext der Trendbeobachtung
- Anpassung an trendbegrenzende Bedingungen
- Umsetzung der Strategie mit MQL5
- Erste Strategietests
- Zusammenführung der neuen Strategie in der Trend Constraint
- Test- und Optimierungsergebnisse
- Schlussfolgerung
Die Strategie des Goldenen und des Totenkreuzes verstehen
Die Strategie des Goldenen und des Todeskreuzes sind zentrale Konzepte in der technischen Analyse, die dazu dienen, potenzielle Aufwärts- oder Abwärtstrends auf der Grundlage von gleitenden Durchschnittskreuzungen zu signalisieren. Ein Goldenes Kreuz tritt auf, wenn ein kürzerfristiger gleitender Durchschnitt, in der Regel der 50-Tage-Durchschnitt, einen längerfristigen gleitenden Durchschnitt, oft den 200-Tage-Durchschnitt, übersteigt. Dieses Ereignis wird als starkes Aufwärtssignal betrachtet, das darauf hindeutet, dass ein langfristiger Aufwärtstrend beginnen könnte. Anleger und Händler könnten dies als Gelegenheit sehen, Aktien zu kaufen oder zu halten, in der Erwartung eines Kursanstiegs.
Umgekehrt ist das Todeskreuz das gegenteilige Szenario, bei dem der kurzfristige gleitende Durchschnitt unter den längerfristigen gleitenden Durchschnitt fällt, was auf einen potenziellen Abwärtstrend hindeutet. Dies wird als Warnung angesehen, dass der Markt in einen anhaltenden Rückgang übergehen könnte. Das Todeskreuz kann Anleger dazu veranlassen, zu verkaufen oder Leerverkäufe zu tätigen, oder zumindest Vorsicht walten zu lassen, da es auf eine Abschwächung der Marktbedingungen hindeutet. Diese beiden Signale werden nicht nur für direkte Handelsentscheidungen verwendet, sondern auch für eine umfassendere Analyse der Marktstimmung, obwohl sie nicht unfehlbar sind und zusammen mit anderen Indikatoren oder Analyseformen zur Bestätigung von Trends verwendet werden sollten.
Analyse ihrer Bedeutung im breiteren Kontext der Trendbeobachtung
Im breiteren Kontext der Trendfolgestrategien dienen das Goldene Kreuz und das Todeskreuz als grundlegende Instrumente zur Identifizierung des Beginns und der potenziellen Umkehrung von Markttrends. Bei der Trendfolge handelt es sich um eine Strategie, bei der Händler versuchen, von anhaltenden Marktpreisbewegungen zu profitieren, indem sie ihre Trades auf die Richtung des etablierten Trends ausrichten. So passen das Goldene Kreuz und das Totenkreuz in dieses Paradigma:
1. Identifizierung von Trends: Die Hauptfunktion dieser Kreuzungen besteht darin, klare Signale für den Beginn neuer Trends zu liefern. Das Goldene Kreuz signalisiert den Beginn eines Aufwärtstrends und veranlasst Trendfolger, Kaufpositionen einzugehen oder ihr Engagement zu erhöhen. Umgekehrt zeigt das Todeskreuz den Beginn eines Abwärtstrends an, was bedeutet, dass es an der Zeit ist, Kaufpositionen zu schließen oder Verkaufspositionen zu erwägen.
2. Bestätigung von Trends: Diese Signale dienen als Bestätigungen im Rahmen von Trendfolgestrategien. Ein Trendfolger könnte dieses Kreuzen zusammen mit anderen Indikatoren wie Preisbewegung, Volumen oder Momentum-Indikatoren verwenden, um zu überprüfen, ob sich tatsächlich ein Trend entwickelt. Dieser Multi-Indikator-Ansatz trägt dazu bei, Fehlsignale zu reduzieren, was bei der Trendfolge von entscheidender Bedeutung ist, da das Ziel darin besteht, dem Trend so lange wie möglich zu folgen.
3. Risikomanagement: Bei der Trendfolge ist das Risikomanagement entscheidend, da sich Trends unerwartet umkehren oder anhalten können. Die Goldenen Kreuze und die Todeskreuze können zur Festlegung von Stop-Loss oder zur Entscheidung über die Reduzierung oder Erhöhung der Positionsgröße verwendet werden. So könnte beispielsweise ein Durchbruch unter die gleitenden Durchschnitte nach einem Goldenen Kreuz nahelegen, die Stopps zu straffen oder das Engagement zu reduzieren.
4. Langfristige Perspektive: Diese Signale sind aufgrund der Verwendung längerer gleitender Durchschnittsperioden von Natur aus langfristig und passen gut zur Trendfolge-Philosophie, die darauf abzielt, eher die großen Bewegungen des Marktes als kurzfristige Schwankungen zu erfassen. Diese langfristige Ausrichtung hilft dabei, Marktrauschen herauszufiltern und sich auf wichtige Kursbewegungen zu konzentrieren.
5. Anpassungsfähigkeit: Obwohl die Strategie traditionell mit gleitenden 50- und 200-Tage-Durchschnitten festgelegt wird, kann sie für andere Zeitrahmen oder Marktbedingungen angepasst werden. Auf schnelllebigen Märkten könnten Händler kürzere Zeiträume verwenden, um schnellere Signale zu erhalten, während sie auf stabileren Märkten längere Zeiträume bevorzugen könnten, um zu vermeiden, dass sie durch kleinere Korrekturen aus dem Konzept gebracht werden.
Die Bedeutung des Goldenen Kreuzes und des Todeskreuzes im Rahmen der Trendfolgebewertung kann jedoch wie folgt kritisch analysiert werden:
- Verzögerung: Einer der Hauptkritikpunkte ist die mit den gleitenden Durchschnitten verbundene Verzögerung. Zu dem Zeitpunkt, an dem diese Überkreuzungen auftreten, haben sich möglicherweise bereits wesentliche Teile des Trends verflüchtigt, was die Gewinne von Handelsgeschäften, die ausschließlich auf diesen Signalen beruhen, verringern kann.
- Falsche Signale: Die Trendfolge birgt naturgemäß das Risiko falscher Ausbrüche oder vorzeitiger Trendumkehrungen. Die Goldenen und die Todeskreuze sind dagegen nicht immun und sollten daher Teil einer umfassenderen Strategie sein, die auch andere Formen der Analyse oder Bestätigungssignale umfasst.
- Marktumfeld: Ihre Wirksamkeit kann je nach Marktbedingungen erheblich variieren. In trendigen Märkten können diese Signale sehr effektiv sein, aber in schwankenden oder unruhigen Märkten können sie zu zahlreichen Fehlstarts führen.
Anpassung an trendbegrenzende Bedingungen
Bei langfristigen Strategien kann die Auferlegung übermäßiger Beschränkungen ihr Potenzial begrenzen. Nehmen wir zum Beispiel ein Szenario an, bei dem die tägliche Marktstimmung rückläufig ist. Ein Signal eines Goldenen Kreuzes, das innerhalb desselben Tages auf niedrigeren Zeitebenen erscheint, könnte auf eine potenzielle Trendwende hindeuten, was wiederum bedeutet, dass der Markt nach oben drehen könnte. Wenn es zu solchen Umkehrungen kommt, passen sich andere eingeschränkte Strategien oft an die entstehende Trendstimmung an und richten sich nach der neuen Marktrichtung aus.
Um von dieser Dynamik zu profitieren, können die Strategien Todeskreuz und Goldenes Kreuz als unabhängige Module in den Trend Constraint EA integriert werden. Auf diese Weise kann der EA seine Leistung maximieren, indem er Umkehrpositionen erfasst, die mit dem neu entstehenden Trend übereinstimmen.
Dieser Ansatz gewährleistet:
- Flexibilität über Zeiträume hinweg: Der EA kann kurzfristige Umkehrungen (z. B. Goldene Kreuze) erkennen und sie mit breiteren Marktbewegungen in Einklang bringen, was die Anpassungsfähigkeit verbessert.
- Verbesserte Einstiegspunkte: Durch das frühzeitige Erkennen von Stimmungsumschwüngen kann der EA strategische Positionen einnehmen und die Verzögerung bei der Reaktion auf Marktveränderungen minimieren.
- Synergie zwischen Strategien: Durch die unabhängige Integration des Goldenen Kreuzes und des Todeskreuzes kann der EA deren Stärken nutzen, ohne die primären Trendfolgemechanismen außer Kraft zu setzen.
Durch die Anwendung dieses zweischichtigen Ansatzes ist der Trend Constraint EA in der Lage, Marktumschwünge effektiv zu steuern und gleichzeitig die langfristige Rentabilität zu erhalten. Gehen wir nun zur nächsten Phase über, in der wir diese Strategie umsetzen und integrieren werden.
Umsetzung der Strategie mit MQL5
Wenn ich einen Multi-Strategie-EA entwickle, entwerfe ich jede Strategie zunächst als unabhängigen EA. Dies ermöglicht ein gezieltes Testen und Verfeinern, bevor es in eine einzige, einheitliche Codebasis zusammengeführt wird. Nach dieser Methode werden wir zunächst den Strategic Golden and Todeskreuz EA aufschlüsseln und unabhängig entwickeln, bevor wir ihn in den Haupt-Expert Advisor integrieren.
Öffnen Sie wie gewohnt Ihre MetaEditor 5-Anwendung von Ihrem Desktop aus, oder drücken Sie F4 in Ihrem MetaTrader 5-Terminal, um sie direkt zu starten. Befolgen Sie die unten beschriebenen Entwicklungsschritte. Anfängern wird empfohlen, den Code manuell einzutippen, anstatt ihn zu kopieren und einzufügen, da dies die Fertigkeit verstärkt und das Verständnis vertieft.
Wir beginnen hier mit unserem Goldenen und dem Totenkreuz:
Kopfzeile und Metadaten:
Dies ist der oberste Teil des Programms. Wir beginnen mit der Definition der Metadaten, um Klarheit und Professionalität zu gewährleisten. In den Metadaten erhält das Programm den Namen „Strategic Golden & Death Cross EA“ und weitere Angaben zum Copyright, eine Beschreibung und die Versionsnummer. Dieser Schritt hilft uns bei der Organisation des Projekts und stellt sicher, dass unsere Arbeit beim Einsatz in MetaTrader 5 richtig zugeordnet wird. Indem wir die Metadaten auf diese Weise einrichten, schaffen wir eine professionelle und gut dokumentierte Grundlage für unseren EA.
//+------------------------------------------------------------------+ //| Strategic Golden & Death Cross EA.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/en/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Clemence Benjamin" #property description "GOLDEN AND DEATH CROSS" #property version "1.0"
Initialization: Einbinden und Instanziieren des Handelsobjektes „trade“.
Um die Ausführung des Handels zu vereinfachen, binden wir die MQL5-Handelsbibliothek mit #include<Trade\Trade.mqh> ein. Diese Bibliothek bietet Zugang zu leistungsstarken Handelsfunktionen. Wir instanziieren die Klasse CTrade für den Handel, sodass der EA Operationen wie Kauf, Verkauf und Schließen von Positionen ohne manuelle Implementierung dieser Routinen durchführen kann. Dies verringert die Komplexität und macht den Code zuverlässiger. Mit diesem Setup können wir uns auf die Strategie konzentrieren und uns bei der Ausführung unserer Aufträge auf die Handelsmanagement-Bibliothek verlassen.
#include<Trade\Trade.mqh>;
CTrade trade;
Eingabe Parameter:
Wir beginnen mit der Definition von vom Nutzer einstellbaren Parametern, um den EA flexibel und anpassbar zu machen.
Zum Beispiel:
- Mit LotSize können wir das Handelsvolumen kontrollieren.
- Die Preisabweichung gibt an, welche Preisabweichungen während der Ausführung zulässig sind.
- FastEMAPeriod und SlowEMAPeriod definieren die Periodenlängen der gleitenden Durchschnitte, die das Rückgrat des Golden und des Todeskreuz bilden.
input double LotSize = 1.0; // Trade volume (lots) input int Slippage = 20; // Slippage in points input int TimerInterval = 10000; // Timer interval in seconds input double TakeProfitPips = 100; // Take Profit in pips input double StopLossPips = 50; // Stop Loss in pips input int FastEMAPeriod = 50; // Fast EMA period (default 50) input int SlowEMAPeriod = 200; // Slow EMA period (default 200)
Durch die Einstellung dieser Parameter ermöglichen wir den Nutzern, den EA an ihre spezifischen Handelsbedingungen anzupassen.
Initialisierung und Timer-Setup:
Stellen wir sicher, dass der EA richtig initialisiert wird. In der Funktion OnInit() fügen wir eine Prüfung hinzu, um festzustellen, ob genügend Balken zur Berechnung des langsamen EMA vorhanden sind. Wenn nicht, protokolliert der EA einen Fehler und bricht die Ausführung ab. Dadurch wird sichergestellt, dass die Strategie nur dann ausgeführt wird, wenn genügend Daten vorhanden sind.
int OnInit() { //--- create timer EventSetTimer(TimerInterval); //--- Check if there are enough bars for EMA calculation if(Bars(_Symbol,PERIOD_CURRENT)<SlowEMAPeriod) { Print("Not enough bars for EMA calculation"); return(INIT_FAILED); } return(INIT_SUCCEEDED); }
Außerdem verwenden wir EventSetTimer(), um die Funktion OnTimer() in regelmäßigen Abständen aufzurufen und die Handelslogik auszuführen. Die Funktion OnDeinit() sorgt dafür, dass der Timer deaktiviert wird, wenn der EA entfernt wird, wodurch Ressourcen frei werden.
void OnDeinit(const int reason) { //--- delete timer EventKillTimer(); }
Handelslogik in OnTimer():
Kommen wir nun zum Kern der Strategie innerhalb der Funktion OnTimer():
EMA-Berechnung:
Zunächst werden mit iMA() die Handles für die schnellen und langsamen EMAs erstellt und ihre Werte mit CopyBuffer() abgefragt. Diese EMAs sind wichtig, um Einstiegssignale zu erkennen.
int fastEMAHandle = iMA(_Symbol, PERIOD_CURRENT, FastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); int slowEMAHandle = iMA(_Symbol, PERIOD_CURRENT, SlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); double fastEMAArray[], slowEMAArray[]; CopyBuffer(fastEMAHandle, 0, 0, 2, fastEMAArray); CopyBuffer(slowEMAHandle, 0, 0, 2, slowEMAArray);
Abruf von Marktdaten:
Als Nächstes rufen wir wichtige Marktdaten ab, wie z. B. den Briefkurs, den Geldkurs und die Punktgröße, um präzise Berechnungen für Stop-Loss und Take-Profit zu gewährleisten.
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
Eintrittssignale:
Hier legen wir die Bedingungen für die Eröffnung von Kauf- und Verkaufsgeschäften fest. Ein Goldenes Kreuz (der schnelle EMA kreuzt den langsamen EMA nach oben) signalisiert einen Kauf, während ein Todeskreuz (der schnelle EMA kreuzt den langsamen EMA nach unten) einen Verkauf signalisiert.
if(fastEMAArray[0] > slowEMAArray[0] && fastEMAArray[1] <= slowEMAArray[1]) // Death Cross { double sl = NormalizeDouble(ask + StopLossPips * point, _Digits); trade.Sell(LotSize, _Symbol, ask, sl); } else if(fastEMAArray[0] < slowEMAArray[0] && fastEMAArray[1] >= slowEMAArray[1]) // Golden Cross { double sl = NormalizeDouble(bid - StopLossPips * point, _Digits); trade.Buy(LotSize, _Symbol, bid, sl); }
Ausstiegssignale:
Stellen wir sicher, dass bestehende Positionen geschlossen werden, wenn sich das gegenteilige Signal ausbildet. Auf diese Weise wird die Strategie an die sich ändernden Marktbedingungen angepasst.
if((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && fastEMAArray[0] < slowEMAArray[0]) || (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && fastEMAArray[0] > slowEMAArray[0])) { trade.PositionClose(PositionGetInteger(POSITION_TICKET)); }
Fehlerbehandlung:
Jetzt fügen wir Routinen zur Fehlerbehandlung hinzu, um alle Probleme bei der Handelsausführung oder Positionsschließung zu protokollieren, was bei der Fehlersuche hilft und eine reibungslose Leistung gewährleistet.
if(!trade.Sell(LotSize, _Symbol, ask, sl)) { Print("Sell order error: ", GetLastError()); }
Hier ist unser vollständiger Code:
//+------------------------------------------------------------------+ //| Golden & Death Cross Strategy.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/en/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Clemence Benjamin" #property description "GOLDEN AND DEATH CROSS" #property version "1.0" //+------------------------------------------------------------------+ //| Includes | //+------------------------------------------------------------------+ #include<Trade\Trade.mqh>; CTrade trade; //+------------------------------------------------------------------+ //| Input parameters | //+------------------------------------------------------------------+ input double LotSize = 1.0; // Trade volume (lots) input int Slippage = 20; // Slippage in points input int TimerInterval = 1000; // Timer interval in seconds input double StopLossPips = 1500; // Stop Loss in pips input int FastEMAPeriod = 50; // Fast EMA period (default 50) input int SlowEMAPeriod = 200; // Slow EMA period (default 200) //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create timer EventSetTimer(TimerInterval); //--- Check if there are enough bars to calculate the EMA if(Bars(_Symbol,PERIOD_CURRENT)<SlowEMAPeriod) { Print("Not enough bars for EMA calculation"); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- delete timer EventKillTimer(); } //+------------------------------------------------------------------+ //| Expert timer function | //+------------------------------------------------------------------+ void OnTimer() { bool hasPosition = PositionSelect(_Symbol); int fastEMAHandle = iMA(_Symbol, PERIOD_CURRENT, FastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); int slowEMAHandle = iMA(_Symbol, PERIOD_CURRENT, SlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); if(fastEMAHandle < 0 || slowEMAHandle < 0) { Print("Failed to create EMA handles. Error: ", GetLastError()); return; } double fastEMAArray[], slowEMAArray[]; if(CopyBuffer(fastEMAHandle, 0, 0, 2, fastEMAArray) <= 0 || CopyBuffer(slowEMAHandle, 0, 0, 2, slowEMAArray) <= 0) { Print("Failed to copy EMA data. Error: ", GetLastError()); return; } double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(!hasPosition) { if(fastEMAArray[0] > slowEMAArray[0] && fastEMAArray[1] <= slowEMAArray[1]) // Death Cross { double sl = NormalizeDouble(ask + StopLossPips * point, _Digits); if(!trade.Sell(LotSize, _Symbol, ask, sl )) Print("Buy order error ", GetLastError()); else Print("Buy order opened with TP ", " and SL ", StopLossPips, " pips"); } else if(fastEMAArray[0] < slowEMAArray[0] && fastEMAArray[1] >= slowEMAArray[1]) // Golden Cross { double sl = NormalizeDouble(bid - StopLossPips * point, _Digits); if(!trade.Buy(LotSize, _Symbol, bid, sl )) Print("Sell order error ", GetLastError()); else Print("Sell order opened with TP ", " and SL ", StopLossPips, " pips"); } } else { if((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && fastEMAArray[0] < slowEMAArray[0]) || (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && fastEMAArray[0] > slowEMAArray[0])) { ulong ticket = PositionGetInteger(POSITION_TICKET); if(!trade.PositionClose(ticket)) Print("Failed to close position (Ticket: ", ticket, "). Error: ", GetLastError()); else Print("Position closed : ", ticket); } } } //+------------------------------------------------------------------+
Erste Strategietests
Nachdem wir den Code erfolgreich kompiliert haben, können wir nun die Leistung unserer Strategie mit dem Strategy Tester testen. Nachfolgend sehen Sie Bilder der Testergebnisse, bevor wir die Strategie in den Trend Constraint Expert Advisor integriert haben.
Einstellungen des Strategietesters: Boom 500 Index
Eingabe-Einstellungen: Boom 500 Index
Boom 500 Index M5: Testen des Goldenen & des Todeskreuzes
Nach den ersten Tests funktioniert die Logik der Auftragsausführung reibungslos, aber die Ausstiegsstrategie muss verbessert werden. Bei der manuellen Beobachtung im Strategietester sind mir viele Positionen aufgefallen, die einen Gewinn hätten erzielen können, aber mit kleinen Gewinnen oder sogar Verlusten abgeschlossen wurden. Dies ist darauf zurückzuführen, dass die Umkehrkurse nach einem starken Rückgang der Kurse gekreuzt wurden, wodurch die Gewinne begrenzt wurden. Während der Marktkonsolidierung führten viele falsche Kreuzungen zu Verlusten. Um solch große Verluste zu vermeiden, muss die Ausstiegsstrategie verbessert werden.
Zusammenführung der neuen Strategie in der Trend Constraint
Schließlich haben wir das Ziel erreicht, einen Expert Advisor für mehrere Strategien zu erstellen, indem wir die zuvor entwickelte Strategie integriert haben. Um Ihr Gedächtnis für die bestehenden Strategien aufzufrischen, können Sie (Teil 9) erneut lesen. Hier finden Sie eine Liste der bereits integrierten Strategien:
- Trendfolge
- Donchian Channel Ausbruch
- Divergenz-Strategie
Heute fügen wir die vierte Strategie hinzu, die, wie ich bereits erklärt habe, unabhängig arbeitet und frei von Zwängen ist, sodass sie alle Umkehrmöglichkeiten nutzen kann. Um dies zu erreichen, werden wir den aktuellen Trend Constraint Expert ändern, indem wir einen booleschen Schalter für die neue Strategie des Goldenen und des Todeskreuzes hinzufügen. Außerdem werden wir andere Codeabschnitte in die entsprechenden Funktionen des Hauptcodes umstrukturieren.
Um Konflikte mit anderen Begriffen, die bereits im Hauptprogramm vorhanden sind, zu vermeiden, haben wir den Variablen, die mit der Strategie des Goldenen und des Todeskreuzes verbunden sind, ein eindeutiges Präfix hinzugefügt. Zum Beispiel haben wir LotSize in GDC_LotSize = 1.0 umbenannt, um Klarheit zu schaffen und Verwirrung zu vermeiden.
Nachstehend finden Sie den vollständigen, fehlerfreien Code. Die neuen Ergänzungen und Änderungen sind zum besseren Verständnis und zur Klarheit deutlich hervorgehoben.
//+------------------------------------------------------------------+ //| Trend Constraint Expert.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/en/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Clemence Benjamini" #property link "https://www.mql5.com/en/users/billionaire2024/seller" #property version "1.03" #include <Trade\Trade.mqh> CTrade trade; // Input parameters for controlling strategies input bool UseTrendFollowingStrategy = false; // Enable/Disable Trend Following Strategy input bool UseBreakoutStrategy = false; // Enable/Disable Breakout Strategy input bool UseDivergenceStrategy = false; // Enable/Disable Divergence Strategy input bool UseGoldenDeathCrossStrategy = true; // Enable/Disable Golden/Death Cross Strategy // Input parameters for Golden/Death Cross Strategy input double GDC_LotSize = 1.0; // Trade volume (lots) for Golden Death Cross input int GDC_Slippage = 20; // Slippage in points for Golden Death Cross input int GDC_TimerInterval = 1000; // Timer interval in seconds for Golden Death Cross input double GDC_StopLossPips = 1500; // Stop Loss in pips for Golden Death Cross input int GDC_FastEMAPeriod = 50; // Fast EMA period for Golden Death Cross input int GDC_SlowEMAPeriod = 200; // Slow EMA period for Golden Death Cross int GDC_fastEMAHandle, GDC_slowEMAHandle; // Handles for EMA indicators in Golden Death Cross // Global variables double prevShortMA, prevLongMA; // Input parameters for Trend Constraint Strategy input int RSI_Period = 14; // RSI period input double RSI_Overbought = 70.0; // RSI overbought level input double RSI_Oversold = 30.0; // RSI oversold level input double Lots = 0.1; // Lot size input double StopLoss = 100; // Stop Loss in points input double TakeProfit = 200; // Take Profit in points input double TrailingStop = 50; // Trailing Stop in points input int MagicNumber = 12345678; // Magic number for the Trend Constraint EA input int OrderLifetime = 43200; // Order lifetime in seconds (12 hours) // Input parameters for Breakout Strategy input int InpDonchianPeriod = 20; // Period for Donchian Channel input double RiskRewardRatio = 1.5; // Risk-to-reward ratio input double LotSize = 0.1; // Default lot size for trading input double pipsToStopLoss = 15; // Stop loss in pips for Breakout input double pipsToTakeProfit = 30; // Take profit in pips for Breakout // Input parameters for Divergence Strategy input int DivergenceMACDPeriod = 12; // MACD Fast EMA period input int DivergenceSignalPeriod = 9; // MACD Signal period input double DivergenceLots = 1.0; // Lot size for Divergence trades input double DivergenceStopLoss = 300; // Stop Loss in points for Divergence input double DivergenceTakeProfit = 500; // Take Profit in points for Divergence input int DivergenceMagicNumber = 87654321; // Magic number for Divergence Strategy input int DivergenceLookBack = 8; // Number of periods to look back for divergence input double profitLockerPoints = 20; // Number of profit points to lock // Indicator handle storage int rsi_handle; int handle; // Handle for Donchian Channel int macd_handle; double ExtUpBuffer[]; // Upper Donchian buffer double ExtDnBuffer[]; // Lower Donchian buffer double ExtMacdBuffer[]; // MACD buffer double ExtSignalBuffer[]; // Signal buffer int globalMagicNumber; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { prevShortMA = 0.0; prevLongMA = 0.0; // Initialize RSI handle rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE); if (rsi_handle == INVALID_HANDLE) { Print("Failed to create RSI indicator handle. Error: ", GetLastError()); return INIT_FAILED; } // Create a handle for the Donchian Channel handle = iCustom(_Symbol, PERIOD_CURRENT, "Free Indicators\\Donchian Channel", InpDonchianPeriod); if (handle == INVALID_HANDLE) { Print("Failed to load the Donchian Channel indicator. Error: ", GetLastError()); return INIT_FAILED; } // Initialize MACD handle for divergence globalMagicNumber = DivergenceMagicNumber; macd_handle = iMACD(_Symbol, PERIOD_CURRENT, DivergenceMACDPeriod, 26, DivergenceSignalPeriod, PRICE_CLOSE); if (macd_handle == INVALID_HANDLE) { Print("Failed to create MACD indicator handle for divergence strategy. Error: ", GetLastError()); return INIT_FAILED; } if(UseGoldenDeathCrossStrategy) { // Check if there are enough bars to calculate the EMA if(Bars(_Symbol, PERIOD_CURRENT) < GDC_SlowEMAPeriod) { Print("Not enough bars for EMA calculation for Golden Death Cross"); return INIT_FAILED; } GDC_fastEMAHandle = iMA(_Symbol, PERIOD_CURRENT, GDC_FastEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); GDC_slowEMAHandle = iMA(_Symbol, PERIOD_CURRENT, GDC_SlowEMAPeriod, 0, MODE_EMA, PRICE_CLOSE); if(GDC_fastEMAHandle < 0 || GDC_slowEMAHandle < 0) { Print("Failed to create EMA handles for Golden Death Cross. Error: ", GetLastError()); return INIT_FAILED; } } // Resize arrays for MACD buffers ArrayResize(ExtMacdBuffer, DivergenceLookBack); ArrayResize(ExtSignalBuffer, DivergenceLookBack); Print("Trend Constraint Expert initialized."); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(rsi_handle); IndicatorRelease(handle); IndicatorRelease(macd_handle); Print("Trend Constraint Expert deinitialized."); } //+------------------------------------------------------------------+ //| Check Golden/Death Cross Trading Logic | //+------------------------------------------------------------------+ void CheckGoldenDeathCross() { double fastEMAArray[2], slowEMAArray[2]; double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(CopyBuffer(GDC_fastEMAHandle, 0, 0, 2, fastEMAArray) <= 0 || CopyBuffer(GDC_slowEMAHandle, 0, 0, 2, slowEMAArray) <= 0) { Print("Failed to copy EMA data for Golden Death Cross. Error: ", GetLastError()); return; } bool hasPosition = PositionSelect(_Symbol); if(!hasPosition) { if(fastEMAArray[0] > slowEMAArray[0] && fastEMAArray[1] <= slowEMAArray[1]) // Death Cross { double sl = NormalizeDouble(ask + GDC_StopLossPips * point, _Digits); if(!trade.Sell(GDC_LotSize, _Symbol, ask, sl )) Print("Sell order error for Golden Death Cross ", GetLastError()); else Print("Sell order opened for Golden Death Cross with SL ", GDC_StopLossPips, " pips"); } else if(fastEMAArray[0] < slowEMAArray[0] && fastEMAArray[1] >= slowEMAArray[1]) // Golden Cross { double sl = NormalizeDouble(bid - GDC_StopLossPips * point, _Digits); if(!trade.Buy(GDC_LotSize, _Symbol, bid, sl )) Print("Buy order error for Golden Death Cross ", GetLastError()); else Print("Buy order opened for Golden Death Cross with SL ", GDC_StopLossPips, " pips"); } } else { if((PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && fastEMAArray[0] < slowEMAArray[0]) || (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && fastEMAArray[0] > slowEMAArray[0])) { ulong ticket = PositionGetInteger(POSITION_TICKET); if(!trade.PositionClose(ticket)) Print("Failed to close position for Golden Death Cross (Ticket: ", ticket, "). Error: ", GetLastError()); else Print("Position closed for Golden Death Cross: ", ticket); } } } //+------------------------------------------------------------------+ //| Check Trend Following Strategy | //+------------------------------------------------------------------+ void CheckTrendFollowing() { if (PositionsTotal() >= 2) return; // Ensure no more than 2 orders from this strategy double rsi_value; double rsi_values[]; if (CopyBuffer(rsi_handle, 0, 0, 1, rsi_values) <= 0) { Print("Failed to get RSI value. Error: ", GetLastError()); return; } rsi_value = rsi_values[0]; double ma_short = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE); double ma_long = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE); bool is_uptrend = ma_short > ma_long; bool is_downtrend = ma_short < ma_long; if (is_uptrend && rsi_value < RSI_Oversold) { double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); double stopLossPrice = currentPrice - StopLoss * _Point; double takeProfitPrice = currentPrice + TakeProfit * _Point; // Corrected Buy method call with 6 parameters if (trade.Buy(Lots, _Symbol, 0, stopLossPrice, takeProfitPrice, "Trend Following Buy")) { Print("Trend Following Buy order placed."); } } else if (is_downtrend && rsi_value > RSI_Overbought) { double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double stopLossPrice = currentPrice + StopLoss * _Point; double takeProfitPrice = currentPrice - TakeProfit * _Point; // Corrected Sell method call with 6 parameters if (trade.Sell(Lots, _Symbol, 0, stopLossPrice, takeProfitPrice, "Trend Following Sell")) { Print("Trend Following Sell order placed."); } } } //+------------------------------------------------------------------+ //| Check Breakout Strategy | //+------------------------------------------------------------------+ void CheckBreakoutTrading() { if (PositionsTotal() >= 2) return; // Ensure no more than 2 orders from this strategy ArrayResize(ExtUpBuffer, 2); ArrayResize(ExtDnBuffer, 2); if (CopyBuffer(handle, 0, 0, 2, ExtUpBuffer) <= 0 || CopyBuffer(handle, 2, 0, 2, ExtDnBuffer) <= 0) { Print("Error reading Donchian Channel buffer. Error: ", GetLastError()); return; } double closePrice = iClose(_Symbol, PERIOD_CURRENT, 0); double lastOpen = iOpen(_Symbol, PERIOD_D1, 1); double lastClose = iClose(_Symbol, PERIOD_D1, 1); bool isBullishDay = lastClose > lastOpen; bool isBearishDay = lastClose < lastOpen; if (isBullishDay && closePrice > ExtUpBuffer[1]) { double stopLoss = closePrice - pipsToStopLoss * _Point; double takeProfit = closePrice + pipsToTakeProfit * _Point; if (trade.Buy(LotSize, _Symbol, 0, stopLoss, takeProfit, "Breakout Buy") > 0) { Print("Breakout Buy order placed."); } } else if (isBearishDay && closePrice < ExtDnBuffer[1]) { double stopLoss = closePrice + pipsToStopLoss * _Point; double takeProfit = closePrice - pipsToTakeProfit * _Point; if (trade.Sell(LotSize, _Symbol, 0, stopLoss, takeProfit, "Breakout Sell") > 0) { Print("Breakout Sell order placed."); } } } //+------------------------------------------------------------------+ //| Check Divergence Trading | //+------------------------------------------------------------------+ bool CheckBullishRegularDivergence() { double priceLow1 = iLow(_Symbol, PERIOD_CURRENT, 2); double priceLow2 = iLow(_Symbol, PERIOD_CURRENT, DivergenceLookBack); double macdLow1 = ExtMacdBuffer[2]; double macdLow2 = ExtMacdBuffer[DivergenceLookBack - 1]; return (priceLow1 < priceLow2 && macdLow1 > macdLow2); } bool CheckBullishHiddenDivergence() { double priceLow1 = iLow(_Symbol, PERIOD_CURRENT, 2); double priceLow2 = iLow(_Symbol, PERIOD_CURRENT, DivergenceLookBack); double macdLow1 = ExtMacdBuffer[2]; double macdLow2 = ExtMacdBuffer[DivergenceLookBack - 1]; return (priceLow1 > priceLow2 && macdLow1 < macdLow2); } bool CheckBearishRegularDivergence() { double priceHigh1 = iHigh(_Symbol, PERIOD_CURRENT, 2); double priceHigh2 = iHigh(_Symbol, PERIOD_CURRENT, DivergenceLookBack); double macdHigh1 = ExtMacdBuffer[2]; double macdHigh2 = ExtMacdBuffer[DivergenceLookBack - 1]; return (priceHigh1 > priceHigh2 && macdHigh1 < macdHigh2); } bool CheckBearishHiddenDivergence() { double priceHigh1 = iHigh(_Symbol, PERIOD_CURRENT, 2); double priceHigh2 = iHigh(_Symbol, PERIOD_CURRENT, DivergenceLookBack); double macdHigh1 = ExtMacdBuffer[2]; double macdHigh2 = ExtMacdBuffer[DivergenceLookBack - 1]; return (priceHigh1 < priceHigh2 && macdHigh1 > macdHigh2); } void CheckDivergenceTrading() { if (!UseDivergenceStrategy) return; // Check if no position is open or if less than 3 positions are open int openDivergencePositions = CountOrdersByMagic(DivergenceMagicNumber); if (openDivergencePositions == 0 || openDivergencePositions < 3) { int barsAvailable = Bars(_Symbol, PERIOD_CURRENT); if (barsAvailable < DivergenceLookBack * 2) { Print("Not enough data bars for MACD calculation."); return; } int attempt = 0; while(attempt < 6) { if (CopyBuffer(macd_handle, 0, 0, DivergenceLookBack, ExtMacdBuffer) > 0 && CopyBuffer(macd_handle, 1, 0, DivergenceLookBack, ExtSignalBuffer) > 0) break; Print("Failed to copy MACD buffer, retrying..."); Sleep(1000); attempt++; } if(attempt == 6) { Print("Failed to copy MACD buffers after ", attempt, " attempts."); return; } if(TimeCurrent() == iTime(_Symbol, PERIOD_CURRENT, 0)) { Print("Skipping trade due to incomplete bar data."); return; } double currentClose = iClose(_Symbol, PERIOD_CURRENT, 0); double dailyClose = iClose(_Symbol, PERIOD_D1, 0); double dailyOpen = iOpen(_Symbol, PERIOD_D1, 0); bool isDailyBullish = dailyClose > dailyOpen; bool isDailyBearish = dailyClose < dailyOpen; // Only proceed with buy orders if D1 is bullish if (isDailyBullish) { if ((CheckBullishRegularDivergence() && ExtMacdBuffer[0] > ExtSignalBuffer[0]) || CheckBullishHiddenDivergence()) { ExecuteDivergenceOrder(true); } } // Only proceed with sell orders if D1 is bearish if (isDailyBearish) { if ((CheckBearishRegularDivergence() && ExtMacdBuffer[0] < ExtSignalBuffer[0]) || CheckBearishHiddenDivergence()) { ExecuteDivergenceOrder(false); } } } else { Print("Divergence strategy: Maximum number of positions reached."); } } void ExecuteDivergenceOrder(bool isBuy) { // Ensure the magic number is set for the trade trade.SetExpertMagicNumber(DivergenceMagicNumber); double currentPrice = isBuy ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); double stopLossPrice = isBuy ? currentPrice - DivergenceStopLoss * _Point : currentPrice + DivergenceStopLoss * _Point; double takeProfitPrice = isBuy ? currentPrice + DivergenceTakeProfit * _Point : currentPrice - DivergenceTakeProfit * _Point; if (isBuy) { if (trade.Buy(DivergenceLots, _Symbol, 0, stopLossPrice, takeProfitPrice, "Divergence Buy")) { Print("Divergence Buy order placed."); } } else { if (trade.Sell(DivergenceLots, _Symbol, 0, stopLossPrice, takeProfitPrice, "Divergence Sell")) { Print("Divergence Sell order placed."); } } } int CountOrdersByMagic(int magic) { int count = 0; for (int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if (PositionSelectByTicket(ticket)) { if (PositionGetInteger(POSITION_MAGIC) == magic) { count++; } } } return count; } //+------------------------------------------------------------------+ //| Profit Locking Logic | //+------------------------------------------------------------------+ void LockProfits() { for (int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if (PositionSelectByTicket(ticket)) { double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN); double currentProfit = PositionGetDouble(POSITION_PROFIT); double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT); // Convert profit to points double profitPoints = MathAbs(currentProfit / _Point); // Check if profit has exceeded 100 points if (profitPoints >= 100) { double newStopLoss; if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { newStopLoss = entryPrice + profitLockerPoints * _Point; // 20 points above entry for buys } else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { newStopLoss = entryPrice - profitLockerPoints * _Point; // 20 points below entry for sells } else { continue; // Skip if not a buy or sell position } // Modify stop loss only if the new stop loss is more protective double currentStopLoss = PositionGetDouble(POSITION_SL); if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { if (currentStopLoss < newStopLoss || currentStopLoss == 0) { if (trade.PositionModify(ticket, newStopLoss, PositionGetDouble(POSITION_TP))) { Print("Profit locking for buy position: Stop Loss moved to ", newStopLoss); } } } else // POSITION_TYPE_SELL { if (currentStopLoss > newStopLoss || currentStopLoss == 0) { if (trade.PositionModify(ticket, newStopLoss, PositionGetDouble(POSITION_TP))) { Print("Profit locking for sell position: Stop Loss moved to ", newStopLoss); } } } } } } } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if (UseTrendFollowingStrategy) CheckTrendFollowing(); if (UseBreakoutStrategy) CheckBreakoutTrading(); if (UseDivergenceStrategy) CheckDivergenceTrading(); if(UseGoldenDeathCrossStrategy) CheckGoldenDeathCross(); }
Test- und Optimierungsergebnisse
Der Trend Constraint Experte: Hinzufügen zum Chart mit Standardeinstellungen
Visualisierung des Goldenen und des Todeskreuzes als Teil anderer Strategien im Strategietester
Schlussfolgerung
Es ist zwar möglich, unseren EA-Code ständig zu erweitern, aber dadurch wird er immer komplexer und ressourcenintensiver in der Verarbeitung. Dies unterstreicht die Notwendigkeit, unsere Techniken der Ressourcenverwaltung zu verbessern. Die Integration von KI-Modellen in diese Konzepte ist besonders vorteilhaft, da sie diese Komplexität effektiv bewältigen können. In diesem Projekt haben wir erfolgreich eine der beliebtesten Strategien für das Management von Umkehrchancen - die neue Strategie des Goldenen und des Todeskreuzes - in den Trend Constraint Expert Advisor integriert.
Das Fundament, das wir von Teil (1) bis jetzt behandelt haben, legten den Grundstein für diesen EA. Um jedoch optimale Ergebnisse zu erzielen, muss der EA durch die Optimierung verschiedener Einstellungen und die Änderung bestimmter struktureller Merkmale verfeinert werden. Dieser Ansatz macht es zu einem wertvollen pädagogischen und experimentellen Instrument. Bitte beachten Sie, dass dieser EA keine Gewinne garantiert; er ist ausschließlich für Bildungs- und Forschungszwecke gedacht.
In den kommenden Teilen plane ich, die bewährten Strategien weiter zu verfeinern und Techniken des maschinellen Lernens einzuführen, um die Fähigkeiten und die Leistung des EA zu verbessern.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16633





- 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.