jeudi 15 août 2013

Création d'un premier indicateur pour MetaTrader 4

Toujours avec le même algorithme, nous allons maintenant faire un indicateur. Un indicateur, à la différence d'un expert advisor, ne peut pas passer d'ordres au broker. Il est là pour donner la valeur d'un calcul sur les cours qui nous sert pour trader. En général, on l'affiche dans un graphique. On s'en sert aussi dans les experts advisors car la (ou les) valeur(s) qu'ils donne sert à la décision pour ouvrir ou clôturer une position. L'indicateur que nous allons faire, va nous donner simplement la moyenne du cours pour chaque chandelier. Toutes les minutes pour un timeframe M1, ou toutes les quatre heures pour un timeframe H4, etc. Cette moyenne sera affichée sous forme de courbe et non pas comme valeur brute dans un label sur le graphique. Vous commencez à connaître l'algorithme qu'on va utiliser sur le bout des doigts. On va utiliser le même que le précédent mais adapté à un traçage de courbe d'indicateur.

Le traçage de courbes avec MetaTrader 4:

Je vais vous décevoir, mais il n'existe pas de fonction toute prête pour tracer une ligne entre deux points ! On peut tracer pleins d'objets graphiques avec les fonctions appropriées, mais pas de ligne toute simple ! Cela pour une raison principale: MetaTrader gère lui même en interne le traçage de courbes avec des lignes pour gérer les performances et la mémoire et avoir un contrôle complet sur ce processus, car si on le fait nous même c'est plus lent, et on risque de consommer bien trop de mémoire. Les concepteurs de MetaTrader ont préféré que le logiciel garde tout le contrôle à ce niveau. Et donc nous n'avons rien à tracer ! INCROYABLE ! Pour tracer une courbe, nous ne traçons rien du tout !! Il suffit juste de donner à MetaTrader les valeurs et il s'en charge. Ces valeurs sont stockées dans ce que les programmeurs appellent un buffer, ou tampon en français. Il s'agit d'une zone mémoire qui contient les données les unes à la suite des autres. Et si vous avez bien suivi, c'est typiquement un tableau ! Nous n'avons même pas à gérer la taille du tableau ! C'est pas beau ça ! :) Nous mettons simplement la valeur la plus récente au début du tableau, et toutes les valeurs se décaleront au fur et à mesure. Il faut donc déclarer un tableau au niveau global du fichier sans la taille, et le remplir, en général, que la ou les premières cases. Il faudra aussi préciser à l'initialisation de l'indicateur que ce tableau déclaré dans le programme est le buffer (mémoire tampon) des valeurs de la courbe grâce à la fonction SetIndexBuffer(). Cette fonction prend deux paramètres: l'index de la ligne à tracer (elles sont numérotées de 0 à 7 car il ne peut y en avoir que huit maximum) et le tableau créé pour servir de tampon. Les deux choses à faire sont: déclarer un tableau sans indication de taille qui sera le tampon et indiquer avec la fonction SetIndexBuffer() que ce tableau est le tampon pour la courbe numéro 0.


   double buffer[];
   SetIndexBuffer(0, buffer);


Les paramètres des indicateurs:

Indiquer juste le tampon des données à MetaTrader 4 n'est pas suffisant, il lui faut d'autres renseignements. Par exemple le nombre de signaux à tracer (courbes), et comment les tracer (courbe de ligne brisée ou histogramme, ou section, ou zigzag etc.). Il faut aussi indiquer le décalage par rapport au temps réel (on peut tracer en décalé temporellement), où on commence le traçage, le nom court de l'indicateur, et la précision du calcul en nombre de décimales. Il en existe d'autres, mais on va s'arrêter sur celles-là. Je vous donne le tout en code MQL4 car les noms des fonctions qui réalisent cela sont explicites sachant que "shift", c'est le décalage et "digits" ce sont les chiffres significatifs de la précision.

   SetIndexStyle(0,DRAW_LINE);
   SetIndexShift(0,shift);
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
   IndicatorShortName("TM");
   SetIndexDrawBegin(0,0);

Dans ce code: "TM" sont les initiales de "Taux Moyen", c'est le nom court que je donne à l'indicateur. 'shift' est une variable qui contient le décalage sous forme de nombre entier (0 par défaut). Cette variable est déclarée comme externe avec le mot-clef extern, ce qui signifie qu'elle devient un paramètre ajustable du programme lorsqu'on va le démarrer en le glissant sur le graphique d'un cours. Ce paramètre s'ajustera dans un onglet de la fenêtre qui s'ouvre lors du lancement de l'expert ou indicateur.

   extern shift = 0;

