English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Générateur de signaux de trading basé sur un indicateur personnalisé

Générateur de signaux de trading basé sur un indicateur personnalisé

MetaTrader 5Exemples | 12 janvier 2022, 17:28
395 0
Vladimir Karputov
Vladimir Karputov

Introduction

Dans cet article, je vais vous expliquer comment créer un générateur de signaux de trading basé sur un indicateur personnalisé. Vous verrez comment vous pouvez écrire votre propre modèle de trading pour un indicateur personnalisé. J'expliquerai également le but du modèle 0 et pourquoi les structures de type IS_PATTERN_USAGE(0) sont utilisées dans le module de signal de trading.

L'article utilisera deux types de code : le code que nous allons modifier et le code que nous avons déjà modifié. Le code modifié sera mis en évidence comme suit :

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

Le code modifié est le code à copier et coller dans le générateur de signaux de trading. J'espère que vous comprendrez mieux le code grâce à la mise en évidence. 

 

1. Indicateur personnalisé

Je suis sûr qu'il doit y avoir un indicateur non inclus dans la livraison standard que vous souhaitez utiliser depuis longtemps. Et c'est l'indicateur sur lequel vous voulez construire un module de signal de trading. J'utiliserai l'indicateur MACD de la livraison standard en tant qu'indicateur. L'emplacement de l'indicateur est le suivant : ...MQL5\Indicators\Examples\MACD.mq5 

Chaque indicateur peut décrire un ou plusieurs modèles de marché. Un modèle de marché est une certaine combinaison de la valeur de l'indicateur et de la valeur du prix. Les modèles disponibles pour l'indicateur MACD sont l'inversion, le croisement de la ligne principale et de la ligne de signal, le croisement du niveau zéro, la divergence et la double divergence.

1.1 Nouveau modèle d'indicateur.

Supposons que nous ne sommes pas satisfaits des modèles de marché disponibles pour l'indicateur et que nous souhaitons introduire notre propre modèle d'indicateur. La description du nouveau modèle d'indicateur : si l'indicateur MACD est en dessous de la ligne zéro et que ses valeurs augmentent, nous pouvons nous attendre à une nouvelle croissance et ouvrir une position longue :

Figure 1 : Modèle de croissance des indicateurs prospectifs 

Figure 1. Modèle de croissance des indicateurs prospectifs

si l'indicateur MACD est au-dessus de la ligne zéro et que ses valeurs diminuent, nous pouvons nous attendre à une nouvelle baisse et ouvrir une position courte :

 Figure 2 : Modèle de baisse des indicateurs prospectifs

Figure 2 : Modèle de chute des indicateurs prospectifs 

Nous avons donc choisi l'indicateur personnalisé et proposé le nouveau modèle de trading pour l'indicateur et sa description. Procédons à l'écriture du code.

 

2. Rédaction du générateur de signaux de trading basé sur notre indicateur personnalisé

Notre générateur est le descendant de la classe de base CExpertSignal. La classe de base CExpertSignal est une classe permettant de créer des générateurs de signaux de trading. La classe CExpertSignal contient un ensemble de méthodes publiques (c'est-à-dire accessibles de l'extérieur) qui permettent à un Expert Advisor de voir l'indication du générateur de signaux de trading concernant la direction d'entrée sur le marché.

Puisque nous travaillons sur notre propre générateur de signaux de trading, il devrait être hérité de la classe CExpertSignal, avec les méthodes virtuelles pertinentes redéfinies (remplies avec le code correspondant).

 

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

Le générateur de signaux de trading doit par défaut se trouver dans le dossier ...MQL5\Include\Expert\Signal. Pour ne pas surcharger le dossier ...\Signal de la bibliothèque standard avec trop d'informations, nous allons créer un nouveau dossier sous le dossier ...\Expert et l'appeler\MySignals:

Figure 3. Création du nouveau dossier MySignals  

Figure 3. Création du nouveau dossier MySignals 

Ensuite, nous allons créer un fichier include en utilisant l'assistant MQL5. Dans MetaEditor, sélectionnez « Nouveau » dans le menu Fichier, puis sélectionnez "Inclure le fichier (*.mqh)".

Figure 4. Assistant MQL5. Création d'un fichier d'inclusion

Figure 4. Assistant MQL5. Création d'un fichier d'inclusion

