English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Le MQL5 Wizard : Comment apprendre à un EA à ouvrir des ordres en attente à n’importe quel prix

Le MQL5 Wizard : Comment apprendre à un EA à ouvrir des ordres en attente à n’importe quel prix

MetaTrader 5Exemples | 13 janvier 2022, 10:59
400 0
Vladimir Karputov
Vladimir Karputov

Introduction

Un Expert Advisor généré en utilisant MQL5 Wizard ne peut ouvrir les ordres en attente qu’à la distance fixe à partir du prix actuel. Cela signifie que si la situation du marché change (par exemple, un changement de volatilité du marché), l’Expert Advisor devra être exécuté à nouveau avec de nouveaux paramètres.

Cela ne conviendrait pas à de nombreux systèmes de trading. Dans la plupart des cas, le niveau de prix des ordres en attente est déterminé dynamiquement par un système de trading. Et la distance par rapport au prix actuel change constamment. Dans cet article, nous expliquerons comment modifier un Expert Advisor généré en utilisant le MQL5 Wizard afin qu’il puisse ouvrir des ordres en attente à des distances variables par rapport au prix actuel.


1. Mécanisme d’ouverture des ordres en attente dans l’Expert Advisor généré en utilisant le MQL5 Wizard

Un Expert Advisor généré aurait à peu près le même code dans son en-tête que celui fourni ci-dessous :

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string             Expert_Title="ExpertMySignalEnvelopes.mq5";      // Document name
ulong                    Expert_MagicNumber        =3915;        // 
bool                     Expert_EveryTick          =false;       // 
//--- inputs for main signal
input int                Signal_ThresholdOpen      =10;          // Signal threshold value to open [0...100]
input int                Signal_ThresholdClose     =10;          // Signal threshold value to close [0...100]
input double             Signal_PriceLevel         =0.0;         // Price level to execute a deal
input double             Signal_StopLevel          =85.0;        // Stop Loss level (in points)
input double             Signal_TakeLevel          =195.0;       // Take Profit level (in points)
input int                Signal_Expiration         =0;           // Expiration of pending orders (in bars)
input int                Signal_Envelopes_PeriodMA =13;          // Envelopes(13,0,MODE_SMA,...) Period of averaging
input int                Signal_Envelopes_Shift    =0;           // Envelopes(13,0,MODE_SMA,...) Time shift
input ENUM_MA_METHOD     Signal_Envelopes_Method   =MODE_SMA;    // Envelopes(13,0,MODE_SMA,...) Method of averaging
input ENUM_APPLIED_PRICE Signal_Envelopes_Applied  =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series
input double             Signal_Envelopes_Deviation=0.2;         // Envelopes(13,0,MODE_SMA,...) Deviation
input double             Signal_Envelopes_Weight   =1.0;         // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0]
//--- inputs for money
input double             Money_FixLot_Percent      =10.0;        // Percent
input double             Money_FixLot_Lots         =0.1;         // Fixed volume
//+------------------------------------------------------------------+

Veuillez noter le paramètre Signal_PriceLevel. Par défaut, l’Expert Advisor est généré avec Signal_PriceLevel=0. Ce paramètre définit la distance par rapport au prix actuel. S’il est égal à zéro, un ordre sera ouvert au prix actuel du marché. Pour ouvrir un ordre en attente, vous devez définir une valeur différente de zéro pour le paramètre Signal_PriceLevel, c’est-à-dire Signal_PriceLevel peut être à la fois négative et positive.

La valeur de Signal_PriceLevel est généralement un nombre assez important. La différence entre les valeurs négatives et positives est illustrée ci-dessous :

Signal_PriceLevel=-50 :

Fig. 1. Signal_PriceLevel=-50

Fig. 1. Signal_PriceLevel=-50

Signal_PriceLevel=50 :

Fig. 2. Signal_PriceLevel=50

Fig. 2. Signal_PriceLevel=50

Ainsi, si Signal_PriceLevel=-50, un ordre en attente sera ouvert au prix qui est moins favorable que le prix actuel, alors que si Signal_PriceLevel=50, un ordre en attente sera ouvert au prix qui est meilleur que le prix actuel.

Cette version de l’Expert Advisor ouvre les ordres Sell Stop et Buy Stop.


2. Où stockons-nous les données sur la distance par rapport au prix d’ouverture d’un ordre en attente ?

Jetons d’abord un coup d’œil à la figure ci-dessous, puis passons aux commentaires :

