vendredi 28 mars 2014

Test du fichier include d'outils pour les indicateurs

Dans le post précédent nous avons créé un fichier include avec des fonctions d'initialisation d'indicateur et d'index. Le résultat de ces fonctions ne peut pas être analysé par un programme, d'ailleurs les fonctions ne retournent rien, elles sont du type void. Le résultat ne peut être que visuel, et il faut en plus initialiser plusieurs fois l'indicateur avec des paramètres différents pour voir comment il réagit.

Une petite précision: il y a eu de gros changements dans MQL4 avec une mise à jour récente. Les nouveautés seront en partie utilisées et d'autres non utilisées pour l'instant car je ne les ai pas testées. Notamment les arguments fournis à la fonction  OnCalculate()  qui font double emploi avec les variables prédéfinies du même nom mais avec une majuscule. Ces arguments sont présents pour une meilleure compatibilité avec le langage C et MQL5. L'argument &spread[] m'a étonné, alors que jusqu'à présent les spreads des périodes n'étaient pas disponibles. En réalité, il est présent, au cas où le broker les fournisse, ce qui a peu de chances de se produire. L'argument rates_total serait équivalent à Bars et l'argument prev_calculated à  IndicatorCounted() . Je mets bien ça au conditionnel car je ne connais pas la gestion interne de ces arguments par MetaTrader, notamment vis-à-vis de la gestion mémoire. Il y aurait une différence car on doit désormais retourner à la fin de nos calculs le nombre de valeurs calculées, pour que Metatrader le donne à nouveau lors de l'appel suivant dans l'argument prev_calculated. Il faudra tester tout ceci à l'avenir. Pour le moment nous utiliserons toujours les anciennes méthodes et toute l'armada très «dirty code» (code sale) des arguments ne nous servira pas. (les variables globales sont aussi du code sale, mais elles ne gênent pas la lisibilité au moins !) Nous pourrions tout simplement utiliser encore la fonction  start() , mais on va commencer à s'habituer aux nouveautés juste avec  OnCalculate() . On constate aussi, que des paramètres des indicateurs et des index peuvent être fixés par des  #property  au début du code. Cela n'empêche en rien de les déclarer à nouveau par nos fonctions d'initialisation, d'autant plus qu'ils n'y sont pas tous et que cela permet de les modifier à la volée lors de l'initialisation, ce que ne permet pas les  #property .

Un signal d'index vite fait pour remplir l'historique:


Vite fait, c'est vite dit ! Nous allons utiliser le signal d'un indicateur déjà présent dans MetaTrader. Donc dans la boucle principale de l'indicateur nous récupérons simplement la valeur d'un indicateur de moyenne mobile  iMA()  et nous la mettons dans notre tableau d'historique. Pour rappel, nous devons à chaque appel de la fonction  OnCalculate()  (on utilisait avant  start()  et on peut toujours) parcourir toutes les périodes à recalculer comme le demande MetaTrader. Le nombre de périodes total dans l'historique est donné par  Bars  et le nombre de périodes depuis le début de l'historique à ne pas recalculer est donné par  IndicatorCounted (). Donc le nombre de périodes à traiter est  Bars - IndicatorCounted()  et le numéro de la première période à traiter est alors  Bars - IndicatorCounted - 1  car la numérotation des cases du tableau est décalée d'une unité. Un schéma vaut mieux qu'un long discours:
tableau d'historique
supposons un historique de 10 périodes au total et 2 périodes déjà calculées
9876543210
Bars - 1  =  10 - 1  =  9       et       Bars - IndicatorCounted - 1  =  10 - 2 - 1  =  7
On commence bien à traiter la période n°7 qui est la première à devoir être calculée!

 Dans notre code nous calculons donc le numéro de la première période à traiter et nous commençons la boucle for à ce numéro et on la continue en décrémentant (diminuant) de 1 à chaque passage le numéro de la période. La boucle s'arrête selon les nécessités des calculs des indicateurs au n°1 ou 0. A chaque passage on récupère la valeur de la moyenne mobile et on l'affecte à la case correspondante de notre tableau, c'est tout ! Pour les besoins de calculs de cet indicateur nous ne devons pas commencer les calculs dès le début de l'historique, puisque pour faire une moyenne mobile de 12 périodes par exemples, il nous faut 12 périodes précédentes. On commence donc à  Bars-1-nbPeriodesMoyenne . Le code de l'indicateur de test est simple:
  1. Initialisation du nombre de périodes à traiter
  2. Si ce nombre est supérieur à  Bars-nbPeriodesMoyenne-1  alors fixer le début à cette valeur.
  3. Sinon fixer le début  nbPeriodesATraiter-1 
  4. Initialiser la boucle For
    1. récupérer la moyenne mobile de l'indicateur déjà existant dans MetaTrader
    2. mettre cette valeur dans notre tableau d'historique.
  5. C'est nouveau: retourner  rates_total  !