Le nom de la classe de générateur de signaux sera MySignal. Il sera situé sous Include\Expert\MySignals\MySignal. Précisons-le :

Figure 5. Assistant MQL5. Emplacement du fichier d'inclusion

Figure 5. Assistant MQL5. Emplacement du fichier d'inclusion

Après avoir cliqué sur « Terminer », l'assistant MQL5 générera un modèle vide. A partir de ce moment, nous allons tout faire manuellement et copier/coller les données. Je voudrais attirer votre attention sur le fait qu'en interne, tous les signaux de la bibliothèque standard sont presque identiques. Ils ne diffèrent que par les algorithmes utilisés pour déterminer les modèles de trading.

Par conséquent, vous pouvez prendre n'importe quel fichier du dossier \Include\Expert\Signal, copier son contenu et le coller dans votre modèle. Vous pouvez ensuite commencer à éditer le fichier résultant du générateur de signaux de trading.

 

4. Description de la classe du générateur de signaux de trading

Comme modèle, j'ai pris le fichier \Include\Expert\Signal\SignalEnvelopes.mqh à partir duquel j'ai tout copié sauf l'en-tête :
//+------------------------------------------------------------------+
//|                                              SignalEnvelopes.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+

et collé le tout dans notre modèle MySignal.mqh presque vide. Voilà ce que j'ai obtenu : 

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

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

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

Remarque ligne 6 :

#include <Expert\ExpertSignal.mqh>

Ici, nous donnons l'ordre au préprocesseur d'inclure la classe de base CExpertSignal pour créer des générateurs de signaux de trading dans notre modèle.

Nous allons continuer à éditer le modèle. Pour que notre modèle soit visible ultérieurement par l'assistant MQL5, nous devons modifier la description de notre classe :

//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of indicator 'Envelopes'                           |
//| Type=SignalAdvanced                                              |
//| Name=Envelopes                                                   |
//| ShortName=Envelopes                                              |
//| Class=CSignalEnvelopes                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodMA,int,45,Period of averaging                    |
//| Parameter=Shift,int,0,Time shift                                 |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging     |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//| Parameter=Deviation,double,0.15,Deviation                        |
//+------------------------------------------------------------------+

Alors, voyons. La ligne

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

 indique le nom de notre classe de signaux sous lequel elle sera affichée dans l'assistant MQL5. Nous allons changer ce nom en quelque chose comme ceci :

//| Title=Signal of the 'Custom Indicator' indicator             |

La ligne suivante : 

//| Name=Envelopes                                                   |

indique le nom pour décrire les variables de notre classe de signaux de trading. Cette description sera utilisée par l'assistant MQL5. Modifions cette ligne comme suit :

//| Name=MyCustomIndicator                                           |

La ligne suivante :

//| ShortName=Envelopes                                              |

Nous donnerons le même nom à ce paramètre :

//| ShortName=MyCustomIndicator                                      |

La ligne suivante définit le nom de la classe :

//| Class=CSignalEnvelopes                                           |

Renommons ce paramètre :

//| Class=CSignalMyCustInd                                           |

Laissez le paramètre suivant tel quel.

//| Page=signal_envelopes                                            |

Le groupe de paramètres suivant est responsable de la description des paramètres de l'indicateur sous-jacent au générateur de signaux de trading. Comme je l'ai mentionné plus tôt, j'utiliserai ...MQL5\Indicators\Examples\MACD.mq5 comme indicateur personnalisé. Il possède les paramètres suivants :

//--- input parameters
input int                InpFastEMA=12;               // Fast EMA period
input int                InpSlowEMA=26;               // Slow EMA period
input int                InpSignalSMA=9;              // Signal SMA period
input ENUM_APPLIED_PRICE  InpAppliedPrice=PRICE_CLOSE; // Applied price

4.1 Paramètre Description Bloc 

Veuillez noter que les paramètres donnés ci-dessus s'appliquent uniquement à MACD.mq5. Votre indicateur personnalisé peut avoir des paramètres complètement différents. L'essentiel ici est de faire correspondre les paramètres de l'indicateur avec leurs descriptions dans la classe de signal de trading. Le bloc de description de paramètre dans la classe de signal de trading pour l'indicateur personnalisé considéré, MACD.mq5 , sera le suivant :

