MetaTrader 5 herunterladen

Expert Advisors Basierend auf Beliebten Handelssystemen und Alchemie der Handelsroboter Optimierung (Forts.)

30 März 2016, 11:15
Nikolay Kositsin
0
407

Einführung

Die Optimierung von Handelssystemen wird in verschiedener Literatur breit besprochen, und es wäre unlogisch, hier ausführlich über etwas zu schreiben, was leicht im Internet zu finden ist. Also besprechen wir hier nur einfache Grundgedanken, um die zugrunde liegende Logik der Verwendung der Ergebnisse aus der Optimierung automatisierter Handelssysteme im Allgemeinen und insbesondere den praktischen Nutzen aus der Optimierung zu verstehen.

Ich nehme an, Sie wissen, dass es einfach ist, in einen Strategietester einen Expert Advisor hochzuladen, der auf Basis eines relativ einfachen Handelssystems konstruiert ist, und nach seiner Optimierung erhalten Sie erstaunliche Testergebnisse auf fast alle historischen Daten, die mit den historischen Daten der Optimierung übereinstimmen. Hier taucht allerdings eine natürliche Frage auf: "Was hat das Ergebnis mit der Prognose des Verhaltens eines automatisierten Handelssystems zu tun, auch wenn das Ergebnis enorm ist, aber erreicht wurde nach der Anpassung des Systems an die Historie?"

Im Moment ist die Frage eher akut. Einer der Gründe dafür ist, dass nach ersten erfolgreichen Optimierungen, ein beginnender EA-Autor eine falsche Vorstellung über den Gedankenlosen Einsatz von Optimierungsergebnissen im Live-Trading bekommen kann, und die Folgen können schädlich sein. Und der EA-Autor kann sein eigenes Geld verlieren oder das Geld derjenigen, die den fertigen Expert Advisor verwenden. Also werde ich meinen Artikel mit diesem Thema beginnen.



Backtesting oder Optimierungsergebnisse ohne Fanatismus Prüfen

In der Regel kann man nach ersten Erfahrungen mit EA-Optimierung entscheiden eine Strategie zur Verwendung im Trading zu konstruieren, mit maximal rentablen Optimierungsergebnissen mit minimalem Drawdown, hoffend, dass das System mit dem gewünschten Satz an Parametern nicht nur in der Optimierungsphase rentabel sein wird. Schematisch wird es wie folgt aussehen:


Dies ist die Logik, die von vielen beginnenden EA-Autoren nach der Bekanntschaft mit einem Tester von Handelsstrategien angewandt wird. Aber leider können wir nicht in die Zukunft blicken und die Effizienz einer Handelsstrategie nach dieser Logik bestimmen, und das Testen einer Strategie auf einem Demokonto im Echtzeit-Modus zu Bedingungen des Live-Markts ist eine ziemlich ermüdende Beschäftigung!

Wenn jemand geduldig genug ist über Jahre auf Ergebnisse zu warten, dann gibt es dabei keine Probleme. Allerdings kann ein System absolut nutzlos werden und es wird sehr enttäuschend sein, so viel Zeit und Internet-Traffic vergeudet zu haben. Darüber hinaus ermöglicht ein solcher Ansatz nicht das Testen vieler Handelsstrategien. Eine oder, maximal, zwei! Und die letzte Sache - so viel investierte Anstrengung in das Testen einer solchen Handelsstrategie, nimmt dem Schöpfer die Fähigkeit ihre Betriebsergebnisse kritisch einzuschätzen!

Psychologisch ist es in einer solchen Situation ziemlich schwierig der Wahrheit zu begegnen und zuzugeben, dass die resultierende Strategie lediglich Mühe und Zeitverschwendung war. Natürlich, eine solche Verschwendung von jemandes Mühe und Zeit kann kaum zum Erschaffen eines rentablen Expert Advisors führen.

Also, in dieser Situation ist der einzige Ausweg das Modellieren der Zukunft auf Basis historischer Daten. Es ist ziemlich einfach. Alles was wir brauchen, ist Verschiebung der Zeitgrenzen des vorherigen Schemas nach links entlang der Zeitachse. In einem solchen Fall nach der Optimierung, werden Sie genug Zeit haben die Ergebnisse der Optimierung auf den jüngsten Daten einzuschätzen, die näher an der Gegenwart sind, als die Daten der Optimierung.

