Die Kursbewegungen. Die Automatisierung der "Engulfing Pattern"-Handelsstrategie

Dmitry Iglakov | 29 April, 2016

Einführung

Alle Devisenhändler befassen sich früher oder später mit den Kursbewegungen. Hierbei handelt es sich nicht nur um eine bloße Chartanalysetechnik, sondern um ein vollständiges System zur Bestimmung der möglichen künftigen Kursbewegungen und deren Richtung. In diesem Artikel werden wir das sogenannte „Engulfing Pattern“ studieren und einen Expert Advisor kreieren, der dieses Muster verfolgen wird, um darauf basierende, relevante Handelsentscheidungen zu treffen.

Wir haben bereits zuvor das automatisierte Trading mit den Mustern der Kursbewegungen studiert, nämlich das sogenannte „Inside Bar“-Trading, und zwar im Artikel Kursbewegungen. Die Automatisierung der „Inside Bar“-Handelsstrategie.


Die Regeln des „Engulfing Pattern“

Das „Engulfing Pattern“ kommt dann zustande, wenn der Körper und die Schatten eines Balkens vollständig den Körper und die Schatten eines vorhergehenden Balkens umschließen. Es gibt zwei verschiedene Musterformen :

  • BUOVB — Bullenhafter außenliegender vertikaler Balken;
  • BEOVB — Bärenhafte außenliegender vertikaler Balken.

Fig. 1. Die verschiedenen Mustertypen veranschaulicht auf dem Chart

Fig. 1. Die verschiedenen Mustertypen veranschaulicht auf dem Chart

Let's have a closer look at this pattern.

BUOVB. Der Chart zeigt, dass das Hoch des außen liegenden Balkens sich oberhalb des Hochs des vorhergehenden Balkens befindet – und das Tief des außen liegenden Balkens liegt unterhalb des Tiefs des vorhergehenden Balkens.

BEOVB. Dieses Muster kann ebenfalls ganz einfach auf dem Chart identifiziert werden. Das Hoch des außen liegenden Balkens liegt oberhalb des Hochs des vorhergehenden Balkens, und das Tief des außen liegenden Balkens liegt unterhalb des Tiefs des vorhergehenden Balkens.

Der Unterschied besteht darin, dass jedes einzelne Muster ein klares Verständnis der potentiellen Richtungen ermöglicht, in die sich der Markt entwickeln könnte.

Fig. 2. Die Struktur des Musters

Fig. 2. Die Struktur des Musters

Die Regeln des „Engulfing Pattern“:
  • Bei diesem Muster ist es erforderlich, mit größeren Zeitrahmen zu arbeiten: H4, D1.
  • Um einen besseren Einstiegspunkt zu finden, sind weitere Elemente der grafischen Analyse anzuwenden, wie etwa Trendlinien, Unterstützungsniveaus und Widerstandsniveaus, Fibonacci-Niveaus, weitere Kursbewegungsmuster etc.
  • Verwenden Sie anstehende Orders, um einen vorzeitigen oder verfehlten Markteintritt zu vermeiden.
  • Muster, welche sich in Handelsflauten immer wiederholen, sollten nicht als Signale zum Einstieg in den Markt benutzt werden.


Das Finden von Einstiegspunkten für "BUOVB", und die Platzierung von Stopporders

Fig. 3. Das Setzen von Kaufstopps und Stopporders

Fig. 3. Das Setzen von Kaufstopps und Stopporders

Wir werden jetzt die Einstiegsregeln und die Platzierung von Stopporders für BUOVB (englische Abkürzung für „bullish outside vertical bar“ – zu deutsch: bullenhafter, außenliegender vertikaler Balken) analysieren, indem wir das obige Beispiel heranziehen :

  1. Wir setzen eine anstehende Kaufstopp-Order zu einem Kursniveau, das sich ganz knapp oberhalb des Höchstkurses des außen liegenden Balkens befindet (lediglich um ein paar Punkte, zur Bestätigung).
  2. Das Verlustbegrenzungsniveau wird unterhalb des Tiefstkurses des außen liegenden Balkens angesiedelt.
  3. Und das Gewinnmitnahmeniveau wird so gesetzt, dass es kurz vor der nächsten Widerstandslinie greift.


