English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Créez votre propre robot de trading en 6 étapes !

Créez votre propre robot de trading en 6 étapes !

MetaTrader 5Exemples | 22 décembre 2021, 17:02
3 428 0
MetaQuotes
MetaQuotes

Parlons une fois de plus de l'assistant MQL5

Le monde qui nous entoure évolue rapidement et nous essayons de nous rattraper. Nous n'avons pas le temps d'apprendre quelque chose de nouveau, et c'est une attitude normale d'un être humain normal. Les traders sont des gens comme tout le monde, ils veulent obtenir un maximum de résultats pour un minimum d'effort. Spécialement pour les traders, MetaEditor 5 propose un merveilleux assistant MQL5. Il existe plusieurs articles décrivant comment créer un système de trading automatisé à l'aide de l'assistant, notamment un assistant MQL5 « version light » pour les incultes et un assistant MQL5 « version de développeurs » - Nouvelle version.

Tout semble bon - un robot de trading est créé en 5 clics de souris, vous pouvez le tester dans le Testeur de stratégie et optimiser les paramètres d'un système de trading, vous pouvez laisser le robot ainsi créé trader sur votre compte sans avoir à faire quoi que ce soit d'autre manuellement. Mais le problème se pose lorsqu'un trader/développeur MQL5 veut créer quelque chose qui lui est propre, quelque chose d'unique qui n'a jamais été décrit nulle part, et va écrire son propre module de signaux de trading. Le trader ouvre la documentation MQL5, accède à la bibliothèque standard et est horrifié de voir...


Cinq classes terribles

Certes, l'assistant MQL5 simplifie grandement la création d'Expert Advisors, mais vous devez d'abord savoir ce qui sera utilisé comme entrée pour cela. Pour créer automatiquement un Expert Advisor à l'aide de l'Assistant MQL5, assurez-vous que ses composants adhèrent aux cinq classes de base de la section Classes de base des Expert Advisors :

  • CExpertBase est une classe de base pour quatre autres classes.
  • CExpert est la classe pour créer un robot de trading ; c'est la classe qui trade.
  • CExpertSignal est une classe pour créer un module de signaux de trading ; l'article concerne cette classe.
  • CExpertTrailing est une classe de suivi d’un Stop Loss de protection.
  • CExpertMoney est la classe de gestion monétaire.

Voici toute la force de la « grande et terrible » approche qu'on appelle la programmation orientée objet (POO). Mais n'ayez pas peur, maintenant presque tout le monde a un téléphone portable avec beaucoup de fonctions, et presque personne ne sait comment il fonctionne. Nous n'avons pas besoin d'étudier tout cela, nous n'aborderons que quelques fonctions de la classe CExpertSignal.


Dans cet article, nous allons passer en revue les étapes de création d'un module de signaux de trading, et vous verrez comment faire cela sans avoir à apprendre la POO ou les cours. Mais si cela vous dit, vous pouvez donc explorer davantage.


1. Créer une classe à partir de zéro

Nous ne modifierons aucun module existant de signaux de trading en fonction de nos besoins, car vous vous créerez de la confusion. Par conséquent, nous allons simplement écrire notre propre classe, mais nous allons d'abord utiliser le Navigateur pour créer a nouveau dossier afin de stocker nos signaux dans MQL5/Include/Expert/.



Effectuez un clic droit sur le dossier que nous avons créé, sélectionnez « Nouveau fichier » et créez une nouvelle classe pour notre module de signaux de trading.


Remplissez les champs :

  • Nom de classe - le nom de la classe. Ce sera un module pour générer des signaux à l'intersection de deux moyennes mobiles, appelons-le donc MA_Cross.
  • Nom de base est la classe à partir de laquelle notre classe est dérivée. Et nous devrions la dériver de la classe de base CExpertSignal.

Cliquez sur « Terminer » et une ébauche de notre module sera prête. Tout va dans la bonne direction jusqu'ici. Il suffit d'ajouter la déclaration #include au fichier qui en résulte pour que le compilateur sache où trouver la classe de base CExpertSignal

#include "..\ExpertSignal.mqh"   // CExpertSignal is in the file ExpertSignal

Le résultat :

