MetaTrader 5 herunterladen

Das MQL5-Kochbuch: Entwickeln eines Grundgerüsts für ein Handelssystem auf Basis der Drei-Bildschirme-Strategie

10 Mai 2016, 10:37
Anatoli Kazharski
0
334

Einleitung

Während ihrer Suche nach oder ihrer Entwicklung von Handelssystemen dürften viele Händler von der Drei-Bildschirme-Strategie von Dr. Alexander Elder gehört haben. Viele bewerten diese Strategie negativ. Doch viele andere sind überzeugt, dass sie zum Gewinn beitragen kann. Sie dürfen keiner der beiden Meinungen blind glauben. Alles sollte immer erst geprüft werden. Wenn Sie Programmierung studieren, liegt alles in Ihren Händen, da Sie die Performance der Handelsstrategie mithilfe von Backtesting prüfen können.

In diesem Beitrag entwickeln wir ein Grundgerüst für ein Handelssystem auf Basis der Drei-Bildschirme-Strategie in MQL5. Der Expert Advisor wird dabei nicht von Grund auf neu entwickelt. Stattdessen modifizieren wir einfach das Programm aus dem vorherigen Beitrag "Das MQL5-Kochbuch: Verwendung von Indikatoren zum Festlegen von Handelsbedingungen in Expert Advisors". Somit wird dieser Beitrag auch demonstrieren, wie Sie Muster vorhandener Programme einfach modifizieren können.

Der Expert Advisor aus dem vorherigen Beitrag bietet bereits die Möglichkeit, die Stop-Loss-/Take-Profit- und Trailing-Stop-Ebenen zu aktivieren/deaktivieren, Volumina von Positionen zu erhöhen und Positionen auf dem entgegengesetzten Signal umzukehren. Alle benötigten Funktionen befinden sich bereits auf ihrem vorgesehenen Platz. Unsere Aufgabe ist es also, die Liste der externen Parameter zu verändern, indem wir zusätzliche Optionen hinzufügen, und einige bestehende Funktionen zu modifizieren.

Zu Illustrationszwecken richten wir die Erzeugung von Signalen auf drei Timeframes anhand des Indikators Moving Average ein. Beim späteren Experimentieren mit dem fertig entwickelten Grundgerüst können Sie jeden beliebigen anderen Indikator einsetzen, indem Sie den Code ein wenig abändern. Wir werden außerdem die Möglichkeit einbauen, Timeframes für jeden Bildschirm festzulegen. Wenn der für den Zeitraum des Indikators verantwortliche Parameter einen Nullwert hat, bedeutet dies, dass der entsprechende Bildschirm nicht verwendet wird. In anderen Worten: Das System kann mit einem oder zwei Timeframes eingerichtet werden.

Bevor Sie beginnen, erstellen Sie eine Kopie des Ordners, der die Dateien des Expert Advisors aus dem vorherigen Beitrag enthält, und benennen Sie sie um.

 

Entwicklung des Expert Advisors

Beginnen wir mit den externen Parametern. Nachfolgend sehen Sie den Code der aktualisierten Liste. Neue Zeilen sind hervorgehoben. Timeframes werden mit dem Aufzählungstyp ENUM_TIMEFRAMES deklariert. Sie können jeden beliebigen Timeframe aus der Dropdown-Liste auswählen.

//--- External parameters of the Expert Advisor
sinput   long              MagicNumber=777;        // Magic number
sinput   int               Deviation=10;           // Slippage
//---
input    ENUM_TIMEFRAMES   Screen01TimeFrame=PERIOD_W1;  // Time frame of the first screen
input    int               Screen01IndicatorPeriod=14;   // Indicator period of the first screen
//---
input    ENUM_TIMEFRAMES   Screen02TimeFrame=PERIOD_D1;  // Time frame of the second screen
input    int               Screen02IndicatorPeriod=24;   // Indicator period of the second screen
//---
input    ENUM_TIMEFRAMES   Screen03TimeFrame=PERIOD_H4;  // Time frame of the third screen
input    int               Screen03IndicatorPeriod=44;   // Indicator period of the third screen
//---
input    double            Lot=0.1;                      // Lot
input    double            VolumeIncrease=0.1;           // Position volume increase
input    double            VolumeIncreaseStep=10;        // Step for position volume increase
input    double            StopLoss=50;                  // Stop Loss
input    double            TakeProfit=100;               // Take Profit
input    double            TrailingStop=10;              // Trailing Stop
input    bool              Reverse=true;                 // Position reversal
sinput   bool              ShowInfoPanel=true;           // Display of the info panel