Das Herausfinden von Einstiegspunkten für "BEOVB", und die Platzierung von Stopporders

Fig. 4. Das Setzen von Verkaufsstopps und Stopporders

Fig. 4. Das Setzen von Verkaufsstopps und Stopporders

Lassen Sie uns jetzt die Regeln für den Einstiegspunkt und die Platzierung von Stopporders bei BEOVB (englische Abkürzung für „bearish outside vertical bar“ – zu deutsch: bärenhafter außenliegender vertikaler Balken) vom obigen Beispiel ableiten :

  1. Wir platzieren die anstehende Verkaufsstopporder bei einem Kursniveau knapp unterhalb des Tiefstkurses eines außen liegenden Balkens (lediglich um ein paar Punkte, zur Bestätigung).
  2. Das Verlustbegrenzungsorderniveau wird oberhalb des Höchstkurses des außen liegenden Balkens angesiedelt.
  3. Das Gewinnmitnahmeniveau wird so gesetzt, dass es greift, kurz bevor der Kurs die nächste Unterstützungslinie erreicht.


Die Erstellung eines Expert Advisors für den Handel mit der „Engulfing Pattern“

Wir haben uns das Muster der „Engulfing Pattern“ ausgiebig angesehen und gelernt, wie man sicher in den Markt einsteigen kann, und wir haben ebenfalls die Niveaus der Stopporders festgelegt, um mögliche Verluste zu begrenzen oder Gewinne zu sichern.

Als nächstes werden wir versuchen, die Algorithmen eines Expert Advisors zu implementieren und somit den Handel mit der „Engulfing Pattern“ zu automatisieren.

Wir öffnen hierzu den MetaEditor aus dem Terminal von MetaTrader 4 heraus, und erstellen einen neuen Expert Advisor (wir werden hier nicht die Grundlagen der Erstellung von Expert Advisors behandeln, weil es auf dieser Webseite bereits genügend Informationen darüber gibt). Zum Zeitpunkt der Erstellung werden wir sämtliche Parameter zunächst leer lassen. Sie können sie allerdings benennen, wenn sie dies wünschen. Schließlich sollten Sie die folgenden Ergebnisse erhalten :

//+------------------------------------------------------------------+
//|                                              BEOVB_BUOVB_Bar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+


Die Umwandlung des Musters in einen MQL4-Algorithmus

Nachdem wir einen Expert Advisor kreiert haben, müssen wir das „Engulfing Pattern“ definieren, nachdem eine Kerze abgeschlossen wurde. Zu diesem Zwecke führen wir neue Variablen ein und ordnen ihnen Werte zu. Sehen Sie sich diesbezüglich den folgenden Code an :

//+------------------------------------------------------------------+
//|                                              BEOVB_BUOVB_Bar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict

double open1,//first candle Open price
open2,      //second candle Open price
close1,     //first candle Close price
close2,     //second candle Close price
low1,       //first candle Low price
low2,       //second candle Low price
high1,      //first candle High price
high2;      //second candle High price
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- define prices of necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
  }
//+------------------------------------------------------------------+

Wir finden hier beide Typen der „Engulfing Pattern“:

void OnTick()
  {
//--- define prices of necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
//--- Finding bearish pattern BEOVB
   if(low1 < low2 &&// First bar's Low is below second bar's Low
      high1 > high2 &&// First bar's High is above second bar's High
      close1 < open2 &&	//First bar's Close price is below second bar's Open
      open1 > close1 && //First bar is a bearish bar
      open2 < close2)	//Second bar is a bullish bar
     {
      //--- we have described all conditions indicating that the first bar completely engulfs the second bar and is a bearish bar
     }

Auf dieselbe Art und Weise finden wir ein bullenhaftes Muster :

//--- Finding bullish pattern BUOVB
   if(low1 < low2 &&// First bar's Low is below second bar's Low 
      high1 > high2 &&// First bar's High is above second bar's High
      close1 > open2 && //First bar's Close price is higher than second bar's Open
      open1 < close1 && //First bar is a bullish bar
      open2 > close2)   //Second bar is a bearish bar
     {
      //--- we have described all conditions indicating that the first bar completely engulfs the second bar and is a bullish bar 
     }
  • Wir kreieren individuell einstellbare Variablen: Stopporders, Slippage, Orderablaufzeit, eine magische EA-Zahl, und die Losgröße. Die Verlustbegrenzungsorder kann weggelassen werden, weil sie nämlich gemäß der Regeln für das Muster eingestellt werden wird.
  • Wir führen lokale Variablen ein, um die Variablen in eine normale Form zu bringen.
  • Darüber hinaus beachten wir bei unserer Arbeit, dass Stopporders mit einem gewissen Abstand zu den Kurswerten der Balken gesetzt werden. Um dies zu implementieren, fügen wir die Variable Interval hinzu, welche für das Intervall zwischen den Höchst- und Tiefstkursen der Balken und die Stopporderniveaus sowie für die Niveaus der anstehenden Orders verantwortlich ist.
  • Wir geben die Variable timeBUOVB_BEOVB ein, um die erneute Eröffnung der Order als Reaktion auf dieses Muster zu verhindern.
  • Wir geben die Variable bar1size ein, um zu überprüfen, ob der außen liegende Balken auch groß genug ist. Daher können wir davon ausgehen, dass die aktuelle Marktsituation keine Flaute darstellt.

Als Ergebnis erhalten wir den folgenden Code:

//+------------------------------------------------------------------+
//|                                              BEOVB_BUOVB_bar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict

extern int     interval          = 25;                               //Interval
extern double  lot               = 0.1;                              //Lot Size
extern int     TP                = 400;                              //Take Profit
extern int     magic             = 962231;                           //Magic number
extern int     slippage          = 2;                                //Slippage
extern int     ExpDate           = 48;                               //Expiration Hour Order
extern int     bar1size          = 900;                              //Bar 1 Size

double buyPrice,//define BuyStop setting price
buyTP,      //Take Profit BuyStop
buySL,      //Stop Loss BuyStop
sellPrice,  //define SellStop setting price
sellTP,     //Take Profit SellStop
sellSL;     //Stop Loss SellStop

double open1,//first candle Open price
open2,    //second candle Open price
close1,   //first candle Close price
close2,   //second candle Close price
low1,     //first candle Low price
low2,     //second candle Low price
high1,    //first candle High price
high2;    //second candle High price

datetime _ExpDate =0; // local variable for defining pending orders expiration time
double _bar1size;// local variable required to avoid a flat market
datetime timeBUOVB_BEOVB;// time of a bar when pattern orders were opened, to avoid re-opening
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double   _bid = NormalizeDouble(MarketInfo (Symbol(), MODE_BID), Digits); // define Low price 
   double   _ask     = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK), Digits); //define High price
   double   _point   = MarketInfo(Symbol(), MODE_POINT);
//--- define prices of necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
//---
   _bar1size=NormalizeDouble(((high1-low1)/_point),0);
//--- Finding bearish pattern BEOVB
   if(timeBUOVB_BEOVB!=iTime(Symbol(),Period(),1) && //orders are not yet opened for this pattern 
      _bar1size > bar1size && //first bar is big enough, so the market is not flat
      low1 < low2 &&//First bar's Low is below second bar's Low
      high1 > high2 &&//First bar's High is above second bar's High
      close1 < open2 && //First bar's Сlose price is lower than second bar's Open price
      open1 > close1 && //First bar is a bearish bar
      open2 < close2)   //Second bar is a bullish bar
     {
      //--- we have described all conditions indicating that the first bar completely engulfs the second bar and is a bearish bar
      timeBUOVB_BEOVB=iTime(Symbol(),Period(),1); // indicate that orders are already placed on this pattern
     }
