English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Assistant MQL5 : Comment Créer un Module de Signaux de Trading

Assistant MQL5 : Comment Créer un Module de Signaux de Trading

MetaTrader 5Systèmes de trading | 12 janvier 2022, 14:17
365 0
MetaQuotes
MetaQuotes

Introduction

MetaTrader 5 fournit un outil puissant pour une vérification rapide des idées de trading. C'est le générateur de stratégies de trading duMQL5 Wizard. L'utilisation de l'assistant MQL5 pour la création automatique de codes Expert Advisor est décrite dans l'article « Assistant MQL5 : Création d'Expert Advisors sans Programmation". L'ouverture du système de génération de code vous permet d'ajouter vos propres classes de signaux de trading, de systèmes de gestion d'argent et de modules de suivi aux celles standard

Cet article décrit les principes d'écriture demodules de signaux de trading pour les utiliser lors de la création d'Expert Advisors avec l'assistant MQL5.

L'Expert Advisor créé avecMQL5 Wizard, est basé sur quatre piliers - quatre classes de base:

Figure 1. La structure de la classe de base CExpert

Figure 1. La structure de la classe de baseCExpert

La classeCExpert (ou sa sous-classe) est le "moteur" principal d'un robot de trading . Une instance de CExpert comporte une copie de chaque classe : CExpertSignal, CExpertMoney et CExpertTrailing (ou leurs sous-classes) :

  1. CExpertSignal est la base du générateur de signaux de trading. Une instance de la classe dérivée CExpertSignal, incluse dansCExpert , fournit à un Expert Advisor des informations sur la possibilité d'entrer sur le marché, les niveaux d'entrée et le placement d’une ordonnance conservatoire, sur la base d'algorithmes intégrés. La décision finale sur l’exécution des opération de tradingest prise par EA.
  2. CExpertMoneyest la base des systèmes de gestion de l'argent et des risques. Une instance de la classe dérivée CExpertMoney calcule les volumes pour ouvrir des positions et émettre des commandes en cours La décision finale sur le volume est prise par l'AE.
  3. CExpertTrailing - est la base du module de support des positions ouvertes. Une instance de la classe dérivée CExpertTrailing informe un EA de la nécessité de modifier les ordonnances conservatoires d'une position. La décision finale sur la modification de la commande est prise par l' EA.