Voici le code:

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[]) {
   double moyenneMobile;
   int noPeriode, noPeriodeDebut;
   int nbPeriodeATraiter = Bars - IndicatorCounted();
   int noPeriodeLimiteCalcul = Bars - nbPeriodesMoyenne - 1;
   if(nbPeriodesATraiter>noPeriodeLimiteCalcul) {
      noPeriodeDebut = noPeriodeLimiteCalcul;
   }
   else { noPeriodeDebut = nbPeriodesATraiter - 1; }
   for(noPeriode=noPeriodeDebut ; noPeriode>=0 ; noPeriode--) {
      moyenneMobile = iMA(NULL, 0, nbPeriodesMoyenne, shift,
                           MODE_SMA, PRICE_MEDIAN, noPeriode);
      bufferMoyenne[noPeriode] = moyenneMobile;
   }
   return(rates_total);
}
Quelques commentaires: variables colorées en rouge sont des variables globales qui servent de paramètre à l'indicateur. Elles sont déclarées désormais input au début du code au lieu de extern jusqu'à la récente mise à jour du langage. Ces paramètres externes permettent de modifier des valeurs pour le programme lorsqu'on le lance sur un graphique. Il suffit de les modifier dans la fenêtre qui s'ouvre, dans l'onglet Paramètres. Autre détail, de taille ! Tous ces arguments à la fonction ! Ils font double emploi avec les variables prédéfinies, et nous ne les utilisons pas pour l'instant. Nous devons impérativement retourner cette valeur désormais. La fonction iMA nous donne la moyenne mobile, et elle a besoin de nombreux paramètres que nous expliquerons dans un post ultérieur. Cette moyenne, à peine récupérée, elle est mise dans notre buffer: C'est le seul traitement que nous faisons dans cet indicateur, car le but n'est pas de calculer une valeur, mais bien de vérifier si nos fonctions réalisent bien leur travail.

Tester l'initialisation de l'indicateur:


La fonction d'initialisation d'indicateurs effectue deux choses: fixer le nombre de décimales et donner le nom court de l'indicateur. Nous allons passer des valeurs à la fonction, en l'occurrence seulement le nom court, et vérifier que l'indicateur la prend bien en compte. Il faudra fournir ce nom en paramètre externe, c'est-à-dire fixé lors de l'initialisation de l'indicateur dans la fenêtre qui s'ouvre. Et il faudra constater le changement sur l'indicateur. Il faudra aussi vérifier que le nombre de décimales de l'indicateur est bien celui de la paire. La plupart des brokers travaillent avec 5 décimales désormais. On va donc tester sur une paire à 5 décimales très probablement et on le fera sur une paire avec le yen qui n'en a que deux ou trois.
En résumé, nous devons choisir un nom en paramètre externe de l'indicateur et vérifier qu'il apparait bien dans le menu contextuel que nous donne MetaTrader avec un clic droit sur un signal de cet indicateur. Nous devons aussi tester cet indicateur sur un paire sans le Yen et une paire avec le Yen et constater dans l'infobulle de MetaTrader lorsqu'on pointe sur le signal graphique qu'il y a 5 décimales pour une paire sans le Yen et 2 ou 3 décimales pour une paire avec le Yen.
Sans oublier la déclaration du paramètre externe nomCourtIndicateur avec sa valeur par défaut, ni oublier l'inclusion du fichier d'outils Indicateurs, la ligne de code de l'initialisation est simplement dans la fonction  OnInit() :

input string nomCourtIndicateur="indicateur-test";

#include <OutilsIndicateurs.mqh>