//--- Finding bullish pattern BUOVB
   if(timeBUOVB_BEOVB!=iTime(Symbol(),Period(),1) && //orders are not yet opened for this pattern 
      _bar1size > bar1size && //first bar is big enough not to consider a flat market
      low1 < low2 &&//First bar's Low is below second bar's Low
      high1 > high2 &&//First bar's High is above second bar's High
      close1 > open2 && //First bar's Close price is higher than second bar's Open price
      open1 < close1 && //First bar is a bullish bar
      open2 > close2)   //Second bar is a bearish bar
     {
      //--- we have described all conditions indicating that the first bar completely engulfs the second bar and is a bullish bar 
      timeBUOVB_BEOVB=iTime(Symbol(),Period(),1); // indicate that orders are already placed on this pattern
     }
  }
//+------------------------------------------------------------------+


Die Definition von Stopporderniveaus

Wir haben sämtliche Bedingungen erfüllt und hochqualitative Muster gefunden. Jetzt ist es notwendig, die Stopporderniveaus, die Kurse der anstehenden Orders, sowie das Ablaufdatum der Orders für jedes Muster zu definieren.

Lassen Sie uns den folgenden Code zu der Funktion OnTick hinzufügen () function body:

//--- Define prices for placing orders and stop orders
   buyPrice =NormalizeDouble(high1 + interval * _point,Digits); //define a price of order placing with intervals
   buySL =NormalizeDouble(low1-interval * _point,Digits); //define stop-loss with an interval
   buyTP =NormalizeDouble(buyPrice + TP * _point,Digits); //define take profit
   _ExpDate =TimeCurrent() + ExpDate*60*60; //pending order expiration time calculation
//--- We also calculate sell orders 
   sellPrice=NormalizeDouble(low1-interval*_point,Digits);
   sellSL=NormalizeDouble(high1+interval*_point,Digits);
   sellTP=NormalizeDouble(sellPrice-TP*_point,Digits);


Die Beseitigung von Ausführungsfehlern

Falls Sie sich jemals an der Entwicklung von Expert Advisors versucht haben, dann wissen Sie vermutlich bereits, dass es häufiger zu Fehlern kommt, was das Schließen und die Einstellung von Orders anbelangt – inklusive der Wartezeit, falscher Stopps etc. Um solche Fehler zu eliminieren, sollten wir eine separate Funktion schreiben, die über einen kleinen eingebauten Identifikator von häufigen Fehlern verfügt.