De plus, les membres de la classeCExpert sont des instances des classes suivantes :

  • CExpertTrade (pour le trading)
  • CIndicators (pour contrôler les indicateurs et les séries chronologiques impliqués dans le travail de l'AE).
  • CSymbolInfo(pour obtenir des informations sur l'instrument)
  • CAccountInfo(pour obtenir des informations sur l'état du compte de trading)
  • CPositionInfo (pour obtenir des informations sur les positions)
  • COrderInfo(pour obtenir des informations sur les commandes en cours)

Ci-après, sous "expert", nous entendons une instance de CExpert ou de sa sous-classe.

Plus de détails sur CExpert et son utilisation seront décrits dans un article séparé.


1. Classe de base CExpertSignal

CExpertSignal est la base du générateur de signaux de trading. Pour communiquer avec le "monde extérieur", CExpertSignal dispose d'un ensemble de méthode virtuelle publique :

Initialisation

 Description

virtual Init

L'initialisation de l'instance de classe assure la synchronisation des données du module avec les données de l'EA

paramètres virtuels de validation

Validation des paramètres réglés

virtuelInitIndicators

Création et initialisation de tous les indicateurs et séries chronologiques nécessaires au fonctionnement du générateur de signaux de trading

Signaux d'ouverture/inversion/clôture de position

 

virtual CheckOpenLong

Générer le signal d'ouverture d’une longue position définir les niveaux d'entrée et émettre des ordonnances conservatoires

virtual CheckOpenShort

Générer le signal d'une ouverture d’un’ courte position, définir les niveaux d'entrée et émettre des ordonnances conservatoires

virtual CheckCloseLong

Génération du signal de clôture d’une longue position, définition du niveau de sortie

virtual CheckCloseShort

Génération du signal de clôture d’une courte position, définition du niveau de sortie

virtual CheckReverseLong

Générer le signal d'inversion d’une longue position , définir les niveaux d'inversion et émettre des ordonnances conservatoires

virtual CheckReverseShort

Générer le signal de retournement d’une courte position , définir les niveaux de retournement et émettre des ordonnances conservatoires

Gérer les commandes en cours

 

virtual CheckTrailingOrderLong

Génération du signal de modification d'une commande d'achat en cours, définition du nouveau prix de la commande

virtual CheckTrailingOrderShort

Génération du signal de modification d'une commande de vente en cours, définition du prix de la nouvelle commande

Description des méthodes

1.1. Méthodes d'initialisation :

1.1.1 Init

La méthodeInit() est automatiquementappelée juste après l'ajout d'une instance de classe à l'expert. La substitution de méthode n'est pas requise.

virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);

1.1.2 ValidationSettings

La méthode ValidationSettings() est appelée directement par l'expert une fois tous les paramètres définis. Vous devez remplacer la méthode s'il existe des paramètres de configuration.

virtual bool ValidationSettings();

La méthode remplacée doit renvoyer true, si toutes les options sont valides (utilisables). Si au moins un des paramètres est incorrect, il doit renvoyer false (la poursuite du travail est impossible).

La classe de baseCExpertSignal n'a pas de paramètres ajustables, par conséquent, la méthode de classe de base renvoie toujours true sans effectuer de vérification.

1.1.3 InitIndicators

La méthodeInitIndicators () implémente la création et l'initialisation de tous les indicateurs et séries chronologiques nécessaires. Il est appelé par l'expert une fois tous les paramètres définis et leur exactitude vérifiée avec succès. La méthode doit être remplacée si le générateur de signaux de trading utilise au moins un indicateur ou une série chronologique.

virtual bool InitIndicators(CIndicators* indicators);

Les indicateurs et/ou les séries chronologiques doivent être utilisés dans les classes appropriées de la bibliothèque Standard Les pointeurs de tous les indicateurs et/ou séries chronologiques doivent être ajoutés à la collection d'indicateurs d'un expert (un pointeur auquel est transmis en paramètre).

La méthode remplacée doit retourner true, si toutes les manipulations avec les indicateurs et/ou les séries chronologiques ont abouti (ils peuvent être utilisés). Si au moins une opération avec les indicateurs et/ou les séries chronologiques a échoué, la méthode doit retourner false (la poursuite du travail est impossible).

La classe de baseCExpertSignaln'utilise pas d'indicateurs ou de séries chronologiques, par conséquent, la méthode de classe de base renvoie toujours true, sans effectuer la moindre action.


1.2. Méthodes de contrôle du signal d'ouverture de position :

1.2.1 CheckOpenLong

La méthodeCheckOpenLong() génère un signal d'ouverture d'une longue position , définissant le niveau d'entrée et les niveaux de placement d'ordonnances conservatoires. Il est convoqué par un expert pour déterminer s'il est nécessaire d'ouvrir une longue position. La méthode doit être remplacée si l'on s'attend à ce qu'un signal d'ouverture d’une longue position soit généré.

virtual bool CheckOpenLong(double& price, double& sl, double& tp, datetime& expiration);

La méthode doit implémenter l'algorithme de vérification de la condition d'une ouverture d’une longue position.. Si la condition est remplie, les variables price, sl, tp et expiration (dont les références sont transmises en tant que paramètres) doivent recevoir des valeurs appropriées et la méthode doit renvoyer true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

La classe de baseCExpertSignal n'a pas d'algorithme intégré pour générer un signal d'ouverture de longue position, donc la méthode de la classe de base renvoie toujours false.

1.2.2 CheckOpenShort

La méthodeCheckOpenShort()génère un signal d'ouverture d'une courte position , définissant le niveau d'entrée et les niveaux de passation d'ordonnances conservatoires. Il est convoqué par un expert pour déterminer s'il est nécessaire d'ouvrir une courte position. La méthode doit être remplacée si l'on s'attend à ce qu'un signal d'ouverture de courte position soit généré. 

virtual bool CheckOpenShort(double& price, double& sl, double& tp, datetime& expiration);

La méthode doit implémenter l'algorithme de vérification de la condition d'ouverture d'une position courte. Si la condition est satisfaite, les variables price, sl, tp et expiration (dont les références sont transmises en tant que paramètres) doivent recevoir les valeurs appropriées et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

La classe de baseCExpertSignal n'a pas d'algorithme intégré pour générer un signal d'ouverture de position courte, donc la méthode de la classe de base renvoie toujours false.


1.3. Méthodes de contrôle du signal de fermeture de position :

1.3.1 CheckCloseLong

La méthode CheckCloseLong() génère un signal de clôture d’une longue position, définissant le niveau de sortie. Il est appelé par un expert pour déterminer s'il est nécessaire de fermer une longue position. La méthode doit être remplacée si l'on s'attend à ce qu'un signal de clôture de longue position soit généré.

virtual bool CheckCloseLong(double& price);

La méthode doit implémenter l'algorithme de vérification de la condition de clôture de la longue position. Si la condition est satisfaite, la variable prix (dont la référence est passée en paramètre) doit se voir attribuer la valeur appropriée et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

La classe de baseCExpertSignal n'a pas d'algorithme intégré pour générer un signal de clôture d’une longue position, donc la méthode de classe de base renvoie toujours false.

1.3.2 CheckCloseShort

La méthodeCheckCloseShort() génère un signal de clôture d'une courte position , définissant le niveau de sortie. Il est appelé par un expert pour déterminer s'il est nécessaire de clôturer une courte position. La méthode doit être remplacée si l'on s'attend à ce qu'un signal de clôture de position courte soit généré.

virtual bool CheckCloseShort(double& price);

La méthode doit implémenter l'algorithme de vérification de la condition de clôture d'une position courte. Si la condition est satisfaite, la variable prix (dont la référence est passée en paramètre) doit se voir attribuer la valeur appropriée et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

La classe de baseCExpertSignal ne dispose pas d'algorithme intégré pour générer un signal de clôturer de courte position , donc la méthode de classe de base renvoie toujours false.


1.4. Méthodes de contrôle du signal d'inversion de position :

1.4.1 CheckReverseLong

La méthode CheckReverseLong génère un signal d'inversion d'une longue position , définissant le niveau d'inversion et les niveaux de passation d'ordonnances conservatoires. Il est appelé par un expert pour déterminer s'il est nécessaire d'inverser une longue position. La méthode doit être remplacée si l'on s'attend à ce qu'un signal d'inversion d’une longue position soit généré.

virtual bool CheckReverseLong(double& price, double& sl, double& tp, datetime& expiration);

La méthode doit implémenter l'algorithme de vérification de la condition d'inversion d’une longue position. Si la condition est satisfaite, les variables price, sl, tp et expiration (dont les références sont transmises en tant que paramètres) doivent recevoir les valeurs appropriées et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

Dans la classe de baseCExpertSignal , l'algorithme suivant pour générer un signal d'inversion d’une longue position est implémenté :

  1. Recherche d'un signal pour clôturer une longue position.
  2. Recherche d'un signal pour ouvrir une position courte.
  3. Si les deux signaux sont actifs (les conditions sont remplies) et que les prix de clôture et d'ouverture correspondent, les variables price, sl, tp et expiration (dont les références sont transmises en tant que paramètres) reçoivent les valeurs appropriées et la méthode renvoie true.
Si la condition n'est pas remplie, la méthode renvoie false.

1.4.2 CheckReverseShort

La méthode CheckReverseShort génère un signal d'inversion d'une position courte, définissant le niveau d'inversion et les niveaux de passation d'ordonnances conservatoires. Il est convoqué par un expert pour déterminer s'il est nécessaire de renverser une position courte. La méthode doit être remplacée, si l'on s'attend à ce qu'un signal d'inversion d’une longue position soit généré selon l'algorithme qui diffère de celui implémenté dans la classe de base.

virtual bool CheckReverseShort(double& price, double& sl, double& tp, datetime& expiration);

La méthode doit implémenter l'algorithme de vérification de la condition de retournement de position courte. Si la condition est satisfaite, les variables price, sl, tp et expiration (dont les références sont transmises en tant que paramètres) doivent recevoir les valeurs appropriées et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

Dans la classe de baseCExpertSignal, l'algorithme suivant pour générer un signal d'inversion de position courte est implémenté :

  1. Recherche d'un signal pour clôturer une position courte.
  2. Recherche d'un signal pour ouvrir une longue position.
  3. Si les deux signaux sont actifs (les conditions sont remplies) et que les prix de clôture et d'ouverture correspondent, les variables price, sl, tp et expiration (dont les références sont transmises en tant que paramètres) reçoivent les valeurs appropriées et la méthode renvoie true.

Si la condition n'est pas remplie, la méthode renvoie false.


1.5. Méthodes de vérification du signal de modification de commande en attente :

1.5.1 CheckTrailingOrderLong

La méthodeCheckTrailingOrderLong() génère le signal de modification d'une commande d'achat en cours, définissant le prix d’une nouvelle commande Il est appelé par un expert pour déterminer s'il est nécessaire de modifier une commande d'achat en cours. La méthode doit être remplacée si l'on s'attend à ce qu'un signal de modification d'une commande d'achat en cours soit généré.

virtual bool CheckTrailingOrderLong(COrderInfo* order, double& price)

La méthode doit implémenter l'algorithme de vérification de la condition de modification d'une commande d'achat en cours. Si la condition est satisfaite, la variable prix (dont la référence est passée en paramètre) doit se voir attribuer la valeur appropriée et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

La classe de baseCExpertSignal n'a pas d'algorithme intégré pour générer un signal de modification d'une commande d'achat en cours, donc la méthode de la classe de base renvoie toujours false.

1.5.2 CheckTrailingOrderShort

La méthode CheckTrailingOrderShort() génère le signal de modification d'une commande de vente en cours, définissant un prix de nouvelle commande. Il est appelé par un expert pour déterminer s'il est nécessaire de modifier une commande de vente en cours. La méthode doit être remplacée si l'on s'attend à ce qu'un signal de modification d'une commande de vente en cours soit généré.

virtual bool CheckTrailingOrderShort(COrderInfo* order, double& price)

La méthode doit implémenter l'algorithme de vérification de la condition de modification d'une commande de vente en cours. Si la condition est satisfaite, la variable prix (dont la référence est passée en paramètre) doit se voir attribuer la valeur appropriée et la méthode doit retourner true. Si la condition n'est pas remplie, la méthode doit renvoyer false.

La classe de baseCExpertSignal n'a pas d'algorithme intégré pour générer un signal de modification d'une commande de vente en cours, donc la méthode de la classe de base renvoie toujours false.


2. Élaborez votre propre générateur de signaux de trading

Maintenant, après avoir passé en revue la structure de la classe de base CExpertSignal , vous pouvez commencer à créer votre propre générateur de signaux de trading.

Comme mentionné ci-dessus, la classeCExpertSignal est un ensemble de "cordes" virtuelles publiques - des méthodes, à l'aide desquelles l'expert peut connaître l'opinion du générateur de signaux de trading sur l'entrée sur le marché dans un sens ou dans un autre.

Par conséquent, notre objectif principal est de créer notre propre classe de générateur de signaux de trading, en la dérivant de la classeCExpertSignal et en remplaçant les méthodes virtuelles appropriées, en implémentant les algorithmes requis.

Notre deuxième problème (qui n'est pas moins important) - rendre notre classe "visible" àMQL5 Wizard. Mais, tout d'abord.

2.1. Création de la classe du générateur de signaux de trading

Commençons.

Tout d'abord, nous créons (par exemple, en utilisant le mêmeMQL5 Wizard) un fichier d'inclusion avec l'extension mqh.

Dans le menu Fichier sélectionnez "Créer" (ou appuyez sur la combinaison de touches Ctrl+N) et indiquez la création d'un fichier inclus :

Figure 2. Créez un fichier d'inclusion à l'aide de l'assistant MQL5. .

Figure 2. Créez un fichier d'inclusion à l'aide de l'assistant MQL5

Il est à noter que pour que le fichier soit ensuite "détecté" parMQL5 Wizard en tant que générateur de signaux, il doit être créé dans le dossier Include \Expert\Signal\.

Afin de ne pas jeter la corbeille dans laBibliothèque Standard , créez notre propre dossier Include\Expert\Signal\MySignals, dans lequel nous créons le fichier SampleSignal.mqh, en indiquant ces paramètres dans l'assistant MQL5 :

Figure 3. Définir l’emplacement du fichier  d’inclusion

Figure 3. Définition de l'emplacement du fichier d'inclusion

À la suite de l'opération de l'assistantMQL5, nous avons le modèle suivant :

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
// #define MacrosHello   "Hello, world!"
// #define MacrosYear    2010
//+------------------------------------------------------------------+
//| DLL imports                                                      |
//+------------------------------------------------------------------+
// #import "user32.dll"
//   int      SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #import "my_expert.dll"
//   int      ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| EX5 imports                                                      |
//+------------------------------------------------------------------+
// #import "stdlib.ex5"
//   string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+

Ce qui suit n'est qu'un travail "manuel". Supprimez les parties inutiles et ajoutez ce qui est requis (incluez le fichier ExpertSignal.mqh de la Bibliothèque Standardet une description de classe qui est maintenant vide).

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| The CSampleSignal class.                                         |
//| Purpose: Class of trading signal generator.                      |
//|          It is derived from the CExpertSignal class.             |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
  };
//+------------------------------------------------------------------+

Maintenant, il faut choisir les algorithmes.

Comme base pour notre générateur de signaux de trading, nous prenons le modèle répandu "le prix traverse la moyenne mobile". Mais nous établissons une autre hypothèse : "Après avoir franchi la moyenne mobile, le prix recule, et ensuite va seulement dans la bonne direction." Reflétez cela dans notre fichier.

Généralement, lorsque vous écrivez quelque chose, ne lésinez pas sur les commentaires. Après un certain temps, la lecture d'un code soigneusement commenté sera si confortable.

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| Class CSampleSignal.                                             |
//| Purpose: Class of trading signal generator when price            |
//|          crosses moving average,                                 |
//|          entering on the subsequent back movement.               |
//|          It is derived from the CExpertSignal class.             |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
  };
//+------------------------------------------------------------------+

Définissons maintenant quelles données sont nécessaires pour prendre des décisions concernant la génération de signaux de trading. Dans notre cas, il s'agit du prix d'ouverture et du prix de clôture de la barre précédente, et de la valeur de la moyenne mobile sur la même barre précédente.

Pour accéder à ces données, nous utilisons les classes de bibliothèque standard CiOpen, CiClose and CiMA. Nous discuterons des indicateurs et des séries chronologiques plus tard.

En attendant, définissons une liste de paramètres pour notre générateur. Tout d'abord, nous devons configurer la moyenne mobile. Ces paramètres incluent la période, le décalage le long de l'axe du temps, la méthode de moyennage et l'objet du moyennage. Deuxièmement, nous devons définir le niveau d'entrée et les niveaux d’émission d'ordonnances conservatoires, et la durée de vie d'une commande en cours, car nous allons travailler avec des commandes en cours.

Tous les paramètres du générateur seront stockés dans des données protégées membres de la classe L'accès aux paramètres sera implémenté par des méthodes publiques appropriées.

Insérons ces changements dans notre fichier :

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| The CSampleSignal class.                                         |
//| Purpose: Class of trading signal generator when price            |
//|             crosses moving average,                              |
//|             entering on the subsequent back movement.            |
//|             It is derived from the CExpertSignal class.          |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
protected:
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;           // level to place a pending order relative to the MA
   double             m_stop_loss;       // level to place a stop loss order relative to the open price
   double             m_take_profit;     // level to place a take profit order relative to the open price
   int                m_expiration;      // lifetime of a pending order in bars

public:
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;   }
   void               ShiftMA(int value)                  { m_shift_ma=value;    }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;   }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;  }
   void               Limit(double value)                 { m_limit=value;       }
   void               StopLoss(double value)              { m_stop_loss=value;   }
   void               TakeProfit(double value)            { m_take_profit=value; }
   void               Expiration(int value)               { m_expiration=value;  }
  };