In vielen Fällen, einschließlich dem oben beschriebenen, ermöglicht ein solcher Ansatz das Einschätzen der tatsächlichen Effizienz der gewollten Strategie mit der Optimierungsergebnissen in jedem bestimmten Expert Advisor, der über optimierte Parameter verfügt. Schematisch kann die Bedeutung einer solchen Analyse der Optimierungsstrategien in der folgenden Form dargestellt werden:

Ich nehme an, dieses Diagramm ist ziemlich klar. Zum Beispiel, nehmen wir das Jahr 2007 als Analysezeitraum. Für die erste Optimierung wird der Zeitraum der Optimierung vom 01.01.2007 bis zum 31.03.2007 sein, und der Testzeitraum - vom 01.04.2007 bis zum 31.05.2007. Nach dem Test und der Aufzeichnung der Ergebnisse, verschieben wir Optimierung-und Test-Periode um einen Monat nach vorne: Optimierungszeitraum wird vom 01.02.2007 bis 30.04.2007 sein, und der Test-Zeitraum - vom 01.05.2007 bis zum 30.06.2007. Als Ergebnis haben wir eine Tabelle zum Aufzeichnen der Ergebnisse jeder Optimierung, zum Beispiel diese:

Abschließende Testparameter/Durchlauf 01 02 03 04 05 06 07 08 09 10 11 12
Netto Gewinn











Gesamtgewinn











Gesamtverlust











Rentabilität











Absoluter Drawdown











Relativer Drawdown











Gesamte Trades











Natürlich müssen Sie die Zellen der Tabelle nach jedem Optimierungsdurchlauf füllen. Es wird keine großen Probleme verursachen, die Tabelle zu analysieren und die in ihr enthaltenen Informationen zu verarbeiten, wodurch sie einfach Ihre Schlussfolgerungen aus dieser Analyse ziehen können. Ich nehme an, diese Art der Analyse von EA-Verhalten auf den verfügbaren historischen Daten, hilft die EA-Optimierungsergebnisse richtig einzuschätzen und vermeidet Täuschungen in Bezug auf diesen Vorgang. Und die Zeitersparnis, im Vergleich zum Testen auf einem Demokonto, ist fantastisch!

Die Technik des Backtests ist von beginnenden EA-Autoren ziemlich leicht zu verstehen, obwohl diese Untersuchung ebenfalls Zeit und Mühe erfordert. Auch wenn Sie während Ihrem Backtest schlechte Ergebnisse erhalten, regen Sie sich nicht auf: virtuelle Verluste sind viel besser, als die Live-Verwendung verlustbringender Strategien, die stark rentabel schienen.

Das ist alles, was ich über Backtests erzählen wollte. Beachten Sie, die Auswahl von maximalem Überschuss mit minimalem Rückgang ist nicht die einzig mögliche Strategie zur Systemoptimierung. Sie wird Ihnen nur zur Einführung in das Backtest-Verfahren angeboten. Im Allgemeinen, wird die meiste Zeit während des Backtests in die Optimierung investiert, während der Test der optimierten Strategien sehr wenig Zeit beansprucht, wodurch es sinnvoller ist mehrere Strategien gleichzeitig zu testen, um mehr statistisches Material für spätere Schlussfolgerungen zu haben. Folglich wird die Tabelle der Testergebnisse viel größer.



Oszillator Trading Strategie

Auf der Grundlage von Oszillatoren kann man viele verschiedene Handelsstrategien konstruieren. In diesem Artikel werde ich die beliebtesten auf Einstiegen und Ausstiegen in überkauften und überverkauften Bereichen basierten Strategien beschreiben:


Die Mehrheit der Oszillatoren ändert ihre Werte von einem bestimmten Minimum bis zu einem gewissen Maximum, jeder Oszillator hat seine eigenen Werte. In gewissem Abstand von seinen Extremwerten, werden die Ebenen UpLevel und DownLevel platziert.

In einem solchen System erscheint ein Signal zum Kaufen, wenn der Oszillator den kein-Trend-Bereich verlässt und in der überkauften Bereich eintritt:

Ein Signal zum Verkaufen tritt auf, wenn der Oszillator den kein-Trend-Bereich verlässt und in den überverkauften Bereich eintritt:

Neben diese Hauptsignalen, hat das System zusätzliche Signale, die auftreten wenn der Oszillator die überkauften und überverkauften Bereiche verlässt und in den kein-Trend-Bereich eintritt, die Signale der sogenannten Korrektur.

Ein Signal zum Kaufen erscheint, wenn der Oszillator den überverkauften Bereich verlässt und in den kein-Trend Bereich eintritt (Korrektur eines fallenden Trends):

Ein Signal zum Verkaufen erscheint, wenn er den überkauften Bereich verlässt und in kein-Trend Bereich eintritt (Korrektur eines steigenden Trends):



Code eines Expert Advisor für das Oszillator Handelssystem

Wir haben also vier Algorithmen für den Eintritt in den Markt. Schauen wir uns die zwei Varianten der Algorithmen für Long-Positionen an, können wir feststellen, dass ise absolut identisch sind und sich nur in der Position eine Breakout-Ebene unterscheiden, die aus der Sicht des Verfassens des Programmcodes absolut irrelevant ist. Die Situation ist gleich für Short-Positionen. Hier ist meine Variante zur Umsetzung des Oszillator Handelssystems:

//+==================================================================+
//|                                                        Exp_3.mq4 |
//|                             Copyright © 2007,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2007, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR BUY TRADES
extern bool   Test_Up1 = true;//filter of trade calculations direction
extern int    Timeframe_Up1 = 240;
extern double Money_Management_Up1 = 0.1;
extern double IndLevel_Up1 = 0.8; // breakout level of the indicator
extern int    JLength_Up1 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Up1 = 8;  // depth of JurX smoothing of obtained indicator
extern int    Phase_Up1 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Up1 = 0;/* Selecting prices on which the indicator will be calculated
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Up1 = 50;  // stoploss
extern int    TAKEPROFIT_Up1 = 100; // takeprofit
extern int    TRAILINGSTOP_Up1 = 0; // trailing stop
extern bool   ClosePos_Up1 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
///---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up2 = true;//filter of trade calculations direction
extern int    Timeframe_Up2 = 240;
extern double Money_Management_Up2 = 0.1;
extern double IndLevel_Up2 = -0.8; // breakout level of the indicator
extern int    JLength_Up2 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Up2 = 8;  // depth of JurX smoothing of obtained indicator
extern int    Phase_Up2 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Up2 = 0;/* Selecting prices on which the indicator will be calculated 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Up2 = 50;  // stoploss
extern int    TAKEPROFIT_Up2 = 100; // takeprofit
extern int    TRAILINGSTOP_Up2 = 0; // trailing stop
extern bool   ClosePos_Up2 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn1 = true;//filter of trade calculations direction
extern int    Timeframe_Dn1 = 240;
extern double Money_Management_Dn1 = 0.1;
extern double IndLevel_Dn1 = 0.8; // breakout level of the indicator
extern int    JLength_Dn1 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Dn1 = 8;  // depth of JurX smoothing of obtained indicator
extern int    Phase_Dn1 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Dn1 = 0;/* Selecting prices on which the indicator will be calculated 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Dn1 = 50;  // stoploss
extern int    TAKEPROFIT_Dn1 = 100; // takeprofit
extern int    TRAILINGSTOP_Dn1 = 0; // trailing stop
extern bool   ClosePos_Dn1 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES
extern bool   Test_Dn2 = true;//filter of trade calculations direction
extern int    Timeframe_Dn2 = 240;
extern double Money_Management_Dn2 = 0.1;
extern double IndLevel_Dn2 = -0.8; // breakout level of the indicator
extern int    JLength_Dn2 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Dn2 = 8;  // depth of JurX smoothing of obtained indicator
extern int    Phase_Dn2 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Dn2 = 0;/* Selecting prices on which the indicator will be calculated 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Dn2 = 50;  // stoploss
extern int    TAKEPROFIT_Dn2 = 100; // takeprofit
extern int    TRAILINGSTOP_Dn2 = 0; // trailing stop
extern bool   ClosePos_Dn2 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- Integer variables for the minimum of calculation bars
int MinBar_Up1, MinBar_Dn1;
int MinBar_Up2, MinBar_Dn2;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up1 variable value
   TimeframeCheck("Timeframe_Up1", Timeframe_Up1);                             
//---- Checking the correctness of Timeframe_Up2 variable value
   TimeframeCheck("Timeframe_Up2", Timeframe_Up2);                              
//---- Checking the correctness of Timeframe_Dn1 variable value
   TimeframeCheck("Timeframe_Dn1", Timeframe_Dn1);  
//---- Checking the correctness of Timeframe_Dn2 variable value
   TimeframeCheck("Timeframe_Dn2", Timeframe_Dn2);  
//---- Initialization of variables
   MinBar_Up1 = 3 + 3 * XLength_Up1 + 30;
   MinBar_Up2 = 3 + 3 * XLength_Up2 + 30;
   MinBar_Dn1 = 3 + 3 * XLength_Dn1 + 30;
   MinBar_Dn2 = 3 + 3 * XLength_Dn2 + 30;                                     
//---- end of initialization
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- End of EA deinitialization
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaring local variables
   double Osc1, Osc2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static int LastBars_Up1, LastBars_Dn1;
   static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1;
   //----+ +---------------------------------------------------------------+
   static int LastBars_Up2, LastBars_Dn2;
   static bool BUY_Sign2, BUY_Stop2, SELL_Sign2, SELL_Stop2;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up1) 
    {
      int IBARS_Up1 = iBars(NULL, Timeframe_Up1);
      
      if (IBARS_Up1 >= MinBar_Up1)
       {
         if (LastBars_Up1 != IBARS_Up1)
          {
           //----+ Initialization of variables
           BUY_Sign1 = false;
           BUY_Stop1 = false;
           LastBars_Up1 = IBARS_Up1; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up1, 
                 "JCCIX", JLength_Up1, XLength_Up1,
                                Phase_Up1, IPC_Up1, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up1, 
                 "JCCIX", JLength_Up1, XLength_Up1,
                                Phase_Up1, IPC_Up1, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up1)
             if (Osc1 > IndLevel_Up1)
                          BUY_Sign1 = true;
                          
           if (Osc1 < IndLevel_Up1)
                          BUY_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyOrder1(BUY_Sign1, 1, Money_Management_Up1, 
                                          STOPLOSS_Up1, TAKEPROFIT_Up1))
                                                                 return(-1);
          if (ClosePos_Up1)
                if (!CloseOrder1(BUY_Stop1, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up1))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 2
   if (Test_Up2) 
    {
      int IBARS_Up2 = iBars(NULL, Timeframe_Up2);
      
      if (IBARS_Up2 >= MinBar_Up2)
       {
         if (LastBars_Up2 != IBARS_Up2)
          {
           //----+ Initialization of variables 
           BUY_Sign2 = false;
           BUY_Stop2 = false;
           LastBars_Up2 = IBARS_Up2; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up2, 
                 "JCCIX", JLength_Up2, XLength_Up2,
                                Phase_Up2, IPC_Up2, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up2, 
                 "JCCIX", JLength_Up2, XLength_Up2,
                                Phase_Up2, IPC_Up2, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up2)
             if (Osc1 > IndLevel_Up2)
                          BUY_Sign2 = true;
                          
           if (Osc1 < IndLevel_Up2)
                          BUY_Stop2 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyOrder1(BUY_Sign2, 2, Money_Management_Up2, 
                                          STOPLOSS_Up2, TAKEPROFIT_Up2))
                                                                 return(-1);
          if (ClosePos_Up2)
                if (!CloseOrder1(BUY_Stop2, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Up2))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+ 
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn1) 
    {
      int IBARS_Dn1 = iBars(NULL, Timeframe_Dn1);
      
      if (IBARS_Dn1 >= MinBar_Dn1)
       {
         if (LastBars_Dn1 != IBARS_Dn1)
          {
           //----+ Initialization of variables 
           SELL_Sign1 = false;
           SELL_Stop1 = false;
           LastBars_Dn1 = IBARS_Dn1; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn1, 
                 "JCCIX", JLength_Dn1, XLength_Dn1,
                                Phase_Dn1, IPC_Dn1, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn1, 
                 "JCCIX", JLength_Dn1, XLength_Dn1,
                                Phase_Dn1, IPC_Dn1, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn1)
             if (Osc1 < IndLevel_Dn1)
                          SELL_Sign1 = true;
                          
           if (Osc1 > IndLevel_Dn1)
                          SELL_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellOrder1(SELL_Sign1, 3, Money_Management_Dn1, 
                                          STOPLOSS_Dn1, TAKEPROFIT_Dn1))
                                                                 return(-1);
          if (ClosePos_Dn1)
                if (!CloseOrder1(SELL_Stop1, 3))
                                        return(-1);
                                        
          if (!Make_TreilingStop(3, TRAILINGSTOP_Dn1))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 2
   if (Test_Dn2) 
    {
      int IBARS_Dn2 = iBars(NULL, Timeframe_Dn2);
      
      if (IBARS_Dn2 >= MinBar_Dn2)
       {
         if (LastBars_Dn2 != IBARS_Dn2)
          {
           //----+ Initialization of variables 
           SELL_Sign2 = false;
           SELL_Stop2 = false;
           LastBars_Dn2 = IBARS_Dn2; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn2, 
                 "JCCIX", JLength_Dn2, XLength_Dn2,
                                Phase_Dn2, IPC_Dn2, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn2, 
                 "JCCIX", JLength_Dn2, XLength_Dn2,
                                Phase_Dn2, IPC_Dn2, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn2)
             if (Osc1 < IndLevel_Dn2)
                          SELL_Sign2 = true;
                          
           if (Osc1 > IndLevel_Dn2)
                          SELL_Stop2 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellOrder1(SELL_Sign2, 4, Money_Management_Dn2, 
                                          STOPLOSS_Dn2, TAKEPROFIT_Dn2))
                                                                 return(-1);
          if (ClosePos_Dn2)
                if (!CloseOrder1(SELL_Stop2, 4))
                                        return(-1);
                                        
           if (!Make_TreilingStop(4, TRAILINGSTOP_Dn2))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+ 
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Der Code ist zweimal länger. als der im vorherigen Artikel vorgestellte. Nun denn, stellen Sie sich vor, wie lang dieser EA-Code sei könnte, würde er den kompletten Programm-Code enthalten, anstatt der Aufrufe von Order-Management Funktionen! Es muss hier angemerkt werden, dass dieser EA neue Eingabe-Parameter enthält: IndLevel_Up1, IndLevel_Up2, IndLevel_Dn1, IndLevel_Dn2. IndLevel_Up1 und IndLevel_Up2 bestimmen die Werte von Uplevel und DownLevel für die zwei Algorithmen der Long-Positionen, während IndLevel_Dn1 und IndLevel_Dn2 die Werte bestimmen für DownLevel und Uplevel für die zwei Algorithmen für Short-Positionen.

Während der Optimierung dieses Expert Advisors sollte beachtet werden, dass der Wert dieser Ebenen von -1.0 bis +1.0 variieren kann. Wenn Sie den JCCIX Oszillator in diesem EA durch irgendeinen anderen Oszillator ersetzen wollen, beachten Sie, dass die maximalen und minimalen Werte dieser Ebenen unterschiedlich sein können. Der Quellindikator JCCIX ist analog zu dem CCI Indikator, in dem der glättende Algorithmus über gemeinsame Moving Averages durch JMA und ultralineare Glättung erstzt wird. Der EA verwendet Traling Stops, deren Werte in den EA-Eingabeparametern bestimmt werden, wie TRAILINGSTOP_Up1, TRAILINGSTOP_Up2, TRAILINGSTOP_Dn1, TRAILINGSTOP_Dn2. In jeder anderen Hinsicht, ist dieser EA vollständig analog zu dem im vorherigen Artikel beschriebenen EA.



Ändern von Sofortigem Einstieg in den Markt in Pending Ordern

In vielen Fällen in EAs analog zum dem oben beschriebenen, ermöglicht das Ändern von direkten Markteinstieg zu Pending Ordern mehr Genauigkeit und den Erwerb größerer Gewinne mit geringerer Wahrscheinlichkeit des Erreichens des Stop Loss. Ein Satz an Funktionen der Datei Lite_EXPERT1.mqh ermöglicht die einfache Durchführung einer solchen Ersetzung.

Alles was wir brauchen, ist die Funktionen OpenBuyOrder1() und OpenSellOrder1() durch OpenBuyLimitOrder1() und OpenSellLimitOrder1() zu ersetzen. Während einen solchen Funktionsersatz müssen neue Eingabe-Variablen dieser Funktionen initialisiert werden: LEVEL und Expiration. Zum Beispiel, wir können eine Handelsstrategie aufbauen, in der die LEVEL Variable durch die EA Eingabeparameter bestimmt wird. Das Datum der Pending-Order-Löschung kann als der Zeitpunkt des nächsten Wechsels des aktuellen Balkens eingestellt werden.

Ich werde nicht den gleichen Code hier wiederholen. Der geänderte Code des obigen EA ist an den Artikel angehangen (Exp_4.mq4). Als Beispiel der Verwendung von Pending Ordern, beschreibe ich ein Oszillator-System mit dem OSMA Oszillator:

//For the EA operation the Metatrader\EXPERTS\indicators folder 
//must contain the 5c_OsMA.mq4 indicator
//+==================================================================+
//|                                                        Exp_5.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up = true;//filter of trade calculations direction
extern int    Timeframe_Up = 240;
extern double Money_Management_Up = 0.1;
extern double IndLevel_Up = 0; // breakout level of the indicator
extern int    FastEMA_Up = 12;  // period of quick EMA
extern int    SlowEMA_Up = 26;  // period of slow EMA
extern int    SignalSMA_Up = 9;  // period of signal SMA
extern int    STOPLOSS_Up = 50;  // stoploss
extern int    TAKEPROFIT_Up = 100; // takeprofit
extern int    TRAILINGSTOP_Up = 0; // trailing stop
extern int    PriceLevel_Up =40; // difference between the current price and
                                         // the price of pending order triggering
extern bool   ClosePos_Up = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn = true;//filter of trade calculations direction
extern int    Timeframe_Dn = 240;
extern double Money_Management_Dn = 0.1;
extern double IndLevel_Dn = 0; // breakout level of the indicator
extern int    FastEMA_Dn = 12;  // period of quick EMA
extern int    SlowEMA_Dn = 26;  // period of slow EMA
extern int    SignalSMA_Dn = 9;  // period of signal SMA
extern int    STOPLOSS_Dn = 50;  // stoploss
extern int    TAKEPROFIT_Dn = 100; // takeprofit
extern int    TRAILINGSTOP_Dn = 0; // trailing stop
extern int    PriceLevel_Dn = 40; // difference between the current price and
                                         // the price of pending order triggering
extern bool   ClosePos_Dn = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- Integer variables for the minimum of calculation bars
int MinBar_Up, MinBar_Dn;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up variable value
   TimeframeCheck("Timeframe_Up", Timeframe_Up);                                                          
//---- Checking the correctness of Timeframe_Dn variable value
   TimeframeCheck("Timeframe_Dn", Timeframe_Dn);  
//---- Initialization of variables
   MinBar_Up  = 3 + MathMax(FastEMA_Up, SlowEMA_Up) + SignalSMA_Up;
   MinBar_Dn  = 3 + MathMax(FastEMA_Dn, SlowEMA_Dn) + SignalSMA_Dn;                               
//---- end of initialization
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- End of EA deinitialization
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaring local variables
   double Osc1, Osc2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static datetime StopTime_Up, StopTime_Dn; 
   static int LastBars_Up, LastBars_Dn;
   static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up) 
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      
      if (IBARS_Up >= MinBar_Up)
       {
         if (LastBars_Up != IBARS_Up)
          {
           //----+ Initialization of variables 
           BUY_Sign1 = false;
           BUY_Stop1 = false;
           LastBars_Up = IBARS_Up;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                            + 60 * Timeframe_Up;
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up, 
                         "5c_OsMA", FastEMA_Up, SlowEMA_Up,
                                               SignalSMA_Up, 5, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up, 
                         "5c_OsMA", FastEMA_Up, SlowEMA_Up,
                                               SignalSMA_Up, 5, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up)
             if (Osc1 > IndLevel_Up)
                          BUY_Sign1 = true;
                          
           if (Osc1 < IndLevel_Up)
                          BUY_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyLimitOrder1(BUY_Sign1, 1, 
              Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up,
                                            PriceLevel_Up, StopTime_Up))
                                                                 return(-1);
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop1, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn) 
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      
      if (IBARS_Dn >= MinBar_Dn)
       {
         if (LastBars_Dn != IBARS_Dn)
          {
           //----+ Initialization of variables 
           SELL_Sign1 = false;
           SELL_Stop1 = false;
           LastBars_Dn = IBARS_Dn;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) 
                                            + 60 * Timeframe_Dn; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn, 
                         "5c_OsMA", FastEMA_Dn, SlowEMA_Dn,
                                               SignalSMA_Dn, 5, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn, 
                         "5c_OsMA", FastEMA_Dn, SlowEMA_Dn,
                                               SignalSMA_Dn, 5, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn)
             if (Osc1 < IndLevel_Dn)
                          SELL_Sign1 = true;
                          
           if (Osc1 > IndLevel_Dn)
                          SELL_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellLimitOrder1(SELL_Sign1, 2, 
              Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn,
                                            PriceLevel_Dn, StopTime_Dn))
                                                                 return(-1);
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop1, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Dn))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Anstelle der zwei Breakout-Ebenen UpLevel und DownLevel, wird eine Ebene verwendet, weshalb der EA nur zwei Algorithmen zu Positionsverwaltung enthält. In der Regel ist diese Ebene bei mit OSMA verbundenen Handelssystemen gleich Null, aber ich habe entschieden sie in einer externen Variable des EA zu belassen, wodurch sie geändert werden kann. Das heißt, es muss berücksichtigt werden, dass der OSMA Indikator kein Maximum und Minimum hat, innerhalb der der Indikator wechselt, folglich hat die Breakout-Ebene keine Grenzen in ihren Werten. Obwohl, wie ich sagte, in der Regel ist sie gleich Null. Um die Zeit zum Stornieren der Pending Order zu bestimmen, werden die statischen Variablen StopTime_Up und StopTime_Dn verwendet, beim Wechsel des Balkens werden sie durch den Zeitkpunkt des nächsten Balkenwechsels initialisiert.



Fazit

In der Schlussfolgerung möchte ich hinzufügen, dass Oszillator Handelssysteme viele falsche Signale gegen den aktuellen Markttrend geben. Also sind solche EAs besser in den Perioden aufgehoben, in denen der Markt sich seitwärts bewegt, oder werden nur zum Öffnen von Positionen durch einen Trend verwendet.

Für den Backtest möchte ich noch einmal sagen, dass dies wahrscheinlich der beste Weg für einen beginnenden EA-Autor ist, um Optimierungsergebnisse korrekt einzuschätzen. Und dabei gibt es keine Probleme mit EAs, die enorme Ergebnisse durch die Anpassung an die Historie zeigen. Allerdings ist es schwieriger zu verstehen, wie fertige EAs verwendet werden sollten, um Situationen zu vermeiden in denen der Markt sich weit von den optimierten EA-Parametern entfernt.



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

Beigefügte Dateien |
EXPERTS.zip (7.48 KB)
INCLUDE.zip (24.26 KB)
indicators.zip (5.59 KB)
TESTER.zip (5.28 KB)
Vergleichende Analyse von 30 Indikatoren und Oszillatoren Vergleichende Analyse von 30 Indikatoren und Oszillatoren

Der Artikel beschreibt einen Expert Advisor, der es ermöglicht die Durchführung der vergleichenden Analyse von 30 Indikatoren und Oszillatoren, mit dem Ziel ein effektives Paket aus Indizes für das Trading zu bilden

Ein Trader Assistent Basierend auf Erweeiterter MACD Analyse Ein Trader Assistent Basierend auf Erweeiterter MACD Analyse

Das Skript 'Trader's Assistant' hilft Ihnen eine Entscheidung beim Öffnen von Positionen zu treffen, auf Grundlage der erweiterten Analyse des MACD-Status für die letzten drei Balken im Echtzeit-Trading auf jedem Zeitrahmen. Es kann außerdem für Backtests verwendet werden.

Die Modellierung der Requotes im Tester und die Stabilitätsanalyse des Expert Advisors Die Modellierung der Requotes im Tester und die Stabilitätsanalyse des Expert Advisors

Requote - ist eine Plage vieler Experten, insbesondere bei denjenigen, die ziemlich empfindlich sind, um einen Trade zu schließen oder zu öffnen. Der Artikel bietet eine Methode an, um die Stabilität des Expertes vor Requotes zu überprüfen.

Probleme bei der technischen Analyse Probleme bei der technischen Analyse

Derzeit ist die technische Analyse zusammen mit der fundamentalen Analyse, ist die wichtigste Methode, die Aktienmärkte zu analysieren. Als eine Methode der Vorhersage der Dynamik bei Börsenpreisen hat die technische Analyse eine große Menge von Nachteilen, und einige von ihnen werfen Zweifel an ihrer praktischen Anwendbarkeit.