//+----------------------------------------------------------------------------------------------------------------------+
//| The function opens or sets an order                                                                                  |
//| symbol      - symbol, at which a deal is performed.                                                                  |
//| cmd         - a deal (may be equal to any of the deal values).                                                       |
//| volume      - amount of lots.                                                                                        |
//| price       - Open price.                                                                                            |
//| slippage    - maximum price deviation for market buy or sell orders.                                                 |
//| stoploss    - position close price when an unprofitability level is reached (0 if there is no unprofitability level).|
//| takeprofit  - position close price when a profitability level is reached (0 if there is no profitability level).     |
//| comment     - order comment. The last part of comment can be changed by the trade server.                            |
//| magic       - order magic number. It can be used as a user-defined ID.                                               |
//| expiration  - pending order expiration time.                                                                         |
//| arrow_color - open arrow color on a chart. If the parameter is absent or equal to CLR_NONE,                          |
//|               the open arrow is not displayed on a chart.                                                            |
//+----------------------------------------------------------------------------------------------------------------------+
int OrderOpenF(string     OO_symbol,
               int        OO_cmd,
               double     OO_volume,
               double     OO_price,
               int        OO_slippage,
               double     OO_stoploss,
               double     OO_takeprofit,
               string     OO_comment,
               int        OO_magic,
               datetime   OO_expiration,
               color      OO_arrow_color)
  {
   int result = -1;// result of opening an order
   int Error = 0; // error when opening an order
   int attempt = 0; // amount of performed attempts 
   int attemptMax = 3; // maximum amount of attempts
   bool exit_loop = false; // exit the loop
   string lang =TerminalInfoString(TERMINAL_LANGUAGE);// trading terminal language for defining the language of the messages
   double stopllvl =NormalizeDouble(MarketInfo (OO_symbol, MODE_STOPLEVEL) * MarketInfo (OO_symbol, MODE_POINT),Digits);// minimum stop loss/take profit level, in points
                                                                                                                     //the module provides safe order opening
//--- checking stop orders for buying
   if(OO_cmd==OP_BUY || OO_cmd==OP_BUYLIMIT || OO_cmd==OP_BUYSTOP)
     {
      double tp = (OO_takeprofit - OO_price)/MarketInfo(OO_symbol, MODE_POINT);
      double sl = (OO_price - OO_stoploss)/MarketInfo(OO_symbol, MODE_POINT);
      if(tp>0 && tp<=stopllvl)
        {
         OO_takeprofit=OO_price+stopllvl+2*MarketInfo(OO_symbol,MODE_POINT);
        }
      if(sl>0 && sl<=stopllvl)
        {
         OO_stoploss=OO_price -(stopllvl+2*MarketInfo(OO_symbol,MODE_POINT));
        }
     }
//--- checking stop orders for selling
   if(OO_cmd==OP_SELL || OO_cmd==OP_SELLLIMIT || OO_cmd==OP_SELLSTOP)
     {
      double tp = (OO_price - OO_takeprofit)/MarketInfo(OO_symbol, MODE_POINT);
      double sl = (OO_stoploss - OO_price)/MarketInfo(OO_symbol, MODE_POINT);
      if(tp>0 && tp<=stopllvl)
        {
         OO_takeprofit=OO_price -(stopllvl+2*MarketInfo(OO_symbol,MODE_POINT));
        }
      if(sl>0 && sl<=stopllvl)
        {
         OO_stoploss=OO_price+stopllvl+2*MarketInfo(OO_symbol,MODE_POINT);
        }
     }
//--- while loop
   while(!exit_loop)
     {
      result=OrderSend(OO_symbol,OO_cmd,OO_volume,OO_price,OO_slippage,OO_stoploss,OO_takeprofit,OO_comment,OO_magic,OO_expiration,OO_arrow_color); //attempt to open an order using the specified parameters
      //--- if there is an error when opening an order
      if(result<0)
        {
         Error = GetLastError();                                     //assign a code to an error
         switch(Error)                                               //error enumeration
           {                                                         //order closing error enumeration and an attempt to fix them
            case  2:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(3000);                                       //3 seconds of delay
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;                                         //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case  3:
               RefreshRates();
               exit_loop = true;                                     //exit while
               break;                                                //exit switch   
            case  4:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(3000);                                       //3 seconds of delay
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case  5:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch   
            case  6:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(5000);                                       //3 seconds of delay
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case  8:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(7000);                                       //3 seconds of delay
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 64:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch
            case 65:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch
            case 128:
               Sleep(3000);
               RefreshRates();
               continue;                                             //exit switch
            case 129:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(3000);                                       //3 seconds of delay
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 130:
               exit_loop=true;                                       //exit while
               break;
            case 131:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch
            case 132:
               Sleep(10000);                                         //sleep for 10 seconds
               RefreshRates();                                       //update data
               //exit_loop = true;                                   //exit while
               break;                                                //exit switch
            case 133:
               exit_loop=true;                                       //exit while
               break;                                                //exit switch
            case 134:
               exit_loop=true;                                       //exit while
               break;                                                //exit switch
            case 135:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //set the number of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 136:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //set the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 137:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  Sleep(2000);
                  RefreshRates();
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 138:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  Sleep(1000);
                  RefreshRates();
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 139:
               exit_loop=true;
               break;
            case 141:
               Sleep(5000);
               exit_loop=true;
               break;
            case 145:
               exit_loop=true;
               break;
            case 146:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  Sleep(2000);
                  RefreshRates();
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 147:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  OO_expiration=0;
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 148:
               exit_loop=true;
               break;
            default:
               Print("Error: ",Error);
               exit_loop=true; //exit while 
               break;          //other options 
           }
        }
      //--- if no errors detected
      else
        {
         if(lang == "Russian") {Print("Ордер успешно открыт. ", result);}
         if(lang == "English") {Print("The order is successfully opened.", result);}
         Error = 0;                                //reset the error code to zero
         break;                                    //exit while
         //errorCount =0;                          //reset the amount of attempts to zero
        }
     }
   return(result);
  }