//| Parameter=PeriodFast,int,12,Period of fast EMA                   |
//| Parameter=PeriodSlow,int,24,Period of slow EMA                   |
//| Parameter=PeriodSignal,int,9,Period of averaging of difference   |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |

Regardez comment les paramètres de l'indicateur correspondent désormais aux descriptions du bloc de description de classe. Suite à toutes les modifications, le bloc description de notre classe sera le suivant :

//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signal of the 'Custom Indicator' indicator                 |
//| Type=SignalAdvanced                                              |
//| Name=MyCustomIndicator                                           |
//| ShortName=MyCustomIndicator                                      |
//| Class=CSignalMyCustInd                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodFast,int,12,Period of fast EMA                   |
//| Parameter=PeriodSlow,int,24,Period of slow EMA                   |
//| Parameter=PeriodSignal,int,9,Period of averaging of difference   |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//+------------------------------------------------------------------+

En programmation, il est considéré comme une bonne pratique de fournir des commentaires à son code, ce qui facilite la compréhension du code, lorsqu'on y revient après un certain temps. Nous allons donc modifier le bloc suivant :

//+------------------------------------------------------------------+
//| Class CSignalEnvelopes.                                          |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Envelopes' indicator.                              |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+

pour correspondre à la description de notre classe :

//+------------------------------------------------------------------+
//| Class CSignalMyCustInd.                                          |
//| Purpose: Class of the trading signal generator based on          |
//|          the custom indicator.                                   |
//| It is derived from the CExpertSignal class.                      |
//+------------------------------------------------------------------+

Pour éviter toute confusion, nous devons remplacer toutes les valeurs « CSignalEnvelopes » par « CSignalMyCustInd »

Figure 6. Remplacement de CSignalEnvelopes par CSignalMyCustInd

Figure 6. Remplacement de CSignalEnvelopes par CSignalMyCustInd 

Examinons maintenant quelques aspects théoriques.

 

5. La classe CiCustom

Nous aurons besoin de la classe CiCustom pour continuer à travailler sur le code de la classe des indicateurs de trading de l'indicateur personnalisé. La classe CiCustom a été créée spécifiquement pour travailler avec des indicateurs personnalisés. La classe CiCustom permet de créer, de paramétrer et d'accéder aux données des indicateurs personnalisés.

 

6. La classe CIndicators.

CIndicators est la classe permettant de rassembler les instances des classes de séries chronologiques et d'indicateurs techniques. La classe CIndicators assure la création, le stockage et la gestion (synchronisation des données, gestion des handles et de la mémoire) des instances de la classe des indicateurs techniques.

Nous sommes particulièrement intéressés par la classe CIndicators à cause de la méthode Create. Cette méthode crée un indicateur d'un type spécifié avec des paramètres spécifiés.

 

7. Continuez à écrire notre classe de signaux de trading