Der Parameter IndicatorSegments sowie die Variable AllowedNumberOfSegments und die Funktion CorrectInputParameters() wurden entfernt, um das Beispiel zu vereinfachen. Wer an dieser Bedingung interessiert ist, kann versuchen, sie selbst umzusetzen. Ebenso muss die Aufzählung der Indikatoren in der Datei Enums.mqh entfernt werden, da dieser Expert Advisor nur einen Indikator einsetzt.

Da es einen separaten Indikator auf jedem Timeframe geben wird, brauchen wir eine gesonderte Variable, um ein Handle jedes der Indikatoren zu erhalten:

//--- Indicator handles
int                  Screen01IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the first screen
int                  Screen02IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the second screen
int                  Screen03IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the third screen

Die Prüfung auf neue Balken wird mithilfe des Mindest-Timeframes durchgeführt. Beim Bestimmen des Mindest-Timeframes in den externen Parametern müssen wir keine bestimmte Reihenfolge befolgen, d. h. Maximum, Mittelwert, Minimum. Die umgekehrte Reihenfolge funktioniert ebenso wie jede andere Reihenfolge. Wir brauchen also eine Funktion, die den Mindest-Timeframe unter allen angegebenen Timeframes erkennt.

Da der Expert Advisor für die Arbeit auf drei Timeframes eingerichtet werden kann sowie auf einem oder zwei, müssen beim Bestimmen des Mindest-Timeframes alle Optionen berücksichtigt werden. Nachfolgend sehen Sie den Code der Funktion GetMinimumTimeframe():

//+------------------------------------------------------------------+
//| Determining the minimum time frame for the new bar check         |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES GetMinimumTimeframe(ENUM_TIMEFRAMES timeframe1,int period1,
                                    ENUM_TIMEFRAMES timeframe2,int period2,
                                    ENUM_TIMEFRAMES timeframe3,int period3)
  {
//--- Default minimum time frame value
   ENUM_TIMEFRAMES timeframe_min=PERIOD_CURRENT;

//--- Convert time frame values to seconds for calculations
   int t1= PeriodSeconds(timeframe1);
   int t2= PeriodSeconds(timeframe2);
   int t3= PeriodSeconds(timeframe3);

//--- Check for incorrect period values
   if(period1<=0 && period2<=0 && period3<=0)
      return(timeframe_min);

//--- Conditions for a single time frame
   if(period1>0 && period2<=0 && period3<=0)
      return(timeframe1);
   if(period2>0 && period1<=0 && period3<=0)
      return(timeframe2);
   if(period3>0 && period1<=0 && period2<=0)
      return(timeframe3);

//--- Conditions for two time frames
   if(period1>0 && period2>0 && period3<=0)
     {
      timeframe_min=(MathMin(t1,t2)==t1) ? timeframe1 : timeframe2;
      return(timeframe_min);
     }
   if(period1>0 && period3>0 && period2<=0)
     {
      timeframe_min=(MathMin(t1,t3)==t1) ? timeframe1 : timeframe3;
      return(timeframe_min);
     }
   if(period2>0 && period3>0 && period1<=0)
     {
      timeframe_min=(MathMin(t2,t3)==t2) ? timeframe2 : timeframe3;
      return(timeframe_min);
     }

//--- Conditions for three time frames
   if(period1>0 && period2>0 && period3>0)
     {
      timeframe_min=(int)MathMin(t1,t2)==t1 ? timeframe1 : timeframe2;
      int t_min=PeriodSeconds(timeframe_min);
      timeframe_min=(int)MathMin(t_min,t3)==t_min ? timeframe_min : timeframe3;
      return(timeframe_min);
     }
   return(WRONG_VALUE);
  }

Zum Speichern des Wertes des Mindest-Timeframes erstellen wir eine weitere globale Variable:

//--- Variable for determining the minimum time frame
ENUM_TIMEFRAMES  MinimumTimeframe=WRONG_VALUE;