//+------------------------------------------------------------------+

Puisque nous utilisons des membres de données protégés, nous devons ajouterun constructeur de classe , dans lequel nous initialiserons ces données par valeurs par défaut.

Pour vérifier les paramètres, remplaçons la méthode virtuelleValidationSettings en fonction de la description de la classe de base.

Descriptif de la classe :

class CSampleSignal : public CExpertSignal
  {
protected:
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;       // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;   }
   void               ShiftMA(int value)                  { m_shift_ma=value;    }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;   }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;  }
   void               Limit(double value)                 { m_limit=value;       }
   void               StopLoss(double value)              { m_stop_loss=value;   }
   void               TakeProfit(double value)            { m_take_profit=value; }
   void               Expiration(int value)               { m_expiration=value;  }
   //--- Methods to validate the parameters
   virtual bool       ValidationSettings();
  };

Implémentation de la méthode ValidationSettings() :


//+------------------------------------------------------------------+
//| Validation of the setup parameters.                              |
//| INPUT:  No.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::ValidationSettings()
  {
//--- Validation of parameters
   if(m_period_ma<=0)
     {
      printf(__FUNCTION__+": the MA period must be greater than zero");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+

Maintenant, lorsque nous aurons terminé le gros du travail préparatoire, nous parlerons davantage sur les indicateurs and séries chronologiques

Les indicateurs et les séries chronologiques sont la principale source d'information pour la prise de décision (on peut certes utiliser le tirage au sort, ou les phases de la lune, mais ils sont assez difficiles à formaliser).

Comme nous l'avons déjà défini ci-dessus, pour prendre des décisions, nous avons besoin des informations suivantes : le prix d'ouverture de la barre précédente, le prix de clôture de la barre précédente et la valeur de la moyenne mobile sur la même barre précédente.

Pour accéder à ces données, nous utiliserons les classes suivantes de laBibliothèque Standard  :

  • CiOpen- pour accéder au prix d'ouverture de la barre précédente,
  • CiClose- pour accéder au prix de clôture de la barre précédente,
  • CiMA- pour accéder à la valeur de la moyenne mobile sur la barre précédente.

Tu peux demander: « Pourquoi utiliser l'indicateur ou les séries chronologiques, « encapsulé » dans une classe, afin d'obtenir un seul nombre ? »

Il y a un sens caché, que nous allons révéler maintenant.

Comment utiliser les données d'un indicateur ou d'une série chronologique ?

Tout d'abord, nous devons créer un indicateur.

Deuxièmement, nous devons copier la quantité de données nécessaire dans un tampon intermédiaire.

Troisièmement, nous devons vérifier si la copie est terminée.

Ce n'est qu'après ces étapes que vous pouvez utiliser les données.

En utilisant les classes de laBibliothèque Standard , vous évitez la nécessité de créer un indicateur, de vous soucier de la disponibilité des tampons intermédiaires et du chargement des données ou de la libération d'un handle. L'objet d'une classe appropriée le fera pour vous. Tous les indicateurs requis seront générés par notre générateur de signaux pendant la phase d'initialisation, et tous les indicateurs seront fournis avec le tampon temporaire nécessaire. Et d'ailleurs, une fois qu'on a ajouté un indicateur ou un objet de série chronologique dans la collection (l'objet d'une classe spéciale), vous pouvez arrêter de vous soucier de la pertinence des données (les données seront automatiquement mises à jour par l'expert).

Nous placerons les objets de ces classes dans les données membres protégées. Pour chaque objet, nous créons une méthode d'initialisation et une méthode d'accès aux données.

Remplaçons la méthode virtuelleInitIndicators (en fonction de la description de la classe de base).

Descriptif de la classe :

class CSampleSignal : public CExpertSignal
  {
protected:
   CiMA               m_MA;              // object to access the values om the moving average
   CiOpen             m_open;            // object to access the bar open prices
   CiClose            m_close;           // object to access the bar close prices
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;      // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;              }
   void               ShiftMA(int value)                  { m_shift_ma=value;               }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;              }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;             }
   void               Limit(double value)                 { m_limit=value;                  }
   void               StopLoss(double value)              { m_stop_loss=value;              }
   void               TakeProfit(double value)            { m_take_profit=value;            }
   void               Expiration(int value)               { m_expiration=value;             }
   //--- Method to validate the parameters
   virtual bool       ValidationSettings();
   //--- Method to validate the parameters
   virtual bool       InitIndicators(CIndicators* indicators);

protected:
   //--- Object initialization method
   bool               InitMA(CIndicators* indicators);
   bool               InitOpen(CIndicators* indicators);
   bool               InitClose(CIndicators* indicators);
   //--- Methods to access object data
   double             MA(int index)                       { return(m_MA.Main(index));       }
   double             Open(int index)                     { return(m_open.GetData(index));  }
   double             Close(int index)                    { return(m_close.GetData(index)); }
  };

Implémentation des méthodes InitIndicators, InitMA, InitOpen, InitClose :

//+------------------------------------------------------------------+
//| Initialization of indicators and timeseries.                     |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitIndicators(CIndicators* indicators)
  {
//--- Validation of the pointer
   if(indicators==NULL)       return(false);
//--- Initialization of the moving average
   if(!InitMA(indicators))    return(false);
//--- Initialization of the timeseries of open prices
   if(!InitOpen(indicators))  return(false);
//--- Initialization of the timeseries of close prices
   if(!InitClose(indicators)) return(false);
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the moving average                             |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitMA(CIndicators* indicators)
  {
//--- Initialization of the MA object
   if(!m_MA.Create(m_symbol.Name(),m_period,m_period_ma,m_shift_ma,m_method_ma,m_applied_ma))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
   m_MA.BufferResize(3+m_shift_ma);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_MA)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of open prices.                 |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitOpen(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_open.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_open)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of close prices.                |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitClose(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_close.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_close)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+

Tous les travaux préparatoires sont terminés. Comme vous pouvez le constater, notre classe a considérablement augmenté.

Mais maintenant, nous sommes prêts à générer des signaux de trading.

Figure 4. Signaux de trading pour le prix traversant la moyenne mobile

Figure 4. Signaux de trading pour le prix franchissant la moyenne mobile

Examinons à nouveau nos algorithmes plus en détail.

1. Le signal d'achat apparaît lorsque les conditions suivantes ont été remplies sur la barre précédente :

  • le prix d'ouverture de la barre est inférieur à la valeur de la moyenne mobile,
  • le prix de clôture de la barre est supérieur à la valeur de la moyenne mobile,
  • la moyenne mobile est en hausse

Dans ce cas, nous vous proposons de passer une commande d'achat en cours avec les paramètres définis par les paramètres. Pour cela, nous surchargeons la méthode virtuelle CheckOpenLong et la remplissons avec la fonctionnalité correspondante.

2. Le signal de vente apparaît lorsque les conditions suivantes ont été remplies sur la barre précédente :

  • le prix d'ouverture de la barre est supérieur à la valeur de la moyenne mobile,
  • le prix de clôture de la barre est inférieur à la valeur de la moyenne mobile,
  • la moyenne mobile diminue.

Dans ce cas, nous vous proposons d’émettre une commande de vente en cours avec les paramètres définis par les paramètres. Pour cela, nous surchargeons la méthode virtuelleCheckOpenShort et la remplissons avec la fonctionnalité correspondante.

3. Nous ne générerons pas de signaux pour clôturer des positions. Que les positions soient clôturées par Stop Loss/Take Profit ордерам.

Par conséquent, nous ne remplacerons pas les méthodes virtuellesCheckCloseLong et CheckCloseShort.

4. Nous proposerons la modification d'une commande en cours le long de la moyenne mobile à la "distance" indiquée par les paramètres.

 À cette fin, nous remplaçons les méthodes virtuelles CheckTrailingOrderLong etCheckTrailingOrderShort,en les remplissant avec la fonctionnalité correspondante.

Descriptif de la classe :

class CSampleSignal : public CExpertSignal
  {
protected:
   CiMA               m_MA;              // object to access the values of the moving average
   CiOpen             m_open;            // object to access the bar open prices
   CiClose            m_close;           // object to access the bar close prices
   //--- Setup parameters
   int                m_period_ma;       // averaging period of the MA
   int                m_shift_ma;        // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;       // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;      // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;       // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters

   void               PeriodMA(int value)                 { m_period_ma=value;              }
   void               ShiftMA(int value)                  { m_shift_ma=value;               }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;              }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;             }
   void               Limit(double value)                 { m_limit=value;                  }
   void               StopLoss(double value)              { m_stop_loss=value;              }
   void               TakeProfit(double value)            { m_take_profit=value;            }
   void               Expiration(int value)               { m_expiration=value;             }
   //--- Method to validate the parameters
   virtual bool       ValidationSettings();
   //--- Method to validate the parameters
   virtual bool       InitIndicators(CIndicators* indicators);
   //--- Methods to generate signals to enter the market
   virtual bool      CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration);
   virtual bool      CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration);
   //--- Methods to generate signals of pending order modification
   virtual bool      CheckTrailingOrderLong(COrderInfo* order,double& price);
   virtual bool      CheckTrailingOrderShort(COrderInfo* order,double& price);

