English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
20 signaux de trade en MQL5

20 signaux de trade en MQL5

MetaTrader 5Exemples | 22 décembre 2021, 16:38
418 0
Sergey Gritsay
Sergey Gritsay

Introduction

Les traders essaient de trouver des régularités dans le comportement des prix, s'efforcent de former des règles à l'aide desquelles ils auront une bonne chance de déterminer un moment favorable pour acheter ou vendre. Pour créer un système entièrement automatique, vous devez apprendre la manière de vous informer de l'arrivée de tels moments - les signaux de trade.

Les signaux informent les traders des points potentiels de prise de position, mais tous ne sont pas obligatoires à exécuter. Des critères supplémentaires peuvent filtrer même la plupart des signaux, mais ce n'est pas important pour nous. Le sujet de l'article est de savoir comment programmer les signaux de trade les plus populaires en MQL5.


1. Quels signaux connaissons-nous ?

Toutes les méthodes de détermination des moments d'entrée sur le marché peuvent être divisées en plusieurs types:

  • intersection de moyennes mobiles
  • passage autorisé d'une gamme
  • sortie de la zone de surachat/survente sur la base de taux stochastiques
  • rebond sur bordures d'un canal
  • passage autorisé des bordures d'un canal
  • changement de tendance


2. Comment mieux le coder ?

Il existe de nombreuses façons d'écrire un code ; il peut être écrit dans OnStart(), OnTick() et les autres fonctions. Vous pouvez trouver des informations plus détaillées à leur sujet dans la documentation de ce site Web ou dans le guide de l'utilisateur intégré au MetaEditor ; Cependant, cette méthode n'est pas efficace et vous devez parfois écrire plusieurs fois les mêmes parties du code. C'est ainsi que nous prendrons une autre voie - nous utiliserons des fonctions personnalisées qui peuvent être appelées à partir de n'importe quelle partie du code de notre programme.

Pour faciliter l'utilisation des fonctions créées, combinons-les dans un groupe séparé en tant que fichier Include externe et nommons-le SignalTrade ; il sera stocké dans le répertoire ...\MQL5\Include. Il permettra de connecter ce module facilement à n'importe quel programme. 

Bien que tous les signaux semblent différents, ils ont beaucoup de choses en commun. Il existe trois variantes qui peuvent être reçues à partir d'une fonction qui génère les signaux :

  • signal d'achat
  • signal de vente
  • pas de signal

Créons donc une énumération qui correspond à ces signaux.

  •  1 - signal d'achat
  • -1 - signal de vente
  •  0 - pas de signal

Écrivons un prototype de la fonction qui renvoie un signal. Divisez notre fonction en plusieurs parties où l'une ou l'autre opération sera effectuée. Les variables nécessaires au stockage des données sont déclarées et initialisées au début de la fonction. Le chargement et la vérification des informations nécessaires à partir de l'indicateur créé seront effectués plus loin. La vérification des informations est essentielle pour éviter les conséquences imprévues du travail avec les données et du programme dans son ensemble. 

Une fois les informations chargées et vérifiées, passez à la formation d'un signal. Dès qu'un signal est formé, quittez la fonction et renvoyez-lui le signal obtenu sous forme de l'une des valeurs mentionnées ci-dessus.

int TradeSignal()
  {
   //--- zero means absence of signal
   int sig=0;
   
   //--- check the handles of indicators

   //--- if all the handles are invalid, create them

   //--- if the handles are valid, copy the values from indicators

   //--- check the copied data

   //--- in case of an error of copying, exit from the function

   //--- perform the indexation of the array as a timeseries

   //--- in case of an indexation error, exit from the function

   //--- check conditions and set the value for sig
 
   //--- return the trade signal
   return(sig);
  }


3. Exemples de 20 signaux de trade

Nous utiliserons différents indicateurs pour obtenir les signaux de trade. Dans MQL5, les indicateurs sont appelés à l'aide des fonctions spéciales, par exemple iMA, iAC, iMACD, iIchimoku, etc. elles créent une copie de l'indicateur technique correspondant dans le cache global du terminal client. Si une copie de l'indicateur avec les mêmes paramètres existe déjà, une nouvelle copie n'est pas créée mais le compteur de liens vers la copie existante augmente.

Ces fonctions renvoient le descripteur de la copie correspondante de l'indicateur. De plus, à l'aide de ce descripteur, on peut obtenir des données calculées par l'indicateur correspondant. Les données du tampon correspondant (les indicateurs techniques contiennent les données calculées dans leurs tampons internes ; le nombre d'entre eux peut varier de 1 à 5, selon le type d'indicateur) peuvent être copiées dans un programme MQL5 à l'aide de la fonction CopyBuffer().

Il est impossible d'utiliser les données d'un indicateur juste après sa création, car un certain temps est nécessaire pour calculer les valeurs de l'indicateur ; le meilleur moyen est donc de créer les descripteurs dans OnInit(). La fonction iCustom() crée l'indicateur personnalisé correspondant ; et si la création est réussie, il renvoie le descripteur de l'indicateur. Les indicateurs personnalisés peuvent contenir jusqu'à 512 tampons d'indicateurs, dont le contenu peut également être obtenu à l'aide de la fonction CopyBuffer() et du descripteur obtenu.

Pour chaque signal, créons une fonction selon notre prototype TradeSignal() et numérotons-les dans l'ordre suivant : TradeSignal_01() - TradeSignal_20(). Examinons en détail la structure de la fonction de formation d'un signal en utilisant l'exemple d'un signal basé sur l'intersection de moyennes mobiles ; puis nous écrirons les fonctions pour les autres signaux de la même manière.

3.1. Intersection des moyennes mobiles

Figure 1. L'intersection de deux moyennes mobiles

Figure 1. L'intersection de deux moyennes mobiles

En utilisant la fonction TradeSignal_01(), nous obtiendrons un signal sur l'intersection de deux moyennes mobiles (МА) : la rapide avec la période 8 et la lente avec la période 16.

Dans notre fonction nous fixerons uniquement le fait d'intersection et renverrons la valeur du signal correspondant à la fonction. D'après nos règles et notre prototype, la fonction ressemblera à ce qui suit :