Le prochain bloc de code que nous allons modifier (lignes 28-42) est le suivant :
class CSignalMyCustInd : public CExpertSignal
  {
protected:
   CiEnvelopes       m_env;            // object-indicator
   //--- adjusted parameters
   int               m_ma_period;      // the "period of averaging" parameter of the indicator
   int               m_ma_shift;       // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;      // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;      // the "deviation" parameter of the indicator
   double            m_limit_in;       // threshold sensitivity of the 'rollback zone'
   double            m_limit_out;      // threshold sensitivity of the 'break through zone'
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

 

8. Création de l'indicateur personnalisé dans le générateur de signaux de trading

Jetez un œil au bloc de code fourni ci-dessus. La ligne

   CiEnvelopes       m_env;            // object-indicator

déclare un objet - l'indicateur de classe CiEnvelopes. CiEnvelopes est la classe pour travailler avec l'indicateur technique de la bibliothèque standard. La classe CiEnvelopes a été créée sur la base de l'indicateur technique de la bibliothèque standard. Cependant, nous écrivons le code du générateur basé sur notre indicateur personnalisé. Par conséquent, il n'existe pas de classe prête à l'emploi pour notre ou votre indicateur personnalisé dans la bibliothèque standard. Ce que nous pouvons faire, c'est utiliser la classe CiCustom.

Déclarons notre indicateur comme la classe CiCustom :

   CiCustom          m_mci;            // indicator object "MyCustomIndicator"

8.1 Quatre variables

Vous souvenez-vous du bloc de description des paramètres dans la classe ? Il y avait trois paramètres dans cette description. Dans la zone protégée de notre classe de générateur, nous allons maintenant déclarer quatre variables pour transmettre les valeurs de nos quatre paramètres :

   //--- adjustable parameters
   int               m_period_fast;    // "fast EMA period"
   int               m_period_slow;    // "slow EMA period"
   int               m_period_signal;  // "difference averaging period"
   ENUM_APPLIED_PRICE m_applied;       // "price type"

Le bloc de code suivant :

   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

Ce code déclare des variables qui donnent du « poids » aux modèles de trading de notre générateur de signaux de trading. Remplaçons le bloc de « poids » par le code suivant :

   //--- "weights" of the market models (0-100)
   int               m_pattern_0;      // model 0 "the oscillator has required direction"
   int               m_pattern_1;      // model 1 "the indicator is gaining momentum - buy; the indicator is falling - sell"

 

9. Modèle 0

Comme vous vous en souvenez, au début de l'article, il a été décidé de décrire un seul nouveau modèle qui sera généré par notre générateur de signaux de trading. Cependant, dans le code ci-dessus, j'ai spécifié deux modèles de marché (modèle 0 et modèle 1). Ici, le modèle 0 est un modèle auxiliaire important. Il est nécessaire lorsque vous tradez avec des ordres en attente. Lorsqu'il est appliqué, le modèle 0 garantit que les ordres en attente évoluent en même temps que le prix. Jetons un coup d'œil à notre générateur de signaux de trading et aux conditions suivantes :

  • l'indicateur personnalisé MACD est en dessous de la ligne zéro,
  • et ses valeurs augmentent,
  • nous faisons du trading avec des ordres en attente fixés à 50 points du prix d'ouverture de la barre (valeur de prix à quatre chiffres).

Ces conditions décrivent parfaitement notre modèle de trading. Voici comment les choses vont évoluer : Les conditions de notre modèle de trading seront vérifiées lors de l'apparition de la barre n°. 1. Ce que nous avons : MACD est en dessous de la ligne zéro, mais il prend de l'ampleur. Cela correspond au signal d'achat. Par conséquent, nous plaçons un ordre Buy Stop en attente :

Figure 7. Placement d'un ordre Buy Stop en attente
 Figure 7. Placer un ordre d'achat stop en attente 

Lors de l'apparition de la barre suivante n°. 2, le contrôle de condition constate que le MACD est inférieur à zéro et est en baisse. Selon notre modèle de trading, il n'existe actuellement aucune condition d'achat ou de vente. Cependant, notez : selon la logique de la classe CExpertSignal, puisqu'il n'y a aucune condition d'achat ou de vente, tous les ordres en attente doivent être SUPPRIMÉS. Dans ce cas, si le prix augmente soudainement et de façon spectaculaire, nous manquerons l'occasion d'entrer sur le marché long à notre avantage car il n'y aura pas d'ordre en attente.

C'est là que le modèle auxiliaire 0 apparaît très utile. Le modèle auxiliaire 0 s'appliquera, à condition que :

  • l'indicateur personnalisé MACD est en dessous de la ligne zéro.

Nous pouvons donc passer un ordre Buy Stop en attente. Puisque nous passons un ordre à 50 points du prix d'ouverture de la barre, nous déplaçons simplement l'ordre Buy Stop en attente en fonction du mouvement du prix :

Figure 8. Déplacement de l'ordre Buy Stop vers le bas
  Figure 8. Déplacer l'ordre Buy Stop vers le bas 

Ainsi, en utilisant le modèle auxiliaire 0, nous avons la possibilité de déplacer un ordre en attente en fonction du mouvement du prix.

 

10. Autres modifications du code de modèle

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

 

Dans ce bloc, nous déclarons des méthodes de définition des paramètres ajustables, des méthodes d'ajustement des poids des modèles de trading, une méthode de vérification des paramètres, une méthode d'initialisation des indicateurs et des méthodes pour vérifier si les modèles de marché sont générés.

Compte tenu du fait que nous avons déclaré quatre variables dans les paramètres réglables, le bloc de méthodes de réglage des paramètres sera le suivant :

   //--- methods of setting adjustable parameters
   void              PeriodFast(int value)               { m_period_fast=value;           }
   void              PeriodSlow(int value)               { m_period_slow=value;           }
   void              PeriodSignal(int value)             { m_period_signal=value;         }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_applied=value;               }