int OnInit() {
   initIndicateur(nomCourtIndicateur);
}
Le paramètre externe du nom court de l'indicateur en rouge est déclaré avec une valeur par défaut mais pourra être modifié à la volée lors de l'initialisation de l'indicateur voire même après. Un paramètre externe est simplement une variable que MetaTrader présente dans la fenêtre d'initialisation pour qu'on puisse la modifier quand on utlise le programme. Avec la nouvelle version du langage, elles sont déclarées en tant qu'entrées du programme (input) et non plus comme variables externes. C'est juste un changement de dénomination, ça reste la même chose. Maintenant l'avantage, c'est qu'elles sont colorées en rouge par l'éditeur.

Tester l'initialisation d'un index:


Pour initialiser un index, notre fonction transmet de nombreux paramètres à MetaTrader, dont la plupart en valeur par défaut. Nous transmettrons le numéro de l'index et le tableau qui lui sert de buffer et le simple fait que MetaTrader trace le signal suffit à confirmer que ça fonctionne car ces deux éléments sont primordiaux pour faire fonctionner l'indicateur, sans ça, pas de signal.

Nous utiliserons le décalage traditionnellement appelé shift dans Metatrader en tant que paramètre externe pour le décalage des périodes de l'indicateur par rapport à l'historique du cours. Comme ça nous pourrons le modifier et voir le décalage modifié en direct.
input int shift=0;
Concernant le début du traçage, nous allons aussi utiliser un paramètre externe pour le modifier à la volée, mais il nous faut savoir combien il y a de périodes dans l'historique car nous risquons sinon de chercher longtemps le début de l'historique. Eh oui ! il y en a beaucoup dans l'historique. Nous allons donc faire afficher à l'initialisation le nombre de périodes dans l'historique pour savoir quel nombre mettre afin de voir le début du traçage vers la fin de l'historique:
input int debutTracage=0;
Print("nombre de périodes dans l'historique: ", Bars);
Il y a ensuite le nom donné à l'index, celui-ci apparaitra dans les infobulles de MetaTrader, il suffit de lui en donner un par une constante déclarée au début que nous concatènerons pendant l'initialisation avec le nombre de périodes de calculs de la moyenne elle aussi en paramètre externe (concaténer signifie mettre les chaines de caractères bout à bout):
input int nbPeriodesMoyenne=12;

string NOM_INDEX = "moy-mobile-";

string nomIndex;

dans OnInit() nomIndex = StringConcatenate(NOM_INDEX, nbPeriodesMoyenne);
Puis vient le tour des caractéristiques de traçage, dont la couleur. Première chose, ces caractéristiques sont aussi définies de manière statique par des  #property  au début du code, et c'est l'assitant de création de nouveau fichier qui nous l'a mis. Le problème, c'est qu'avec ces définitions, statiques, nos tentatives de définitions des caractéristiques de manière dynamique dans le code échoueront et même il n'y aura pas de traçage. Nous devons donc supprimer ces définitions statiques car nous les définissons de manière dynamique avec notre fonction d'initialisation d'index. Dans l'appel de la fonction d'initialisation d'index, nous mettons simplement le nom de la couleur nouvellement défini dans la mise à jour du langage: les noms de couleur commencent tous par le préfixe «clr». Ici nous mettons  clrBlue .

La même chose pour le style, le mode de traçage et l'épaisseur du trait qu'on définit en paramètres externes histoire de les changer un peu pour voir le résultat.
input int styleDeTracage=STYLE_SOLID;
input int modeDeTracage=DRAW_LINE;
input int epaisseurDuTrait=EMPTY;

Dernier paramètre et c'est celui qui a le moins de chances d'être modifié (c'est pour ça qu'il est placé en dernier): la valeur signifiant «pas de valeur calculée». C'est la valeur vide de l'indicateur. Quand elle est présente dans une case du tableau d'historique de l'index, elle signifie pour MetaTrader qu'aucune valeur n'est calculée pour cette période, et MetaTrader ne trace rien à cette période. Normalement on y place la valeur  EMPTY_VALUE  mais on peut la modifier. Nous la mettons en paramètre externe, avec sa valeur par défaut, mais lorsque l'indicateur fonctionnera on y placera une valeur particulière qui est utilisée sur le moment dans l'indicateur pour voir que MetaTrader ne trace plus lorsqu'il y a cette valeur. (voir la vidéo pour bien comprendre)
input double valeurNonCalculee=EMPTY_VALUE;

