English Русский 中文 Español 日本語 Português
preview
Tests von verschiedenen gleitenden Durchschnitten, um zu sehen, wie aufschlussreich sie sind

Tests von verschiedenen gleitenden Durchschnitten, um zu sehen, wie aufschlussreich sie sind

MetaTrader 5Tester | 11 Oktober 2023, 10:20
643 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

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:

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.

Haftungsausschluss: Alle Informationen werden in der vorliegenden Form nur zu Informationszwecken bereitgestellt und sind nicht für Handelszwecke oder als Ratschläge gedacht. Die Informationen garantieren keinerlei Ergebnis. Wenn Sie sich dafür entscheiden, diese Materialien auf einem Ihrer Handelskonten zu verwenden, tun Sie dies auf eigenes Risiko und Sie sind allein verantwortlich.

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:

SMA-Ergebnisse

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

Schritt eins

Zweiter Schritt: Berechnung der Glättungskonstante (SC)

Schritt 2

Dritter Schritt: Berechnung des Wirkungsgrads (ER)

 Schritt 3

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:

AMA-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:

DEMA-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:

TEMA-Ergebnisse

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:

 FrAMA

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:

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

Beigefügte Dateien |
SMA_System.mq5 (2.07 KB)
iAMA_System.mq5 (2.15 KB)
iDEMA_System.mq5 (2.06 KB)
iTEMA_System.mq5 (2.06 KB)
iFrAMA_System.mq5 (2.08 KB)
Der erste Einsatz des MetaTrader VPS: eine Schritt-für-Schritt-Anleitung Der erste Einsatz des MetaTrader VPS: eine Schritt-für-Schritt-Anleitung
Jeder, der Handelsroboter oder Signalabonnements verwendet, erkennt früher oder später die Notwendigkeit, einen zuverlässigen 24/7-Hosting-Server für seine Handelsplattform zu mieten. Wir empfehlen die Verwendung von MetaTrader VPS aus einer Reihe von Gründen. Sie können den Dienst bequem über Ihr MQL5.community-Konto bezahlen und das Abonnement verwalten.
Monte Carlo Permutationstests im MetaTrader 5 Monte Carlo Permutationstests im MetaTrader 5
In diesem Artikel sehen wir uns an, wie wir Permutationstests auf der Grundlage von vermischten Tick-Daten für jeden Expert Advisor durchführen können, der nur Metatrader 5 verwendet.
Entwicklung eines Replay-Systems — Marktsimulation (Teil 08): Sperren des Indikators Entwicklung eines Replay-Systems — Marktsimulation (Teil 08): Sperren des Indikators
In diesem Artikel werden wir uns ansehen, wie man den Indikator sperren kann, indem man einfach die Sprache MQL5 verwendet, und zwar auf eine sehr interessante und erstaunliche Weise.
Kategorientheorie in MQL5 (Teil 18): Natürliches Quadrat (Naturality Square) Kategorientheorie in MQL5 (Teil 18): Natürliches Quadrat (Naturality Square)
In diesem Artikel setzen wir unsere Reihe zur Kategorientheorie fort, indem wir natürliche Transformationen, eine der wichtigsten Säulen des Fachs, vorstellen. Wir befassen uns mit der scheinbar komplexen Definition und gehen dann auf Beispiele und Anwendungen dieser Serie ein: Volatilitätsprognosen.