Le prochain fragment de code restera inchangé :

   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   void              Pattern_1(int value)                { m_pattern_1=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and time series
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are generated
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);

Le prochain bloc de code à modifier est le suivant : 

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

Ce bloc sera fortement modifié. Veuillez noter que j'utilise la méthode GetData de la classe CIndicator. Les noms des méthodes appelées seront fournis directement dans le code :

protected:
   //--- indicator initialization method
   bool              InitMyCustomIndicator(CIndicators *indicators);
   //--- methods for getting data
   //- getting the indicator value
   double            Main(int ind) { return(m_mci.GetData(0,ind));      }
   //- getting the signal line value
   double            Signal(int ind) { return(m_mci.GetData(1,ind));    }
   //- difference between two successive indicator values
   double            DiffMain(int ind) { return(Main(ind)-Main(ind+1)); }
   int               StateMain(int ind);
   double            State(int ind) { return(Main(ind)-Signal(ind)); }
   //- preparing data for the search
   bool              ExtState(int ind);
   //- searching the market model with the specified parameters
   bool              CompareMaps(int map,int count,bool minimax=false,int start=0);
  };

 Le bloc de code suivant est le constructeur.

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalMyCustInd::CSignalMyCustInd(void) : m_ma_period(45),
                                           m_ma_shift(0),
                                           m_ma_method(MODE_SMA),
                                           m_ma_applied(PRICE_CLOSE),
                                           m_deviation(0.15),
                                           m_limit_in(0.2),
                                           m_limit_out(0.2),
                                           m_pattern_0(90),
                                           m_pattern_1(70)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
  }

Dans le constructeur, nous allons changer les noms des variables. De plus, nous n'utiliserons que deux séries : USE_SERIES_HIGH+USE_SERIES_LOW

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalMyCustInd::CSignalMyCustInd(void) : m_period_fast(12),
                                           m_period_slow(24),
                                           m_period_signal(9),
                                           m_applied(PRICE_CLOSE),
                                           m_pattern_0(10),
                                           m_pattern_1(50)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
  }

Modifions la méthode ValidationSettings de notre classe.

//+------------------------------------------------------------------+
//| Validation settings protected data.                              |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_ma_period<=0)
     {
      printf(__FUNCTION__+": period MA must be greater than 0");
      return(false);
     }
//--- ok
   return(true);
  }

Dans le bloc de vérification, nous vérifions la condition principale pour l'indicateur personnalisé donné : m_period_fast>=m_period_slow

//+------------------------------------------------------------------+
//| Checking parameters of protected data                            |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_period_fast>=m_period_slow)
     {
      printf(__FUNCTION__+": slow period must be greater than fast period");
      return(false);
     }
//--- ok
   return(true);
  }

Le bloc suivant traite de la création d'indicateurs :

//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitIndicators(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- initialization of indicators and time series of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- create and initialize MA indicator
   if(!InitMA(indicators))
      return(false);
//--- ok
   return(true);
  }

Comme appliqué à notre indicateur personnalisé : 

//+------------------------------------------------------------------+
//| Creation of indicators.                                          |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitIndicators(CIndicators *indicators)
  {
//--- check of pointer is performed in the method of the parent class
//---
//--- initialization of indicators and time series of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- creation and initialization of the custom indicator
   if(!InitMyCustomIndicator(indicators))
      return(false);
//--- ok
   return(true);
  }

Le bloc suivant est le bloc d'initialisation de l'indicateur :

