
Entwicklung eines Toolkit zur Analyse von Preisaktionen (Teil 7): Der EA Signal Pulse
Inhalt
Einführung
In diesem Artikel werden wir untersuchen, wie man einen Expert Advisor (EA) in MQL5 namens Signal Pulse EA entwickelt. Der EA verwendet eine Kombination aus Bollinger Bands und Stochastik-Oszillator-Indikatoren in drei verschiedenen Zeitrahmen, um Kauf- und Verkaufssignale zu erkennen. Dieser EA soll Händlern helfen, fundierte Entscheidungen zu treffen, indem er Signale aus mehreren Zeitrahmen bestätigt, bevor sie einen Handel eingehen. Wir haben mehrere Zeitrahmen, Bollinger Bands (BB) und den Stochastic Oscillator für die Signalgenerierung integriert. Unser Ziel ist es, falsche Signale, die für Händler frustrierend sein können, zu minimieren. Durch die Kombination dieser Elemente wollen wir die Genauigkeit unserer Handelssignale verbessern. Im Folgenden habe ich die Bedeutung der einzelnen Komponenten unseres Signalerzeugungstools tabellarisch dargestellt.
- Mehrere Zeitrahmen
Vorteil | Beschreibung |
---|---|
Risikomanagement | Durch die Verwendung mehrerer Zeitrahmen kann der EA den Markt aus verschiedenen Blickwinkeln analysieren, was die Auswirkungen von Fehlsignalen verringert und das Risikomanagement verbessert. |
Vertrauen in Signale | Durch die Bestätigung von Signalen über mehrere Zeitrahmen hinweg gewinnt der EA Vertrauen in die Handelsrichtung und verringert die Wahrscheinlichkeit, einen Handel mit einem schwachen oder falschen Signal einzugehen. |
Diversifizierung | Die Analyse mehrerer Zeitrahmen bietet eine breitere Sicht auf den Markt, die es dem EA ermöglicht, sich an veränderte Marktbedingungen anzupassen und fundiertere Handelsentscheidungen zu treffen. |
- Stochastic
Vorteil | Beschreibung |
---|---|
Überkauf/Überverkauf Bedingungen | Die Stochastik hilft dabei, überkaufte und überverkaufte Bedingungen zu erkennen, die auf potenzielle Umkehrpunkte auf dem Markt hinweisen. |
Bestätigungswerkzeug | Die Stochastik dient als Bestätigungsinstrument für die Bollinger Bänder und stellt sicher, dass der EA nicht allein aufgrund von BB-Signalen in den Handel einsteigt. |
Falsche Signale herausfiltern | Durch die Verwendung der Stochastik kann der EA falsche Signale herausfiltern, die von den Bollinger-Bändern erzeugt werden, insbesondere in Zeiten hoher Volatilität. |
- Bollinger-Bänder
Vorteil | Beschreibung |
---|---|
Volatilitätsindikator | Bollinger Bänder zeigen den Grad der Volatilität im Markt an und helfen dem EA, die Stimmung des Marktes und potenzielle Handelsmöglichkeiten zu verstehen. |
Unterstützungs-/Widerstandsniveaus | Bollinger Bänder fungieren als dynamische Unterstützungs- und Widerstandsniveaus, die dem EA potenzielle Einstiegs- und Ausstiegspunkte bieten. |
Trendbestätigung | Die Breite der Bollinger-Bänder kann das Vorhandensein eines Trends bestätigen oder verneinen und hilft dem EA, fundierte Handelsentscheidungen zu treffen. |
Die Interaktion zwischen mehreren Zeitrahmen, der Stochastik und den Bollinger Bändern (BB) steigert die Effektivität des EA bei der Generierung zuverlässiger Handelssignale und dem Risikomanagement erheblich. Durch die Analyse von Signalen über verschiedene Zeitrahmen hinweg stellt der EA sicher, dass Handelsmöglichkeiten durch ein starkes Zusammentreffen von Indikatoren sowohl der Stochastik als auch der BB bestätigt werden. Dieser mehrdimensionale Ansatz verringert die Wahrscheinlichkeit von Fehlsignalen, da der EA potenzielle Handelsgeschäfte nur dann identifiziert, wenn es robuste Beweise gibt, die die Entscheidung unterstützen. Durch die Kombination dieser Elemente wird die Zuverlässigkeit der generierten Signale erhöht und das Risikomanagement insgesamt verbessert, sodass die Händler fundiertere Entscheidungen auf der Grundlage eines höheren Maßes an Vertrauen und Präzision treffen können.
Die Strategie verstehen
Das Signal Pulse Skript generiert Handelssignale basierend auf der Ausrichtung der Bollinger Bänder und des Stochastik Oszillators über drei Zeitrahmen (M15, M30 und H1). Die Bedingungen für jedes Signal sind wie folgt:
Kaufsignal
- Bedingung der Bollinger Bänder: Der Kurs berührt das untere Band der Bollinger Bänder auf allen drei Zeitskalen.
- Bedingung des Oszillators Stochastic: Der Stochastic Oscillator zeigt auf allen drei Zeitebenen einen überverkauften Zustand an, der in der Regel unter 20 liegt.
- Bestätigungsanforderung: Beide Bedingungen müssen gleichzeitig im M15-, M30- und H1-Zeitrahmen erfüllt sein, um ein Kaufsignal zu generieren.
Abb. 1. Bedingungen zum Kaufen
Verkaufssignal
- Bedingung der Bollinger Bänder: Der Kurs berührt das obere Band der Bollinger Bänder auf allen drei Zeitskalen.
- Bedingung des Oszillators Stochastic: Der Stochastic Oscillator zeigt auf allen drei Zeitebenen einen überkauften Zustand an, der in der Regel über 80 liegt.
- Bestätigungsanforderung: Beide Bedingungen müssen gleichzeitig im M15-, M30- und H1-Zeitrahmen erfüllt sein, um ein Verkaufssignal zu generieren.
Abb. 2. Bedingungen zum Verkauf
Veranschaulichen wir uns diesen Prozess anhand des folgenden Diagramms.
Abb. 3. Prozess der Signalerzeugung
MQL5 Code
//+------------------------------------------------------------------+ //| Signal Pulse EA.mq5 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" // Input parameters input ENUM_TIMEFRAMES Timeframe1 = PERIOD_M15; // M15 timeframe input ENUM_TIMEFRAMES Timeframe2 = PERIOD_M30; // M30 timeframe input ENUM_TIMEFRAMES Timeframe3 = PERIOD_H1; // H1 timeframe input int BB_Period = 20; // Bollinger Bands period input double BB_Deviation = 2.0; // Bollinger Bands deviation input int K_Period = 14; // Stochastic %K period input int D_Period = 3; // Stochastic %D period input int Slowing = 3; // Stochastic slowing input double SignalOffset = 10.0; // Offset in points for signal arrow input int TestBars = 10; // Number of bars after signal to test win condition input double MinArrowDistance = 5.0; // Minimum distance in points between arrows to avoid overlapping // Signal tracking structure struct SignalInfo { datetime time; double price; bool isBuySignal; }; // Arrays to store signal information datetime signalTimes[]; double signalPrices[]; bool signalBuySignals[]; //+------------------------------------------------------------------+ //| Retrieve Bollinger Band Levels | //+------------------------------------------------------------------+ bool GetBollingerBands(ENUM_TIMEFRAMES timeframe, double &upper, double &lower, double &middle) { int handle = iBands(Symbol(), timeframe, BB_Period, 0, BB_Deviation, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Error creating iBands for timeframe: ", timeframe); return false; } double upperBand[], middleBand[], lowerBand[]; if(!CopyBuffer(handle, 1, 0, 1, upperBand) || !CopyBuffer(handle, 0, 0, 1, middleBand) || !CopyBuffer(handle, 2, 0, 1, lowerBand)) { Print("Error copying iBands buffer for timeframe: ", timeframe); IndicatorRelease(handle); return false; } upper = upperBand[0]; middle = middleBand[0]; lower = lowerBand[0]; IndicatorRelease(handle); return true; } //+------------------------------------------------------------------+ //| Retrieve Stochastic Levels | //+------------------------------------------------------------------+ bool GetStochastic(ENUM_TIMEFRAMES timeframe, double &k_value, double &d_value) { int handle = iStochastic(Symbol(), timeframe, K_Period, D_Period, Slowing, MODE_SMA, STO_CLOSECLOSE); if(handle == INVALID_HANDLE) { Print("Error creating iStochastic for timeframe: ", timeframe); return false; } double kBuffer[], dBuffer[]; if(!CopyBuffer(handle, 0, 0, 1, kBuffer) || // %K line !CopyBuffer(handle, 1, 0, 1, dBuffer)) // %D line { Print("Error copying iStochastic buffer for timeframe: ", timeframe); IndicatorRelease(handle); return false; } k_value = kBuffer[0]; d_value = dBuffer[0]; IndicatorRelease(handle); return true; } //+------------------------------------------------------------------+ //| Check and Generate Signal | //+------------------------------------------------------------------+ void CheckAndGenerateSignal() { double upper1, lower1, middle1, close1; double upper2, lower2, middle2, close2; double upper3, lower3, middle3, close3; double k1, d1, k2, d2, k3, d3; if(!GetBollingerBands(Timeframe1, upper1, lower1, middle1) || !GetBollingerBands(Timeframe2, upper2, lower2, middle2) || !GetBollingerBands(Timeframe3, upper3, lower3, middle3)) { Print("Error retrieving Bollinger Bands data."); return; } if(!GetStochastic(Timeframe1, k1, d1) || !GetStochastic(Timeframe2, k2, d2) || !GetStochastic(Timeframe3, k3, d3)) { Print("Error retrieving Stochastic data."); return; } // Retrieve the close prices close1 = iClose(Symbol(), Timeframe1, 0); close2 = iClose(Symbol(), Timeframe2, 0); close3 = iClose(Symbol(), Timeframe3, 0); bool buySignal = (close1 <= lower1 && close2 <= lower2 && close3 <= lower3) && (k1 < 5 && k2 < 5 && k3 < 5); // Oversold condition bool sellSignal = (close1 >= upper1 && close2 >= upper2 && close3 >= upper3) && (k1 > 95 && k2 > 95 && k3 > 95); // Overbought condition // Check if an arrow already exists in the same region before placing a new one if(buySignal && !ArrowExists(close1)) { Print("Buy signal detected on all timeframes with Stochastic confirmation!"); string arrowName = "BuySignal" + IntegerToString(TimeCurrent()); ObjectCreate(0, arrowName, OBJ_ARROW, 0, TimeCurrent(), close1); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 241); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrGreen); ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2); // Store signal data ArrayResize(signalTimes, ArraySize(signalTimes) + 1); ArrayResize(signalPrices, ArraySize(signalPrices) + 1); ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + 1); signalTimes[ArraySize(signalTimes) - 1] = TimeCurrent(); signalPrices[ArraySize(signalPrices) - 1] = close1; signalBuySignals[ArraySize(signalBuySignals) - 1] = true; } if(sellSignal && !ArrowExists(close1)) { Print("Sell signal detected on all timeframes with Stochastic confirmation!"); string arrowName = "SellSignal" + IntegerToString(TimeCurrent()); ObjectCreate(0, arrowName, OBJ_ARROW, 0, TimeCurrent(), close1); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 242); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrRed); ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2); // Store signal data ArrayResize(signalTimes, ArraySize(signalTimes) + 1); ArrayResize(signalPrices, ArraySize(signalPrices) + 1); ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + 1); signalTimes[ArraySize(signalTimes) - 1] = TimeCurrent(); signalPrices[ArraySize(signalPrices) - 1] = close1; signalBuySignals[ArraySize(signalBuySignals) - 1] = false; } } //+------------------------------------------------------------------+ //| Check if an arrow already exists within the MinArrowDistance | //+------------------------------------------------------------------+ bool ArrowExists(double price) { for(int i = 0; i < ArraySize(signalPrices); i++) { if(MathAbs(signalPrices[i] - price) <= MinArrowDistance) { return true; // Arrow exists in the same price region } } return false; // No arrow exists in the same region } //+------------------------------------------------------------------+ //| OnTick Event | //+------------------------------------------------------------------+ void OnTick() { CheckAndGenerateSignal(); } //+------------------------------------------------------------------+ //| OnDeinit Function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Clean up the objects long chart_id = 0; for(int i = ObjectsTotal(chart_id) - 1; i >= 0; i--) { string name = ObjectName(chart_id, i); if(StringFind(name, "Signal") != -1) { ObjectDelete(chart_id, name); } } Print("Multitimeframe Bollinger-Stochastic Analyzer deinitialized."); } //+------------------------------------------------------------------+
Code-Aufschlüsselung
In dieser Aufschlüsselung des Signal Pulse EA werden die verschiedenen Komponenten des Expert Advisors, seine Funktionsmechanismen und die zugrundeliegende Logik seiner Funktionalitäten Schritt für Schritt erläutert. - Kopfzeilen, Eigenschaften und Eingabeparameter
Ganz am Anfang unseres EAs stehen die Kopfzeilen, die wichtige Metadaten enthalten. Diese besteht aus dem Namen des EA, Angaben zum Urheberrecht und einem Link, über den Sie mehr über unsere Arbeit erfahren können. Aber was Ihnen als Händler wirklich hilft, sind die Eingabeparameter. Diese anpassbaren Einstellungen ermöglichen es Ihnen, das Verhalten des EAs an Ihren Handelsstil anzupassen.
//+------------------------------------------------------------------+ //| Signal Pulse EA.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Christian Benjamin" #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.00" // Input parameters input ENUM_TIMEFRAMES Timeframe1 = PERIOD_M15; // M15 timeframe input ENUM_TIMEFRAMES Timeframe2 = PERIOD_M30; // M30 timeframe input ENUM_TIMEFRAMES Timeframe3 = PERIOD_H1; // H1 timeframe input int BB_Period = 20; // Bollinger Bands period input double BB_Deviation = 2.0; // Bollinger Bands deviation input int K_Period = 14; // Stochastic %K period input int D_Period = 3; // Stochastic %D period input int Slowing = 3; // Stochastic slowing input double SignalOffset = 10.0; // Offset in points for signal arrow input int TestBars = 10; // Number of bars after signal to test win condition input double MinArrowDistance = 5.0; // Minimum distance in points between arrows to avoid overlappingHier legen wir verschiedene Zeitrahmen fest (M15, M30 und H1), die es Ihnen ermöglichen, Kursbewegungen über mehrere Zeiträume hinweg zu analysieren. Wir definieren auch Parameter für die Bollinger-Bänder, wie z. B. ihre Periode und Abweichung, sowie Einstellungen für den Stochastik-Oszillator, einschließlich seiner %K- und %D-Perioden. Wir bieten sogar visuelle Einstellungen für die Pfeile, die Kauf- und Verkaufssignale auf Ihrem Chart markieren, sowie Parameter, die die visuelle Unübersichtlichkeit minimieren, indem sie überlappende Pfeile verhindern.
- Signalverfolgung und Strukturen
Als Nächstes definieren wir die SignalInfo-Struktur, die eine wichtige Rolle bei der Organisation unserer Handelssignale spielt. Diese Struktur sammelt Informationen darüber, wann ein Signal aufgetreten ist, wie hoch der Preis zu diesem Zeitpunkt war und ob es sich um ein Kauf- oder Verkaufssignal handelte. Außerdem richten wir Arrays ein, um diese Informationen dynamisch zu speichern.
// Signal tracking structure struct SignalInfo { datetime time; double price; bool isBuySignal; }; // Arrays to store signal information datetime signalTimes[]; double signalPrices[]; bool signalBuySignals[];Mit den Arrays signalTimes, signalPrices und signalBuySignals führen wir eine klare Aufzeichnung der Handelssignale, die der EA im Laufe der Zeit generiert, sodass es viel einfacher ist, mit mehreren Signalen umzugehen, ohne durcheinander zu kommen.
- Funktionen zum Abrufen von Indikatoren
Lassen Sie uns nun auf die Funktionen eingehen, die wir zum Abrufen von Indikatorwerten verwenden, insbesondere die Bollinger-Bänder und den Stochastik Oszillator.
//+------------------------------------------------------------------+ //| Retrieve Bollinger Band Levels | //+------------------------------------------------------------------+ bool GetBollingerBands(ENUM_TIMEFRAMES timeframe, double &upper, double &lower, double &middle) { int handle = iBands(Symbol(), timeframe, BB_Period, 0, BB_Deviation, PRICE_CLOSE); if(handle == INVALID_HANDLE) { Print("Error creating iBands for timeframe: ", timeframe); return false; } double upperBand[], middleBand[], lowerBand[]; if(!CopyBuffer(handle, 1, 0, 1, upperBand) || !CopyBuffer(handle, 0, 0, 1, middleBand) || !CopyBuffer(handle, 2, 0, 1, lowerBand)) { Print("Error copying iBands buffer for timeframe: ", timeframe); IndicatorRelease(handle); return false; } upper = upperBand[0]; middle = middleBand[0]; lower = lowerBand[0]; IndicatorRelease(handle); return true; } //+------------------------------------------------------------------+ //| Retrieve Stochastic Levels | //+------------------------------------------------------------------+ bool GetStochastic(ENUM_TIMEFRAMES timeframe, double &k_value, double &d_value) { int handle = iStochastic(Symbol(), timeframe, K_Period, D_Period, Slowing, MODE_SMA, STO_CLOSECLOSE); if(handle == INVALID_HANDLE) { Print("Error creating iStochastic for timeframe: ", timeframe); return false; } double kBuffer[], dBuffer[]; if(!CopyBuffer(handle, 0, 0, 1, kBuffer) || // %K line !CopyBuffer(handle, 1, 0, 1, dBuffer)) { // %D line Print("Error copying iStochastic buffer for timeframe: ", timeframe); IndicatorRelease(handle); return false; } k_value = kBuffer[0]; d_value = dBuffer[0]; IndicatorRelease(handle); return true; }Die erste Funktion, GetBollingerBands(), ermittelt das obere, mittlere und untere Niveau der Bollinger-Bänder für einen bestimmten Zeitrahmen. Er erstellt einen Handle für den Indikator und prüft, ob er erfolgreich erstellt wurde. Wenn alles in Ordnung ist, werden die Bandwerte in Arrays kopiert, die wir später für unsere Handelslogik verwenden können. In ähnlicher Weise ruft die Funktion GetStochastic() die Werte %K und %D des stochastischen Oszillators ab. Es verwendet dieselben Verfahren zur Fehlerprüfung und Datenkopie, um sicherzustellen, dass wir stets korrekte Daten für unsere Entscheidungsfindung erhalten.
- Signalüberprüfung und -generierung
Nachdem wir uns um die Indikatoren gekümmert haben, gehen wir nun zur Funktion CheckAndGenerateSignal() über, die die Kernlogik unseres EA enthält. Diese Funktion ruft unsere zuvor definierten Indikatorfunktionen auf, um Daten der Indikatoren Bollinger Bänder und Stochastic über alle angegebenen Zeitrahmen zu sammeln. Außerdem werden die letzten Schlusskurse für diese Zeiträume ermittelt.
Die Funktion sucht auf der Grundlage der aktuellen Marktbedingungen nach Kauf- und Verkaufssignalen. Ein Kaufsignal wird ausgelöst, wenn die Schlusskurse unter dem unteren Bollinger Band liegen und die Stochastik-Werte auf überverkaufte Bedingungen hinweisen (weniger als 5). Umgekehrt entstehen Verkaufssignale, wenn die Kurse das obere Bollinger Band überschreiten und der Stochastic über 95 anzeigt, was auf überkaufte Bedingungen hindeutet.
//+------------------------------------------------------------------+ //| Check and Generate Signal | //+------------------------------------------------------------------+ void CheckAndGenerateSignal() { double upper1, lower1, middle1, close1; double upper2, lower2, middle2, close2; double upper3, lower3, middle3, close3; double k1, d1, k2, d2, k3, d3; if(!GetBollingerBands(Timeframe1, upper1, lower1, middle1) || !GetBollingerBands(Timeframe2, upper2, lower2, middle2) || !GetBollingerBands(Timeframe3, upper3, lower3, middle3)) { Print("Error retrieving Bollinger Bands data."); return; } if(!GetStochastic(Timeframe1, k1, d1) || !GetStochastic(Timeframe2, k2, d2) || !GetStochastic(Timeframe3, k3, d3)) { Print("Error retrieving Stochastic data."); return; } // Retrieve the close prices close1 = iClose(Symbol(), Timeframe1, 0); close2 = iClose(Symbol(), Timeframe2, 0); close3 = iClose(Symbol(), Timeframe3, 0); bool buySignal = (close1 <= lower1 && close2 <= lower2 && close3 <= lower3) && (k1 < 5 && k2 < 5 && k3 < 5); // Oversold condition bool sellSignal = (close1 >= upper1 && close2 >= upper2 && close3 >= upper3) && (k1 > 95 && k2 > 95 && k3 > 95); // Overbought condition // Check if an arrow already exists in the same region before placing a new one if(buySignal && !ArrowExists(close1)) { Print("Buy signal detected on all timeframes with Stochastic confirmation!"); string arrowName = "BuySignal" + IntegerToString(TimeCurrent()); ObjectCreate(0, arrowName, OBJ_ARROW, 0, TimeCurrent(), close1); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 241); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrGreen); ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2); // Store signal data ArrayResize(signalTimes, ArraySize(signalTimes) + 1); ArrayResize(signalPrices, ArraySize(signalPrices) + 1); ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + 1); signalTimes[ArraySize(signalTimes) - 1] = TimeCurrent(); signalPrices[ArraySize(signalPrices) - 1] = close1; signalBuySignals[ArraySize(signalBuySignals) - 1] = true; } if(sellSignal && !ArrowExists(close1)) { Print("Sell signal detected on all timeframes with Stochastic confirmation!"); string arrowName = "SellSignal" + IntegerToString(TimeCurrent()); ObjectCreate(0, arrowName, OBJ_ARROW, 0, TimeCurrent(), close1); ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 242); ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrRed); ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2); // Store signal data ArrayResize(signalTimes, ArraySize(signalTimes) + 1); ArrayResize(signalPrices, ArraySize(signalPrices) + 1); ArrayResize(signalBuySignals, ArraySize(signalBuySignals) + 1); signalTimes[ArraySize(signalTimes) - 1] = TimeCurrent(); signalPrices[ArraySize(signalPrices) - 1] = close1; signalBuySignals[ArraySize(signalBuySignals) - 1] = false; } }
Außerdem stellt die Funktion vor der Platzierung eines Pfeils zur Anzeige eines Signals im Chart sicher, dass sich kein bestehender Pfeil überschneidet, indem sie die Funktion ArrowExists() aufruft. Wenn alles in Ordnung ist, wird der entsprechende Pfeil erstellt und die Informationen über das Signal in den zuvor definierten Arrays gespeichert.
- Existenzprüfung des Pfeils
In unserem Streben nach einem aufgeräumten Chart spielt die Funktion ArrowExists() eine wichtige Rolle, indem sie prüft, ob sich ein vorhandener Pfeil in der Nähe des Preises des aktuellen Signals befindet. Dadurch wird verhindert, dass sich mehrere Pfeile überschneiden, was zu Verwechslungen führen könnte. Durch den Vergleich des neuen Signalpreises mit den im Array signalPrices gespeicherten Preisen wird festgestellt, ob ein vorhandener Pfeil nahe genug ist, um die Erstellung eines neuen zu überspringen.
//+------------------------------------------------------------------+ //| Check if an arrow already exists within the MinArrowDistance | //+------------------------------------------------------------------+ bool ArrowExists(double price) { for(int i = 0; i < ArraySize(signalPrices); i++) { if(MathAbs(signalPrices[i] - price) <= MinArrowDistance) { return true; // Arrow exists in the same price region } } return false; // No arrow exists in the same region }
- Die Funktionen OnTick und OnDeinit
Schließlich gibt es noch die Funktionen OnTick() und OnDeinit(). Die Funktion OnTick() wird jedes Mal aufgerufen, wenn es einen neuen Markttick gibt, um sicherzustellen, dass unser EA reaktionsfähig und aktuell bleibt. Sie ruft die Funktion CheckAndGenerateSignal() auf, um potenzielle Handelssignale auf der Grundlage der neuesten Daten neu zu bewerten.
Im Gegensatz dazu wird die Funktion OnDeinit() aufgerufen, wenn der EA entfernt oder das Terminal geschlossen wird. Seine Aufgabe ist es, alle vom EA erstellten grafischen Objekte zu bereinigen - insbesondere die Pfeile, die Kauf- und Verkaufssignale markieren - und so für ein übersichtliches Chart zu sorgen.
//+------------------------------------------------------------------+ //| OnTick Event | //+------------------------------------------------------------------+ void OnTick() { CheckAndGenerateSignal(); } //+------------------------------------------------------------------+ //| OnDeinit Function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Clean up the objects long chart_id = 0; for(int i = ObjectsTotal(chart_id) - 1; i >= 0; i--) { string name = ObjectName(chart_id, i); if(StringFind(name, "Signal") != -1) { ObjectDelete(chart_id, name); } } Print("Multitimeframe Bollinger-Stochastic Analyzer deinitialized."); }
Darüber hinaus haben wir im Signal Pulse EA die Schwellenwerte für den stochastischen Oszillator angepasst, um sicherzustellen, dass nur die zuverlässigsten Signale erzeugt werden. Diese Anpassungen konzentrieren sich darauf, zu bestätigen, dass sich der Markt in einem extremen Zustand befindet - entweder überverkauft bei Kaufsignalen oder überkauft bei Verkaufssignalen - bevor gehandelt wird.
- Überverkaufter Zustand: Kaufsignal
bool buySignal = (close1 <= lower1 && close2 <= lower2 && close3 <= lower3) && (k1 < 5 && k2 < 5 && k3 < 5); // Oversold condition
Für ein Kaufsignal muss der Kurs in allen drei Zeitrahmen (M15, M30, H1) am oder unter dem unteren Bollinger Band liegen, was auf einen starken Abwärtsdruck hindeutet. Außerdem muss der %K-Wert des Stochastik-Oszillators in allen drei Zeitrahmen unter 5 liegen. Dieser Wert deutet auf einen extrem überverkauften Zustand hin, in dem der Markt höchstwahrscheinlich nach oben drehen wird. Der strengere Schwellenwert von < 5 stellt sicher, dass der EA nur Signale berücksichtigt, bei denen die Wahrscheinlichkeit einer Umkehrung signifikant hoch ist.
- Überkaufter Zustand: Verkaufssignal
bool sellSignal = (close1 >= upper1 && close2 >= upper2 && close3 >= upper3) && (k1 > 95 && k2 > 95 && k3 > 95); // Overbought condition
Für ein Verkaufssignal muss der Kurs in allen drei Zeitrahmen am oder über dem oberen Bollinger Band liegen, was auf ein starkes Aufwärtsmomentum hinweist, das sich bald umkehren könnte. Der %K-Wert des Stochastik-Oszillators muss in allen Zeitrahmen über 95 liegen, was auf einen extrem überkauften Zustand hindeutet, in dem der Markt wahrscheinlich nach unten drehen wird. Diese strenge Bedingung stellt sicher, dass der EA falsche Verkaufssignale bei moderaten Kursbewegungen oder Konsolidierungen vermeidet.
Tests und Ergebnisse
- Backtesting mit historischen Daten
1. Laden der historischen Daten
Um mit dem Backtesting zu beginnen, müssen Sie unbedingt hochwertige historische Daten auf Tick-Ebene für das gewählte Instrument und den gewählten Zeitrahmen laden. Diese Daten dienen als Grundlage für die Bewertung der Leistung der EA. Es ist von entscheidender Bedeutung, dass die Daten genau und zuverlässig sind, da Unstimmigkeiten zu falschen Schlussfolgerungen über die Leistung der EA führen können.
Sobald die Daten geladen sind, ist es an der Zeit, den Strategietester im MetaTrader mit den erforderlichen Parametern zu konfigurieren. Dazu gehören:2. Prüfparameter festlegen
- Symbol: Wählen Sie das Währungspaar oder den Vermögenswert, mit dem Sie handeln möchten.
- Period: Verwenden Sie die gleichen Zeitrahmen wie die Einstellungen des EA (z. B. M15, M30, H1).
- Spread: Legen Sie einen realistischen oder fixen Spread fest, um die Handelskosten zu simulieren und sicherzustellen, dass die Ergebnisse repräsentativ für reale Handelsbedingungen sind.
- Optimierung: Testen Sie die Eingabeparameter (z. B. Bollinger-Band-Periode, Stochastik-Schwellenwerte) auf optimale Leistung.
3. Ergebnisse auswertenNachdem die Testparameter festgelegt wurden, ist es an der Zeit, die Ausgabemetriken zu analysieren:
- Rentabilität: Bewerten Sie den Nettogewinn und den Gewinnfaktor des EA, um seine Gesamtrentabilität zu ermitteln.
- Risiko: Beurteilen Sie den maximalen Drawdown, um die Risikotoleranz des EA zu ermitteln.
- Gewinnrate und Handelshäufigkeit: Analysieren Sie die Anzahl der erfolgreichen Trades und die Handelshäufigkeit, um die Leistung des EA unter verschiedenen Marktbedingungen zu verstehen.
Schauen wir uns die unten aufgeführten Testergebnisse an.
Abb. 4. Testergebnis 1
Abb. 5. Testergebnis 2
Die obigen Charts veranschaulichen den Leistungstest des EA. Im GIF können wir die Aufzeichnung jedes erkannten Signals beobachten. Sie können weitere Tests durchführen, indem Sie Eingabeparameter, Zeitrahmen und stochastische Niveaus ändern, bis Sie Ergebnisse erzielen, die Ihren Anforderungen entsprechen.
Schlussfolgerung
In diesem Artikel haben wir den „Pulse Trader“ Expert Advisor entwickelt, der die Indikatoren Bollinger Bands und Stochastic Oscillator kombiniert, um Handelssignale für die Zeitrahmen M15, M30 und H1 zu generieren. Das System erkennt überkaufte/überverkaufte Bedingungen nur, wenn mehrere Zeitrahmen übereinstimmen, was die Erfolgswahrscheinlichkeit erhöht. Gründliches Backtesting unter verschiedenen Marktbedingungen ist unerlässlich. Zukünftige Verbesserungen könnten das Hinzufügen von Trendrichtungsfiltern, ein erweitertes Risikomanagement und die Verfeinerung der Signallogik für verschiedene Markttypen umfassen. Wir ermutigen Händler, „Signal Pulse“ zusammen mit ihren eigenen Strategien und Techniken zu verwenden, um einen umfassenden Ansatz für den Handel zu erhalten.
Datum | Name des Werkzeugs | Beschreibung | Version | Aktualisierungen | Hinweis |
---|---|---|---|---|---|
01/10/24 | Chart Projector | Skript zur Überlagerung der Kursentwicklung des Vortages mit Geistereffekt. | 1.0 | Erste Veröffentlichung | Erstes Werkzeug in Lynnchris Tool Chest |
18/11/24 | Analytical Comment | Er liefert Informationen zum Vortag in Tabellenform und nimmt die zukünftige Marktentwicklung vorweg. | 1.0 | Erste Veröffentlichung | Zweites Werkzeug in Lynnchris Tool Chest |
27/11/24 | Analytics Master | Regelmäßige Aktualisierung der Marktmetriken alle zwei Stunden | 1.01 | Zweite Veröffentlichung | Drittes Werkzeug in Lynnchris Tool Chest |
02/12/24 | Analytics Forecaster | Regelmäßige Aktualisierung der Marktmetriken alle zwei Stunden mit Telegram-Integration | 1.1 | Dritte Auflage | Werkzeug Nummer 4 |
09/12/24 | Volatility Navigator | Der EA analysiert die Marktbedingungen anhand der Indikatoren Bollinger Bands, RSI und ATR | 1.0 | Erste Veröffentlichung | Werkzeug Nummer 5 |
19/12/24 | Mean Reversion Signal Reaper | Analysiert den Markt anhand der Mean-Reversion-Strategie und liefert Signale | 1.0 | Erste Veröffentlichung | Werkzeug Nummer 6 |
9/01/2025 | Signal Pulse | Analysator für mehrere Zeitrahmen | 1.0 | Erste Veröffentlichung | Werkzeug Nummer 7 |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16861





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