int TradeSignal_01()
  {
//--- zero means that there is no signal
   int sig=0;

//--- check the handles of indicators
   if(h_ma1==INVALID_HANDLE)//--- if the handle is invalid
     {
      //--- create is again                                                      
      h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE);
      //--- exit from the function
      return(0);
     }
   else //--- if the handle is valid
     {
      //--- copy value of the indicator to the array
      if(CopyBuffer(h_ma1,0,0,3,ma1_buffer)<3) //--- if the array of data is less than required
         //--- exit from the function
         return(0);
      //--- set the indexation in the array as in a timeseries                                   
      if(!ArraySetAsSeries(ma1_buffer,true))
         //--- in case of an indexation error, exit from the function
         return(0);
     }

   if(h_ma2==INVALID_HANDLE)//--- if the handle is invalid
     {
      //--- create it again                                                      
      h_ma2=iMA(Symbol(),Period(),16,0,MODE_SMA,PRICE_CLOSE);
      //--- exit from the function
      return(0);
     }
   else //--- if the handle is valid 
     {
      //--- copy values of the indicator to the array
      if(CopyBuffer(h_ma2,0,0,2,ma2_buffer)<2) //--- if there is less data than required
         //--- exit from the function
         return(0);
      //--- set the indexation in the array as in a timeseries                                   
      if(!ArraySetAsSeries(ma1_buffer,true))
         //--- in case of an indexation error, exit from the function
         return(0);
     }

//--- check the condition and set a value for the sig
   if(ma1_buffer[2]<ma2_buffer[1] && ma1_buffer[1]>ma2_buffer[1])
      sig=1;
   else if(ma1_buffer[2]>ma2_buffer[1] && ma1_buffer[1]<ma2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

Examinons maintenant plus en détail chaque partie du code. Au début de la fonction nous déclarons une variable locale qui stockera le type de signal, et l'initialiserons à zéro ce qui signifie l'absence de signal.

int sig=0;

De plus, nous vérifions la validité du descripteur ; si le descripteur n’est pas valide, alors nous le créons et sortons de la fonction, car le calcul de l'indicateur prend un certain temps. Il est mis en œuvre pour éviter l'erreur de copie de données à partir du tampon d’indicateur.

   if(h_ma1==INVALID_HANDLE)//--- if the handle is invalid
     {
      //--- create it again                                                      
      h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE);
      //--- exit from the function
      return(0);
     }

Si le descripteur est valide, copiez les données dans le tableau. Pour analyser la situation, il suffit de copier les données des trois dernières barres de MA rapide et deux barres de MA lente. Utilisez la fonction suivante à cette fin :

int  CopyBuffer(
   int       indicator_handle,     // handle of an indicator
   int       buffer_num,           // number of buffer of an indicator
   int       start_pos,            // where to start from 
   int       count,                // amount to be copied
   double    buffer[]              // an array to copy data to
   );

Vérifiez-les : s'il y a moins de données que nécessaire, cela signifie qu'une erreur de copie s'est produite ; et se référer en outre au tableau où les données auraient dû être stockées conduira à une erreur. Pour l'éviter, nous sortons de la fonction. Nous devons également définir l'indexation dans le tableau comme dans une série temporelle ; la fonction suivante lui est destinée :

bool  ArraySetAsSeries(
   void  array[],     // array by a link
   bool  set          // true means that the indexation order is reversed
   );

Si une erreur s'est produite lors de l'indexation du tableau, quittez la fonction, sinon nous pouvons obtenir des résultats incorrects.

else //--- if the handle is valid 
     {
      //--- copy values of the indicator to the array
      if(CopyBuffer(h_ma1,0,0,3,ma1_buffer)<3) //--- if there is less data than required
         //--- exit from the function
         return(0);
      //--- set the indexation in the array like in a timeseries                                   
      if(!ArraySetAsSeries(ma1_buffer,true))
         //--- in case of an indexation error, exit from the function
         return(0);
     }

Maintenant que les indicateurs sont créés et que toutes les informations nécessaires sont obtenues, passons à l'étape principale - la formation d'un signal.

Pour éliminer le scintillement du signal au niveau de la barre actuelle, n'analysez que les 1ère et 2ème barres fermées.

Formation du signal d'achat. Pour cela, prenez la valeur de la MA rapide à la 2ème barre et comparez-la à la valeur de la MA lente au niveau de la barre-1 ; et comparez la valeur de la MA rapide à la 1ère barre avec la valeur de la MA lente à la 1ère barre. Si la valeur de la MA rapide à la 2ème barre est inférieure à la valeur de la MA lente à la 1ère barre et que la valeur de la MA rapide à la 1ère barre est supérieure à la valeur de la MA lente MA à la 1ère barre, cela signifie que le MA rapide a croisé la lente vers le haut ; c'est notre signal d'achat. Si notre condition est vraie, écrivez 1 dans la variable sig.

Le signal de vente se forme de la même manière. Si la MA rapide à la 2ème barre est supérieure à MA lente au niveau de la 1ère barre, et si la MA rapide au niveau de la 1ère barre est inférieure à MA lente au niveau de la 1ère barre, cela signifie un croisement haut-bas de la MA lente par la MA rapide. Si notre condition est vraie, écrivez la valeur -1 dans la variable sig. Si les deux conditions sont fausses, cela signifie qu'il n'y a pas de signal, nous écrivons donc la valeur 0 dans la variable sig. Maintenant que les signaux sont formés, renvoyez le type de signal obtenu à notre fonction TradeSignal_01()

//--- check the condition and set a value for the sig
   if(ma1_buffer[2]<ma2_buffer[1] && ma1_buffer[1]>ma2_buffer[1])
      sig=1;
   else if(ma1_buffer[2]>ma2_buffer[1] && ma1_buffer[1]<ma2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);

3.2. Intersection de la ligne principale et de la ligne de signal MACD

Figure 2. L'intersection de la ligne principale et de la ligne de signal de l'indicateur MACD

Dans la fonction TradeSignal_02(), nous obtiendrons le signal sur l'intersection du signal et de la ligne principale de MACD. Si la ligne de signal croise la ligne principale de haut en bas, c'est le signal d'achat. Si la ligne de signal croise la ligne principale de bas en haut, c'est le signal de vente. D'autres cas seront considérés comme l'absence de signal.