Ensuite, dans ce même code, pour obtenir le nombre de décimales servant à la précision des calculs, on fait appel à la fonction MarketInfo() qui donne le nombre de décimales fournies par le broker (MODE_DIGITS) pour la paire sur laquelle l'indicateur a été lancé (Symbol()). Au final on indique que le dessin du signal numéro 0 commence à l'indice 0 du tableau tampon. Les tableaux étant inversé: plus l'indice grandit et plus on remonte dans l'historique. L'indice zéro étant celui du chandelier en cours. L'indice du chandelier complètement terminé et le plus récent est le 1. C'est bien joli tout ça, mais il y a des informations supplémentaires à indiquer et une aurte fonction à connaître. Ces informations sont: où dessiner la ou les courbes (dans la fenêtre principale ou une autre), combien de buffers sont à réserver (un par signal,  autrement appelé courbe, et huit maximum) et quelles sont les couleurs des courbes.

   #property indicator_chart_window
   #property indicator_buffers 1
   #property indicator_color1 Aqua

Ces lignes ne sont pas du code, mais des instructions pour le préprocesseur car elles commencent par le signe dièse. Et c'est pour ça qu'il n'y a pas de point-virgule à la fin de chaque ligne. MetaTrader saura ce que ces lignes veulent dire. La dernière fonction à voir est celle-ci: IndicatorCounted(). Cette fonction nous donne le nombre de chandeliers qui n'ont pas changé depuis la dernière fois que l'indicateur a été lancé. Il faut l'utiliser pour éviter à MetaTrader de faire trop de calculs inutiles. Les tampons contiennent toujours les valeurs, et il est inutile de tout recalculer si ça n'a pas changé. On récupère donc ce nombre pour savoir le nombre de chandeliers qu'il ne faut pas refaire. Et ce nombre est sûrement différent du nombre fourni par la variable prédéfinie Bars qui est le nombre de chandeliers ou barres (bars) dans l'historique du graphique, modifiés ou non. Ça suffit largement, le compte est bon pour aujourd'hui, ça fait pas mal d'informations à digérer. Je vous le fais faire en tutoriel vidéo, puis je vous donne le code complet.



//+------------------------------------------------------------------+
//|                                              testsIndicateur.mq4 |
//|                  Copyright 2013, argent-facile-avec-robots-forex |
//|               http://argent-facile-avec-robots-forex.blogspot.fr |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, argent-facile-avec-robots-forex"
#property link   "http://argent-facile-avec-robots-forex.blogspot.fr"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Aqua

extern int shift = 0;

double buffer[];
int ancienCompteBars, nbTicksDansBar;
double sommeCours;

double obtenirCoursActuel() {
   double cours = (Bid + Ask) / 2.0;
   return(cours);
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   ancienCompteBars = IndicatorCounted();
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
   IndicatorShortName("TM");
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,buffer);
   SetIndexShift(0,shift);
   SetIndexDrawBegin(0,0);
   sommeCours = 0.0;
   nbTicksDansBar = 0;
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   double coursActuel = obtenirCoursActuel();
   double moyenneCours = coursActuel;
   int nbBarsActuel = IndicatorCounted();
   if(nbBarsActuel < ancienCompteBars) {
      if(nbTicksDansBar > 0) { moyenneCours = sommeCours / nbTicksDansBar; }
      buffer[1] = moyenneCours;
      sommeCours = 0.0;
      nbTicksDansBar = 0;
      ancienCompteBars = nbBarsActuel;
   }
   sommeCours += coursActuel;
   nbTicksDansBar++;
   buffer[0] = sommeCours / nbTicksDansBar;
   return(0);
  }
//+------------------------------------------------------------------+  

Nous allons améliorer cet indicateur dès le prochain post. J'espère que celui-ci vous a été profitable, à la prochaine ;)

4 commentaires:

  1. bonjour,

    merci pour ce tuto.
    Mais comment fait-on si on veut dessiner 2 coubres ?
    merci

    RépondreSupprimer
    Réponses
    1. Bonjour,
      De rien =)
      Pour une deuxième courbe on doit ajouter un deuxième buffer, le déclarer dans les directives du début et le remplir !

      Supprimer
    2. mettre 2 pour la propriété indicator_buffer,
      donner la couleur avec indicator_color2
      déclarer un autre buffer2[]
      dans init(): refaire toutes les initialisation de buffer avec le numéro 1
      voilà

      Supprimer
  2. bonjour,

    merci pour ce tuto.
    Mais comment fait-on si on veut dessiner 2 coubres ?
    merci

    RépondreSupprimer