Le tutoriel et le code de test:




//+------------------------------------------------------------------+
//|                                        testsOutilsIndicateurs.mq4|
//|                   Copyright 2014, argent-facile-avec-robots-forex|
//|                     http://argent-facile-robots-forex.blogspot.fr|
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, argent-facile-avec-robots-forex"
#property link   "http://argent-facile-avec-robots-forex.blogspot.fr"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//--plot moyenne
//#property indicator_label1 "moyenne"
//#property indicator_type2 DRAW_LINE
//#property indicator_color1 clrRed
//#property indicator_style1 STYLE_SOLID
//#property indicator_witdh1 1

//+------------------------------------------------------------------+
//| Tampons d'historique des index                                   |
//+------------------------------------------------------------------+

double bufferMoyenne[];

//+------------------------------------------------------------------+
//| Paramètres externes                                              |
//+------------------------------------------------------------------+

input string nomCourtIndicateur="indicateur-test";
input int shift=0;
input int debutTracage=0;
input int nbPeriodesMoyenne=12;
input int styleDeTracage=STYLE_SOLID;
input int modeDeTracage=DRAW_LINE;
input int epaisseurDuTrait=EMPTY;
input double valeurNonCalculee=EMPTY_VALUE;

//+------------------------------------------------------------------+
//| Includes                                                         |
//+------------------------------------------------------------------+

#include <OutilsIndicateurs.mqh>

//+------------------------------------------------------------------+
//| Constantes globales                                              |
//+------------------------------------------------------------------+

string NOM_INDEX = "moy-mobile-";

//+------------------------------------------------------------------+
//| Variables globales                                               |
//+------------------------------------------------------------------+

string nomIndex;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

int OnInit() {
   nomIndex = StringConcatenate(NOM_INDEX, nbPeriodesMoyenne);
   Print("nombre de périodes dans l'historique: ", Bars);
   initIndicateur(nomCourtIndicateur);
   initIndex(0, bufferMoyenne, shift, debutDuTracage, nomIndex, clrBlue,
            styleDeTracage, modeDeTracage, epaisseurDuTrait, valeurNonCalculee);
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+

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[]) {
   double moyenneMobile;
   int noPeriode, noPeriodeDebut;
   int nbPeriodeATraiter = Bars - IndicatorCounted();
   int noPeriodeLimiteCalcul = Bars - nbPeriodesMoyenne - 1;
   if(nbPeriodesATraiter>noPeriodeLimiteCalcul) {
      noPeriodeDebut = noPeriodeLimiteCalcul;
   }
   else { noPeriodeDebut = nbPeriodesATraiter - 1; }
   for(noPeriode=noPeriodeDebut ; noPeriode>=0 ; noPeriode--) {
      moyenneMobile = iMA(NULL, 0, nbPeriodesMoyenne, shift,
                           MODE_SMA, PRICE_MEDIAN, noPeriode);
      bufferMoyenne[noPeriode] = moyenneMobile;
   }
   return(rates_total);
}

//+------------------------------------------------------------------+

vendredi 7 mars 2014

Un fichier include .mqh d'outils pour les indicateurs

Après un fichier de fonctions pour les calculs temporels et les calculs sur les cotations, que nous étofferons par la suite, nous allons faire un fichier pour nous faciliter la tache lors de la création d'indicateurs. Il n'y aura que deux fonctions pour l'instant, très simples algorithmiquement, elles nous soulageront des nombreuses lignes de codes à répéter pour créer des indicateurs. Et les valeurs par défaut nous éviteront de les préciser à chaque fois.

Ce que fait un indicateur:


Un indicateur va chercher les valeurs du cours dans l'historique et fait des calculs pour donner un résultat chiffré par période. Ce résultat doit être stocké dans un historique spécialement créé pour l'indicateur, et MetaTrader se sert de cet historique pour tracer une courbe ou un histogramme correspondant à l'évolution de notre valeur calculée. La courbe ainsi créée se rajoute au cours sur le graphique pour nous donner l'évolution de notre valeur. C'est cette valeur qui va nous donner des indications pour trader, ou bien qui va servir à des experts advisors pour prendre des décisions.

Les initialisations nécessaires