int TradeSignal_02()
  {
   int sig=0;

   if(h_macd==INVALID_HANDLE)
     {
      h_macd=iMACD(Symbol(),Period(),12,26,9,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_macd,0,0,2,macd1_buffer)<2)
         return(0);
      if(CopyBuffer(h_macd,1,0,3,macd2_buffer)<3)
         return(0);
      if(!ArraySetAsSeries(macd1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(macd2_buffer,true))
         return(0);
     }

//--- check the condition and set a value for sig
   if(macd2_buffer[2]>macd1_buffer[1] && macd2_buffer[1]<macd1_buffer[1])
      sig=1;
   else if(macd2_buffer[2]<macd1_buffer[1] && macd2_buffer[1]>macd1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.3. Passage autorisé de la gamme de canaux de prix

Figure 3. Passage autorisé des bordures inférieure et supérieure du Canal des Prix

Dans la fonction TradeSignal_03(), nous recevrons le signal d'un passage autorisé des bordures supérieures ou inférieures du canal des prix.

Si le prix perce la bordure supérieure du canal de prix et que le prix est fixé au-dessus de cette bordure, c'est le signal d'achat. Si le prix perce la bordure inférieure du canal des prix et que le prix est fixé en dessous de cette bordure, alors c'est le signal de vente. D'autres cas sont considérés comme l'absence de signal.

Contrairement aux deux fonctions précédentes, nous avons besoin ici d'un tableau pour stocker les prix de clôture. Utilisez la fonction suivante pour les obtenir :

int  CopyClose(
   string           symbol_name,       // symbol name
   ENUM_TIMEFRAMES  timeframe,          // period
   int              start_pos,         // where to start from 
   int              count,             // amount to be copied
   double           close_array[]      // array for copying close prices to
   );
int TradeSignal_03()
  {
   int sig=0;

   if(h_pc==INVALID_HANDLE)
     {
      h_pc=iCustom(Symbol(),Period(),"Price Channel",22);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_pc,0,0,3,pc1_buffer)<3)
         return(0);
      if(CopyBuffer(h_pc,1,0,3,pc2_buffer)<3)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(pc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(pc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the conditions and set a value for sig
   if(Close[1]>pc1_buffer[2])
      sig=1;
   else if(Close[1]<pc2_buffer[2])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.4. Passage autorisé de la gamme du canal adaptatif ADX

Figure 4. Le passage autorisé des bordures supérieure et inférieure du canal adaptatif ADX.

En utilisant la fonction TradeSignal_04(), nous obtiendrons le signal d'un passage autorisé des bordures supérieures ou inférieures du canal adaptatif ADX.

Si le prix perce la bordure supérieure du canal adaptatif ADX et que le prix de clôture est fixé au-dessus de cette bordure, c'est le signal d'achat. Si le prix perce la bordure inférieure du canal de prix et que le prix de clôture est fixé en dessous de cette bordure, c'est le signal de vente. D'autres cas sont considérés comme l'absence de signal.

int TradeSignal_04()
  {
   int sig=0;

   if(h_acadx==INVALID_HANDLE)
     {
      h_acadx=iCustom(Symbol(),Period(),"AdaptiveChannelADX",14);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_acadx,0,0,2,acadx1_buffer)<2)
         return(0);
      if(CopyBuffer(h_acadx,1,0,2,acadx2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(acadx1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(acadx2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for the sig
   if(Close[1]>acadx1_buffer[1])
      sig=1;
   else if(Close[1]<acadx2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.5. Sortie des zones de surachat/survente du stochastique

Figure 5. Croisement des niveaux de surachat et de survente par le stochastique.

En utilisant le TradeSignal_05(), nous obtiendrons le signal de sortie du stochastique des zones de surachat/survente ; les ; niveaux de ces zones seront des niveaux avec les valeurs 80 et 20.

Nous achetons, car l'oscillateur (%K ou %D) tombe en dessous d'un certain niveau (généralement, il est de 20) puis monte au-dessus. Nous vendons, car l'oscillateur monte au-dessus d'un certain niveau (généralement, il est de 80) puis tombe en dessous.

int TradeSignal_05()
  {
   int sig=0;

   if(h_stoh==INVALID_HANDLE)
     {
      h_stoh=iStochastic(Symbol(),Period(),5,3,3,MODE_SMA,STO_LOWHIGH);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_stoh,0,0,3,stoh_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(stoh_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(stoh_buffer[2]<20 && stoh_buffer[1]>20)
      sig=1;
   else if(stoh_buffer[2]>80 && stoh_buffer[1]<80)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.6. Sortie des zones de surachat/survente de RSI

Figure 6. Croisement des niveaux de surachat et de survente par l'indicateur RSI

En utilisant la fonction TradeSignal_06(), nous obtiendrons le signal de sortie de l'indicateur RSI des zones de surachat/survente;  ; les niveaux pour ces zones sont les niveaux avec les valeurs 70 et 30.

Nous achetons, comme le RSI tombe en dessous d'un certain niveau (généralement, il est de 30) puis le dépasse. Nous vendons, alors que le RSI monte au-dessus d'un certain niveau (généralement, il est de 70) puis tombe en dessous.

int TradeSignal_06()
  {
   int sig=0;

   if(h_rsi==INVALID_HANDLE)
     {
      h_rsi=iRSI(Symbol(),Period(),14,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_rsi,0,0,3,rsi_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(rsi_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(rsi_buffer[2]<30 && rsi_buffer[1]>30)
      sig=1;
   else if(rsi_buffer[2]>70 && rsi_buffer[1]<70)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
 
3.7. Sortie des zones de surachat/survente de CCI

Figure 7. Croisement des niveaux de surachat et de survente par l'indicateur CCI

En utilisant le TradeSignal_07(), nous obtiendrons le signal de sortie de l'indicateur CCI des zones de surachat/survente;  ; les niveaux pour ces zones sont les niveaux avec les valeurs 100 et -100.

Nous achetons, car le CCI chute plus bas que le niveau -100 puis remonte au-dessus. Nous vendons, car le CCI monte au-dessus du niveau 100 puis tombe en dessous.

int TradeSignal_07()
  {
   int sig=0;

   if(h_cci==INVALID_HANDLE)
     {
      h_cci=iCCI(Symbol(),Period(),14,PRICE_TYPICAL);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_cci,0,0,3,cci_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(cci_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(cci_buffer[2]<-100 && cci_buffer[1]>-100)
      sig=1;
   else if(cci_buffer[2]>100 && cci_buffer[1]<100)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.8. Sortie des zones de surachat/survente de Williams %

Figure 8. Croisement des niveaux de surachat et de survente par l'indicateur Williams %

En utilisant la fonction TradeSignal_08(), nous obtiendrons le signal de sortie de l'indicateur Williams % des zones de surachat/survente;  ; les niveaux pour ces zones sont les niveaux avec les valeurs -20 et -80.

Nous achetons, car Williams % tombe en dessous du niveau -80 puis remonte au-dessus. Nous vendons, car Williams % s'élève au-dessus du niveau -20 puis retombe en dessous.

int TradeSignal_08()
  {
   int sig=0;

   if(h_wpr==INVALID_HANDLE)
     {
      h_wpr=iWPR(Symbol(),Period(),14);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_wpr,0,0,3,wpr_buffer)<3)
         return(0);

      if(!ArraySetAsSeries(wpr_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(wpr_buffer[2]<-80 && wpr_buffer[1]>-80)
      sig=1;
   else if(wpr_buffer[2]>-20 && wpr_buffer[1]<-20)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }
3.9. Rebond sur les bordures du canal Bollinger

Figure 9. Rebond du prix de la bordure du canal Bollinger

En utilisant la fonction TradeSignal_09(), nous obtiendrons le signal lorsque le prix rebondira des bordures du canal Bollinger.

Si le prix perce ou touche la bordure supérieure de Bollinger puis recule, c'est le signal de vente. Si le prix perce ou touche la bordure inférieure de Bollinger, alors c'est le signal d'achat.

int TradeSignal_09()
  {
   int sig=0;

   if(h_bb==INVALID_HANDLE)
     {
      h_bb=iBands(Symbol(),Period(),20,0,2,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_bb,1,0,2,bb1_buffer)<2)
         return(0);
      if(CopyBuffer(h_bb,2,0,2,bb2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(bb1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(bb2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<=bb2_buffer[1] && Close[1]>bb2_buffer[1])
      sig=1;
   else if(Close[2]>=bb1_buffer[1] && Close[1]<bb1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.10. Rebond des bordures du canal d’écart standard

Figure 10. Rebond du prix des bordures du canal d'écart standard

En utilisant la fonction TradeSignal_10(), nous obtiendrons le signal si le prix rebondit des bordures du canal d'écart standard.

Si le prix perce ou touche la bordure supérieure du canal de l'écart standard, puis recule, c'est le signal de vente. Si le prix perce ou touche la bordure inférieure du canal de l'écart standard, alors c'est le signal d'achat.

int TradeSignal_10()
  {
   int sig=0;

   if(h_sdc==INVALID_HANDLE)
     {
      h_sdc=iCustom(Symbol(),Period(),"StandardDeviationChannel",14,0,MODE_SMA,PRICE_CLOSE,2.0);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_sdc,0,0,2,sdc1_buffer)<2)
         return(0);
      if(CopyBuffer(h_sdc,1,0,2,sdc2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(sdc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(sdc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<=sdc2_buffer[1] && Close[1]>sdc2_buffer[1])
      sig=1;
   else if(Close[2]>=sdc1_buffer[1] && Close[1]<sdc1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.11. Rebond des bordures du canal des prix

Figure 11. Le rebond des prix des bordures du canal des prix

En utilisant la fonction TradeSignal_11(), nous obtiendrons le signal si le prix rebondit des bordures du canal des prix.

Si le prix perce ou touche la bordure supérieure du canal des prix et recule, c'est le signal de vente. Si le prix perce ou touche la bordure inférieure du canal des prix, alors c'est le signal d'achat.

int TradeSignal_11()
  {
   int sig=0;

   if(h_pc==INVALID_HANDLE)
     {
      h_pc=iCustom(Symbol(),Period(),"Price Channel",22);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_pc,0,0,4,pc1_buffer)<4)
         return(0);
      if(CopyBuffer(h_pc,1,0,4,pc2_buffer)<4)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(pc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(pc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[1]>pc2_buffer[2] && Close[2]<=pc2_buffer[3])
      sig=1;
   else if(Close[1]<pc1_buffer[2] && Close[2]>=pc1_buffer[3])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.12. Rebond des bordures du canal Enveloppes

Figure 12. Le rebond du prix des bordures du canal Enveloppes

En utilisant la fonction TradeSignal_12(), nous obtiendrons le signal si le prix rebondit des bordures du canal Enveloppes.

Si le prix perce ou touche la bordure supérieure du canal Enveloppes puis recule, c'est le signal de vente. Si le prix perce ou touche la bordure inférieure du canal Enveloppes, c'est le signal d'achat.

int TradeSignal_12()
  {
   int sig=0;

   if(h_env==INVALID_HANDLE)
     {
      h_env=iEnvelopes(Symbol(),Period(),28,0,MODE_SMA,PRICE_CLOSE,0.1);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_env,0,0,2,env1_buffer)<2)
         return(0);
      if(CopyBuffer(h_env,1,0,2,env2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(env1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(env2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<=env2_buffer[1] && Close[1]>env2_buffer[1])
      sig=1;
   else if(Close[2]>=env1_buffer[1] && Close[1]<env1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.13. Passage autorisé du canal Donchian

Figure 13. Passage autorisé des bordures du Canal Donchian

Dans la fonction TradeSignal_13(), nous obtiendrons le signal lorsque le prix percera les bordures du canal Donchian.

Si le prix perce la bordure supérieure du canal Donchian et que le prix de clôture est fixé au-dessus de cette bordure, c'est le signal d'achat. Si le prix perce la bordure inférieure du canal Donchian et que le prix de clôture est fixé en dessous de cette bordure, c'est le signal de vente.

int TradeSignal_13()
  {
   int sig=0;

   if(h_dc==INVALID_HANDLE)
     {
      h_dc=iCustom(Symbol(),Period(),"Donchian Channels",24,3,-2);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_dc,0,0,3,dc1_buffer)<3)
         return(0);
      if(CopyBuffer(h_dc,1,0,3,dc2_buffer)<3)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(dc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(dc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[1]>dc1_buffer[2])
      sig=1;
   else if(Close[1]<dc2_buffer[2])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.14. Passage autorisé du canal Silver

Figure 14. Passage autorisé des bordures du canal Silver

Dans la fonction TradeSignal_14(), nous obtiendrons le signal lorsque le prix percera les bordures du canal Silver.  L'indicateur Silver-Channel dessine 8 frontières qui peuvent également servir de niveaux de support et de résistance. Pour obtenir le signal, nous utiliserons 2 bordures médianes. 

Si le prix perce la bordure supérieure du canal Silver et que le prix de clôture est fixé au-dessus de cette bordure, c'est le signal d'achat. Si le prix perce la bordure inférieure du canal Silver et que le prix de clôture est fixé en dessous de cette bordure, c'est le signal de vente.

int TradeSignal_14()
  {
   int sig=0;

   if(h_sc==INVALID_HANDLE)
     {
      h_sc=iCustom(Symbol(),Period(),"Silver-channels",26,38.2,23.6,0,61.8);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_sc,0,0,2,sc1_buffer)<2)
         return(0);
      if(CopyBuffer(h_sc,1,0,2,sc2_buffer)<2)
         return(0);
      if(CopyClose(Symbol(),Period(),0,3,Close)<3)
         return(0);
      if(!ArraySetAsSeries(sc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(sc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[2]<sc1_buffer[1] && Close[1]>sc1_buffer[1])
      sig=1;
   else if(Close[2]>sc2_buffer[1] && Close[1]<sc2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.15. Passage autorisé du canal Gallagher

Figure 15. Passage autorisé des bordures du canal Gallagher

Dans le canal TradeSignal_15(), nous obtiendrons le signal lorsque le prix percera les bordures du canal Gallagher. L'indicateur du canal Gallagher est tracé par des maximums et des minimums pour 10 jours. 

Si le cours perce la bordure supérieure du canal Gallagher et que le cours de clôture est fixé au-dessus de cette bordure, c'est le signal d'achat. Si le prix perce la frontière inférieure du canal Gallagher et que le prix de clôture est fixé en dessous de cette frontière, c'est le signal de vente.

int TradeSignal_15()
  {
   int sig=0;

   if(h_gc==INVALID_HANDLE)
     {
      h_gc=iCustom(Symbol(),Period(),"PriceChannelGalaher");
      return(0);
     }
   else
     {
      if(CopyBuffer(h_gc,0,0,3,gc1_buffer)<3)
         return(0);
      if(CopyBuffer(h_gc,1,0,3,gc2_buffer)<3)
         return(0);
      if(CopyClose(Symbol(),Period(),0,2,Close)<2)
         return(0);
      if(!ArraySetAsSeries(gc1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(gc2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(Close,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(Close[1]>gc1_buffer[2])
      sig=1;
   else if(Close[1]<gc2_buffer[2])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.16. Changement de tendance par NRTR

Figure 16. Identification d'un changement de tendance à l'aide de l'indicateur NRTR

Dans la fonction TradeSignal_16(), nous obtiendrons le signal lorsque la tendance NRTR change.

Si l'indicateur NRTR montre une tendance à la hausse, c'est le signal d'achat. Si NRTR montre une tendance à la baisse, c'est le signal de vente.

int TradeSignal_16()
  {
   int sig=0;

   if(h_nrtr==INVALID_HANDLE)
     {
      h_nrtr=iCustom(Symbol(),Period(),"NRTR",40,2.0);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_nrtr,0,0,2,nrtr1_buffer)<2)
         return(0);
      if(CopyBuffer(h_nrtr,1,0,2,nrtr2_buffer)<2)
         return(0);
      if(!ArraySetAsSeries(nrtr1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(nrtr2_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(nrtr1_buffer[1]>0)
      sig=1;
   else if(nrtr2_buffer[1]>0)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.17. Changement de tendance par alligator

Figure 17. Changement de tendance par Alligator

Dans la fonction TradeSignal_17(), nous obtiendrons le signal lorsque la tendance Alligator changera.

Si la Mâchoire, les Dents et les Lèvres sont fermées et recourbées, l'Alligator s'endort ou dort déjà. Lorsqu'il dort, sa faim grandit ; et plus il dort, plus il aura faim en se réveillant. La première chose qu'il fait au réveil est d'ouvrir la bouche et de bâiller. Il commence ensuite à sentir la nourriture - viande d'un taureau (bull) ou d'un ours (bear), et commence ensuite à chasser. Dès que l'alligator a suffisamment mangé, il perd son intérêt du champ nourriture-prix (les lignes d'équilibre convergent) ; il est temps de fixer le profit.

int TradeSignal_17()
  {
   int sig=0;

   if(h_al==INVALID_HANDLE)
     {
      h_al=iAlligator(Symbol(),Period(),13,0,8,0,5,0,MODE_SMMA,PRICE_MEDIAN);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_al,0,0,2,al1_buffer)<2)
         return(0);
      if(CopyBuffer(h_al,1,0,2,al2_buffer)<2)
         return(0);
      if(CopyBuffer(h_al,2,0,2,al3_buffer)<2)
         return(0);
      if(!ArraySetAsSeries(al1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(al2_buffer,true))
         return(0);
      if(!ArraySetAsSeries(al3_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(al3_buffer[1]>al2_buffer[1] && al2_buffer[1]>al1_buffer[1])
      sig=1;
   else if(al3_buffer[1]<al2_buffer[1] && al2_buffer[1]<al1_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.18. Changement de tendance par AMA

Figure 18. Changement de tendance par AMA

Dans la fonction TradeSignal_18(), nous obtiendrons le signal lorsque la tendance AMA change.

Si l'indicateur AMA est orienté vers le haut, c'est le signal d'achat. Si l'AMA est orienté vers le bas, alors c'est le signal de vente.

int TradeSignal_18()
  {
   int sig=0;

   if(h_ama==INVALID_HANDLE)
     {
      h_ama=iAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_ama,0,0,3,ama_buffer)<3)
         return(0);
      if(!ArraySetAsSeries(ama_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(ama_buffer[2]<ama_buffer[1])
      sig=1;
   else if(ama_buffer[2]>ama_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.19. Changement de couleur de l'Oscillateur Awesome

Figure 19. Identification d'un changement de tendance à l'aide de l'indicateur Awesome Oscillator

Dans la fonction TradeSignal_19(), nous obtiendrons le signal lorsque la couleur de l'histogramme Awesome Oscillator change.

L'une des fonctionnalités de MQL5 est la possibilité de créer des tampons pour les indicateurs, où l'on peut stocker des indices de la couleur des lignes configurées dans les propriétés #property Indicator_colorN. Lorsque la couleur de l'histogramme Awesome Oscillator est verte, c'est le signal d'achat. Si sa couleur passe au rouge, c'est le signal de vente.

int TradeSignal_19()
  {
   int sig=0;

   if(h_ao==INVALID_HANDLE)
     {
      h_ao=iAO(Symbol(),Period());
      return(0);
     }
   else
     {
      if(CopyBuffer(h_ao,1,0,20,ao_buffer)<20)
         return(0);
      if(!ArraySetAsSeries(ao_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(ao_buffer[1]==0)
      sig=1;
   else if(ao_buffer[1]==1)
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }

3.20. Changement de tendance par Ichimoku

Figure 20. Identification d'un changement de tendance à l'aide de l'indicateur Ichimoku

Dans la fonction TradeSignal_20(), nous obtiendrons le signal lorsque la tendance Ichimoku change. Pour cela nous analyserons l'intersection des lignes Tenkan-sen et Kijun-sen.

Le signal d'achat est généré lorsque la ligne Tenkan-sen croise Kijun-sen de bas en haut. Le croisement haut-bas est le signal de vente.

int TradeSignal_20()
  {
   int sig=0;

   if(h_ich==INVALID_HANDLE)
     {
      h_ich=iIchimoku(Symbol(),Period(),9,26,52);
      return(0);
     }
   else
     {
      if(CopyBuffer(h_ich,0,0,2,ich1_buffer)<2)
         return(0);
      if(CopyBuffer(h_ich,1,0,2,ich2_buffer)<2)
         return(0);
      if(!ArraySetAsSeries(ich1_buffer,true))
         return(0);
      if(!ArraySetAsSeries(ich2_buffer,true))
         return(0);
     }
//--- check the condition and set a value for sig
   if(ich1_buffer[1]>ich2_buffer[1])
      sig=1;
   else if(ich1_buffer[1]<ich2_buffer[1])
      sig=-1;
   else sig=0;

//--- return the trade signal
   return(sig);
  }


4. Faites-le sous d’indicateur

Maintenant que nous avons les blocs d'indicateurs prêts à l'emploi, nous pouvons commencer à écrire un indicateur qui montre les signaux sur la base de toutes les méthodes sélectionnées. En utilisant le modèle créé, nous pouvons mettre en œuvre la réception du signal de n'importe quel indicateur ; il suffit de formuler correctement une condition de signal et de l'ajouter au code.

Écrivons un indicateur avec des paramètres intégrés de manière inflexible. Les signaux des indicateurs seront tracés sous la forme de flèches (flèche vers le haut - achat, vers le bas - vente, une croix - pas de signal) sur la partie droite du graphique. Prenons la police Wingdings standard pour dessiner les flèches. Nous devons également créer plusieurs autres fonctions pour afficher les informations concernant les signaux sur le graphique d'un symbole. Nous les combinerons dans un bloc séparé en tant que bibliothèque pouvant être utilisée pour écrire vos propres programmes en y ajoutant de nouvelles fonctions. Appelons cette bibliothèque LibFunctions.

Dans l'en-tête de notre futur indicateur, écrire la connexion du fichier avec les fonctions de génération de signal et la fonction d’importation nécessaires à l'affichage graphique du signal, et déclarer les variables sur global scape qui stockeront le type de signal reçu de l'indicateur.

//--- Connect necessary libraries of functions
#include <SignalTrade.mqh>
//--- Import of functions from the LibFunctions library
#import "LibFunctions.ex5"
void SetLabel(string nm,string tx,ENUM_BASE_CORNER cn,ENUM_ANCHOR_POINT cr,int xd,int yd,string fn,int fs,double yg,color ct);
string arrow(int sig);
color Colorarrow(int sig);
#import
//+------------------------------------------------------------------+
//| Declare variables for storing signals of indicators              |
//+------------------------------------------------------------------+
int SignalMA;
int SignalMACD;
int SignalPC;
int SignalACADX;
int SignalST;
int SignalRSI;
int SignalCCI;
int SignalWPR;
int SignalBB;
int SignalSDC;
int SignalPC2;
int SignalENV;
int SignalDC;
int SignalSC;
int SignalGC;
int SignalNRTR;
int SignalAL;
int SignalAMA;
int SignalAO;
int SignalICH;

Comme je l'ai mentionné précédemment, les indicateurs ne sont chargés sur le terminal qu'une seule fois et les pointeurs (descripteurs) vers ces indicateurs sont créés ; c'est pourquoi implémentons leur création dans la fonction OnInit(), puisque cette fonction n'est exécutée qu'une seule fois au démarrage du programme.

int OnInit()
  {
//--- create indicator handles
   h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE);
   h_ma2=iMA(Symbol(),Period(),16,0,MODE_SMA,PRICE_CLOSE);
   h_macd=iMACD(Symbol(),Period(),12,26,9,PRICE_CLOSE);
   h_pc=iCustom(Symbol(),Period(),"Price Channel",22);
   h_acadx=iCustom(Symbol(),Period(),"AdaptiveChannelADX",14);
   h_stoh=iStochastic(Symbol(),Period(),5,3,3,MODE_SMA,STO_LOWHIGH);
   h_rsi=iRSI(Symbol(),Period(),14,PRICE_CLOSE);
   h_cci=iCCI(Symbol(),Period(),14,PRICE_TYPICAL);
   h_wpr=iWPR(Symbol(),Period(),14);
   h_bb=iBands(Symbol(),Period(),20,0,2,PRICE_CLOSE);
   h_sdc=iCustom(Symbol(),Period(),"StandardDeviationChannel",14,0,MODE_SMA,PRICE_CLOSE,2.0);
   h_env=iEnvelopes(Symbol(),Period(),28,0,MODE_SMA,PRICE_CLOSE,0.1);
   h_dc=iCustom(Symbol(),Period(),"Donchian Channels",24,3,-2);
   h_sc=iCustom(Symbol(),Period(),"Silver-channels",26,38.2,23.6,0,61.8);
   h_gc=iCustom(Symbol(),Period(),"PriceChannelGalaher");
   h_nrtr=iCustom(Symbol(),Period(),"NRTR",40,2.0);
   h_al=iAlligator(Symbol(),Period(),13,0,8,0,5,0,MODE_SMMA,PRICE_MEDIAN);
   h_ama=iAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE);
   h_ao=iAO(Symbol(),Period());
   h_ich=iIchimoku(Symbol(),Period(),9,26,52);
   return(0);
  }

Tous les calculs principaux sont effectués dans la fonction OnCalculate() ; là, nous placerons le reste du code de l'indicateur.

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---assign the signal value to the variable
   SignalMA    = TradeSignal_01();
   SignalMACD  = TradeSignal_02();
   SignalPC    = TradeSignal_03();
   SignalACADX = TradeSignal_04();
   SignalST    = TradeSignal_05();
   SignalRSI   = TradeSignal_06();
   SignalCCI   = TradeSignal_07();
   SignalWPR   = TradeSignal_08();
   SignalBB    = TradeSignal_09();
   SignalSDC   = TradeSignal_10();
   SignalPC2   = TradeSignal_11();
   SignalENV   = TradeSignal_12();
   SignalDC    = TradeSignal_13();
   SignalSC    = TradeSignal_14();
   SignalGC    = TradeSignal_15();
   SignalNRTR  = TradeSignal_16();
   SignalAL    = TradeSignal_17();
   SignalAMA   = TradeSignal_18();
   SignalAO    = TradeSignal_19();
   SignalICH   = TradeSignal_20();

//--- draw graphical objects on the chart in the upper left corner
   int size=((int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS)/22);
   int i=0;
   int x=10;
   int y=0;
   int fz=size-4;

   y+=size;
   SetLabel("arrow"+(string)i,arrow(SignalMA),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalMA));
   x+=size;
   SetLabel("label"+(string)i,"Moving Average",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalMACD),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalMACD));
   x+=size;
   SetLabel("label"+(string)i,"MACD",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalPC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalPC));
   x+=size;
   SetLabel("label"+(string)i,"Price Channell",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalACADX),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalACADX));
   x+=size;
   SetLabel("label"+(string)i,"Adaptive Channel ADX",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalST),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalST));
   x+=size;
   SetLabel("label"+(string)i,"Stochastic Oscillator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalRSI),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalRSI));
   x+=size;
   SetLabel("label"+(string)i,"RSI",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalCCI),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalCCI));
   x+=size;
   SetLabel("label"+(string)i,"CCI",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalWPR),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalWPR));
   x+=size;
   SetLabel("label"+(string)i,"WPR",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalBB),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalBB));
   x+=size;
   SetLabel("label"+(string)i,"Bollinger Bands",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalSDC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalSDC));
   x+=size;
   SetLabel("label"+(string)i,"StDevChannel",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalPC2),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalPC2));
   x+=size;
   SetLabel("label"+(string)i,"Price Channell 2",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalENV),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalENV));
   x+=size;
   SetLabel("label"+(string)i,"Envelopes",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalDC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalDC));
   x+=size;
   SetLabel("label"+(string)i,"Donchian Channels",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalSC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalSC));
   x+=size;
   SetLabel("label"+(string)i,"Silver-channels",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalGC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalGC));
   x+=size;
   SetLabel("label"+(string)i,"Galaher Channel",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalNRTR),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalNRTR));
   x+=size;
   SetLabel("label"+(string)i,"NRTR",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalAL),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAL));
   x+=size;
   SetLabel("label"+(string)i,"Alligator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalAMA),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAMA));
   x+=size;
   SetLabel("label"+(string)i,"AMA",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalAO),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAO));
   x+=size;
   SetLabel("label"+(string)i,"Awesome oscillator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);
   i++;y+=size;x=10;
   SetLabel("arrow"+(string)i,arrow(SignalICH),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalICH));
   x+=size;
   SetLabel("label"+(string)i,"Ichimoku Kinko Hyo",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet);

   return(rates_total);
  }

Eh bien, notre indicateur est prêt. En fin de compte, nous avons l'image suivante sur le graphique.



5. Faites-le sous forme d’un Expert Advisor

De la même manière, nous pouvons écrire un Expert Advisor qui montre le signal de l'indicateur sur le graphique. Implémentons un système d'information avec les éléments de contrôle graphique. Il est possible de choisir un indicateur nécessaire et de configurer ses paramètres via l'interface graphique.


Nous n'allons pas discuter de l'implémentation de l'interface graphique ; vous pouvez trouver les informations à ce sujet dans l'article Création de panneaux de contrôle actifs dans MQL5 pour le trading.

Pour modifier les paramètres des indicateurs via notre interface graphique, améliorons notre bibliothèque SignalTrade.mqh et nommons-la SignalTradeExp.mqh.

Tout d'abord, nous avons besoin de variables supplémentaires pour stocker les paramètres des indicateurs.

//--- input parameters Moving Average
int                periodma1=8;
int                periodma2=16;
ENUM_MA_METHOD     MAmethod=MODE_SMA;
ENUM_APPLIED_PRICE MAprice=PRICE_CLOSE;
//--- input parameters MACD
int                FastMACD=12;
int                SlowMACD=26;
int                MACDSMA=9;
ENUM_APPLIED_PRICE MACDprice=PRICE_CLOSE;
//--- input parameters Price Channel
int                PCPeriod=22;
//--- input parameters Adaptive Channel ADX
int                ADXPeriod=14;
//--- input parameters Stochastic Oscillator
int                SOPeriodK=5;
int                SOPeriodD=3;
int                SOslowing=3;
ENUM_MA_METHOD     SOmethod=MODE_SMA;
ENUM_STO_PRICE     SOpricefield=STO_LOWHIGH;
//--- input parameters RSI
int                RSIPeriod=14;
ENUM_APPLIED_PRICE RSIprice=PRICE_CLOSE;
//--- input parameters CCI
int                CCIPeriod=14;
ENUM_APPLIED_PRICE CCIprice=PRICE_TYPICAL;
//--- input parameters WPR
int                WPRPeriod=14;
//--- input parameters Bollinger Bands
int                BBPeriod=20;
double             BBdeviation=2.0;
ENUM_APPLIED_PRICE BBprice=PRICE_CLOSE;
//--- input parameters Standard Deviation Channel
int                SDCPeriod=14;
double             SDCdeviation=2.0;
ENUM_APPLIED_PRICE SDCprice=PRICE_CLOSE;
ENUM_MA_METHOD     SDCmethod=MODE_SMA;
//--- input parameters Price Channel 2
int                PC2Period=22;
//--- input parameters Envelopes
int                ENVPeriod=14;
double             ENVdeviation=0.1;
ENUM_APPLIED_PRICE ENVprice=PRICE_CLOSE;
ENUM_MA_METHOD     ENVmethod=MODE_SMA;
//--- input parameters Donchian Channels
int                DCPeriod=24;
int                DCExtremes=3;
int                DCMargins=-2;
//--- input parameters Silver-channels
int                SCPeriod=26;
double             SCSilvCh=38.2;
double             SCSkyCh=23.6;
double             SCFutCh=61.8;
//--- input parameters NRTR
int                NRTRPeriod   =  40;
double             NRTRK        =  2.0;
//--- input parameters Alligator
int                ALjawperiod=13;
int                ALteethperiod=8;
int                ALlipsperiod=5;
ENUM_MA_METHOD     ALmethod=MODE_SMMA;
ENUM_APPLIED_PRICE ALprice=PRICE_MEDIAN;
//--- input parameters AMA
int                AMAperiod=9;
int                AMAfastperiod=2;
int                AMAslowperiod=30;
ENUM_APPLIED_PRICE AMAprice=PRICE_CLOSE;
//--- input parameters Ichimoku Kinko Hyo
int                IKHtenkansen=9;
int                IKHkijunsen=26;
int                IKHsenkouspanb=52;

Remplacez les valeurs constantes des indicateurs par les variables. Les autres choses doivent rester inchangées.

h_ma1=iMA(Symbol(),Period(),periodma1,0,MAmethod,MAprice);

Un point important est l'utilisation économique de la mémoire de l'ordinateur ; lors de la modification des paramètres, il est nécessaire de décharger la copie de l'indicateur avec les anciens paramètres et d'en charger un nouveau. Cela peut être fait à l'aide de la fonction suivante :

bool  IndicatorRelease(
   int       indicator_handle,     // indicator handle
   );
   if(id==CHARTEVENT_OBJECT_ENDEDIT && sparam=="PIPSetEditMA2")
     {
      periodma2=(int)ObjectGetString(0,"PIPSetEditMA2",OBJPROP_TEXT);
      ObjectSetString(0,"PIPSetEditMA2",OBJPROP_TEXT,(string)periodma2);
      //--- unload old copy of the indicator
      IndicatorRelease(h_ma2);
      //--- create new copy of the indicator
      h_ma2=iMA(Symbol(),Period(),periodma2,0,MAmethod,MAprice);
      ChartRedraw();
     }

Conclusion

Ainsi, nous avons appris à lire les informations des indicateurs et à les transmettre à l’Expert Advisor. De cette manière, vous pouvez obtenir des signaux de n'importe quel indicateur.

Remarque

  • Le fichier des indicateurs SignalTrade.mq5, AdaptiveChannelADX.mq5, Donchian Channels.mq5, NRTR.mq5, Price Channel.mq5, PriceChannelGalaher.mq5, Silver-channels.mq5, StandardDeviationChannel.mq5 doit être copié dans le ...\MQL5\ Dossier des indicateurs.
  • Les fichiers Include SignalTrade.mqh et SignalTradeExp.mqh doivent être copiés dans le dossier ...\MQL5\Include.
  • La bibliothèque de fonctions LibFunctions.mq5 doit être copiée dans le dossier ...\MQL5\Libraries.
  • L’Expert Advisor ExpSignalTrade.mq5 doit être copié dans ...\MQL5\Experts.

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

Fichiers joints |
indicators.zip (8.9 KB)
expsignaltrade.mq5 (165.84 KB)
signaltrade.mq5 (10.57 KB)
signaltrade.mqh (20.16 KB)
signaltradeexp.mqh (23.26 KB)
Le prototype du robot de trading Le prototype du robot de trading
Cet article résume et systématise les principes de création d'algorithmes et d'éléments de systèmes de trading. L'article considère la conception d'algorithmes experts. À titre d'exemple, la classe CExpertAdvisor est considérée, qui peut être utilisée pour le développement rapide et facile de systèmes de trading.
Comment écrire un indicateur à partir d'un autre indicateur Comment écrire un indicateur à partir d'un autre indicateur
Dans MQL5, vous pouvez écrire un indicateur à la fois à partir de zéro et à partir d'un autre indicateur déjà existant, intégré au terminal client ou personnalisé. Et ici, vous avez également deux manières - d'améliorer un indicateur en lui ajoutant de nouveaux calculs et styles graphiques, ou d'utiliser un indicateur intégré au terminal client ou un indicateur personnalisé via les fonctions iCustom() ou IndicatorCreate().
Comment créer votre propre Trailing Stop Comment créer votre propre Trailing Stop
La règle de base du trader : Laisse que le bénéfice croisse et que les pertes tombent ! Cet article considère l'une des techniques de base, permettant de suivre cette règle - déplacer le niveau d’arrêt protecteur (niveau de stop loss) après avoir augmenté le bénéfice de la position, c'est-à-dire - le niveau Trailing Stop. Vous trouverez la procédure étape par étape pour créer une classe pour le trailing stop sur les indicateurs SAR et NRTR. Chacun pourra insérer ce trailing stop dans ses experts ou l'utiliser de manière autonome pour contrôler les positions dans leurs comptes.
Fonctions de gestion monétaire dans un Expert Advisor Fonctions de gestion monétaire dans un Expert Advisor
Le développement de stratégies de trading se concentre principalement sur la recherche de modèles d’entrée et de sortie du marché, ainsi que sur le maintien des positions. Si nous sommes en mesure de formaliser certains modèles dans des règles de trading automatisé, alors le trader est confronté à la question de calculer le volume des positions, la taille des marges, ainsi que de maintenir un niveau sûr de fonds hypothécaires pour assurer des positions ouvertes en mode automatisé. Dans cet article, nous utiliserons le langage MQL5 pour construire des exemples simples de réalisation de ces calculs.