Die Funktion GetMinimumTimeframe() muss aufgerufen werden, wenn der Expert Advisor in der Funktion OnInit() initialisiert wird.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Determine the minimum time frame for the new bar check
   MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                        Screen02TimeFrame,Screen02IndicatorPeriod,
                                        Screen03TimeFrame,Screen03IndicatorPeriod);
//--- Get indicator handles
   GetIndicatorHandles();
//--- Initialize the new bar
   CheckNewBar();
//--- Get the properties
   GetPositionProperties(P_ALL);
//--- Set the info panel
   SetInfoPanel();
//---
   return(0);
  }

Der Wert der Variable MinimumTimeframe wird dann in den Funktionen CheckNewBar() und GetBarsData() genutzt.

Die Funktion GetIndicatorHandle() sieht nun aus, wie unten dargestellt. Die Periode und der Timeframe werden für jeden Indikator festgelegt.

//+------------------------------------------------------------------+
//| Getting indicator handles                                        |
//+------------------------------------------------------------------+
void GetIndicatorHandles()
  {
//--- Get handles of the indicators specified in the parameters
   if(Screen01IndicatorPeriod>0)
     Screen01IndicatorHandle=iMA(_Symbol,Screen01TimeFrame,Screen01IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
   if(Screen02IndicatorPeriod>0)
     Screen02IndicatorHandle=iMA(_Symbol,Screen02TimeFrame,Screen02IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
   if(Screen03IndicatorPeriod>0)
     Screen03IndicatorHandle=iMA(_Symbol,Screen03TimeFrame,Screen03IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
     
//--- If the indicator handle for the first time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 1!");
//--- If the indicator handle for the second time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 2!");
//--- If the indicator handle for the third time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 3!");
  }

Ferner müssen wir Arrays zum Abrufen von Indikatorwerten hinzufügen (separat für jeden Timeframe):

//--- Arrays for values of the indicators
double               indicator_buffer1[];
double               indicator_buffer2[];
double               indicator_buffer3[];

Die Funktion GetIndicatorsData() zum Abrufen von Indikatorwerten sieht nun aus, wie unten dargestellt. Die erhaltenen Handles werden auf Genauigkeit geprüft. Wenn alles in Ordnung ist, werden die Arrays mit Indikatorwerten befüllt.

//+------------------------------------------------------------------+
//| Getting indicator values                                         |
//+------------------------------------------------------------------+
bool GetIndicatorsData()
  {
//--- Number of indicator buffer values for determining the trading signal   
   int NumberOfValues=3;
//--- If indicator handles have not been obtained
   if((Screen01IndicatorPeriod>0 && Screen01IndicatorHandle==INVALID_HANDLE) ||
      (Screen02IndicatorPeriod>0 && Screen02IndicatorHandle==INVALID_HANDLE) ||
      (Screen03IndicatorPeriod>0 && Screen03IndicatorHandle==INVALID_HANDLE))
      //--- try to get them again
      GetIndicatorHandles();

//--- If the time frame of the first screen is used and the indicator handle has been obtained
   if(Screen01TimeFrame>0 && Screen01IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer1,true);
      //--- Get indicator values
      if(CopyBuffer(Screen01IndicatorHandle,0,0,NumberOfValues,indicator_buffer1)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer1 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//--- If the time frame of the second screen is used and the indicator handle has been obtained
   if(Screen02TimeFrame>0 && Screen02IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer2,true);
      //--- Get indicator values
      if(CopyBuffer(Screen02IndicatorHandle,0,0,NumberOfValues,indicator_buffer2)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer2 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//--- If the time frame of the third screen is used and the indicator handle has been obtained
   if(Screen03TimeFrame>0 && Screen03IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer3,true);
      //--- Get indicator values
      if(CopyBuffer(Screen03IndicatorHandle,0,0,NumberOfValues,indicator_buffer3)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer3 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//---
   return(true);
  }

Die Funktionen GetTradingSignal() und GetSignal() sollten gemäß der vorliegenden Aufgabe modifiziert werden. Nachfolgend sehen Sie den Code dieser Funktionen.

//+------------------------------------------------------------------+
//| Determining trading signals                                      |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetTradingSignal()
  {
//--- If there is no position
   if(!pos.exists)
     {
      //--- A Sell signal
      if(GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      //--- A Buy signal
      if(GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
     }
//--- If the position exists
   if(pos.exists)
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- Get the last deal price
      GetPositionProperties(P_PRICE_LAST_DEAL);

      //--- A Sell signal
      if(pos.type==POSITION_TYPE_BUY && 
         GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      if(pos.type==POSITION_TYPE_SELL && 
         GetSignal()==ORDER_TYPE_SELL && 
         close_price[1]<pos.last_deal_price-CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
         return(ORDER_TYPE_SELL);

      //--- A Buy signal
      if(pos.type==POSITION_TYPE_SELL && 
         GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
      if(pos.type==POSITION_TYPE_BUY && 
         GetSignal()==ORDER_TYPE_BUY && 
         close_price[1]>pos.last_deal_price+CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
         return(ORDER_TYPE_BUY);

     }
//--- No signal
   return(WRONG_VALUE);
  }

Die Funktion GetSignal() berücksichtigt genauso wie beim Bestimmen des Mindest-Timeframes alle möglichen Varianten der Zustände der externen Parameter in Bezug auf Bedingungen zum Öffnen von Positionen. Der Code der Funktion ist nachfolgend aufgeführt:

//+------------------------------------------------------------------+
//| Checking the condition and returning a signal                    |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetSignal()
  {
//--- A SELL SIGNAL: the current value of the indicators on completed bars is lower than on the previous bars
//--- Conditions for a single time frame
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer2[1]<indicator_buffer2[2])
         return(ORDER_TYPE_SELL);
     }
//---
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }

//--- Conditions for two time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer2[1]<indicator_buffer2[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer2[1]<indicator_buffer2[2] && 
         indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }

//--- Conditions for three time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer2[1]<indicator_buffer2[2] && 
         indicator_buffer3[1]<indicator_buffer3[2]
         )
         return(ORDER_TYPE_SELL);
     }

//--- A BUY SIGNAL: the current value of the indicators on completed bars is higher than on the previous bars
//--- Conditions for a single time frame
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer2[1]>indicator_buffer2[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }
     
//--- Conditions for two time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer2[1]>indicator_buffer2[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer2[1]>indicator_buffer2[2] && 
         indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }

//--- Conditions for three time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer2[1]>indicator_buffer2[2] && 
         indicator_buffer3[1]>indicator_buffer3[2]
         )
         return(ORDER_TYPE_BUY);
     }
     
//--- No signal
   return(WRONG_VALUE);
  }

Nun müssen wir nur noch kleine Änderungen an den Funktionen OnInit() und OnDeinit() vornehmen. Die Änderungen wurden im unten dargestellten Code markiert:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Determine the minimum time frame for the new bar check
   MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                        Screen02TimeFrame,Screen02IndicatorPeriod,
                                        Screen03TimeFrame,Screen03IndicatorPeriod);
//--- Get indicator handles
   GetIndicatorHandles();
//--- Initialize the new bar
   CheckNewBar();
//--- Get the properties
   GetPositionProperties(P_ALL);
//--- Set the info panel
   SetInfoPanel();
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Print the deinitialization reason to the journal
   Print(GetDeinitReasonText(reason));
//--- When deleting from the chart
   if(reason==REASON_REMOVE)
     {
      //--- Delete all objects relating to the info panel from the chart
      DeleteInfoPanel();
      //--- Delete the indicator handles
      IndicatorRelease(Screen01IndicatorHandle);
      IndicatorRelease(Screen02IndicatorHandle);
      IndicatorRelease(Screen03IndicatorHandle);
     }
  } 