L'historique de cet indicateur est simplement un tableau, dont la taille est gérée par MetaTrader. Nous n'avons qu'à déclarer son existence et le remplir. MetaTrader doit, pour effectuer ce travail, être averti de certaines choses. Pour l'indicateur globalement:
  • Donner un nom à l'indicateur.
  • Fixer la précision de l'indicateur: le nombre de décimales.
Dans chaque indicateur il peut y avoir jusqu'à huit valeurs basées sur huit calculs différents avec chacune leur historique. Chaque valeur calculée avec son historique est appelée un index. Pour chacun des huit index possibles, il faut:
  • Préciser le tableau à utiliser pour l'historique.
  • Fixer le décalage entre les périodes de l'indicateur et celle du cours.
  • Fixer le style graphique pour le traçage de la valeur.
  • Préciser la période de début de traçage.
  • Préciser le label à afficher pour l'index.
  • Préciser la valeur signifiant aucune donnée pour la période.

Une fonction d'initialisation de l'indicateur


Nous devons préciser à MetaTrader le nombre de décimales que l'indicateur doit fournir, en général, le même nombre de décimales que celui de la paire sur laquelle il s'exécute. Nous utilisons donc la fonction  MarketInfo()  qui va nous donner cette information grâce aux paramètres  Symbol()  qui donne le nom de la paire de devises courante. (sur laquelle on est) et  MODE_DIGITS  qui est un code signifiant à la fonction  MarketInfo()  qu'on veut le nombre de décimales (digits). Et ce nombre de décimales est fourni à la fonction  IndicatorDigits()  qui va le fixer pour notre indicateur.

string paireCourante = Symbol();
int nombreDecimales = MarketInfo(paireCourante, MODE_DIGITS);
IndicatorDigits(nombreDecimales);

On doit également donner un nom court à l'indicateur, utilisable par MetaTrader notamment pour l'afficher dans les graphiques et pour être appelé par un expert advisor. Ce nom on le donne à la fonction IndicatorShortName() qui va le fixer pour cet indicateur.

IndicatorShortName(nomCourt);

La fonction d'initialisation de l'indicateur reçoit alors juste le nom court de l'indicateur et exécute les lignes de code précédentes. Elle ne retourne aucune valeur, elle est donc du type void:

void initIndicateur(string nomCourt) {
   string paireCourante = Symbol();
   int nombreDecimales = MarketInfo(paireCourante, MODE_DIGITS);
   IndicatorDigits(nombreDecimales);
   IndicatorShortName(nomCourt);
}

Une fonction d'initialisation d'un index


L'initialisation d'un index doit indiquer le numéro de l'index sur les huit possibles: de 0 à 7. Il faut donc transmettre ce numéro en argument à la fonction et le fournir à toutes les fonctions que nous allons appeler pour paramétrer cet index.
Nous devons déclarer le tableau qui nous sert d'historique pour l'indicateur, il y a en au moins un. Nous pouvons en créer jusqu'à huit par indicateur. Pour ces déclarations, nous ne précisons pas la taille du tableau, MetaTrader s'en chargera. Cette déclaration de tableau sera faite manuellement pour chaque indicateur, car nous ne pouvons pas retourner un tableau avec une fonction, donc pas de déclaration de ces tableaux dans une fonction. Nous devrons par contre passer le tableau à la fonction et par référence (pas de copie) pour qu'elle puisse passer cette référence à MetaTrader qui saura alors quel tableau utiliser pour l'historique. C'est la fonction SetIndexBuffer() qui transmet la référence.

SetIndexBuffer(noIndex, tamponHistorique);

Nous devons ensuite régler le décalage de l'indicateur par rapport aux périodes des courts. C'est-à-dire le décalage voulu entre la valeur calculée pour une période et la période qu'elle représente. Normalement il n'y en a pas, on calcule une valeur pour une période et cette valeur ressort quand on demande cette période précisément. Mais on peut vouloir décaler toutes les valeurs de chaque période pour avancer ou reculer le signal par rapport aux cotations de la paire. Ce décalage est fourni en argument, sans valeur par défaut, car elle peut être modifiée à chaque initialisation de l'indicateur. On doit donc la transmettre à chaque fois:

SetIndexShift(noIndex, decalagePeriodes);