//+------------------------------------------------------------------+
//|                                                     MA_Cross.mqh |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include "..\ExpertSignal.mqh"   // CExpertSignal is in the file ExpertSignal
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class MA_Cross : public CExpertSignal
  {
private:

public:
                     MA_Cross();
                    ~MA_Cross();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
MA_Cross::MA_Cross()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
MA_Cross::~MA_Cross()
  {
  }
//+------------------------------------------------------------------+

Vérifiez la classe qui en résulte (elle doit être exempte d'erreurs de compilation) et cliquez sur F7. Il n'y a pas d'erreurs et nous pouvons progresser.


2. Un descripteur au module

Notre classe est complètement vide, elle n'a pas d'erreurs et nous pouvons la tester - essayons de créer un nouvel Expert Advisor dans l'assistant MQL5 en nous basant sur ce dernier. Nous arrivons à l'étape de la sélection d'un module de signaux de trading et remarquons... que notre module n'est pas là.


Et comment cela peut-il être là ? Nous n'ajoutons aucune indication pour que l'assistant MQL5 comprenne que notre classe pourrait être quelque chose d'utile. Corrigeons cela. Si vous regardez les modules du paquet standard, vous verrez que chacun d'eux contient un en-tête au début du fichier. C'est le descripteur du module compilé selon certaines règles. Et les règles sont très simples.

Ouvrez, par exemple, le code source du module de signaux de trading basés sur l'AMA (voir la description logique dans Signaux de la moyenne mobile adaptative.) Et lancez l'assistant MQL5 en choisissant ce module. Comparez :

Le dernier bloc du descripteur fait référence aux paramètres du module, la première ligne contient le nom du module à afficher dans l'assistant MQL5. Comme vous pouvez le voir, il n'y a rien de compliqué. Ainsi, le descripteur de chaque module contient les entrées suivantes :

  • Titre  - le nom du module à afficher dans l'assistant MQL5.
  • Type - la version du module de signaux. Il doit toujours être SignalAdvanced.
  • Nom - le nom du module après sa sélection dans l'assistant MQL5 et est utilisé dans les commentaires pour décrire les paramètres internes de l'Expert Advisor généré (de préférence spécifié).
  • ShortName - un préfixe pour la désignation automatique des paramètres externes dans l'Expert Advisor généré (sous la forme de Signal_<ShortName>_<ParameterName>).
  • Classe - le nom qui est contenu dans le module.
  • Page - un paramètre pour obtenir de l'aide pour ce module (uniquement pour les modules de la livraison standard).

Vient ensuite la description des paramètres sous la forme de Parameter=list_of_values, dans laquelle les éléments suivants sont spécifiés (séparés par des virgules) :

  1. Le nom de la fonction pour définir la valeur du paramètre lors du démarrage de l'Expert Advisor.
  2. Le type de paramètre peut être une énumération.
  3. La valeur par défaut du paramètre, c'est-à-dire la valeur qui sera définie sur le paramètre, si vous ne la modifiez pas dans l'assistant MQL5.
  4. Description du paramètre, que vous voyez lorsque vous démarrez l'Expert Advisor généré dans l'assistant MQL5.

Maintenant, sachant tout cela, créons le descripteur de notre module de signaux de trading. Nous écrivons donc un module pour obtenir des signaux de trading à l'intersection de deux moyennes mobiles. Nous devons définir au moins quatre paramètres externes :

  • FastPeriod - la période de la moyenne mobile rapide
  • FastMethod - le type de lissage de la moyenne mobile rapide
  • SlowPeriod - la période de la moyenne mobile lente
  • SlowMethod - le type de lissage de la moyenne mobile lente

Vous pouvez également ajouter un décalage et le type de prix pour calculer chacune des moyennes mobiles, mais cela ne change rien fondamentalement. La version actuelle est donc la suivante :

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals at the intersection of two MAs                     |
//| Type=SignalAdvanced                                              |
//| Name=My_MA_Cross                                                 |
//| ShortName=MaCross                                                |
//| Class=MA_Cross                                                   |
//| Page=Not needed                                                  |
//| Parameter=FastPeriod,int,13,Period of fast MA                    |
//| Parameter=FastMethod,ENUM_MA_METHOD,MODE_SMA,Method of fast MA   |
//| Parameter=SlowPeriod,int,21,Period of slow MA                    |
//| Parameter=SlowMethod,ENUM_MA_METHOD,MODE_SMA,Method of slow MA   |
//+------------------------------------------------------------------+
// wizard description end

Le descripteur du module est prêt et nous y avons décrit ce qui suit :

  1. Le nom affiché dans l'assistant MQL5 - « Signaux à l'intersection de deux moyennes mobiles ».
  2. Quatre paramètres externes pour configurer les signaux de trading.
    • FastPeriod - la période de la moyenne mobile rapide avec la valeur par défaut de 13.
    • FastMethod - le type de lissage de la moyenne mobile rapide, lissage simple par défaut.
    • SlowPeriod - la période de la moyenne mobile lente avec la valeur par défaut de 21.
    • SlowMethod - le type de lissage de la moyenne mobile lente, lissage simple par défaut.

Enregistrez les modifications et compilez. Il ne devrait pas y avoir d'erreurs. Exécutez l'assistant MQL5 pour vérifier. Vous voyez, notre module est maintenant disponible pour la sélection, et il montre tous nos paramètres !


Félicitations, notre module de signal de trading est parfait maintenant !


3. Méthodes de définition des paramètres

Il est maintenant temps de travailler avec les paramètres externes. Puisque notre module de trading est représenté par la classe MA_Cross, alors ses paramètres doivent être stockés dans la même classe que les membres privés. Ajoutons quatre lignes (égales au nombre de paramètres) à la déclaration de classe. Nous avons déjà décrit le paramètre dans le descripteur et savons ce qui suit :

class MA_Cross : public CExpertSignal
  {
private:
   //--- Configurable module parameters
   int               m_period_fast;    // Period of the fast MA
   int               m_period_slow;    // Period of the slow MA
   ENUM_MA_METHOD    m_method_fast;    // Type of smoothing of the fast MA
   ENUM_MA_METHOD    m_method_slow;    // Type of smoothing of the slow MA

Mais comment les valeurs ​​des paramètres externes du module apparaissent-ils dans les membres appropriés de notre classe MA_Cross ? Tout est très simple, il suffit de déclarer les méthodes publiques du même nom dans la classe, à savoir d'ajouter quatre lignes à la section publique :

class MA_Cross : public CExpertSignal
  {
private:
   //--- Configurable module parameters
   int               m_period_fast;    // Period of the fast MA
   int               m_period_slow;    // Period of the slow MA
   ENUM_MA_METHOD    m_method_fast;    // Type of smoothing of the fast MA
   ENUM_MA_METHOD    m_method_slow;    // Type of smoothing of the slow MA

public:
   //--- Constructor of class
                     MA_Cross();
   //--- Destructor of class
                    ~MA_Cross();
   //--- Methods for setting
   void              FastPeriod(int value)               { m_period_fast=value;        }
   void              FastMethod(ENUM_MA_METHOD value)    { m_method_fast=value;        }
   void              SlowPeriod(int value)               { m_period_slow=value;        }
   void              SlowMethod(ENUM_MA_METHOD value)    { m_method_slow=value;        }
   };

Lorsque vous générez un Expert Advisor à partir de ce module à l'aide de l'Assistant MQL5 et que vous l'exécutez sur le graphique, ces quatre méthodes sont automatiquement appelées lors de l'initialisation de l'Expert Advisor. Voici donc une règle simple :

La règle de création de paramètres dans le module - pour chaque paramètre que nous avons déclaré dans le descripteur, nous devons créer un membre privé dans la classe pour stocker sa valeur et un membre public pour lui attribuer une valeur. Le nom de la méthode doit correspondre au nom du paramètre.

Et le dernier moment est de définir des valeurs par défaut ​​pour nos paramètres qui seront utilisés au cas où les méthodes de mise en valeur ne seraient pas appelées. Chaque variable ou membre de classe déclaré doit être initialisé. Cette technique permet d'éviter de nombreuses erreurs difficiles à trouver.

Pour l'initialisation automatique, ce qui convient le mieux est le constructeur de classe ; il est toujours le premier à être appelé lors de la création d'un objet. Pour les valeurs par défaut, nous utiliserons celles écrites dans le descripteur du module.

class MA_Cross : public CExpertSignal
  {
private:
   //--- Configurable module parameters
   int               m_period_fast;    // Period of the fast MA
   ENUM_MA_METHOD    m_method_fast;     // Type of smoothing of the fast MA
   int               m_period_slow;    // Period of the slow MA
   ENUM_MA_METHOD    m_method_slow;     // Type of smoothing of the slow MA

public:
   //--- Constructor of class
                     MA_Cross(void);
   //--- Destructor of class
                    ~MA_Cross(void);
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
MA_Cross::MA_Cross(void) : m_period_fast(13),          // Default period of the fast MA is 3
                           m_method_fast(MODE_SMA),    // Default smoothing method of the fast MA
                           m_period_slow(21),          // Default period of the slow MA is 21
                           m_method_slow(MODE_SMA)     // Default smoothing method of the slow MA
  {
  }

Ici, les membres de la classe sont initialisés à l'aide de la liste d’initialisation.

Comme vous pouvez le voir, nous n'avons pas encore utilisé d'indicateurs de moyenne mobile. Nous avons trouvé une règle simple : comme de nombreux paramètres sont indiqués dans le descripteur du module, de nombreuses méthodes et membres doivent être dans la classe qui implémente le module. Il n'y a rien de compliqué ! Cependant, n'oubliez pas de définir les valeurs par défaut des paramètres sur le constructeur.


4. Vérification de l'exactitude des paramètres d'entrée

Nous avons créé des paramètres pour notre module de trading et des méthodes écrites pour en définir les ​valeurs, et maintenant vient la prochaine phase importante - l'exactitude des paramètres doit être vérifiée. Dans notre cas, il faut vérifier les périodes des moyennes mobiles et le type de lissage pour leur calcul. À cette fin, vous devez écrire votre propre méthode ValidationSettings() dans la classe. Cette méthode est définie dans la classe parent CExpertBase, et dans tous ses enfants elle est obligatoirement redéfinie.

Mais si vous ne connaissez rien à la programmation orientée objet, souvenez-vous simplement - dans notre classe, nous devrions écrire la fonction ValidationSettings(), qui ne nécessite aucun paramètre et renvoie true ou false.

class MA_Cross : public CExpertSignal
  {
...
   //--- Constructor of class
                     MA_Cross(void);
   //--- Destructor of class
                    ~MA_Cross(void);
   //--- Checking correctness of input data
   bool              ValidationSettings();
...
   };
//+------------------------------------------------------------------+
//| Checks input parameters and returns true if everything is OK     |
//+------------------------------------------------------------------+
bool MA_Cross:: ValidationSettings()
  {
   //--- Call the base class method
   if(!CExpertSignal::ValidationSettings())  return(false);
   //--- Check periods, number of bars for the calculation of the MA >=1
   if(m_period_fast<1 || m_period_slow<1)
     {
      PrintFormat("Incorrect value set for one of the periods! FastPeriod=%d, SlowPeriod=%d",
                  m_period_fast,m_period_slow);
      return false;
     }
//--- Slow MA period must be greater that the fast MA period
   if(m_period_fast>m_period_slow)
     {
      PrintFormat("SlowPeriod=%d must be greater than FastPeriod=%d!",
                  m_period_slow,m_period_fast);
      return false;
     }
//--- Fast MA smoothing type must be one of the four values of the enumeration
   if(m_method_fast!=MODE_SMA && m_method_fast!=MODE_EMA && m_method_fast!=MODE_SMMA && m_method_fast!=MODE_LWMA)
     {
      PrintFormat("Invalid type of smoothing of the fast MA!");
      return false;
     }
//--- Show MA smoothing type must be one of the four values of the enumeration
   if(m_method_slow!=MODE_SMA && m_method_slow!=MODE_EMA && m_method_slow!=MODE_SMMA && m_method_slow!=MODE_LWMA) 
     {
      PrintFormat("Invalid type of smoothing of the slow MA!");
      return false;
     }
//--- All checks are completed, everything is ok
   return true;
  }
Comme vous pouvez le voir, dans la partie publique de la classe MA_Cross, nous avons ajouté la déclaration de la méthode ValidationSettings(), puis ajouté le corps de la méthode sous la forme suivante :
bool MA_Cross:: ValidationSettings()

Vient d'abord le type de retour, puis le nom de la classe, ensuite l'opérateur de résolution de portée ::, et tout cela est suivi du nom de la méthode précédemment déclarée. N'oubliez pas que le nom et le type des paramètres doivent correspondre dans la déclaration et la description de la méthode de classe. Cependant, le compilateur vous avertira d'une telle erreur.

Notez que la méthode de la classe de base est d'abord appelée, puis les paramètres d'entrée sont vérifiés.

//--- Call the base class method
   if(!CExpertSignal::ValidationSettings())  return(false);
//--- Our code to check the values of parameters

Si vous n'ajoutez pas cette ligne, l'Expert Advisor généré ne pourra pas initialiser notre module de signaux de trading.


5. Où sont nos indicateurs ?

Il est temps de travailler avec les indicateurs, car tous les travaux préparatoires avec les paramètres pour eux sont terminés. Chaque module de signaux de trading contient la méthode InitIndicators(), qui est automatiquement appelée lorsque vous exécutez l'Expert Advisor généré. Dans cette méthode, nous devons fournir des indicateurs de moyennes mobiles pour notre module.

Tout d'abord, déclarez la méthode InitIndicators() dans la classe et collez son ébauche :

public:
   //--- Constructor of class
                     MA_Cross(void);
   //--- Destructor of class
                    ~MA_Cross(void);
   //--- Methods for setting
   void              FastPeriod(int value)               { m_period_fast=value;        }
   void              FastMethod(ENUM_MA_METHOD value)    { m_method_fast=value;        }
   void              SlowPeriod(int value)               { m_period_slow=value;        }
   void              SlowMethod(ENUM_MA_METHOD value)    { m_method_slow=value;        }
   //--- Checking correctness of input data
   bool              ValidationSettings();
   //--- Creating indicators and timeseries for the module of signals
   bool              InitIndicators(CIndicators *indicators);
  };
...
//+------------------------------------------------------------------+
//| Creates indicators                                               |
//| Input:  a pointer to a collection of indicators                  |
//| Output: true if successful, otherwise false                      |
//+------------------------------------------------------------------+
bool MA_Сross::InitIndicators(CIndicators* indicators)
  {
//--- Standard check of the collection of indicators for NULL
   if(indicators==NULL)                           return(false);
//--- Initializing indicators and timeseries in additional filters
   if(!CExpertSignal::InitIndicators(indicators)) return(false);
//--- Creating our MA indicators
   ... Some code here
//--- Reached this part, so the function was successful, return true
   return(true);
  }

Il n'y a donc rien de compliqué, on déclare la méthode puis on crée simplement le corps de la méthode, comme nous l'avons fait pour la méthode ValidationSettings(). Surtout, n'oubliez pas d'insérer le nom de la classe et l'opérateur :: dans la définition de la fonction. Nous avons une ébauche, que nous pouvons insérer dans un code pour créer des moyennes mobiles. Faisons-le correctement - pour chaque indicateur, nous créons une fonction distincte dans la classe, qui renvoie true en cas de succès. La fonction peut avoir n'importe quel nom, mais que celui-ci reflète son objectif, appelons donc les fonctions CreateFastMA() et CreateSlowMA().

protected:
   //--- Creating MA indicators
   bool              CreateFastMA(CIndicators *indicators);
   bool              CreateSlowMA(CIndicators *indicators);
  };
//+------------------------------------------------------------------+
//| Creates indicators                                               |
//| Input:  a pointer to a collection of indicators                  |
//| Output: true if successful, otherwise false                      |
//+------------------------------------------------------------------+
bool MA_Cross::InitIndicators(CIndicators *indicators)
  {
//--- Standard check of the collection of indicators for NULL
   if(indicators==NULL) return(false);
//--- Initializing indicators and timeseries in additional filters
   if(!CExpertSignal::InitIndicators(indicators)) return(false);
//--- Creating our MA indicators
   if(!CreateFastMA(indicators))                  return(false);
   if(!CreateSlowMA(indicators))                  return(false);
//--- Reached this part, so the function was successful, return true
   return(true);
  }
//+------------------------------------------------------------------+
//| Creates the "Fast MA" indicator                                  |
//+------------------------------------------------------------------+
bool MA_Cross::CreateFastMA(CIndicators *indicators)
  {
... Some code
//--- Reached this part, so the function was successful, return true
   return(true);
  }
//+------------------------------------------------------------------+
//| Creates the "Slow MA" indicator                                  |
//+------------------------------------------------------------------+
bool MA_Cross::CreateSlowMA(CIndicators *indicators)
  {
... Some code
//--- Reached this part, so the function was successful, return true
   return(true);
  }

C'est tout, nous avons seulement besoin d'écrire du code qui génère les indicateurs MA et intègre en quelque sorte les descripteurs de ces indicateurs dans le module de trading, afin que le module puisse utiliser les valeurs ​de ces indicateurs. C'est pourquoi un pointeur vers une variable de type CIndicators est passé en paramètre. Ce qui suit est écrit dans la documentation à ce sujet :

CIndicators est une classe de collecte d'instances de séries temporelles et de classes d'indicateurs techniques. La classe CIndicators permet la création d'instances de classes d'indicateurs techniques, leur stockage et leur gestion (synchronisation des données, gestion des descripteurs et de la mémoire).

Cela signifie que nous devons créer nos indicateurs et les placer dans cette collection. Étant donné que seuls les indicateurs de la forme CIndicator et de ses enfants peuvent être stockés dans la collection, nous devons utiliser ce fait. Nous utiliserons CiCustom, qui est l'enfant mentionné ci-dessus. Pour chaque moyenne mobile nous déclarons un objet de type CiCustom dans la partie privée de la classe :

class MA_Cross : public CExpertSignal
  {
private:
   CiCustom          m_fast_ma;            // The indicator as an object
   CiCustom          m_slow_ma;            // The indicator as an object
   //--- Configurable module parameters
   int              m_period_fast;   // Period of the fast MA
   ENUM_MA_METHOD    m_method_fast;    // Type of smoothing of the fast MA
   int              m_period_slow;   // Period of the slow MA
   ENUM_MA_METHOD    m_method_slow;    // Type of smoothing of the slow MA

Bien entendu, vous pouvez créer votre propre classe d'indicateurs, qui sera dérivée de CIndicator, et implémenter toutes les méthodes nécessaires à utiliser avec l'assistant MQL5. Mais dans ce cas, nous voulons montrer comment vous pouvez utiliser n'importe quel indicateur personnalisé dans le module de signaux de trading à l'aide de CiCustom.

Voici à quoi cela ressemble dans le code :

//+------------------------------------------------------------------+
//| Creates the "Fast MA" indicator                                  |
//+------------------------------------------------------------------+
bool MA_Cross::CreateFastMA(CIndicators *indicators)
  {
//--- Checking the pointer
   if(indicators==NULL) return(false);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(m_fast_ma)))
     {
      printf(__FUNCTION__+": Error adding an object of the fast MA");
      return(false);
     }
//--- Setting parameters of the fast MA
   MqlParam parameters[4];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="Examples\\Custom Moving Average.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=m_period_fast;      // Period
   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=0;                  // Shift
   parameters[3].type=TYPE_INT;
   parameters[3].integer_value=m_method_fast;      // Averaging method
//--- Object initialization  
   if(!m_fast_ma.Create(m_symbol.Name(),m_period,IND_CUSTOM,4,parameters))
     {
      printf(__FUNCTION__+": Error initializing the object of the fast MA");
      return(false);
     }
//--- Number of buffers
   if(!m_fast_ma.NumBuffers(1)) return(false);
//--- Reached this part, so the function was successful, return true
   return(true);
  }

Dans la méthode CreateFastMA(), vérifiez d'abord le pointeur de la collection d'indicateurs, puis ajoutez un pointeur de la MA rapide m_fast_ma à cette collection. Déclarez ensuite la structure MqlParam, spécialement conçue pour stocker les paramètres d'indicateurs personnalisés, et remplissez-la de valeurs.

Nous utilisons la moyenne mobile personnalisée du pack de livraison du terminal standard comme indicateur MA personnalisé. Le nom de l'indicateur doit être indiqué par rapport au dossier data_folder/MQL5/Indicators/. Étant donné que Custom Moving Average.mq5' du paquet standard se trouve dans data_folder/MQL5/Indicators/Examples/, nous spécifions son chemin, y compris le dossier Exemples :

parameters[0].string_value="Examples\\Custom Moving Average.ex5";

Si vous regardez le code de cet indicateur, vous pouvez voir toutes les données requises :

//--- input parameters
input int            InpMAPeriod=13;       // Period
input int            InpMAShift=0;         // Shift
input ENUM_MA_METHOD InpMAMethod=MODE_SMMA;  // Method

Les valeurs ​​de la structure contiennent les paires type-valeur :

  1. type de paramètre - chaîne (pour transférer le nom de l'indicateur)
  2. le nom du fichier exécutable de l'indicateur personnalisé - « Custom Moving Averages.exe »
  3. type de paramètre - int (valeur de la période)
  4. période de la moyenne mobile
  5. type de paramètre - int (valeur de décalage)
  6. décalage horizontal de la moyenne en barres
  7. type de paramètre - int (la valeur d'énumération est un nombre entier)
  8. méthode de moyenne

Après avoir rempli la structure, l'indicateur est initialisé par la méthode Create() de tous les paramètres requis : le nom du symbole et la période sur laquelle il est calculé, le type de l'indicateur issu de l'énumération ENUM_INDICATOR, le nombre de paramètres de l'indicateur et la structure MqlParam avec les valeurs des paramètres. Et le dernier paramètre spécifie le nombre de tampons d'indicateurs à l'aide de la méthode NumBuffers().

La méthode CreateSlowMA() pour créer la moyenne mobile lente est simple. Lorsque vous utilisez des indicateurs personnalisés dans le module, n'oubliez pas que l'Expert Advisor généré par l'assistant MQL5 fonctionnera également dans le testeur. Ainsi au début de notre fichier nous ajoutons la propriété #property tester_indicator qui communique au testeur l'emplacement des indicateurs requis :

#include "..\ExpertSignal.mqh"   // The CExpertSignal class is in the file ExpertSignal
#property tester_indicator "Examples\\Custom Moving Average.ex5"

Si nous utilisons plusieurs indicateurs différents, nous devons ajouter cette ligne pour chacun d'eux. Nous avons donc ajouté les indicateurs. Pour plus d’aisance, proposons deux méthodes de réception des valeurs MA :

   //--- Checking correctness of input data
   bool              ValidationSettings(void);
   //--- Creating indicators and timeseries for the module of signals
   bool              InitIndicators(CIndicators *indicators);
   //--- Access to indicator data
   double            FastMA(const int index)             const { return(m_fast_ma.GetData(0,index)); }
   double            SlowMA(const int index)             const { return(m_slow_ma.GetData(0,index)); }

Comme vous pouvez le voir, les méthodes sont très simples, elles ont utilisé la méthode GetData() de la classe parent SIndicator, qui renvoie une valeur du tampon d'indicateur spécifié à la position spécifiée.

Si vous avez besoin de classes pour travailler avec des indicateurs classiques du paquet standard, elles sont disponibles dans la section Classes pour travailler avec des indicateurs. Nous sommes prêts à passer à l'étape finale.


6. Définir les méthodes LongCondition et ShortCondition

Tout est prêt pour faire fonctionner notre module et générer des signaux de trading. Cette fonctionnalité est fournie par deux méthodes qui doivent être décrites dans chaque enfant de CExpertSignal:

  • LongCondition() vérifie les conditions d'achat et renvoie la force du signal Long de 0 à 100.
  • ShortCondition() - vérifie la condition de vente et renvoie la force du signal Short de 0 à 100.

Si la fonction renvoie une valeur nulle, cela signifie qu'il n'y a pas de signal de trading. S'il existe des conditions pour le signal, vous pouvez estimer la force du signal et renvoyer toute valeur ne dépassant pas 100. L'évaluation de la force du signal vous permet de créer de manière flexible des systèmes de trading basés sur plusieurs modules et modèles de marché. En savoir plus à ce sujet dans l'assistant MQL5 : Nouvelle version.

Puisque nous écrivons un module simple de signaux de trading, nous pouvons convenir que les signaux d'achat et de vente sont évalués de manière égale (100). Ajoutons les méthodes nécessaires dans la déclaration de classe.

   ...
   bool              InitIndicators(CIndicators *indicators);
   //--- Access to data of the indicators
   double            FastMA(const int index)             const { return(m_fast_ma.GetData(0,index)); }
   double            SlowMA(const int index)             const { return(m_slow_ma.GetData(0,index)); }
   //--- Checking buy and sell conditions
   virtual int       LongCondition();
   virtual int       ShortCondition();

Créons également la description des fonctions. C'est ainsi que se vérifie le signal d'achat (c'est la même chose avec le signal de vente) :

//+------------------------------------------------------------------+
//| Returns the strength of the buy signal                           |
//+------------------------------------------------------------------+
int MA_Cross::LongCondition()
  {
   int signal=0;
//--- For operation with ticks idx=0, for operation with formed bars idx=1
   int idx=StartIndex();
//--- Values of MAs at the last formed bar
   double last_fast_value=FastMA(idx);
   double last_slow_value=SlowMA(idx);
//--- Values of MAs at the last but one formed bar
   double prev_fast_value=FastMA(idx+1);
   double prev_slow_value=SlowMA(idx+1);
//---If the fast MA crossed the slow MA from bottom upwards on the last two closed bars
   if((last_fast_value>last_slow_value) && (prev_fast_value<prev_slow_value))
     {
      signal=100; // There is a signal to buy
     }
//--- Return the signal value
   return(signal);
  }

Notez que nous avons déclaré la variable idx, à laquelle est affectée la valeur renvoyée par la fonction StartIndex() de la classe parent CExpertBase. La fonction StartIndex() renvoie 0, si l'Expert Advisor est conçu pour fonctionner sur tous les traits, et dans ce cas l'analyse commence par la barre courante. Si l'Expert Advisor est conçu pour fonctionner avec des cours d’ouverture, StartIndex() renvoie 1 et l'analyse commence par la dernière barre formée.

Par défaut StartIndex() renvoie 1, ce qui signifie que l'Expert Advisor généré par l'assistant MQL5 ne s'exécutera qu'à l'ouverture d'une nouvelle barre et ignorera les traits entrants lors de la formation de la barre actuelle.

Comment activer ce mode et comment il peut être utilisé sera décrit plus loin dans le caractère final.

Le module est prêt à l'emploi, créons donc un robot de trading dans l'assistant MQL5 basé sur ce module.


Vérification d'un conseiller expert dans le testeur

Pour tester l'efficacité de notre module, générons un Expert Advisor basé sur celui-ci dans l'assistant MQL5 et exécutons-le sur le graphique. L'onglet « Entrées » de la fenêtre de démarrage apparue contient les paramètres du module MA_Cross.

Tous les autres paramètres ont également été ajoutés par l'assistant MQL5 lors de la génération de l'EA en fonction du module de gestion de l'argent sélectionné et du module de rétention de position (Trailing Stop). Ainsi, nous n'avons eu qu'à écrire un module de signaux de trading et avons reçu une solution complète. C'est le principal avantage de l'utilisation de l'assistant MQL5 ! 

Testons maintenant le robot de trading dans le testeur de stratégie MetaTrader 5. Essayons d'exécuter une optimisation rapide des paramètres clés.

Dans ces réglages de paramètres d'entrée, plus d'un demi-million de passes sont nécessaires pour une optimisation complète. Par conséquent, nous choisissons l'optimisation rapide (algorithme génétique) et utilisons en outre MQL5 Cloud Network pour accélérer l’optimisation. L'optimisation a été faite en 10 minutes et nous avons les résultats.


Comme vous pouvez le voir, la création d'un robot de trading dans MQL5 et l'optimisation des paramètres d'entrée ont pris beaucoup moins de temps que ce qui serait nécessaire pour écrire la logique de service de gestion de position, déboguer et rechercher les meilleurs algorithmes. 


Caractère final

Vous pouvez ignorer cet élément ou y revenir plus tard lorsque vous êtes complètement à l'aise avec la technique d'écriture d'un module de signaux de trading.

Si vous ouvrez le code source de l'Expert Advisor généré par l'assistant MQL5, vous trouverez la variable universelle Expert_EveryTick avec la fausse valeur. Sur la base de cette variable, la fonction StartIndex() renvoie sa valeur. Elle communique à l'Expert Advisor le mode dans lequel il doit fonctionner.

//+------------------------------------------------------------------+
//|                                                 TestMA_Cross.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include                                                          |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\MySignals\MA_Cross.mqh>
//--- available trailing
#include <Expert\Trailing\TrailingNone.mqh>
//--- available money management
#include <Expert\Money\MoneyFixedLot.mqh>
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string         Expert_Title             ="TestMA_Cross";  // Document name
ulong               Expert_MagicNumber       =22655;          // Expert Advisor ID
bool                  Expert_EveryTick             =false;          // Work of the EA inside the bar
//--- 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]

Si vous définissez Expert_EveryTick sur true et compilez le code, le robot de trading analysera chaque trait entrant et prendra ainsi des décisions sur les valeurs ​de la barre incomplète actuelle. Ne le faites que si vous comprenez comment cela fonctionne. Tous les systèmes de trading ne sont pas conçus pour fonctionner à l'intérieur de la barre.

Vous pouvez également ajouter une entrée de mot-clé pour le paramètre Expert_EveryTick pour obtenir un nouveau paramètre de l'Expert Advisor, que vous pouvez définir au démarrage d'EA sur un graphique ou dans le testeur :

input bool          Expert_EveryTick         =false;          // Work of the EA inside the bar

Et maintenant il est temps de résumer ce que nous avons fait.


6 étapes pour créer un module de signaux de trading

Si vous maîtrisez MQL5, vous n'avez plus besoin d'écrire un Expert Advisor à partir de zéro. Créez simplement un module de signaux de trading et, sur la base de ce module, générez automatiquement un robot de trading avec les modules de suivi et de gestion du volume de trading activés. Et même si vous n'êtes pas familier avec la POO ou que vous ne voulez pas trop vous plonger dans la structure des classes en trading, vous pouvez simplement suivre 6 étapes :

  1. Créer une nouvelle classe à l'aide de l'assistant MQL5 dans un dossier séparé MQL5/Include/MySignals/. Notre module de signaux de trading y sera stocké.
  2. Créer un descripteur de module qui décrit les paramètres, leur type et leurs valeurs par défaut.
  3. Déclarer les paramètres de module dans la classe et ajoutez des méthodes d'initialisation dans le constructeur.
  4. Vérifier les paramètres d'entrée et n'oubliez pas d'appeler ValidationSettings() de la classe de base CExpertSignal.
  5. Créer des objets d’indicateur et ajoutez une méthode d'initialisation prédéfinie InitIndicators().
  6. Identifiez les conditions des signaux de trading dans les méthodes LongCondition() et ShortCondition().

Chaque étape est simple et nécessite peu de compétences en programmation MQL5. Vous n'avez besoin d'écrire votre module qu'une seule fois, en suivant les instructions, et une vérification supplémentaire de toute idée Trade ne prendra pas plus d'une heure, sans heures fatigantes de codage et de débogage. 


Du simple au complexe

N'oubliez pas que la stratégie de trading mise en œuvre par votre robot de trading créé à l'aide de l'assistant MQL5 est aussi complexe que le module de signaux de trading qu'il utilise. Mais avant de commencer à construire un système de trading complexe basé sur un ensemble de règles d'entrée et de sortie, divisez-le en plusieurs systèmes simples et vérifiez chacun séparément.

Sur la base de modules simples, vous pouvez créer des stratégies de trading complexes en utilisant les modules prêts à l'emploi de signaux de trading, mais c'est un sujet pour un autre article !

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

Fichiers joints |
testma_cross.mq5 (7.14 KB)
ma_cross.mqh (11.57 KB)
MetaTrader 5 - Plus que vous ne pouvez l'imaginer ! MetaTrader 5 - Plus que vous ne pouvez l'imaginer !
Le terminal client MetaTrader 5 a été développé à partir de zéro et surpasse de loin son prédécesseur, c’est bien évident. La nouvelle plateforme de trading offre des opportunités illimitées de trading sur n'importe quel marché financier. De plus, ses fonctionnalités ne cessent de développer pour offrir des fonctionnalités et une commodité encore plus utiles. Il est donc désormais assez difficile de lister tous les nombreux avantages de MetaTrader 5. Nous avons essayé de les décrire brièvement dans un article, et nous avons été surpris du résultat. L'article est loin d'être bref !
Systèmes de trading simples utilisant des indicateurs de sémaphore Systèmes de trading simples utilisant des indicateurs de sémaphore
Si nous examinons en profondeur tout système de trading complexe, nous verrons qu’il est basé sur un ensemble de signaux de trading simples. Par conséquent, il n’est pas nécessaire que les développeurs novices commencent à écrire des algorithmes complexes immédiatement. Cet article fournit un exemple de système de trading qui utilise des indicateurs de sémaphore pour effectuer des transactions.
Visualisation d’une stratégie dans le testeur MetaTrader 5 Visualisation d’une stratégie dans le testeur MetaTrader 5
Nous connaissons tous le dicton « Mieux vaut voir une fois qu'entendre cent fois ». Vous pouvez lire divers livres sur Paris ou Venise, mais sur la base des images mentales, vous n'auriez pas les mêmes sensations que lors d'une promenade nocturne dans ces villes fabuleuses. L'avantage de la visualisation peut facilement être projeté sur n'importe quel aspect de notre vie, y compris le travail sur le marché, par exemple, l'analyse des prix sur des graphiques à l'aide d'indicateurs, et bien sûr, la visualisation des tests de stratégie. Cet article contient des descriptions de toutes les fonctionnalités de visualisation du testeur de stratégie MetaTrader 5.
Approche orientée objet pour créer des panneaux multi-délais et multi-devises Approche orientée objet pour créer des panneaux multi-délais et multi-devises
Cet article décrit comment la programmation orientée objet peut être utilisée pour créer des panneaux multi-délais et multi-devises pour MetaTrader 5. L'objectif principal est de créer un panneau universel, qui peut être utilisé pour afficher de nombreux types de données, tels que les prix, les changements de prix, les valeurs des indicateurs ou les conditions d'achat/vente personnalisées sans avoir besoin de modifier le code du panneau lui-même.