Das Grundgerüst für Handelssysteme auf Basis der Drei-Bildschirme-Strategie ist fertig. Es kann jederzeit modifiziert werden, indem Sie die Indikatoren ändern oder bei Bedarf zusätzliche Bedingungen hinzufügen.

 

Optimieren von Parametern und Testen des Expert Advisors

Fahren wir mit der Optimierung der Parameter fort und sehen uns die Ergebnisse an. Der Strategietester wird eingestellt, wie nachfolgend abgebildet (stellen Sie sicher, dass Sie den geringsten der drei Timeframes angeben):

Abb. 1. Einstellungen des Strategietesters

Abb. 1. Einstellungen des Strategietesters.

Die Parameter des Expert Advisors für die Optimierung wurden festgelegt, wie nachfolgend dargestellt. Timeframes können zum Optimieren eingestellt werden, aber ich bevorzuge es, sie manuell einzustellen.

Abb. 2. Einstellungen des Expert Advisors

Abb. 2. Einstellungen des Expert Advisors.

Die Optimierung wurde auf einem Dual-Core-Prozessor in etwa 30 Minuten abgeschlossen. Nachfolgend sehen Sie das Optimierungsdiagramm:

Abb. 3. Optimierungsdiagramm

Abb. 3. Optimierungsdiagramm.