Le calcul d'une valeur d'index pour une période, demande presque tout le temps d'utiliser les cours antérieurs à la période calculée. Or pour la toute première période et les quelques suivantes de l'historique, il n'y a pas suffisamment de cotations antérieures pour faire ce calcul. On ne doit donc pas tracer l'indicateur pour ces toutes premières périodes car s'il on y calcule des valeurs, elles ne seront pas bonnes par manque de cotations antérieures. On peut préciser à MetaTrader de ne pas tracer l'index pour un certain nombre de périodes au début de l'historique:

SetIndexDrawBegin(noIndex, debutTracage);

Pour afficher le nom de l'index lorsqu'on pointe dessus avec la souris, ou pour avoir un intitulé dans la fenêtre de description, on peut assigner un label à un index:

SetIndexLabel(noIndex, intitule);

Ensuite, on peut, et c'est conseillé de donner un style de traçage à l'index. On peut modifier
  • le mode (ligne, section, histogramme, flèches, zigzag, remplissage ou aucun traçage).
  • le style du tracé (continu, traits interrompus, points, trait-point et trait-point-point).
  • l'épaisseur du trait en pixel (de 1 à 5) ou EMPTY pour aucun changement d'épaisseur.
  • la couleur (clrNONE pour aucun changement de couleur).

SetIndexStyle(noIndex, modeTracage, style, epaisseur, couleur);

Pour finir, il faut indiquer la valeur vide à utiliser pour signaler à MetaTrader qu'il n'y a pas de valeur calculée dans une période, lui indiquant ainsi qu'il ne faut pas tracer pour cette période. Cette valeur vide par défaut pour chaque index est  EMPTY_VALUE . On la reçoit en argument avec cette valeur par défaut.

SetIndexEmptyValue(noIndex, valeurVide);

La fonction d'initialisation de l'index reçoit tous ces paramètres et exécute les lignes de code précédentes. Elle ne retourne aucune valeur, elle est donc du type void:

void initIndex(int noIndex, double &tamponHistorique[], int decalagePeriodes,
               int debutTracage=0, string intitule="",
               color couleur=clrNONE, int style=STYLE_SOLID,
               int modeTracage=DRAW_LINE, int epaisseur=EMPTY,
               double valeurVide=EMPTY_VALUE) {
   SetIndexBuffer(noIndex, tamponHistorique);
   SetIndexShift(noIndex, decalagePeriodes);
   SetIndexDrawBegin(noIndex, debutTracage);
   SetIndexLabel(noIndex, intitule);
   SetIndexStyle(noIndex, modeTracage, style, epaisseur, couleur);
   SetIndexEmptyValue(noIndex, valeurVide);
}

Le tutoriel vidéo et le code complet de l'include




Voici le fichier include «OutilsIndicateurs.mqh» que nous créons dans sa première version:

//+------------------------------------------------------------------+
//|                                            OutilsIndicateurs.mqh |
//|                  Copyright 2014, argent-facile-avec-robots-forex |
//|               http://argent-facile-avec-robots-forex.blogspot.fr |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, argent-facile-avec-robots-forex"
#property  link  "http://argent-facile-avec-robots-forex.blogspot.fr"
#property  strict
//+------------------------------------------------------------------+
//| Defines                                                          |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Constantes                                                       |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Fonctions d'initialisation                                       |
//+------------------------------------------------------------------+

void initIndicateur(string nomCourt) {
   string paireCourante = Symbol();
   int nombreDecimales = MarketInfo(paireCourante, MODE_DIGITS);
   IndicatorDigits(nombreDecimales);
   IndicatorShortName(nomCourt);
}

void initIndex(int noIndex, double &tamponHistorique[], int decalagePeriodes,
               int debutTracage=0, string intitule="",
               color couleur=clrNONE, int style=STYLE_SOLID,
               int modeTracage=DRAW_LINE, int epaisseur=EMPTY,
               double valeurVide=EMPTY_VALUE) {
   SetIndexBuffer(noIndex, tamponHistorique);
   SetIndexShift(noIndex, decalagePeriodes);
   SetIndexDrawBegin(noIndex, debutTracage);
   SetIndexLabel(noIndex, intitule);
   SetIndexStyle(noIndex, modeTracage, style, epaisseur, couleur);
   SetIndexEmptyValue(noIndex, valeurVide);
}

//+------------------------------------------------------------------+
Et voilà de quoi nous soulager pour programmer des indicateurs ! Nous allons évidemment tester ce code dès le prochain post pour garantir que le tout fonctionne !