Fig. 3. Stockage des données sur la distance par rapport au prix actuel

Fig. 3. Stockage des données sur la distance par rapport au prix actuel

Interprétation de la figure ci-dessus.

Expert Advisor est l’Expert Advisor généré en utilisant le MQL5 Wizard.

  • L’objet ExtExpert de la classe CExpert est déclaré dans l’Expert Advisor au niveau mondial. 
  • Ensuite, dans la fonction OnInit() de l’Expert Advisor, nous déclarons un pointeur vers l’objet signal de la classe CExpertSignal et l’objet signal est immédiatement créé à l’aide du nouvel opérateur.
  • Tout en étant dans la fonction OnInit(), nous appelons la fonction InitSignal de l’objet ExtExpert et initialisons l’objet signal.
  • Tout en étant dans la fonction OnInit(), nous appelons la fonction PriceLevel de l’objet signal qui obtient le paramètre Signal_PriceLevel.

Ainsi, le paramètre Signal_PriceLevel où la distance par rapport au prix actuel est stockée et qui a été déclarée dans l’Expert Advisor est transmise à l’objet signal de la classe CExpertSignal.

La classe CExpertSignal stocke la valeur de la distance par rapport au prix actuel dans la variable m_price_level déclarée avec l’étendue de classe protégée :