//+------------------------------------------------------------------+
//| Initialize MA indicators.                                        |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitMA(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- add object to collection
   if(!indicators.Add(GetPointer(m_env)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- initialize object
   if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- ok
   return(true);
  }

Tout d'abord, nous ajoutons un objet à la collection. Nous définissons ensuite les paramètres de notre indicateur et créons l'indicateur personnalisé à l'aide de la méthode  Create de la classe CIndicators :

//+------------------------------------------------------------------+
//| Initialization of indicators.                                    |
//+------------------------------------------------------------------+
bool CSignalMyCustInd::InitMyCustomIndicator(CIndicators *indicators)
  {
//--- add an object to the collection
   if(!indicators.Add(GetPointer(m_mci)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- set parameters of the indicator
   MqlParam parameters[4];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="Examples\\MACD.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=m_period_fast;
   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=m_period_slow;
   parameters[3].type=TYPE_INT;
   parameters[3].integer_value=m_period_signal;
//--- object initialization
   if(!m_mci.Create(m_symbol.Name(),0,IND_CUSTOM,4,parameters))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- number of buffers
   if(!m_mci.NumBuffers(4)) return(false);
//--- ok
   return(true);
  }

Le bloc suivant vérifie les conditions d'achat :

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

Selon notre implémentation du modèle 0, deux modèles sont vérifiés :  

//+------------------------------------------------------------------+
//| "Voting" that the price will grow.                               |
//+------------------------------------------------------------------+
int CSignalMyCustInd::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
//--- check direction of the main line
   if(DiffMain(idx)>0.0)
     {
      //--- the main line goes upwards, which confirms the possibility of the price growth
      if(IS_PATTERN_USAGE(0))
         result=m_pattern_0;      // "confirming" signal number 0
      //--- if the model 1 is used, look for a reverse of the main line
      if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0)
         result=m_pattern_1;      // signal number 1
     }
//--- return the result
   return(result);
  }

Le bloc suivant vérifie les conditions de vente :  

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

Selon notre implémentation du modèle 0, deux modèles sont vérifiés :  

//+------------------------------------------------------------------+
//| "Voting" that the price will fall.                               |
//+------------------------------------------------------------------+
int CSignalMyCustInd::ShortCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
//--- check direction of the main line
   if(DiffMain(idx)<0.0)
     {
            //--- the main line gown downwards, which confirms the possibility of the price fall
      if(IS_PATTERN_USAGE(0))
         result=m_pattern_0;      // "confirming" signal number 0
      //--- if the model 1 is used, look for a reverse of the main line
      if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0)
         result=m_pattern_1;      // signal number 1
     }
//--- return the result
   return(result);
  }

 

Conclusion

J'espère que cet article vous a aidé à comprendre comment vous pouvez créer un générateur de signaux de trading basé sur votre indicateur personnalisé.


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

Fichiers joints |
mysignal.mqh (9.38 KB)
Résultats du MQL5 Market pour le T2 2013 Résultats du MQL5 Market pour le T2 2013
Opérant avec succès depuis 1,5 ans, MQL5 Market est devenu le plus grand magasin de stratégies de trading et d’indicateurs techniques des traders. Il propose environ 800 applications de trading fournies par 350 développeurs du monde entier. Plus de 100 000 programmes de trading ont déjà été achetés et téléchargés par les traders sur leurs terminaux MetaTrader 5.
Résultats du MQL5 Market pour le 1er trimestre 2013 Résultats du MQL5 Market pour le 1er trimestre 2013
Depuis sa création, le magasin de robots de trading et d'indicateurs techniques MQL5 Market a déjà attiré plus de 250 développeurs qui ont publié 580 produits. Le premier trimestre de 2013 s'est avéré assez fructueux pour certains vendeurs du MQL5 Market qui ont réussi à faire de beaux profits en vendant leurs produits.
Le trading social avec les plateformes de trading MetaTrader 4 et MetaTrader 5 Le trading social avec les plateformes de trading MetaTrader 4 et MetaTrader 5
Qu’est-ce que le trading social ? Il s’agit d’une coopération mutuellement bénéfique des traders et des investisseurs par laquelle les traders qui réussissent autorisent le suivi de leur trading, et les investisseurs potentiels en profitent pour surveiller leurs performances et copier les trades de ceux qui leurs semblent les plus prometteurs.
Jeremy Scott - Vendeur à succès de MQL5 Market Jeremy Scott - Vendeur à succès de MQL5 Market
Jeremy Scott, plus connu sous le pseudonyme de Johnnypasado sur MQL5.community, est devenu célèbre en proposant des produits dans notre service MQL5 Market. Jeremy a déjà gagné plusieurs milliers de dollars sur le marché et ce n'est pas la limite. Nous avons décidé de nous intéresser de plus près au futur millionnaire et de recevoir quelques conseils pour les vendeurs de MQL5 Market.