//+------------------------------------------------------------------+

Als Ergebnis davon erhalten wir den folgenden Code:

//+------------------------------------------------------------------+
//|                                              BEOVB_BUOVB_bar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict

extern int     interval          = 25;                               //Interval
extern double  lot               = 0.1;                              //Lot Size
extern int     TP                = 400;                              //Take Profit
extern int     magic             = 962231;                           //Magic number
extern int     slippage          = 2;                                //Slippage
extern int     ExpDate           = 48;                               //Expiration Hour Order
extern int     bar1size          = 900;                              //Bar 1 Size

double buyPrice,//define BuyStop price
buyTP,      //Take Profit BuyStop
buySL,      //Stop Loss BuyStop
sellPrice,  //define SellStop price
sellTP,     //Take Profit SellStop
sellSL;     //Stop Loss SellStop

double open1,//first candle Open price
open2,    //second candle Open price
close1,   //first candle Close price
close2,   //second candle Close price
low1,     //first candle Low price
low2,     //second candle Low price
high1,    //first candle High price
high2;    //second candle High price

datetime _ExpDate =0; // local variable for defining pending orders expiration time
double _bar1size;// local variable required to avoid a flat market
datetime timeBUOVB_BEOVB;// time of a bar when pattern orders were opened, to avoid re-opening
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double   _bid = NormalizeDouble(MarketInfo (Symbol(), MODE_BID), Digits); // define Low price 
   double   _ask     = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK), Digits); //define High price
   double   _point   = MarketInfo(Symbol(), MODE_POINT);
//--- define prices of necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
   
//--- Define prices for placing orders and stop orders
   buyPrice =NormalizeDouble(high1 + interval * _point,Digits); //define a price of order placing with intervals
   buySL =NormalizeDouble(low1-interval * _point,Digits); //define stop loss with an interval
   buyTP =NormalizeDouble(buyPrice + TP * _point,Digits); //define take profit
   _ExpDate =TimeCurrent() + ExpDate*60*60; //pending order expiration time calculation
//--- We also calculate sell orders 
   sellPrice=NormalizeDouble(low1-interval*_point,Digits);
   sellSL=NormalizeDouble(high1+interval*_point,Digits);
   sellTP=NormalizeDouble(sellPrice-TP*_point,Digits);
//---
   _bar1size=NormalizeDouble(((high1-low1)/_point),0);
//--- Finding bearish pattern BEOVB
   if(timeBUOVB_BEOVB!=iTime(Symbol(),Period(),1) && //orders are not yet opened for this pattern 
      _bar1size > bar1size && //first bar is big enough, so the market is not flat
      low1 < low2 &&//First bar's Low is below second bar's Low
      high1 > high2 &&//First bar's High is above second bar's High
      close1 < open2 && //First bar's Close price is lower than second bar's Open price
      open1 > close1 && //First bar is a bearish bar
      open2 < close2)   //Second bar is a bullish bar
     {
      //--- we have described all conditions indicating that the first bar completely engulfs the second bar and is a bearish bar
      OrderOpenF(Symbol(),OP_SELLSTOP,lot,sellPrice,slippage,sellSL,sellTP,NULL,magic,_ExpDate,Blue);
      timeBUOVB_BEOVB=iTime(Symbol(),Period(),1); //indicate that orders are already placed on this pattern
     }
//--- Finding bullish pattern BUOVB
   if(timeBUOVB_BEOVB!=iTime(Symbol(),Period(),1) && //orders are not yet opened for this pattern 
      _bar1size > bar1size && //first bar is big enough, so the market is not flat
      low1 < low2 &&//First bar's Low is below second bar's Low
      high1 > high2 &&//First bar's High is above second bar's High
      close1 > open2 && //First bar's Close price is higher than second bar's Open price
      open1 < close1 && //First bar is a bullish bar
      open2 > close2)   //Second bar is a bearish bar
     {
      //--- we have described all conditions indicating that the first bar completely engulfs the second bar and is a bullish bar 
      OrderOpenF(Symbol(),OP_BUYSTOP,lot,buyPrice,slippage,buySL,buyTP,NULL,magic,_ExpDate,Blue);
      timeBUOVB_BEOVB = iTime(Symbol(),Period(),1); //indicate that orders are already placed on this pattern
     }
  }