class CExpertSignal : public CExpertBase
  {
protected:
   //--- variables
   double            m_base_price;     // base price for detection of level of entering (and/or exit?)
   //--- variables for working with additional filters
   CArrayObj         m_filters;        // array of additional filters (maximum number of fileter is 64)
   //--- Adjusted parameters
   double            m_weight;         // "weight" of a signal in a combined filter
   int               m_patterns_usage; // bit mask of  using of the market models of signals
   int               m_general;        // index of the "main" signal (-1 - no)
   long              m_ignore;         // bit mask of "ignoring" the additional filter
   long              m_invert;         // bit mask of "inverting" the additional filter
   int               m_threshold_open; // threshold value for opening
   int               m_threshold_close;// threshold level for closing
   double            m_price_level;    // level of placing a pending orders relatively to the base price
   double            m_stop_level;     // level of placing of the "stop loss" order relatively to the open price
   double            m_take_level;     // level of placing of the "take profit" order relatively to the open price
   int               m_expiration;     // time of expiration of a pending order in bars


3. Structure de l’Expert Advisor généré en utilisant le MQL5 Wizard

L’Expert Advisor se compose de plusieurs blocs avec des fonctionnalités différentes.


Fig. 4. Structure de l’Expert Advisor 

Fig. 4. Structure de l’Expert Advisor

Interprétation de la figure ci-dessus :

  • Expert Advisor est l’Expert Advisor généré en utilisant le MQL5 Wizard.
  • CExpert est la classe de base pour la mise en œuvre de stratégies de trading.
  • CExpertSignal est la classe de base pour la création de générateurs de signal de trading.
  • filter0 ... filtern sont des générateurs de signal de trading, les descendants de la classe CExpertSignal. Il convient de noter que notre système de trading est basé sur le générateur de signal de trading de l’indicateur Enveloppes, mais les signaux au sein du générateur ont été modifiés. Nous parlerons de ces changements à l’article 7.


4. Blocs d’Expert Advisor conseillés pour la modification

Comme vous pouvez le voir dans la structure de l’Expert Advisor généré en utilisant le MQL5 Wizard, il existe des blocs de classe de base. Les classes de base font partie de la bibliothèque standard.

Les classes en soi sont des descendants d’autres classes de base et elles se composent à leur tour d’une ou plusieurs classes de base. Vous trouverez ci-dessous les premières lignes du code de deux classes - CExpert et CExpertSignal :

//+------------------------------------------------------------------+
//|                                                       Expert.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
#include "ExpertTrade.mqh"
#include "ExpertSignal.mqh"
#include "ExpertMoney.mqh"
#include "ExpertTrailing.mqh"
//+------------------------------------------------------------------+
.
.
.
class CExpert : public CExpertBase

et

//+------------------------------------------------------------------+
//|                                                 ExpertSignal.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
.
.
.
class CExpertSignal : public CExpertBase

Je suis fortement opposé à toute modification des classes de base :

  1. Lorsque MetaEditor est mis à jour, toutes les modifications que vous apportez aux classes de base sont remplacées et les classes de base sont restaurées à leur état initial.
  2. La succession serait plus approprié dans ce cas. Mais alors vous devrez modifier la bibliothèque standard ENTIÈRE.

Au lieu de cela, il serait préférable de modifier le bloc des modules Expert Advisor et générateur de signal de trading, d’autant plus que notre système de trading aura déjà un module modifié en cours d’utilisation - le générateur de signal de trading de l’indicateur Envelopes.

Donc, c’est réglé : nous allons apporter des modifications aux blocs de l’Expert Advisor et au bloc du générateur de signal de trading.


5. La logique d’implémentation

Le pointeur sera transmis de l’Expert Advisor au générateur de signal de trading.

À cette fin, nous devons en outre déclarer une variable avec l’étendue protégée et écrire une méthode qui stocke le pointeur de l’Expert Advisor dans la variable interne :


  Fig. 5. La logique d’implémentation

Fig. 5. La logique d’implémentation


6. Système de trading

La cadre temporel du graphique est D1. L’indicateur à utiliser est enveloppes avec une période de moyenne de 13 et une méthode de moyenne exponentielle. Les types d’ordres que l’Expert Advisor peut ouvrir sont Sell Stop et Buy Stop.

Si la barre précédente était haussière, nous définissons un ordre Sell Stop. Si la barre précédente était baissière, nous définissons un ordre Buy Stop. En d’autres termes, nous espérons un repli :

Fig. 6. Système de trading

Fig. 6. Système de trading

Pour générer des signaux de trading comme requis par le système de trading, le module standard du générateur de signal de trading SignalEnvelopes.mqh a été modifié.

Notez qu’ici, vous pouvez utiliser n’importe quel générateur de signal de trading de la bibliothèque standard.


7. Modification du générateur de signal de trading. Obtenir le prix de barre

Alors, commençons. Je dois dire que je préfère enregistrer mes programmes dans MQL5 Storage.

La première chose que nous devrions faire pour commencer à modifier le générateur de signal de trading est de créer un fichier d’inclusion vide, de tout supprimer de celui-ci et de coller tout le contenu du générateur de signal de trading standard de l’indicateur Enveloppes.

Par défaut, le générateur de signal de trading doit être situé sous ...MQL5\Include\Expert\Signal. Ne pas surcharger le ...\Signal de la bibliothèque standard avec trop d’informations, créons un nouveau dossier sous le dossier ...\Expert et appelez-le \MySignals :

Fig. 7. Création du dossier MySignals

Fig. 7. Création du dossier MySignals

Ensuite, nous allons créer un fichier d’inclusion en utilisant le MQL5 Wizard.

Dans MetaEditor, sélectionnez 'New' dans le menu Fichier, puis sélectionnez 'Include file (*.mqh)'.

Fig. 8. Le MQL5 Wizard. Création d’un fichier d’inclusion

Fig. 8. Le MQL5 Wizard. Création d’un fichier d’inclusion

Le nom de notre classe de générateur de signal sera MySignalEnvelopes.

Et il sera situé sous : Include\Expert\MySignals\MySignalEnvelopes. Précisons-le :

Fig. 9. Assistant MQL5. Emplacement du fichier d’inclusion

Fig. 9. Le MQL5 Wizard. Emplacement du fichier include

Après avoir cliqué sur 'Terminer', le MQL5 Wizard génère un modèle vide.

Le fichier MySignalEnvelopes.mqh généré doit ensuite être ajouté au MQL5 Storage :

Fig. 10. Le MQL5 Storage. Ajout du fichier

Fig. 10. Le MQL5 Storage. Ajout du fichier

Une fois le fichier ajouté, nous devons valider les modifications apportées au MQL Storage :

Fig. 11. Le MQL Storage. Validation des modifications

Fig. 11. Le MQL5 Storage. Validation des modifications

Après avoir terminé les étapes ci-dessus, nous pouvons procéder à la modification de notre générateur de signal de trading.

Étant donné que le générateur est basé sur le fichier \Include\Expert\Signal\SignalEnvelopes.mqh, nous copions tout le contenu du fichier et le collons dans le fichier du générateur, en ne laissant que l’en-tête d’origine :

//+------------------------------------------------------------------+
//|                                            MySignalEnvelopes.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2013, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of indicator 'Envelopes'                           |
//| Type=SignalAdvanced                                              |
//| Name=Envelopes                                                   |
//| ShortName=Envelopes                                              |
//| Class=CSignalEnvelopes                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodMA,int,45,Period of averaging                    |
//| Parameter=Shift,int,0,Time shift                                 |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging     |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//| Parameter=Deviation,double,0.15,Deviation                        |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalEnvelopes.                                          |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Envelopes' indicator.                              |
//| Is derived from the CExpertSignal class.                         |
//+------------------------------------------------------------------+
class CSignalEnvelopes : public CExpertSignal
  {
protected:
   CiEnvelopes       m_env;            // object-indicator
   //--- adjusted parameters
   int               m_ma_period;      // the "period of averaging" parameter of the indicator
   int               m_ma_shift;       // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;      // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;      // the "deviation" parameter of the indicator
   double            m_limit_in;       // threshold sensitivity of the 'rollback zone'
   double            m_limit_out;      // threshold sensitivity of the 'break through zone'
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

public:
                     CSignalEnvelopes(void);
                    ~CSignalEnvelopes(void);
   //--- methods of setting adjustable parameters
   void              PeriodMA(int value)                 { m_ma_period=value;        }
   void              Shift(int value)                    { m_ma_shift=value;         }
   void              Method(ENUM_MA_METHOD value)        { m_ma_method=value;        }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_ma_applied=value;       }
   void              Deviation(double value)             { m_deviation=value;        }
   void              LimitIn(double value)               { m_limit_in=value;         }
   void              LimitOut(double value)              { m_limit_out=value;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   void              Pattern_1(int value)                { m_pattern_1=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);

protected:
   //--- method of initialization of the indicator
   bool              InitMA(CIndicators *indicators);
   //--- methods of getting data
   double            Upper(int ind)                      { return(m_env.Upper(ind)); }
   double            Lower(int ind)                      { return(m_env.Lower(ind)); }
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45),
                                           m_ma_shift(0),
                                           m_ma_method(MODE_SMA),
                                           m_ma_applied(PRICE_CLOSE),
                                           m_deviation(0.15),
                                           m_limit_in(0.2),
                                           m_limit_out(0.2),
                                           m_pattern_0(90),
                                           m_pattern_1(70)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CSignalEnvelopes::~CSignalEnvelopes(void)
  {
  }
//+------------------------------------------------------------------+
//| Validation settings protected data.                              |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_ma_period<=0)
     {
      printf(__FUNCTION__+": period MA must be greater than 0");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitIndicators(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- initialization of indicators and timeseries of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- create and initialize MA indicator
   if(!InitMA(indicators))
      return(false);
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialize MA indicators.                                        |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitMA(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- add object to collection
   if(!indicators.Add(GetPointer(m_env)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- initialize object
   if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| "Voting" that price will grow.                                   |
//+------------------------------------------------------------------+
int CSignalEnvelopes::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+
//| "Voting" that price will fall.                                   |
//+------------------------------------------------------------------+
int CSignalEnvelopes::ShortCondition(void)
  {
   int result  =0;
   int idx     =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+

Maintenant, nous allons travailler sur des modifications de certaines parties du code.

Pour éviter toute confusion, le code modifié sera mis en évidence :

//+------------------------------------------------------------------+
//|                                                     MySignal.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+

Le code modifié est le code qui doit être copié et collé dans le générateur de signal de trading. J’espère qu’une telle mise en évidence vous aidera à mieux comprendre le code.

Puisque nous écrivons notre propre classe du générateur de signal de trading, son nom doit être différent du nom de la classe de base. Nous remplaçons donc CSignalEnvelopes par CMySignalEnvelopes dans l’ensemble du code :

Fig. 12. Renommer la classe

Fig. 12. Renommer la classe

Pour vous assurer que la classe du générateur de signal de trading est affichée dans le MQL5 Wizard sous son nom, modifiez le nom de la classe dans le bloc de description

//| Title=Signals of indicator 'Envelopes'                           |

en

//| Title=Signals of indicator 'MySignalEnvelopes'                   |

Changer la valeur de la période MA

//| Parameter=PeriodMA,int,45,Period of averaging                    |

à 13 (ce n’est que ma suggestion, vous pouvez définir n’importe quelle valeur que vous préférez)

//| Parameter=PeriodMA,int,13,Period of averaging                    |

En outre, nous modifions également le paramètre Deviation

//| Parameter=Deviation,double,0.15,Deviation                        |

en définissant une valeur supérieure

//| Parameter=Deviation,double,1.15,Deviation                        |

Selon notre logique d’implémentation,nous devons déclarer une variable interne qui stockera le pointeur vers le signal principal.

Comme il doit s’agir d’une variable interne (dans le cadre de la classe du générateur de signal de trading uniquement), elle sera ajoutée au bloc de code suivant :

protected:
   CiEnvelopes       m_env;          // object-indicator
   //--- adjusted parameters
   int               m_ma_period;    // the "period of averaging" parameter of the indicator
   int               m_ma_shift;     // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;     // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;    // the "deviation" parameter of the indicator
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0
   CExpertSignal    *m_signal;         // storing the pointer to the main signal

Veuillez également noter que j’ai supprimé les variables inutiles du code. 

La méthode de stockage du pointeur vers le signal principal sera déclarée dans un autre bloc de code - la 'méthode de réglage du pointeur sur le signal principal'. Ici, j’ai également supprimé certaines méthodes non pertinentes.

public:
                     CMySignalEnvelopes(void);
                    ~CMySignalEnvelopes(void);
   //--- methods of setting adjustable parameters
   void              PeriodMA(int value)                 { m_ma_period=value;        }
   void              Shift(int value)                    { m_ma_shift=value;         }
   void              Method(ENUM_MA_METHOD value)        { m_ma_method=value;        }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_ma_applied=value;       }
   void              Deviation(double value)             { m_deviation=value;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);
   //--- method of setting the pointer to the main signal
   virtual bool      InitSignal(CExpertSignal *signal=NULL);

Spécifions maintenant certains paramètres modifiés dans le constructeur et supprimons les variables qui ne sont plus nécessaires :

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13),
                                               m_ma_shift(0),
                                               m_ma_method(MODE_SMA),
                                               m_ma_applied(PRICE_CLOSE),
                                               m_deviation(1.15),
                                               m_pattern_0(50)  

À ce stade, nous pouvons procéder à la modification de la logique de génération de signal de trading en fonction de notre système de trading.

Le bloc de code responsable d’un signal d’achat :

int CMySignalEnvelopes::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }

sera comme indiqué ci-dessous, en suivant les changements nécessaires :

int CMySignalEnvelopes::LongCondition(void) //---buy
  {
   int result=0;
   int idx   =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close<open)
        {
         prlevel=GetPriceLevelStopp(open,Open(0));
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }

Le bloc de code responsable d’un signal de vente :

int CMySignalEnvelopes::ShortCondition(void)
  {
   int result  =0;
   int idx     =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }

sera comme indiqué ci-dessous, en suivant les changements nécessaires :

int CMySignalEnvelopes::ShortCondition(void) //---sell
  {
   int result  =0;
   int idx     =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close>open)
        {
         prlevel=GetPriceLevelStopp(Open(0),open);
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }


8. Quelques commentaires sur le bloc de code de signal

Si la condition requise pour un certain signal est remplie, nous appelons la méthode GetPriceLevelStopp qui renvoie un nombre comme "20" ou "15" - la valeur de la distance par rapport au prix actuel.

Ceci est suivi par l’appel de la méthode PriceLevel de l’objet m_signal (qui définit la distance pour déterminer le prix du niveau d'ordre en attente). Il convient de rappeler que m_signal est l’objet de classe CExpertSignal qui stocke le pointeur vers le signal principal.

Le code de la méthode GetPriceLevelStopp est fourni ci-dessous :

double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
  {
   double level;
   double temp;
   temp-=(price_0-min)/PriceLevelUnit();
   level=NormalizeDouble(temp,0);
   return(level);
  }

Nous devons déclarer cette méthode dans l’en-tête de classe :

protected:
   //--- method of initialization of the indicator
   bool              InitMA(CIndicators *indicators);
   //--- methods of getting data
   double            Upper(int ind)                      { return(m_env.Upper(ind)); }
   double            Lower(int ind)                      { return(m_env.Lower(ind)); }
   double            GetPriceLevelStopp(double price,double min);
  };

Une autre méthode dont nous aurons besoin est la méthode de passage du pointeur au signal principal à la variable interne:

bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
  {
   m_signal=signal;
   return(true);
  }

 Après cela, nous devons créer un Expert Advisor dans le MQL5 Wizard et y inclure le module de signal 'MySignalEnvelopes'.

Nous devons également ajouter l’appel de méthode InitSignal au code de l’Expert Advisor généré en utilisant le MQL5 Wizard :

//--- Set filter parameters
   filter0.PeriodMA(Signal_Envelopes_PeriodMA);
   filter0.Shift(Signal_Envelopes_Shift);
   filter0.Method(Signal_Envelopes_Method);
   filter0.Applied(Signal_Envelopes_Applied);
   filter0.Deviation(Signal_Envelopes_Deviation);
   filter0.Weight(Signal_Envelopes_Weight);
   filter0.InitSignal(signal);
//...

Pour une meilleure visualisation du fonctionnement de l’Expert Advisor, j’ai fourni une courte vidéo :

Le code de l’Expert Advisor généré en utilisant le MQL5 Wizard, ainsi que le code du module de signal, sont joints à l’article.

Vous trouverez ci-dessous les résultats des tests de l’Expert Advisor. Il a été testé pour EURUSD et USDJPY avec les paramètres suivants: période de test 2013.01.01 - 2013.09.01, période - D1, niveau Stop Loss = 85, niveau Take Profit = 195.

Fig. 13. Test pour EURUSD sur D1

Fig. 13. Test pour EURUSD sur D1

Fig. 14. Test pour USDJPY sur D1

Fig. 14. Test pour USDJPY sur D1


Conclusion

Nous venons de voir comment nous pouvons modifier le code du module de signal de trading pour la mise en œuvre de la fonctionnalité nous permettant de définir des ordres en attente à n’importe quelle distance du prix actuel : il peut s’agir du prix Close ou Open de la barre précédente ou de la valeur de la moyenne mobile. Il y a beaucoup d’options. Il est important que vous puissiez définir n’importe quel prix d’ouverture pour un ordre en attente.

L’article a montré comment nous pouvons accéder au pointeur vers le signal principal, et donc aux méthodes de classe CExpertSignal.   Je crois que l’article s’avérera utile aux traders qui tradent avec des ordres en attente.


Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/723

Émerveillez vos clients MQL5 avec un cocktail de technologies utilisables ! Émerveillez vos clients MQL5 avec un cocktail de technologies utilisables !
MQL5 fournit aux programmeurs un ensemble très complet de fonctions et d'API orientées objet grâce auxquelles ils peuvent faire tout ce qu'ils veulent dans l'environnement MetaTrader. Cependant, la technologie Web est un outil extrêmement polyvalent de nos jours qui peut venir à la rescousse dans certaines situations lorsque vous devez faire quelque chose de très spécifique, voulez émerveiller vos clients avec quelque chose de différent ou tout simplement vous n'avez pas assez de temps pour maîtriser une partie spécifique de Bibliothèque standard MT5. L'exercice d'aujourd'hui vous présente un exemple pratique sur la façon dont vous pouvez gérer votre temps de développement tout en créant un cocktail technologique incroyable.
Construire un trader automatique de nouvelles Construire un trader automatique de nouvelles
Ceci est la suite d’un autre article sur la classe MQL5 POO qui vous a montré comment créer un simple EA OO à partir de zéro et vous a donné quelques conseils sur la programmation orientée objet. Aujourd’hui, je vous montre les bases techniques nécessaires pour développer un EA capable d’échanger les nouvelles. Mon objectif est de continuer à vous donner des idées sur la POO et de couvrir également un nouveau sujet dans cette série d’articles, en travaillant avec le système de fichiers.
Élevez vos systèmes de trading linéaires au rang de puissance Élevez vos systèmes de trading linéaires au rang de puissance
L'article d'aujourd'hui montre aux programmeurs MQL5 intermédiaires comment ils peuvent tirer plus de bénéfice de leurs systèmes de trading linéaire (Fixed Lot) en implémentant facilement la technique dite de l'exponentiation. En effet, la croissance de la courbe d'équité qui en résulte est alors géométrique, ou exponentielle, prenant la forme d'une parabole. Plus précisément, nous mettrons en œuvre une variante pratique MQL5 du dimensionnement de la position fractionnée fixe développée par Ralph Vince.
Création d’EA de réseau de neurones en utilisant MQL5 Wizard et Hlaiman EA Generator Création d’EA de réseau de neurones en utilisant MQL5 Wizard et Hlaiman EA Generator
L’article décrit une méthode de création automatisée d’EA de réseau de neurones en utilisant MQL5 Wizard et Hlaiman EA Generator. Il vous montre comment vous pouvez facilement commencer à travailler avec des réseaux de neurones, sans avoir à apprendre tout le corps des informations théoriques et à écrire votre propre code.