protected:
   //--- Object initialization method
   bool               InitMA(CIndicators* indicators);
   bool               InitOpen(CIndicators* indicators);
   bool               InitClose(CIndicators* indicators);
   //--- Methods to access object data
   double             MA(int index)                       { return(m_MA.Main(index));       }
   double             Open(int index)                     { return(m_open.GetData(index));  }
   double             Close(int index)                    { return(m_close.GetData(index)); }
  };

Implémentation des méthodes CheckOpenLong, CheckOpenShort, CheckTrailingOrderLong, CheckTrailingOrderShort :

//+------------------------------------------------------------------+
//| Check whether a Buy condition is fulfilled                       |
//| INPUT:  price      - variable for open price                     |
//|         sl         - variable for stop loss price,               |
//|         tp         - variable for take profit price              |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double spread=m_symbol.Ask()-m_symbol.Bid();
   double ma    =MA(1);
   double unit  =PriceLevelUnit();
//--- Checking the condition
   if(Open(1)<ma && Close(1)>ma && ma>MA(2))
     {
      price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
      sl   =m_symbol.NormalizePrice(price-m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price+m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether a Sell condition is fulfilled.                     |
//| INPUT:  price      - variable for open price,                    |
//|         sl         - variable for stop loss,                     |
//|         tp         - variable for take profit                    |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
//--- Checking the condition
   if(Open(1)>ma && Close(1)<ma && ma<MA(2))
     {
      price=m_symbol.NormalizePrice(ma+m_limit*unit);
      sl   =m_symbol.NormalizePrice(price+m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price-m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//|  of a Buy order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderLong(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double spread   =m_symbol.Ask()-m_symbol.Bid();
   double ma       =MA(1);
   double unit     =PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//| of a Sell order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderShort(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma+m_limit*unit);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+

Nous avons donc résolu le premier problème. Le code ci-dessus est un code source de la classe des générateurs de signaux de trading qui répond à notre tâche principale.


2.2. Préparation d'une description de la classe créée des signaux de trading pour l'assistant MQL5

Passons maintenant à la résolution du deuxième problème. Notre signal doit être « reconnu » par le générateur de stratégies de trading MQL5 Wizard.

Nous avons accompli la première condition nécessaire : nous avons placé le fichier là où il sera « trouvé » par l'assistant MQL5. Mais ce n'est pas assez. L'assistant MQL5 doit non seulement "trouver" le fichier, mais aussi le "reconnaître". Pour ce faire, nous devons ajouter au texte original le descripteur de classe for the Assistant MQL5.

Un descripteur de classe est un bloc de commentaires composé conformément à certaines règles.

Examinons ces règles.

1. Le bloc de commentaires doit commencer par les lignes suivantes :

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |

2. La ligne suivante est un descripteur de texte (ce que nous constaterons dans l'assistant MQL5 lors du choix du signal) au format "//| Title=<Text> |". Si le texte est trop gros pour une ligne, vous pouvez ajouter une ligne supplémentaire (mais pas plus) après. 

Dans notre cas, nous avons les éléments suivants :

//| Title=Signal on the crossing of a price and the MA               |
//| entering on its back movement                                    |

3. Vient ensuite une ligne avec le type de classe indiqué au format "//| Type=<Type> |". Le champ <Type> doit avoir la valeur Signal (en plus des signaux, l'assistant MQL5 connaît d'autres types de classes).

Écrivez:

//| Type=Signal                                                      |

4. La ligne suivante au format "//| Name=<Name> |" est le nom court du signal (il est utilisé par l'assistant MQL5 pour générer les noms des variables globales de l'expert).

Nous obtenons ce qui suit :

//| Name=Sample                                                      |

5. Le nom d'une classe est un élément important de la description. Dans la ligne au format "//| Class=<ClassNameа> |", le paramètre <ClassName> doit correspondre au nom de notre classe :

//| Class=CSampleSignal                                              |

6. Nous ne remplissons pas cette ligne, mais elle doit être présente (il s'agit d'un lien vers la section de référence de langue):

//| Page=                                                            |

7. De plus, il y a des descriptions des paramètres de configuration du signal.

Il s'agit d'un ensemble de lignes (le nombre de lignes est égal au nombre de paramètres).

Le format de chaque ligne est "//| Parameter=<NameOfMethod>,<TypeOfParameter>,<DefaultValue> |".

Voici notre ensemble de paramètres :

//| Parameter=PeriodMA,int,12                                        |
//| Parameter=ShiftMA,int,0                                          |
//| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA                       |
//| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE               |
//| Parameter=Limit,double,0.0                                       |
//| Parameter=StopLoss,double,50.0                                   |
//| Parameter=TakeProfit,double,50.0                                 |
//| Parameter=Expiration,int,10                                      |

8. Le bloc de commentaire doit se terminer par les lignes suivantes :

//+------------------------------------------------------------------+
// wizard description end

Ajoutons le descripteur au code source.

//+------------------------------------------------------------------+
//|                                                 SampleSignal.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signal on crossing of the price and the MA                 |
//| entering on the back movement                                    |
//| Type=Signal                                                      |
//| Name=Sample                                                      |
//| Class=CSampleSignal                                              |
//| Page=                                                            |
//| Parameter=PeriodMA,int,12                                        |
//| Parameter=ShiftMA,int,0                                          |
//| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA                       |
//| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE               |
//| Parameter=Limit,double,0.0                                       |
//| Parameter=StopLoss,double,50.0                                   |
//| Parameter=TakeProfit,double,50.0                                 |
//| Parameter=Expiration,int,10                                      |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| CSampleSignal class.                                             |
//| Purpose: Class of trading signal generator when price            |
//|             crosses moving average,                              |
//|             entering on the subsequent back movement.            |
//|             It is derived from the CExpertSignal class.          |
//+------------------------------------------------------------------+
class CSampleSignal : public CExpertSignal
  {
protected:
   CiMA               m_MA;               // object to access the values of the moving average
   CiOpen             m_open;             // object to access the bar open prices
   CiClose            m_close;            // object to access the bar close prices
   //--- Setup parameters
   int                m_period_ma;        // averaging period of the MA
   int                m_shift_ma;         // shift of the MA along the time axis
   ENUM_MA_METHOD     m_method_ma;        // averaging method of the MA
   ENUM_APPLIED_PRICE m_applied_ma;       // averaging object of the MA
   double             m_limit;            // level to place a pending order relative to the MA
   double             m_stop_loss;        // level to place a stop loss order relative to the open price
   double             m_take_profit;      // level to place a take profit order relative to the open price
   int                m_expiration;       // lifetime of a pending order in bars

public:
                      CSampleSignal();
   //--- Methods to set the parameters
   void               PeriodMA(int value)                 { m_period_ma=value;              }
   void               ShiftMA(int value)                  { m_shift_ma=value;               }
   void               MethodMA(ENUM_MA_METHOD value)      { m_method_ma=value;              }
   void               AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value;             }
   void               Limit(double value)                 { m_limit=value;                  }
   void               StopLoss(double value)              { m_stop_loss=value;              }
   void               TakeProfit(double value)            { m_take_profit=value;            }
   void               Expiration(int value)               { m_expiration=value;             }
   //---Method to validate the parameters
   virtual bool       ValidationSettings();
   //--- Method to validate the parameters
   virtual bool       InitIndicators(CIndicators* indicators);
   //--- Methods to generate signals to enter the market
   virtual bool      CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration);
   virtual bool      CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration);
   //--- Methods to generate signals of pending order modification
   virtual bool      CheckTrailingOrderLong(COrderInfo* order,double& price);
   virtual bool      CheckTrailingOrderShort(COrderInfo* order,double& price);

protected:
   //--- Object initialization method
   bool               InitMA(CIndicators* indicators);
   bool               InitOpen(CIndicators* indicators);
   bool               InitClose(CIndicators* indicators);
   //--- Methods to access object data
   double             MA(int index)                       { return(m_MA.Main(index));       }
   double             Open(int index)                     { return(m_open.GetData(index));  }
   double             Close(int index)                    { return(m_close.GetData(index)); }
  };
//+------------------------------------------------------------------+
//| CSampleSignal Constructor.                                       |
//| INPUT:  No.                                                      |
//| OUTPUT: No.                                                      |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
void CSampleSignal::CSampleSignal()
  {
//--- Setting the default values
   m_period_ma  =12;
   m_shift_ma   =0;
   m_method_ma  =MODE_EMA;
   m_applied_ma =PRICE_CLOSE;
   m_limit      =0.0;
   m_stop_loss  =50.0;
   m_take_profit=50.0;
   m_expiration =10;
  }
//+------------------------------------------------------------------+
//| Validation of parameters.                                        |
//| INPUT:  No.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::ValidationSettings()
  {
//--- Validation of parameters
   if(m_period_ma<=0)
     {
      printf(__FUNCTION__+": the MA period must be greater than zero");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of indicators and timeseries.                     |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitIndicators(CIndicators* indicators)
  {
//--- Validation of the pointer
   if(indicators==NULL)       return(false);
//--- Initialization of the moving average
   if(!InitMA(indicators))    return(false);
//--- Initialization of the timeseries of open prices
   if(!InitOpen(indicators))  return(false);
//--- Initialization of the timeseries of close prices
   if(!InitClose(indicators)) return(false);
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the moving average                             |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitMA(CIndicators* indicators)
  {
//--- Initialization of the MA object
   if(!m_MA.Create(m_symbol.Name(),m_period,m_period_ma,m_shift_ma,m_method_ma,m_applied_ma))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
   m_MA.BufferResize(3+m_shift_ma);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_MA)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of open prices.                 |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitOpen(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_open.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_open)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialization of the timeseries of close prices.                |
//| INPUT:  indicators - pointer to the object - collection of       |
//|                      indicators and timeseries.                  |
//| OUTPUT: true in case of success, otherwise false.                |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::InitClose(CIndicators* indicators)
  {
//--- Initialization of the timeseries object
   if(!m_close.Create(m_symbol.Name(),m_period))
     {
      printf(__FUNCTION__+": object initialization error");
      return(false);
     }
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_close)))
     {
      printf(__FUNCTION__+": object adding error");
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Check whether a Buy condition is fulfilled                       |
//| INPUT:  price      - variable for open price                     |
//|         sl         - variable for stop loss price,               |
//|         tp         - variable for take profit price              |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double spread=m_symbol.Ask()-m_symbol.Bid();
   double ma    =MA(1);
   double unit  =PriceLevelUnit();
//--- Checking the condition
   if(Open(1)<ma && Close(1)>ma && ma>MA(2))
     {
      price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
      sl   =m_symbol.NormalizePrice(price-m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price+m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether a Sell condition is fulfilled.                     |
//| INPUT:  price      - variable for open price,                    |
//|         sl         - variable for stop loss,                     |
//|         tp         - variable for take profit                    |
//|         expiration - variable for expiration time.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration)
  {
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
//--- Checking the condition
   if(Open(1)>ma && Close(1)<ma && ma<MA(2))
     {
      price=m_symbol.NormalizePrice(ma+m_limit*unit);
      sl   =m_symbol.NormalizePrice(price+m_stop_loss*unit);
      tp   =m_symbol.NormalizePrice(price-m_take_profit*unit);
      expiration+=m_expiration*PeriodSeconds(m_period);
      //--- Condition is fulfilled
      return(true);
     }
//--- Condition is not fulfilled
   return(false);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//|  of a Buy order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderLong(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double spread   =m_symbol.Ask()-m_symbol.Bid();
   double ma       =MA(1);
   double unit     =PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma-m_limit*unit+spread);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+
//| Check whether the condition of modification                      |
//| of a Sell order is fulfilled.                                    |
//| INPUT:  order - pointer at the object-order,                     |
//|         price - a variable for the new open price.               |
//| OUTPUT: true if the condition is fulfilled, otherwise false.     |
//| REMARK: No.                                                      |
//+------------------------------------------------------------------+
bool CSampleSignal::CheckTrailingOrderShort(COrderInfo* order,double& price)
  {
//--- Checking the pointer
   if(order==NULL) return(false);
//--- Preparing the data
   double ma  =MA(1);
   double unit=PriceLevelUnit();
   double new_price=m_symbol.NormalizePrice(ma+m_limit*unit);
//--- Checking the condition
   if(order.PriceOpen()==new_price) return(false);
   price=new_price;
//--- Condition is fulfilled
   return(true);
  }
//+------------------------------------------------------------------+

Eh bien c’est tout. Le signal est prêt à être utilisé.

Pour que le générateur des stratégies de trading MQL5 Wizardpuisse utiliser notre signal ,nous devons redémarrer MetaEditor (MQL5 Wizard scanne le fichier Include\Expert seulement au démarrage).

Après avoir redémarréMetaEditor, le module créé de signaux de trading peut être utilisé dans l'assistant MQL5 :

Figure 5. Le générateur créé des signaux de trading  dans l’assistant MQL5

Figure 5. Le générateur de signaux de trading créé dans l'assistant MQL5

Les paramètres d'entrée indiqués dans la section de description des paramètres du générateur de signaux de trading sont désormais disponibles :

Figure 6. Paramètres d’entrée du générateur crée dans l’Assistant MQL5

Figure 6. Paramètres d'entrée du générateur de signaux de trading créé dans l'assistant MQL5

Les meilleures valeurs des paramètres d'entrée de la stratégie de trading implémentée peuvent être trouvées à l'aide duStrategy Tester duMetaTrader 5 terminal.


Conclusion

Le générateur des stratégies de trading de l’Assistant MQL5 simplifie considérablement le test des idées de trading. Le code de l'expert généré est basé sur les classes des stratégies de tradingde la bibliothèque standard, qui sont utilisées pour créer certaines implémentations de classes de signaux de trading, de classes de gestion de l'argent et des risques et de classes de support de position. 

L'article explique comment écrire votre propre classe de signaux de trading avec la mise en œuvre de signaux sur le croisement du prix et de la moyenne mobile, et comment l'inclure dans le générateur de stratégies de trading duMQL5 Wizard, et décrit également la structure et le format de la description de la classe générée pour l'assistant MQL5.

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

Fichiers joints |
samplesignal.mqh (15.49 KB)
Tableaux Électroniques en MQL5 Tableaux Électroniques en MQL5
L'article décrit une classe de tableau dynamique à deux dimensions qui comporte des données de différents types dans sa première dimension. Le stockage des données sous la forme d'un tableau est pratique pour résoudre un large éventail de problèmes d'agencement, de stockage et d'exploitation avec des informations liées de différents types. Le code source de la classe qui implémente la fonctionnalité de travail avec des tableaux est joint à l'article.
Approche Économétrique de l'Analyse des Graphiques Approche Économétrique de l'Analyse des Graphiques
Cet article décrit les méthodes d'analyse économétriques, l'analyse d'auto-corrélation et l'analyse de variance conditionnelle en particulier. Quel est l'avantage de l'approche décrite ici? L'utilisation des modèles GARCH non linéaires permet de représenter formellement la série analysée du point de vue mathématique et de créer une prévision pour un nombre spécifié d'étapes.
Assistant MQL5 : Comment Créer un Module de Gestion des Risques et de fonds Assistant MQL5 : Comment Créer un Module de Gestion des Risques et de fonds
Le générateur de stratégies de trading de l'assistant MQL5 simplifie considérablement le test des idées de trading. L'article décrit comment élaborer un module de gestion des risques et de fonds personnalisé et l'activer dans l'assistant MQL5. À titre d'exemple, nous avons examiné un algorithme de gestion de l'argent, dans lequel la taille du volume de trade est déterminée par les résultats du deal précédent. La structure et le format de description de la classe créée pour l'Assistant MQL5 sont également abordés dans l'article.
Les indicateurs des tendances micro, moyenne et principale Les indicateurs des tendances micro, moyenne et principale
Le but de cet article est d'étudier les possibilités de l'automatisation du trade et de l'analyse, sur la base de quelques idées d'un livre de James Hyerczyk "Pattern, Price & Time: Utilisation de la théorie de Gann dans les systèmes de trading" sous forme d'indicateurs et d'Expert Advisor. Sans prétendre à l'exhaustivité, nous n'étudions ici que le Modèle - la première partie de la théorie de Gann.