//+------------------------------------------------------------------+

Jetzt möchten wir einmal die Kompilierung durchlaufen lassen und anschließend im Logbuch nach Fehlermeldungen suchen.


Testen des Expert Advisors

Jetzt ist die Zeit gekommen, um unseren Expert Advisor einem ersten Test zu unterziehen. Wir starten hierzu den Strategietester und stellen die Eingabeparameter ein.

Fig. 5. Eingabeparameter zu Testzwecken

Fig. 5. Eingabeparameter zu Testzwecken

  1. Wählen Sie ein Währungspaar für den Test aus. Ich habe EURAUD gewählt.
  2. Stellen Sie sicher, den Modus „Jeder Tick“ einzustellen, und bestimmen Sie, dass der Test mit Daten aus der Chronik erfolgen soll. Ich habe mich dazu entschlossen, das gesamte Jahr von 2014 hierzu zu verwenden.
  3. Legen Sie den Zeitraum D1 fest.
  4. Starten Sie den Test.
  5. Nachdem der Test abgeschlossen ist, überprüfen Sie das Logbuch. Wie wir sehen können, gab es im Rahmen dieses Prozesses keinerlei Fehler bei der Ausführung.

Fig. 6. Die Einstellung der Testbedingungen

Fig. 6. Die Einstellung der Testbedingungen

Untenstehend sehen Sie das EA-Testjournal :

Fig. 7. Expert Advisor Testjournal

Fig. 7. Expert Advisor Testjournal

Stellen Sie sicher, dass sich hierbei keine Fehler finden, und optimieren Sie den EA.


Die Optimierung

Ich habe die folgenden Parameter zur Optimierung ausgewählt :

Fig. 8. Optimierungsparameter

Fig. 8. Optimierungsparameter


Fig. 9. Optimierungseinstellungen

Fig. 9. Optimierungseinstellungen

Als Ergebnis unserer Optimierungsbemühungen und der Tests verfügen wir jetzt über einen einsatzfähigen Roboter.


Die Ergebnisse der Optimierung und der Tests

Nach der Optimierung der populärsten Währungspaare erhalten wir die folgenden Resultate:

Währungspaar Nettogewinn Gewinnfaktor Verluste (%) Gross Profit   Gesamtverlust  
EURAUD 523,90$ 3,70 2,13  727,98$ 196,86$
USDCHF 454,19$ - 2,25  454,19$ 0,00$
GBPUSD 638,71$ - 1,50  638,71$ 0,00$
EURUSD 638,86$ - 1,85  638,86$ 0,00$
USDJPY 423,85$ 5,15 2,36  525,51$ 102,08$
USDCAD 198,82$ 2,41 2,74  379,08$ 180,26$
AUDUSD 136,14$ 1,67 2,39  339,26$ 203,12$

 Table 1. Optimierungsergebnisse

Detailliertere Testergebnisse wurden mit dem Währungspaar EURAUD ermittelt:

Fig. 10. Testergebnisse

Fig. 10. Testergebnisse


Fig. 11. Testergebnis-Chart

Fig. 11. Testergebnis-Chart


Schlussfolgerung

  1. In diesem Artikel haben wir einen Expert Advisor erstellt, der zum Handel mit der sogenannten „Engulfing Pattern“ dient.
  2. Wir haben dabei sichergestellt, dass die Muster der Kursbewegungen funktionieren können – sogar ohne zusätzliche Filter für den Markteinstieg.
  3. Keinerlei Tricks (wie etwa das System von Martingale oder die Durchschnittswertbildung) kamen hierbei zum Einsatz.
  4. Die erlittenen Verluste wurden durch die korrekte Einstellung der Stopporders minimiert.
  5. Es wurden keinerlei technische Indikatoren verwendet. Der EA basiert lediglich auf der Analyse eines „nackten“ Charts.

Vielen Dank für Ihre Aufmerksamkeit – ich hoffe, dass Sie diesen Artikel als hilfreich empfanden.