
Tests von verschiedenen gleitenden Durchschnitten, um zu sehen, wie aufschlussreich sie sind
Einführung
In meinem vorherigen Artikel haben wir die gängigsten Arten von gleitenden Durchschnitten (einfache, gewichtete, exponentielle) betrachtet: Lernen Sie, wie man verschiedene Systeme mit gleitenden Durchschnitten entwirft. Wir werden dieses Thema in diesem Artikel fortsetzen und den einfachen Typ verwenden, um seine Ergebnisse mit anderen Arten von gleitenden Durchschnitten zu vergleichen. Viele Händler verwenden den gleitenden Durchschnitt in den verschiedenen Arten je nach ihren Vorlieben. Daher werden wir in diesem Artikel verschiedene Arten von ihnen im Detail betrachten, ihre Leistungen testen und die Ergebnisse vergleichen, um zu bestimmen, welche der Arten besser abschneidet.
In diesem Artikel werden wir eine einfache Anwendung erstellen, um ein Backtesting der Durchschnittswerte im integrierten MetaTrader 5 Strategy Tester durchzuführen. Um zu verstehen, worauf wir uns bei der Untersuchung von Testergebnissen konzentrieren müssen, lesen Sie bitte meinen früheren Artikel MQL5 Strategietester verstehen und effektiv nutzen; er enthält eine Menge nützlicher Informationen.
Um die verschiedenen Arten von gleitenden Durchschnitten zu betrachten und zu sehen, wie sie funktionieren, werden wir die folgenden Themen durchgehen:
- Einfacher gleitender Durchschnitt (SMA) Systemtest
- Adaptiver gleitender Durchschnitt (iAMA)
- Doppelt exponentiell gleitender Durchschnitt (iDEMA)
- Dreifacher Exponentieller Gleitender Durchschnitt (iTEMA)
- Fraktaler Adaptiver gleitender Durchschnitt (iFrAMA)
- Vergleich der Ergebnisse mit den Ergebnissen des einfachen gleitenden Durchschnitts (SMA)
- Schlussfolgerung
Bitte beachten Sie, dass ich zwar versuchen werde, die Einstellungen jedes gleitenden Durchschnitts zu optimieren, um die besten Ergebnisse zu erzielen, dass Sie aber selbst mehr überprüfen und testen müssen, da es hier nur um Ausbildung geht. Sie sollten also testen, optimieren und bessere Einstellungen finden, mit denen Sie bessere Ergebnisse erzielen können. Es kann vorkommen, dass eine oder alle dieser Arten nicht für Ihren Handelsstil geeignet sind. Aber ich hoffe, dass Sie Einblicke finden, die Ihnen bei der Verbesserung Ihres Handels behilflich sein können. Unabhängig vom Ideal ist es wichtig, die Leistung jeder Handelsstrategie zu messen, bevor man sie in einem realen Konto einsetzt.
Einfacher gleitender Durchschnitt (SMA) Systemtest
In diesem Teil werde ich die Ergebnisse des einfachen Systems vorstellen, das nur auf einer einfachen Strategie mit einem gleitenden Durchschnitt basiert. Es findet die Kreuzung zwischen dem Preis und der einfachen gleitenden Durchschnittslinie, die Kauf- und Verkaufssignale erzeugt. Wir werden ein System entwickeln, das diese Signale automatisch ausführen kann.
Wir werden die folgenden Signale verwenden, um Handelsoperationen durchzuführen:
Kaufsignal:
Der Schlusskurs liegt über dem einfachen gleitenden Durchschnitt.
Und: Der vorherige Schlusskurs lag unter dem vorherigen einfachen gleitenden Durchschnitt.
Verkaufssignal:
Der Schlusskurs liegt unter dem einfachen gleitenden Durchschnitt.
Und: Der vorherige Schlusskurs lag über dem vorherigen einfachen gleitenden Durchschnitt.
Wenn Sie mehr über den einfachen gleitenden Durchschnitt und andere gängige gleitende Durchschnittstypen lesen möchten, empfehle ich Ihnen, meinen vorherigen Artikel Lernen Sie, wie man verschiedene gleitende Durchschnittssysteme entwirft zu lesen, der Ihnen helfen wird, sie gut zu verstehen.
Im Folgenden werden die Schritte zur Erstellung eines solchen Handelssystems beschrieben, das in der Lage ist, Kauf- und Verkaufsaufträge automatisch auf der Grundlage der genannten Signale auszuführen.
Im globalen Bereich werden wir die Trade-Include-Datei in die Software einbinden, die die Ausführung von Aufträgen auf der Grundlage unserer Signale mit Hilfe des Präprozessors #include ermöglicht. Wenn Sie mehr über den Präprozessor lesen möchten, können Sie den Artikel Alles, was Sie über die MQL5-Programmstruktur wissen müssen lesen, um mehr Details zu erfahren.
#include <Trade\Trade.mqh>
Wir erstellen drei Nutzereingaben für die Double-Variable von lotSize, die ENUM_TIMEFRAMES-Variable von timeFrame und die Integer-Variable von MAPeriod, die nach Wunsch des Nutzers geändert werden können, indem Sie Standardwerte für sie festlegen:
input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50;
Wir erstellen zwei Integer-Variablen simpleMA und barsTotal ohne Zuweisung, da wir sie später im OnInit()-Teil definieren werden
int simpleMA; int barsTotal;
Wir erstellen „trade“ als Objekt der Klasse CTrade, um einen einfachen Zugriff auf die Handelsfunktionen zu ermöglichen.
CTrade trade;
In OnInit() definieren wir den SimpleMA, indem wir die iMA-Funktion verwenden, um das Handle des Indikators für den gleitenden Durchschnitt zurückzugeben, und seine Parameter sind:
- symbol: Angabe des Symbolnamens, wir verwenden _Symbol für das aktuelle Symbol.
- period: Zur Angabe des Zeitrahmens wird die Nutzereingabe mit einem Standardwert von 1 Stunde verwendet, jedoch angepasst werden.
- ma_period: Angabe des einfachen gleitenden Durchschnittszeitraums wird die Nutzereingabe mit einem Standardwert von 50 verwendet, aber er kann angepasst werden.
- ma_shift: um die horizontale Verschiebung anzugeben, wird 0 verwendet.
- applied_price: Angabe des Preistyps, wir verwenden den Schlusskurs für die Berechnung des einfachen gleitenden Durchschnitts.
simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
Und barsTotal mit Hilfe der Funktion iBars, die die Anzahl der Balken zurückgibt; ihre Parameter sind:
- symbol: Angabe des Symbols wird (_Symbol) verwendet, das für das aktuelle Symbol gilt.
- timeframe: Zur Angabe des Zeitrahmens wird der vom Nutzer erstellte Zeitrahmen mit dem Standardwert von 1 Stunde verwendet, er kann angepasst werden.
barsTotal=iBars(_Symbol,timeFrame);
In OnTick() werden wir zwei Arrays erstellen, eines für die Preise, indem wir MqlRates verwenden, um Informationen über Preise, Volumen und Spread zu speichern, und das andere für den einfachen gleitenden Durchschnitt:
MqlRates priceArray[]; double mySMAArray[];
Wir setzen das Flag AS_SERIES für diese beiden erstellten Arrays mit Hilfe der Funktion ArraySetAsSeries, deren Parameter sind:
- array[]: um das Array per Referenz anzugeben.
- flag: Angabe der Indizierungsrichtung des Arrays.
ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true);
Definition von Brief- und Geldkursen nach Erstellung von zwei Double-Variablen:
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
Abrufen historischer Daten von MqlRates mit Hilfe der Funktion CopyRates, ihre Parameter sind:
- symbol_name: zur Bestimmung des Symbolnamens.
- timeframe: zur Bestimmung des Zeitrahmens.
- start_pos: Angabe der Startposition.
- count: Angabe der Anzahl der zu kopierenden Daten.
- rates_array[]: Angabe des zu kopierenden Ziel-Arrays.
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
Abrufen von Daten aus dem Indikatorpuffer mit der Funktion CopyBuffer, deren Parameter sind:
- indicator_handle: Angabe des Indikator-Handles, hier einfachMA.
- buffer_num: Angabe der Puffernummer des Indikators, hier 0.
- start_pos: zur Bestimmung der Startposition, hier 0, d.h. der aktuellen Kerze.
- count: Angabe der zu kopierenden Menge, hier 3.
- buffer[]: Angabe des zu kopierenden Ziel-Arrays, hier mySMAArray.
CopyBuffer(simpleMA,0,0,3,mySMAArray);
Definition des letzten Schlusskurses und des einfachen gleitenden Durchschnittswerts derselben Kerze nach Erstellung von zwei Double-Variablen für diese beiden Werte:
double lastClose=(priceArray[1].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
Die Definition des vorherigen Schlusskurses und des einfachen gleitenden Durchschnitts dieser Kerze, nachdem zwei weitere Double-Variablen für diese beiden Werte erstellt wurden:
double prevClose=(priceArray[2].close); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
Erstellen der Integer-Variable bars, die mit der erstellten Variable barsTotal verglichen werden soll:
int bars=iBars(_Symbol,timeFrame);
Prüfung, ob ein neuer Balken erstellt wurde, indem barsTotal überprüft wird, wenn es nicht gleich bars ist:
if(barsTotal != bars)
Wenn barsTotal nicht gleich bars ist, müssen wir barsTotal mit dem Wert von bars aktualisieren:
barsTotal=bars;
Wenn barsTotal nicht gleich bars ist, müssen wir auch unsere Bedingungen der Strategie überprüfen, wenn der vorherige der letzte Schlusskurs unter dem Wert des einfachen gleitenden Durchschnitts derselben Kerze liegt und gleichzeitig der letzte Schlusskurs über dem Wert des einfachen gleitenden Durchschnitts derselben Kerze liegt. Wir brauchen das Programm, um die aktuell geöffnete Position zu schließen und eine Kaufposition zu eröffnen:
if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); }
Wenn der vorherige Schlusskurs über dem Wert des einfachen gleitenden Durchschnitts der gleichen Kerze liegt und gleichzeitig der letzte Schlusskurs unter dem Wert des einfachen gleitenden Durchschnitts der gleichen Kerze liegt. Wir brauchen das Programm, um die aktuell geöffnete Position zu schließen und eine Verkaufsposition zu eröffnen:
if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); }
Dann kompilieren wir den Code, und wir werden feststellen, dass er ohne Fehler oder Warnungen kompiliert wurde.
Im Folgenden wird der vollständige Code in einem einzigen Block dargestellt:
//+------------------------------------------------------------------+ //| SMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int simpleMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Wir kompilieren den EA und lassen ihn auf den EURUSD-Daten laufen, um die Strategie zu testen. Der Testzeitraum ist vom 1. Januar bis zum 30. Juni 2022, genau wie bei den anderen gleitenden Durchschnittswerten. Unsere Einstellungen für die SMA werden wie folgt sein:
- Losgröße: 1
- Zeitrahmen: 1 Stunde
- MA-Periode: 50
Die Ergebnisse des Tests:
Wie wir sehen können, müssen wir die folgenden Zahlen nach dem Testen des SMA-Indikators untersuchen:
- Reingewinn (NetProfit): 2700.30 (27%)
- Salden-DD relativ: 37.07%
- Kapital-DD relativ: 41.76%
- Gewinnfaktor: 1.10
- Erwartete Auszahlung: 12.68
- Erholungsfaktor: 0.45
- Sharpe Ratio: 0.57
Adaptiver gleitender Durchschnitt (iAMA)
In diesem Teil werden wir eine andere Art von gleitendem Durchschnitt kennenlernen, nämlich den AMA (Adaptive Moving Average). Es wurde von Perry J. Kaufman entwickelt und wird auch (KAMA) genannt, und das Hauptkonzept besteht darin, das Rauschen in der Preisbewegung zu reduzieren. Er folgt der Preisbewegung, unabhängig von der Volatilität dieser Preisbewegung, da er sich ihr anpasst. Der Indikator ist ein Trendfolger-Indikator, d.h. er kann zur Identifizierung des Trends und der Wendepunkte verwendet werden.
Die Berechnung des Indikators erfolgt in mehreren Schritten.
Schritt eins: Berechnung von AMA oder KAMA
Zweiter Schritt: Berechnung der Glättungskonstante (SC)
Dritter Schritt: Berechnung des Wirkungsgrads (ER)
Jetzt haben wir gelernt, wie man den AMA-Indikator manuell berechnet, aber das ist nicht nötig, da wir ihn automatisch in den MetaTrader 5 einfügen können, indem wir ihn aus den verfügbaren vorgefertigten Indikatoren auswählen. Es ist an der Zeit, ein Handelssystem zu entwickeln, das Kauf- und Verkaufsaufträge auf der Grundlage des Crossovers zwischen dem Schlusskurs und dem AMA-Indikator ausführen kann. Wir werden also die folgenden Signale für unsere Strategie verwenden.
Kaufsignal:
Der Schlusskurs liegt über dem adaptiven gleitenden Durchschnittswert.
Und: Der vorherige Schlusskurs lag unter dem vorherigen adaptiven gleitenden Durchschnittswert.
Verkaufssignal:
Der Schlusskurs liegt unter dem adaptiven gleitenden Durchschnittswert.
Und: Der vorherige Schlusskurs lag über dem vorherigen adaptiven gleitenden Durchschnittswert.
Im Folgenden finden Sie den vollständigen Code für die Erstellung dieser Art von Handelssystem:
//+------------------------------------------------------------------+ //| iAMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; input int fastMAPeriod= 5; input int slowMAPeriod= 100; int adaptiveMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { adaptiveMA = iAMA(_Symbol, timeFrame, MAPeriod,fastMAPeriod,slowMAPeriod, 0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myAMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myAMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(adaptiveMA,0,0,3,myAMAArray); double lastClose=(priceArray[1].close); double AMAVal = NormalizeDouble(myAMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevAMAVal = NormalizeDouble(myAMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>AMAVal && prevClose<prevAMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<AMAVal && prevClose>prevAMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Der Unterschied in diesem Code ist die Verwendung der iAMA-Funktion, die das Handle des adaptiven gleitenden Durchschnittsindikators zurückgibt und deren Parameter sind:
- symbol: Angabe des Symbolnamens, wir verwenden _Symbol für das aktuelle Symbol.
- period: Angabe des Zeitraums wird die Nutzereingabe mit einem Standardwert von 1 Stunde verwendet.
- ama_period: Angabe der Periodenlänge des adaptiven gleitenden Durchschnitts.
- fast_ma_period: Angabe der Periodenlänge der schnellen MA.
- slow_ma_period: Angabe der Periodenlänge des langsamen MA.
- ama_shift: Angabe der horizontalen Verschiebung wird 0 verwendet.
- applied_price: um den Preistyp zu spezifizieren, es wird der Schlusskurs verwendet.
Wir müssen den AMA-Indikator für denselben Zeitraum einem Backtest unterziehen, um seine Ergebnisse zu sehen:
- Losgröße =1
- Zeitrahmen = 1 Stunde
- MA-Period = 50
- Schneller MA = 5
- Langsamer MA = 100
Die Ergebnisse:
Wie wir sehen können, können wir die folgenden Zahlen nach dem Testen des AMA-Indikators untersuchen:
- Reingewinn (NetProfit): 3638.20 (36.39%)
- Salden-DD relativ: 22.48%
- Kapital-DD relativ: 35.53%
- Gewinnfaktor: 1.31
- Erwartete Auszahlung: 35.67
- Erholungsfaktor: 0.65
- Sharpe Ratio: 0.86.
Doppelt exponentiell gleitender Durchschnitt (iDEMA)
In diesem Teil werden wir einen weiteren gleitenden Durchschnittstyp identifizieren, nämlich den technischen Indikator Double Exponential Moving Average (DEMA). Es handelt sich um einen Trendfolgeindikator, der von Patrick Mulloy entwickelt wurde. Das Hauptziel dieses Indikators ist es, die Verzögerung der EMAs zu verringern, aber ihn auch reaktionsfähiger auf die Marktbewegung zu machen, wie wir bei der Berechnung dieses Indikators sehen werden.
Dieser Indikator kann verwendet werden, um den Trend oder Wendepunkte im Trend zu identifizieren, indem die Position der Preise relativ zu diesem gleitenden Durchschnitt ermittelt wird. Die Schritte zur Berechnung des Indikators werden im Folgenden dargestellt:
1. Berechnung des ersten Exponential Moving Average (EMA)
EMA eins = EMA mit der Periodenlänge n der Preise.
2. Berechnung des EMA von EMA eins
EMA zwei = EMA von EMA eins
3. Berechnung der DEMA
DEMA = (2 * EMA eins) - EMA zwei
Wie wir wissen, brauchen wir diese manuelle Berechnung nicht zu machen, es ist für das Verständnis gut den Indikator, aber wir haben diesen Indikator die gleiche wie eine Menge von technischen Indikatoren in der MetaTrader 5. Jetzt müssen wir dasselbe Handelssystem erstellen, das wir zuvor erstellt haben, aber wir werden dieses Mal die DEMA verwenden, um ihre Ergebnisse im Vergleich zu anderen Typen zu testen. Dieses Handelssystem führt die gleichen Aufträge aus, die auf der Grundlage der Kreuzung gekauft und verkauft werden, aber dieses Mal wird der Kreuzung zwischen dem Preis und dem DEMA-Indikator sein. Die Signale sind:
Kaufsignal:
Der Schlusskurs liegt über dem Wert des doppelt exponentiellen gleitenden Durchschnitts (DEMA).
Und: Der vorherige Schlusskurs lag unter dem vorherigen DEMA-Wert.
Verkaufssignal:
Der Schlusskurs liegt unter dem DEMA-Wert.
Und: Der vorherige Schlusskurs lag über dem vorherigen DEMA-Wert.
Es folgt der vollständige Code dieses Handelssystems mit dem kleinen Unterschied, dass die Funktion iDEMA verwendet wird, um den Handle des Indikators für den doppelten exponentiellen gleitenden Durchschnitt zurückzugeben, und seine Parameter sind:
- symbol: Angabe des Symbolnamens wird (_Symbol) für das aktuelle Symbol verwendet.
- period: Angabe des Zeitrahmens wird die Nutzereingabe mit einem Standardzeitraum von 1 Stunde verwendet.
- ma_period: Angabe der Periode des gleitenden Durchschnitts wird die Nutzereingabe mit einem Standardwert von 50 verwendet.
- ma_shift: Angabe der horizontalen Verschiebung, wir verwenden 0, da wir keine Verschiebung im Diagramm benötigen.
- applied_price: Angabe des Preistyps, wir werden den Schlusskurs zur Berechnung des gleitenden Durchschnitts verwenden.
Es wird dasselbe sein wie der unten stehende Codeblock:
//+------------------------------------------------------------------+ //| iDEMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int DEMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { DEMA = iDEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myDEMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myDEMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(DEMA,0,0,3,myDEMAArray); double lastClose=(priceArray[1].close); double DEMAVal = NormalizeDouble(myDEMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevDEMAVal = NormalizeDouble(myDEMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>DEMAVal && prevClose<prevDEMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<DEMAVal && prevClose>prevDEMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Nachdem wir diesen Code kompiliert haben, können wir den Backtest über den gleichen Zeitraum wie bei den anderen Typen machen, und die Einstellungen oder Eingaben dieses Indikators sind wie folgt:
- Losgröße = 1
- Zeitrahmen = 1 Stunde
- MA-Period = 50
Nach der Durchführung des Tests erhalten wir die folgenden Ergebnisse:
Wie wir sehen können, können wir die folgenden Zahlen nach dem Testen von iDEMA untersuchen:
- Nettogewinn: - 961,60 (- 9,62%)
- Salden-DD relativ: 39.62%
- Kapital-DD relativ: 41.15%
- Gewinnfaktor: 0.97
- Erwartete Auszahlung: - 3,12
- Erholungsfaktor: - 0,18
- Sharpe Ratio: - 0,21
Dreifacher Exponentieller Gleitender Durchschnitt (iTEMA)
Jetzt werden wir einen weiteren gleitenden Durchschnittstyp identifizieren, den Triple Exponential Moving Average (TEMA), der von Patrick Mulloy entwickelt wurde, um dem Indikator noch mehr Reaktionsfähigkeit zu verleihen, damit er für den kurzfristigen Handel geeignet ist. In diesem Indikator verwenden wir dreifach geglättete EMAs, einfache und doppelt geglättete EMAs. Also, dieser Indikator wird sich näher am Preis bewegen und schneller reagieren als die bereits erwähnten. Genauso wie wir den doppelten exponentiellen gleitenden Durchschnitt verwendet haben, können wir den TEMA auf die gleiche Art und Weise verwenden, zusätzlich zu seiner schnelleren Reaktion auf den Preis, sodass er verwendet werden kann, um den Trend und Wendepunkte oder Änderungen im Trend zu identifizieren.
Im Folgenden werden die Schritte zur Berechnung dieses TEMA-Indikators beschrieben:
1. Berechnung des ersten Exponential Moving Average (EMA)
EMA eins = EMA mit der Periodenlänge n der Preise:
2. Berechnung des EMA von EMA eins
EMA zwei = EMA von EMA eins
3. Berechnung des EMA von EMA zwei
EMA drei = EMA von EMA zwei
4. Berechnung des TEMA
DEMA = (3 * EMA eins) - (3 * EMA zwei) + (EMA3)
Wir können diesen Indikator aus den verfügbaren vorgefertigten technischen Indikatoren im MetaTrader 5 ohne manuelle Berechnung einfügen. Dann müssen wir unser Handelssystem mit diesem TEMA-Indikator erstellen, um ihn zu testen und seine Ergebnisse mit anderen Typen zu vergleichen. Im Folgenden finden Sie den vollständigen Code zur Erstellung dieses Handelssystems, wie wir es zuvor getan haben, mit dem Unterschied, dass wir die iTEMA-Funktion verwenden, um das Handle des Triple Exponential Moving Average-Indikators zurückzugeben, und seine Parameter sind die gleichen wie die, die wir beim DEMA und SMA erwähnt haben.
//+------------------------------------------------------------------+ //| iTEMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int TEMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { TEMA = iTEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myTEMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myTEMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(TEMA,0,0,3,myTEMAArray); double lastClose=(priceArray[1].close); double TEMAVal = NormalizeDouble(myTEMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevTEMAVal = NormalizeDouble(myTEMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>TEMAVal && prevClose<prevTEMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<TEMAVal && prevClose>prevTEMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Nach dem Kompilieren und Ausführen dieser Software können wir einen Backtest für denselben Zeitraum durchführen, um die Ergebnisse mit anderen gleitenden Durchschnittstypen zu vergleichen, und die folgenden Einstellungen oder Eingaben werden verwendet, um zu versuchen, alle Parameter in diesem Testprozess festzulegen:
- Losgröße = 1
- Zeitrahmen = 1 Stunde
- MA-Period = 50
Nach Durchführung und Abschluss dieser Tests können wir die folgenden Ergebnisse feststellen:
Wie wir aus den folgenden Zahlen ersehen können, können wir diese untersuchen:
- Nettogewinn: - 3973,10 (- 39,74%)
- Salden-DD relativ: 63.98%
- Kapital-DD relativ: 66.06%
- Gewinnfaktor: 0.90
- Erwartete Auszahlung: - 10,59
- Erholungsfaktor: - 0,52
- Sharpe Ratio: - 0,83
Fraktaler Adaptiver gleitender Durchschnitt (iFrAMA)
Wir haben die letzte Art von gleitendem Durchschnitt, die wir in diesem Artikel identifizieren müssen. Es handelt sich um den Indikator Fractal Adaptive Moving Average (FrAMA), der von John Ehlers entwickelt wurde. Er ist ein trendfolgender Indikator und geht davon aus, dass die Marktpreise fraktal sind. Sie kann auch dazu verwendet werden, Trends und Wendepunkte zu erkennen. Nachfolgend wird beschrieben, wie man sie berechnen kann:
Wir können diesen Indikator aus den verfügbaren vorgefertigten technischen Indikatoren im MetaTrader 5 einfügen. Jetzt müssen wir das gleiche Handelssystem mit der gleichen Strategie erstellen, aber wir werden hier stattdessen den FrAMA-Indikator verwenden, um seine Ergebnisse zu vergleichen, nachdem wir auch mit anderen Typen getestet haben. Die Strategie ist der Crossover zwischen dem Preis und dem FrAMA-Indikator. Wenn der Preis über dem FrAMA liegt, ist das ein Kaufsignal, und wenn der Preis unter dem FrAMA liegt, ist das ein Verkaufssignal.
Kaufsignal:
Der Schlusskurs liegt über dem Wert des fraktalen adaptiven gleitenden Durchschnitts (FrAMA).
Und: Der vorherige Schlusskurs lag unter dem vorherigen FrAMA-Wert.
Verkaufssignal:
Der Schlusskurs liegt unter dem FrAMA-Wert.
Und: Der vorherige Schlusskurs lag über dem vorherigen FrAMA-Wert.
Im Folgenden finden Sie den vollständigen Code, um dieses Handelssystem zu erstellen. Es wird dasselbe sein wie das, was wir zuvor in anderen Typen erwähnt haben, aber wir werden die (iFrAMA)-Funktion verwenden, die uns das Handle des fraktalen adaptiven gleitenden Durchschnitts gibt, die Parameter sind:
- symbol: Angabe des Symbolnamens, wir verwenden _Symbol für das aktuelle Symbol.
- period: Angabe des Zeitraums wird die Nutzereingabe mit einem Standardwert von 1 Stunde verwendet.
- ma_period: Angabe der Periode des gleitenden Durchschnitts wird die Nutzereingabe mit einem Standardwert von 50 verwendet.
- ma_shift: um die horizontale Verschiebung anzugeben, wird 0 verwendet.
- applied_price: Angabe des Preistyps, wir verwenden den Schlusskurs
//+------------------------------------------------------------------+ //| iFrAMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int FrAMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { FrAMA = iFrAMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myFrAMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myFrAMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(FrAMA,0,0,3,myFrAMAArray); double lastClose=(priceArray[1].close); double FrAMAVal = NormalizeDouble(myFrAMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevFrAMAVal = NormalizeDouble(myFrAMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>FrAMAVal && prevClose<prevFrAMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<FrAMAVal && prevClose>prevFrAMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Nach dem Kompilieren und Ausführen dieses EA, um diese Strategie mit dem FrAMA-Indikator mit den folgenden gleichen Einstellungen oder Eingaben zu testen:
- Losgröße: 1
- Zeitrahmen: 1 Stunde
- MA-Periode: 50
Wir testen diesen EA im gleichen Zeitraum wie alle anderen genannten gleitenden Durchschnitte und erhalten folgende Ergebnisse:
Wie wir sehen können, sind die wichtigsten Zahlen, die wir untersuchen müssen, die folgenden:
- Nettogewinn: - 2993,70 (- 29,94%)
- Salden-DD relativ: 73.28%
- Kapital-DD relativ: 74.81%
- Gewinnfaktor: 0.93
- Erwartete Auszahlung: - 6,45
- Erholungsfaktor: - 0,33
- Sharpe Ratio: - 0,46
Vergleich der Ergebnisse mit den Ergebnissen des einfachen gleitenden Durchschnitts (SMA)
In diesem Teil werde ich einen Vergleich der Ergebnisse jedes erwähnten gleitenden Durchschnittstyps liefern, und Sie müssen wissen, dass ich versuchen werde, die besten Ergebnisse so weit wie möglich zu liefern, aber jeder gleitende Durchschnitt kann unterschiedliche Ergebnisse liefern, wenn wir ihn optimieren und Perioden oder getestete Perioden ändern, da wir wissen, dass gleitende Durchschnitte unterschiedliche Ergebnisse basierend auf den Einstellungen des Indikators und den Marktbedingungen liefern können.
Das Hauptziel besteht darin, so viele gleiche Bedingungen wie möglich zu schaffen, um zu sehen, ob es einen Typ gibt, der besser ist als andere, mit den besten Einstellungen, die wir von unserem Standpunkt aus wählen können. Aber damit Sie verstehen, wonach wir suchen, müssen die jeweils besten Werte der wichtigsten Maßzahlen suchen:
- Reingewinn (NetProfit): Je höher, desto besser
- Drawdown (DD): Je niedriger, desto besser
- Gewinn-Faktor (profit factor): Je höher, desto besser
- Erwartete Auszahlung: Je höher, desto besser
- Erholungsfaktor: Je höher, desto besser
- Sharpe Ratio: Je höher Sharpe Ratio, desto besser
In der folgenden Tabelle werden nun die Ergebnisse des einfachen gleitenden Durchschnitts mit anderen gleitenden Durchschnittswerten verglichen, die auf diesem vorherigen Kontext basieren:
Maßzahl | SMA | AMA | DEMA | TEMA | FrAMA |
---|---|---|---|---|---|
Reingewinn | 2700.30 (27%) | 3638.20 (36.39%) | - 961.60 (- 9.62%) | - 3973.10 (- 39.74%) | - 2993.70 (- 29.94%) |
Relativer Drawdown vom Saldo | 37.07% | 22.48% | 39.62% | 63.98% | 73.28% |
Relativer Drawdown vom Kapital | 41.76% | 35.53% | 41.15% | 66.06% | 74.81% |
Profit-Faktor | 1.10 | 1.31 | 0.97 | 0.90 | 0.93 |
Erwartetes Ergebnis | 12.68 | 35.67 | - 3.12 | - 10.59 | - 6.45 |
Erholungsfaktor | 0.45 | 0.65 | - 0.18 | - 0.52 | - 0.33 |
Sharpe Ratio | 0.57 | 0.86. | - 0.21 | - 0.83 | - 0.46 |
Nach den Ergebnissen all unserer Tests haben wir zwei Typen, die auf der Grundlage der Einstellungen und des Testzeitraums die beste Leistung erbringen. Dies sind der einfache gleitende Durchschnitt und der adaptive gleitende Durchschnitt. Die beste Methode ist der adaptive gleitende Durchschnitt. Er hat:
- den höchsten Nettogewinn,
- den niedrigsten relativen DD vom Saldo,
- den niedrigsten relativen DD vom Kapital,
- den beste Profit-Faktor,
- die höchste erwartete Auszahlung,
- den höheren Erholungsfaktor,
- die höhere Sharpe Ratio.
Wie wir bereits erwähnt haben, können wir bessere Ergebnisse erzielen, wenn wir die Einstellungen und Strategien weiter optimieren, aber das Ziel hier ist, dass wir den Testprozess verstehen und an einem realen Beispiel anwenden, und dann können wir denselben Prozess für alle Testzwecke verwenden.
Schlussfolgerung
In diesem Artikel haben wir die Leistungsergebnisse der folgenden Arten von gleitenden Durchschnitten untersucht:
- Der adaptive gleitende Durchschnitt (AMA)
- Der doppelte exponentielle gleitende Durchschnitt (DEMA)
- Der dreifache exponentielle gleitende Durchschnitt (TEMA)
- Der Fractal Adaptive Moving Average (FrAMA)
Wir haben Handelssysteme für jeden Typ erstellt und vergleichen ihre Ergebnisse mit dem einfachen gleitenden Durchschnitt, dem beliebtesten Typ gleitender Durchschnitte. Die Testergebnisse zeigen, dass die besten Ergebnisse mit dem einfachen gleitenden Durchschnitt und dem adaptiven gleitenden Durchschnitt erzielt wurden, wobei der adaptive Durchschnitt (AMA) am besten abschnitt. Wir haben die folgenden Kennzahlen analysiert und verglichen, um den Gewinner zu ermitteln:
- Reingewinn
- Drawdown (DD)
- Profit-Faktor
- Erwartetes Ergebnis
- Erholungsfaktor
- Sharpe Ratio
Testen ist ein sehr wichtiges Thema im Handel. Ich möchte Sie daher ermutigen, mehr Strategien zu testen. Neben der Bewertung der Strategie selbst kann sie Ihnen auch unerwartete Erkenntnisse bringen, da jeder Test Ihr Verständnis vertieft.
Ich danke Ihnen für die Zeit, die Sie mit dem Lesen dieses Artikels verbracht haben. Ich hoffe, dass dieser Artikel für Sie nützlich war und dass er Ihr Wissen erweitert hat. Wenn Sie mehr Artikel über die Erstellung von Handelssystemen auf der Grundlage der beliebten technischen Indikator wie RSI, MACD, Stochastik, Bollinger Bands, und andere Themen zu lesen, können Sie meine Artikel durch die Publikationen zu überprüfen, ich hoffe, Sie werden sie auch nützlich finden.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/13130





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