Die Testergebnisse der maximalen Bilanz weisen einen geringeren Wertverlust auf als die Testergebnisse des maximalen Erholungsfaktors, deshalb werden die Testergebnisse der maximalen Bilanz für Demonstrationszwecke genutzt:

Abb. 4. Testergebnisse der maximalen Bilanz

Abb. 4. Testergebnisse der maximalen Bilanz.

Abb. 5. Testdiagramm der maximalen Bilanz

Abb. 5. Testdiagramm der maximalen Bilanz.

 

Fazit

Der Beitrag hat demonstriert, dass der Expert Advisor ziemlich schnell modifiziert werden kann, wenn die Hauptfunktionen verfügbar sind. Sie können ein neues Handelssystem erhalten, indem Sie einfach den Signalblock und die Indikatoren austauschen. Im Anhang des Beitrags finden Sie ein Archiv mit den Quellcodes des hier beschriebenen Expert Advisors für Ihre eigenen Studien sowie eine set-Datei mit den Einstellungen der Eingabeparameter.

Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/647

Beigefügte Dateien |
Universeller Expert Advisor: Benutzerstrategien und Hilfsklassen (Teil 3) Universeller Expert Advisor: Benutzerstrategien und Hilfsklassen (Teil 3)

In diesem Artikel werden wir mit der Analyse der Algorithmen der Klasse CStrategy Trading Engine fortfahren. Der dritte Teil der Serie enthält die detaillierte Analyse von Beispielen, wie bestimmte Handelsstrategien mit diesem Ansatz entwickelt werden können. Ein besonderes Augenmerk wird auf die Hilfsalgorithmen gelegt — Ein Expert Advisor Protokollierungs-System (logging) und der Datenzugriff über gewöhnliche Indexe (Close[1], Open[0] etc.)

Wie sicher ist der Kauf von MQL5 Market-Produkten? Wie sicher ist der Kauf von MQL5 Market-Produkten?

Bei dem Verkauf von auf MetaTrader 5 basierenden Trading-Apps räumen wir der Sicherheit unserer Kunden eine unvergleichliche Priorität ein. Da wir alle damit in Verbindung stehenden Risiken minimiert haben, ist es Ihnen möglich, sich auf wichtigere Dinge zu konzentrieren - wie beispielsweise die Suche nach einem Handelsroboter, der Ihren Wünschen entspricht.

Das MQL5-Kochbuch: Mehrwährungsfähiger Expert Advisor – eine einfache, saubere und schnelle Herangehensweise Das MQL5-Kochbuch: Mehrwährungsfähiger Expert Advisor – eine einfache, saubere und schnelle Herangehensweise

In diesem Beitrag wird die Umsetzung einer einfachen Herangehensweise an einen mehrwährungsfähigen Expert Advisor beschrieben. Das heißt, Sie werden in der Lage sein, den Expert Advisor für das Testen/den Handel unter identischen Bedingungen aber mit unterschiedlichen Parametern je Symbol einzurichten. Als Beispiel erstellen wir ein Muster für zwei Symbole auf eine Weise, mit der Sie nach Bedarf zusätzliche Symbole hinzufügen können, indem Sie kleine Änderungen am Code vornehmen.

Das MQL5-Kochbuch: Entwicklung eines mehrwährungsfähigen Expert Advisors mit unbegrenzter Anzahl von Parametern Das MQL5-Kochbuch: Entwicklung eines mehrwährungsfähigen Expert Advisors mit unbegrenzter Anzahl von Parametern

In diesem Beitrag werden wir ein Muster erstellen, das einen einzelnen Satz von Parametern für die Optimierung eines Handelssystems nutzt und gleichzeitig eine unbegrenzte Anzahl von Parametern ermöglicht. Die Liste der Symbole wird in einer Standard-Textdatei (*.txt) erstellt. Die Eingabeparameter jedes Symbols werden ebenfalls in Dateien gespeichert. Auf diese Weise können wir die Terminal-seitige Begrenzung der Anzahl von Eingabeparametern eines Expert Advisors umgehen.