English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Comment écrire un indicateur à partir d'un autre indicateur

Comment écrire un indicateur à partir d'un autre indicateur

MetaTrader 5Exemples | 22 décembre 2021, 16:32
409 0
Dmitry Fedoseev
Dmitry Fedoseev

Introduction

Dans MQL5, en plus de la création d'un nouvel indicateur personnalisé à partir de zéro, comme décrit dans le « MQL5 : Créez votre propre indicateur », vous pouvez en écrire un à partir d'un autre indicateur, intégré au terminal client ou personnalisé. Il y a deux manières : la première consiste à améliorer un indicateur, ajouter de nouveaux calculs et tracés (cette variante s'applique uniquement aux indicateurs personnalisés qui ont du code source ouvert), la deuxième consiste à utiliser un indicateur intégré au terminal ou à utiliser un indicateur personnalisé existant via les fonctions iCustom() ou IndicatorCreate().

Première manière. Ajout d'un tracé

Considérons en détail ce mode de création d’un indicateur sur l'exemple d'amélioration de l'indicateur True_Strength_Index_ver3 à partir de l’article « Application d’un indicateur sur un autre ». Ajoutons à l'indicateur une ligne de signal avec possibilité de choisir le type et la période de lissage. L'ensemble du processus se compose de 8 étapes.

1. Faire une copie du fichier

Ouvrez l'indicateur True_Strength_Index_ver3 dans MetaEditor et enregistrez-le sous un nouveau nom, par exemple, STI. Le nouveau fichier doit être enregistré dans le répertoire MQL5/Indicators du dossier racine du terminal.

2. Modification des propriétés de l'indicateur

Recherchez les propriétés indicator_buffers et indicator_plots dans le code de l'indicateur. La propriété indicator_buffers détermine le nombre total de tampons d'indicateur utilisés dans l'indicateur, la propriété indicator_plots - le nombre de tampons affichés sur un graphique. Actuellement, huit tampons sont utilisés dans l'indicateur ; l'un d'eux est affiché sur un graphique. Nous devons ajouter un autre tampon qui devrait être affiché sur un graphique. Augmenter les valeurs d'indicator_buffers et indicator_plots d'une unité.

#property indicator_buffers 8 
#property indicator_plots 2

3. Détermination des propriétés d'affichage du nouveau tampon

Configuration des propriétés d'affichage du nouveau tampon. Utilisez le code déjà préparé à partir de cet indicateur. A l'aide de la souris, copiez tout le code qui détermine les propriétés d'affichage de la première ligne de l'indicateur.

//---- plot TSI
#property indicator_label1 "TSI"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Blue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

Insérez-le sous les propriétés de la première ligne et modifiez-le.

//---- plot TSI Signal
#property indicator_label2 "TSISignal" // Line name that is displayed in a pop up help when the mouse cursor is put over the line
#property indicator_type2 DRAW_LINE    // Type of buffer 
#property indicator_color2 Red         // Color of the line
#property indicator_style2 STYLE_SOLID // Style
#property indicator_width2 1           // Thickness of the line

Tout d'abord, changez le nombre de propriétés de 1 à 2 car c'est la propriété du deuxième tampon. Remplacez la propriété indicator_label2 par TSISignal - c'est le nom de la ligne qui s'affiche dans une aide contextuelle lorsque le curseur de la souris est placé sur la ligne ainsi que celui affiché dans la fenêtre de données. La propriété indicator_type2 doit être laissée invariable, le tampon doit être affiché sous forme de ligne. Remplacez la propriété indicator_color2 par Red - la nouvelle ligne aura la couleur rouge. La propriété indicator_style2 reste la même - la ligne de signal est continue tout comme la ligne principale. La propriété indicator_width2 doit également rester la même - la nouvelle ligne aura une épaisseur de 1 pixel.

4. Déclaration de variables externes

Les variables externes modifiables via l'indicateur (lignes commençant par le mot « entrée ») sont situées sous les propriétés des lignes du code. La ligne de signal doit également avoir ses paramètres - période et type de lissage.

Déclarez une variable externe de type int avec la valeur 5 et nommez-la « sp » (période de lissage), et une variable de type ENUM_MA_METHOD nommée « sm » (méthode de lissage) qui a la valeur MODE_EMA (la ligne de signal aura la période de lissage 5 et le type de lissage exponentiel par défaut). Maintenant, la section du code qui contient les variables externes se présente comme suit :

input int r=25;
input int s=13;
input int sp=5;
input ENUM_MA_METHOD sm=MODE_EMA;

5. Déclarer un tableau pour un nouveau tampon

Déclarons un tableau qui sera utilisé par le tampon d’indicateur. Recherchez la fonction OnInit() dans le code et localisez les appels de la fonction SetIndexBuffer() pour vous guider à travers les tableaux déjà existants de tampons d'indicateur dans l'indicateur. Dans l'indicateur True_Strength_Index_ver3, ces tableaux sont TSIBuffer, MTMBuffer, AbsMTMBuffer, EMA_MTMBuffer, EMA2_MTMBuffer, EMA_AbsMTMBuffer, EMA2_AbsMTMBuffer.

La fonction SetIndexBuffer() du tableau TSIBuffer est appelée avec le paramètre INDICATOR_DATA, cela signifie que le tampon est affiché sur un graphique. Tous les autres tableaux sont appelés avec le paramètre INDICATOR_CALCULATIONS. Cela signifie que les tableaux sont auxiliaires et sont utilisés pour des calculs intermédiaires.

Le nouveau tampon doit être affiché sur un graphique, déclarons-le donc après la déclaration du tableau TSIBuffer pour conserver l'ordre logique et pour une orientation plus facile dans le code en cas d'amélioration supplémentaire de l'indicateur.

Ainsi, nous déclarons d'abord deux tableaux pour les tampons qui sont affichés sur un graphique, puis des tableaux pour les tampons qui sont utilisés pour les calculs intermédiaires.

//--- indicator buffers
double TSIBuffer[];
double TSISigBuffer[]; // Array for new buffer of the signal line
double MTMBuffer[];
double AbsMTMBuffer[];
double EMA_MTMBuffer[];
double EMA2_MTMBuffer[];
double EMA_AbsMTMBuffer[];
double EMA2_AbsMTMBuffer[]; 

6. Associer un tableau à un tampon

C'est maintenant une étape assez importante qui nécessite une attention et un soin extrêmes - l'association d'un tableau avec un tampon d'indicateur. L'association est effectuée à l'aide de la fonction SetIndexBuffer(). Le premier paramètre de l'appel de fonction est l'indice du tableau ; le deuxième est le nom du tableau ; le troisième - l’identifiant qui indique le but du tampon. Les tampons sont situés dans l'onglet « Couleurs » de la fenêtre des propriétés de l'indicateur en fonction de l'indice (le premier paramètre), dans le même ordre qu'ils sont dessinés sur un graphique, d'abord le tampon 0, puis le tampon 1 au-dessus de lui, etc.

Il n'est pas nécessaire que la fonction SetIndexBuffer() soit appelée séquentiellement pour les tampons d'indices 0, 1, 2..., néanmoins, gardons l'ordre des appels des fonctions SetIndexBuffer(). Exécutez l'appel du tableau TSISigBuffer après avoir appelé la fonction pour le tableau TSIBuffer. Le tampon de la ligne principale (le tableau TSIBuffer) a l'indice 0, cela signifie que le tampon suivant (le tableau TSISigBuffer) doit avoir l'indice 1.

Le troisième paramètre d'appel de la fonction SetIndexBuffer() pour le tableau TSISigBuffer est la constante INDICATOR_DATA (le tampon est affiché sur un graphique).

SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);

Ré-indexez le reste des tampons pour que la fonction SetIndexBuffer() soit appelée avec une valeur séquentiellement augmentée du premier paramètre.

SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);
SetIndexBuffer(2,MTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,AbsMTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,EMA_MTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(5,EMA2_MTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(6,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(7,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);

Pour cette situation spécifique, il est recommandé de conserver la séquence d'appel de la fonction SetIndexBufer() conformément aux indices émergents. Ainsi, en cas d'améliorations supplémentaires, cela demandera moins d'attention et de travail.

Nous avons maintenant huit tampons, deux d'entre eux sont affichés sur un graphique. Assurez-vous que les mêmes valeurs sont spécifiées dans les propriétés des indicateurs indicator_buffers et indicator_plots (étape 2).

7. Calcul des valeurs de la ligne de signal

La ligne de signal représente une moyenne mobile tirée sur les données de la ligne principale de l'indicateur. Nous n'avons pas besoin de faire de calculs pour cela ; la livraison du terminal client comprend une bibliothèque pour le calcul des moyennes mobiles sur un tableau d'informations (fichier MovingAverages.mqh). Soit dit en passant, il est déjà inclus dans le code indicateur (ligne 14) :

#include <MovingAverages.mqh>

Il ne reste plus qu'à utiliser ses fonctionnalités.

Dans la fonction OnCalculate() recherchez un point où les calculs de la ligne principale de l'indicateur sont terminés (le tableau TSIBuffer). Utilisons la fonction de recherche ; sélectionner le nom du tableau TSIBuffer, par exemple, dans la partie du code où il est déclaré (fig. 1). Exécutez ensuite la commande « Menu principal » - « Modifier » - « Rechercher et remplacer » - « Rechercher » ou utilisez la combinaison de touches Ctrl+F


Fig. 1. Nom sélectionné du tableau.

Le mot « TSIBuffer » sera déjà tapé dans le champ « Recherche » de la fenêtre « Recherche » ouverte. Sélectionnez « Up » dans la section « Direction ». Maintenant, lorsque la fenêtre « Find » est ouverte, placez le curseur juste après la fonction OnCalculate(), appuyez une fois sur le bouton « Find Next » et vous trouverez l'endroit où les calculs du tableau TSIBuffer se terminent nettement. Les calculs sont effectués dans la boucle « for ». Nous ajouterons le code de calcul de la ligne de signal juste après cette boucle (fig. 2).

Dernière localisation de calcul de la valeur TSIBuffer (flèche rouge). Le cycle où les calculs sont effectués est marqué par le cadre rouge.
Fig. 2. Dernière localisation de calcul de la valeur TSIBuffer (flèche rouge). Le cycle où les calculs sont effectués est marqué par le cadre rouge.

Les fonctions de calcul des quatre principaux types de moyennes mobiles sont incluses dans la bibliothèque MovingAverages.mqh :

  • pour le type simple - SimpleMAOnBuffer(),
  • pour le type exponentiel - ExponentialMAOnBuffer(),
  • pour le linéaire pondéré - LinearWeightedMAOnBuffer(),
  • pour le type affiné - SmoothedMAOnBuffer().

Toutes ces fonctions ont la même gamme de paramètres : 

const int rates_total, const int prev_calculated, const int begin, const int period, const double& price[],double& buffer[]

Le paramètre price[] de la fonction détermine un tableau avec les données initiales sur lesquelles le calcul d'une moyenne mobile sera effectué. Le paramètre tampon est le tableau qui stockera les valeurs de la moyenne mobile. Les paramètres rates_total et prev_calculated sont les mêmes que les paramètres rates_total et prev_calculated de la fonction onCalculate(), ils déterminent la taille du tableau price[] et le nombre d'éléments déjà traités du tableau. Le paramètre begin est l'indice d'un élément du tableau à partir duquel les données importantes commencent. 

Compte tenu des particularités des algorithmes de calcul des moyennes mobiles dans la bibliothèque MovingAverages.mqh (ces fonctionnalités ne sont pas pertinentes au regard du sujet de cet article), nous avons besoin d'une approche prudente pour définir le paramètre begin.

Ce paramètre ne doit en aucun cas être défini sur un élément du tableau antérieur à celui à partir duquel les valeurs des données sources commencent (le tableau TSIBuffer). Il est permis de spécifier postérieurement un élément, s'il ne conduit pas à des erreurs de calcul.

Pour déterminer une valeur acceptable de begin, faites attention aux paramètres for cycle, où les valeurs du tableau TSIBuffer sont calculées - le cycle commence à partir de la valeur de la variable start. Nous devons connaître la valeur de la variable start qu'elle avait lors du premier calcul de l'indicateur (lorsque la valeur prev_calculated est égale à 0). La valeur de la variable « start » est calculée juste avant le cycle, lorsque prev_calculated=0 ; le calcul est effectué à l'aide de la formule suivante :

start=begin+r+s-1;

La valeur de la variable begin qui est transmise à la fonction de calcul des moyennes mobiles doit être égale à cette valeur.

Après la boucle de calcul du tableau TSIBuffer, déclarer la variable begin2 et lui attribuer la valeur begin+r+s-1.

int begin2=begin+r+s-1; 

Pour offrir la possibilité d'utiliser différentes fonctions de lissage selon la valeur du paramètre externe « sm », utilisez l'opérateur switch. Pour chaque variante de valeur de la variable sm, écrivez l'appel de la fonction correspondante.

switch(sm)
  {
   case MODE_EMA:
      ExponentialMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
   case MODE_LWMA:
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
   case MODE_SMA:
      SimpleMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
   case MODE_SMMA:
      SmoothedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
  }

Après cela, nous pouvons voir l'indicateur avec la ligne de signal. Appuyez sur le bouton « Compiler », ouvrez le terminal client et attachez l'indicateur à un graphique (fig. 3).



Fig. 3. Indicator TSIs, bleu - main line, rouge - new, ligne de signal.

8. Interruption au commencement du tracé du tampon

Si vous faites défiler un graphique avec l'indicateur vers le bord gauche, vous verrez que l'indicateur trace des lignes dans la partie pour laquelle les valeurs n'ont pas été calculées. Ce n'est pas beau (fig. 4).



Fig. 4. Tracé de l'indicateur dans la partie où le calcul n'a pas été effectué. 

À l'aide de la fonction PlotIndexSetInteger() qui est appelée avec l'identificateur PLOT_DRAW_BEGIN, déterminez le nombre de premières barres où le tampon n'est pas tracé. L'appel de la fonction doit être effectué à partir de la fonction OnInit() de l'indicateur. Ajoutez l'appel de la fonction à la fin-même de OnInit(), mais avant l'appel de return(0), bien entendu.

PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,r+s+sp);

Appuyez à nouveau sur le bouton « Compiler » pour avoir le bon début du tracé de l'indicateur (fig. 5).  



Fig. 5. Début correct du tracé de l'indicateur. 

Deuxième manière. Créer un nouvel indicateur en superposition d’un qui existe déjà


Nous allons considérer ce mode à l'aide d'un exemple de création d'un indicateur de convergence et de divergence des lignes principales et de signal de l'indicateur STI. L'indicateur sera tracé sous forme d'histogramme et aura deux couleurs comme les indicateurs AO, AC. Si la valeur de l'indicateur augmente, l'histogramme sera coloré en vert ; s'il diminue, l'histogramme sera coloré en rouge. Comme déjà mentionné ci-dessus dans l'introduction, pour faire référence à un autre indicateur, vous pouvez utiliser la fonction iCustom() ou IndicatorCreate(). Dans un premier temps, examinons la création d'un indicateur à l'aide de la fonction iCustom().

Création d'un indicateur à l'aide de la fonction iCustom()


1. Création d'un nouvel indicateur

Créons un nouvel indicateur. Pour créer un nouvel indicateur dans MetaEditor, vous devez exécuter la commande « Menu principal » - « Fichier » - « Nouveau » - « Indicateur personnalisé » ou appuyez sur la combinaison de touches « Ctrl+N ». Dans le champ « Nom » de la fenêtre affichée, spécifiez le nom du nouvel indicateur - TSIsCDiCust, puis appuyez sur le bouton « Ajouter ». Ajoutez un paramètre externe, son nom n'est pas aussi important que la détermination partielle des paramètres externes dans le code ; en outre, il sera plus facile de copier tous les paramètres externes de l'indicateur STI (fig. 6).


Première étape de création d'un indicateur personnalisé dans l'assistant.
Fig. 6. Première étape de création d'un indicateur personnalisé dans l'assistant.

Appuyez sur le bouton « Suivant ».

Dans la fenêtre suivante, spécifiez que l'indicateur sera tracé dans une fenêtre séparée. Se garder de définir de minimum et de maximum. Appuyez sur le bouton « Ajouter » et un nouveau tampon apparaîtra dans la liste des tampons indicateurs ; spécifiez son nom - TSIsCD (il sera affiché dans une aide contextuelle si vous placez le curseur de la souris sur la ligne d’indicateur et dans la fenêtre de données) et son type - Histogramme des couleurs.

Après cela, plusieurs exemples de couleur apparaîtront dans le champ « Couleur ». Spécifiez la couleur verte pour le premier exemple, la couleur rouge pour le second, et laissez les autres invariables. Ajoutez deux autres tampons nommés Tsi et TsiSignal, ils seront utilisés pour recevoir et stocker les valeurs de l'indicateur TSI (fig. 7).


Deuxième étape de création d'un indicateur personnalisé dans l'assistant. 
Fig. 7. Deuxième étape de création d'un indicateur personnalisé dans l'assistant.

Appuyez sur le bouton « Terminer » et le modèle du nouvel indicateur sera ouvert dans MetaEditor.

2. Modification des propriétés de l'indicateur et des tampons d'indicateur

A l'étape 1, nous avons déterminé 3 tampons ; cependant, la valeur de #property indicator_buffers est égale à 4. Le fait est qu'un histogramme coloré utilise deux tampons - l'un est affiché sur un graphique et est destiné aux valeurs d'un indicateur ; et le second est destiné à déterminer la couleur d'affichage du premier tampon. Laissez la valeur #property indicator_buffers invariable. Remplacez la valeur #property indicator_plots par 1 - un seul tampon doit être affiché sur un graphique.

Les tampons Tsi et TsiSignal ne doivent pas être affichés sur un graphique, c'est pourquoi supprimez toutes leurs propriétés (toutes les propriétés d'indicateur qui se terminent par 2 et 3).

//--- plot Tsi
#property indicator_label2 "Tsi"
#property indicator_type2 DRAW_LINE
#property indicator_color2 Red
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot TsiSignal
#property indicator_label3 "TsiSignal"
#property indicator_type3 DRAW_LINE
#property indicator_color3 Red
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
Dans la fonction OnInit(), recherchez les appels de la fonction SetIndexBuffer() pour ces tampons (les noms de tableaux sont TsiBuffer et TsiSignalBuffer), modifiez la valeur du troisième paramètre de INDICATOR_DATA en INDICATOR_CALCULATIONS.
SetIndexBuffer(2,TsiBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,TsiSignalBuffer,INDICATOR_CALCULATIONS);

Modifiez la propriété indicateur_color1 - ne laissez que les deux premières couleurs. 

#property indicator_color1 Green,Red

3. Déclaration de paramètres externes

Ouvrez l'indicateur STI dans MetaEditor et copiez-y toutes les variables externes, remplacez la variable externe Input1 par ces paramètres.

//--- input parameters
input int r=25;
input int s=13;
input int sp=5;                 // Smoothing period
input ENUM_MA_METHOD sm=MODE_EMA; // Smoothing type

4. Déclaration d'une variable du descripteur d'indicateur et appel de l'indicateur

Dans la section commune de l'indicateur, déclarez une variable de type int et nommez-la Handle. Appelez la fonction iCustom() au bas de OnInit(). La fonction renvoie handle de l'indicateur créé ; nous en avons besoin pour recevoir les valeurs de l'indicateur. Assignez la valeur renvoyée par la fonction à la variable Handle.

Les deux premiers paramètres de la fonction iCustom() déterminent un symbole et un délai dont les données seront utilisées pour le calcul de l'indicateur. Spécifions un symbole et une période auxquels l'indicateur est attaché - _Symbol and PERIOD_CURRENT. Le troisième paramètre est le nom d'un indicateur personnalisé ; dans ce cas, il s'agit des STI. Tous les paramètres externes de l'indicateur appelé sont répertoriés plus loin :

Handle=iCustom(_Symbol,PERIOD_CURRENT,"TSIs",r,s,sp,sm);

5. Préparation de la fonction OnCalculate()

Passons à la fonction OnCalculate(). L'indicateur STI est calculé sur un tampon de données, nous utiliserons donc la première forme de la fonction OnCalculate(). Remplacez la deuxième forme existante de la fonction OnCalculate() dans le modèle par la première.

int OnCalculate(const int rates_total,         // size of the price[] array
                const int prev_calculated,   // bars processed during the previous call
                const int begin,             // from where the significant data begin
                const double &price[]        // array for calculation
                )
  {
   return(rates_total);
  }

Le travail ultérieur sur l'indicateur sera effectué dans le cadre de cette fonction.

6. Détermination des limites de calcul de l'indicateur

La première priorité et importance dans le développement de tout indicateur est la détermination des limites de la gamme des barres traitées. Au début de l'indicateur, nous devons effectuer le calcul de l'indicateur pour chaque barre, pendant son fonctionnement - pour une seule qui est actuellement formée. Vous pouvez détecter le moment de démarrage de l'indicateur grâce à la valeur de la variable prev_calculated. Si cette valeur est égale à zéro, il s'agit de la première exécution de la fonction OnCalculate() depuis le début de l'indicateur.

Lors de la première exécution de la fonction OnCalculate(), vous devez déterminer l'indice de la première barre à partir de laquelle les calculs doivent être lancés. Sa valeur est déterminée par le nombre de barres nécessaires au calcul de la valeur de l'indicateur (l'indexation est effectuée de gauche à droite).

L'inclinaison de la ligne de l'indicateur est déterminée par deux barres, nous avons donc besoin d'une autre barre, la précédente. L'indice d'une barre, à partir duquel les données importantes du tableau price[] commencent, est connu - c'est la valeur de la variable begin ; nous commençons donc le calcul des barres à partir de la barre start=begin+1.

De plus, pendant le fonctionnement de l'indicateur, l'indice d'une barre à partir de laquelle le calcul commence est déterminé par la valeur de la variable prev_calculated - cette variable contient le nombre de barres déjà traitées. Ainsi, pour connaître l'indice de la dernière barre pour laquelle les calculs ont été effectués, vous devez soustraire 1 de prev_calculated.

La dernière des barres déjà traitées sera à nouveau prise en compte car il peut s'agir d'une barre de formation. La limite de calcul est déterminée par la taille du tableau price[] - la variable rates_total. L'indice de la dernière barre pour laquelle les calculs sont effectués est égal à rates_total-1 (il est inférieur d’une unité à la taille du tableau).

Étant donné que l'indicateur utilise les données d'un autre indicateur pour son calcul, nous devrions obtenir ces données. Vous pouvez obtenir les données d'un autre indicateur en utilisant la fonction CopyBuffer(). Dans le premier paramètre de la fonction, vous devez spécifier le descripteur d'un indicateur, dont les données doivent être copiées (handle est obtenu à l'étape 4) ; dans le deuxième paramètre, spécifiez un indice du tampon copié (la valeur nécessaire peut être déterminée via l'onglet « Couleur » des propriétés de l'indicateur copié, le comptage commence à partir de zéro).

Le troisième paramètre est l'indice d'une barre à partir de laquelle la copie est lancée ; dans ce cas, l'indexation est effectuée de droite à gauche de sorte que la barre la plus à droite est zéro. Le quatrième paramètre est le nombre d'éléments du tableau à copier. Vous devez être prudent en déterminant le nombre d'éléments copiés autant qu'en déterminant la plage de barres prises en compte dans le calcul. Cela affecte les performances de l'indicateur. L'indice d'une barre à partir duquel le calcul de l'indicateur commence est déterminé au préalable, de sorte que le nombre d'éléments copiés est calculé comme rates_total-start. Pendant le processus de travail, lorsque l'indicateur est calculé pour la barre de formation uniquement, un seul élément du tableau est copié.

Si les fonctions CopyBuffer() renvoient -1 lors d'une tentative de copie d'informations, cela signifie que les données ne peuvent pas être copiées, il est donc inutile d'effectuer des calculs. Cette erreur doit être traitée. Au tout début du CopyBuffer() déclarez une variable statique de type bool et nommez-la « erreur ». Si une erreur survient lors du processus de calcul de l'indicateur, notamment l'erreur de copie des données de l'indicateur, assignez la valeur True à cette variable et terminez l'exécution de la fonction OnCalculate().

Recalculez à nouveau l'ensemble de l'indicateur au prochain trait si la valeur d'erreur indique qu'il y a eu une erreur lors de l'exécution précédente de la fonction OnCalculate(). Ainsi, le début de la fonction OnCalculate() ressemblera à ceci :

   static bool error=true; 
   int start;
   if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start
     {
      error=true; // Set the value True for the indicator to be calculated for all bars
     }
   if(error) // If value of error=true, then it is the first execution of the function after 
             // the start of the indicator, or there was an error of copying of data at the previous start
     {
      start=begin+1;
      error=false;
     }
   else
     {
      start=prev_calculated-1;
     }

   if(CopyBuffer(Handle,0,0,rates_total-start,TsiBuffer)==-1) // Copying data of main line of the indicator
     {
      error=true; // Failed to copy data, set the value True for the error variable to recalculate the whole 
                 // indicator at the next call of OnCalculate()
      return(0);  // End working of the function
     }
   if(CopyBuffer(Handle,1,0,rates_total-start,TsiSignalBuffer)==-1) // Copy data of the signal line of the indicator
     {
      error=true; // Failed to copy data, set the value true for the error variable to recalculate the whole
                 // indicator at the next call of the OnCalculate() function
      return(0);  // End working of the function
     }

Les limites du calcul de l'indicateur sont déterminées, faites une boucle de calculs dans cette plage de barres.

for(int i=start;i<rates_total;i++)
  {

  }

Calculez la valeur de l'indicateur (le code est situé à l'intérieur de la boucle qui vient d'être créée).

TsiCDBuffer[i]=TsiBuffer[i]-TsiSignalBuffer[i];

Maintenant, la chose la plus intéressante - la coloration du tampon. Auparavant, à l'étape 1, nous avons déterminé l'utilisation d'un histogramme de couleurs pour le tampon indicateur. Ce type de dessin nécessite deux tampons - l'un pour la valeur de l'indicateur et l'autre pour la couleur. La liste des couleurs est configurée dans la propriété indicateur_couleur1. Lorsque la valeur 0 est configurée pour l'élément tampon, l'indicateur est affiché avec la couleur verte ; lorsque la valeur 1 est configurée, l'indicateur est rouge (conformément à leur emplacement dans l'indicateur_couleur1 dans la liste ; la numérotation commence à partir de zéro).

Il est impossible d'éviter une situation où les valeurs de l'indicateur sont égales à deux barres adjacentes ; dans ce cas, l'indicateur doit être affiché avec la couleur précédente (car nous n'avons que deux couleurs pour les mouvements de haut en bas). Ainsi, au début des calculs on recopiera la valeur du tampon TsiCDColors sur la barre précédente : 

TsiCDColors[i]=TsiCDColors[i-1];

Lorsque vous vous déplacez vers le haut, colorez l'indicateur avec la couleur Verte :

if(TsiCDBuffer[i]>TsiCDBuffer[i-1])TsiCDColors[i]=0;

Lorsque vous descendez, colorez l'indicateur avec la couleur Rouge :

if(TsiCDBuffer[i]<TsiCDBuffer[i-1])TsiCDColors[i]=1;

Cela nous amène presque à la fin du travail sur l'indicateur ; il reste à déterminer le début du dessin de l'indicateur.

7. Fin du travail sur l'indicateur 

Bien que la variable begin soit utilisée pour déterminer le calcul de l'indicateur, cela ne signifie pas que les données de l'indicateur commencent à partir de la barre identifiée avec la variable begin. Si l'algorithme d'un indicateur personnalisé n'est pas connu, il est presque impossible de détecter le nombre de barres nécessaire au calcul de l'indicateur. C'est pourquoi cette étape peut être sautée ou vous pouvez détecter une valeur sur la base de l'expérience. Cependant, nous connaissons l'algorithme de l'indicateur STI, nous pouvons donc détecter exactement le début de l'indicateur. Ajoutez l'appel de la fonction PlotIndexSetInteger() avec l'identifiant PLOT_DRAW_BEGIN à la fonction OnInit()

PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s+sp);

L'indicateur STI affiche des valeurs précises à deux décimales près ; définissez la même précision à l'aide de la fonction IndicatorSetInteger() avec l'identifiant INDICATOR_DIGITS :

IndicatorSetInteger(INDICATOR_DIGITS,2);

Compilez l'indicateur et attachez-le à un tableau (fig. 8).

 
Fig. 8. Indicateur STIsCDiCust.

Création d'un indicateur à l'aide de la fonction IndicatorCreate() 


La création d'un indicateur à l'aide de la fonction IndicatorCreate() est identique à sa création à l'aide de la fonction iCustom(), à l'exception de l'étape 4 - la fonction IndicatorCreate() est utilisée à la place de iCustom().

1. Enregistrez une copie de l'indicateur TSIsCDiCust sous le nom TSIsCDiCreate.

2. Trouvez où la fonction iCustom() est appelée dans le code. Désormais, l'appel de la fonction IndicatorCreate() sera effectué à la place de iCustom(). Comme dans iCustom(), les deux premiers paramètres de la fonction IndicatorCreate() déterminent des symboles et une période qui seront utilisés pour le calcul de l'indicateur. Le troisième paramètre est un identifiant de type indicateur, pour un indicateur personnalisé il s'agit de IND_CUSTOM. Les paramètres de l'indicateur de création sont transmis vers la fonction via le tableau de structures MqlParam.

Le MqlParam contient quatre variables - trois d'entre elles sont des variables de différents types utilisées pour les valeurs : double_value, integer_value et string_value ; et un autre est type, elle détermine le type de variable utilisée. L'indicateur STI a quatre paramètres externes. Étant donné que l'indicateur est personnalisé, le premier élément du tableau détermine le nom de l'indicateur personnalisé, ainsi, le tableau doit contenir cinq éléments. Déclarez un tableau de structures (le code se trouve là où iCustom() a été appelé) :

MqlParam Params[5];

Remplissage du tableau avec des valeurs :

   Params[0].type=TYPE_STRING;
   Params[0].string_value="TSIs"; // Specify name of the called custom indicator in the first parameter
   
   Params[1].type=TYPE_INT;
   Params[1].integer_value=r;
   
   Params[2].type=TYPE_INT;
   Params[2].integer_value=s;   
   
   Params[3].type=TYPE_INT;
   Params[3].integer_value=sp;      
   
   Params[4].type=TYPE_INT;
   Params[4].integer_value=sm;  

Nous avons déjà traité les trois premiers paramètres transmis vers la fonction IndicatorCreate(). La taille du tableau de paramètres est transmise au travers du quatrième paramètre ; le dernier est le tableau avec les paramètres lui-même :

Handle=IndicatorCreate(_Symbol,PERIOD_CURRENT,IND_CUSTOM,5,Params);

Il reste à appuyer sur le bouton « Compiler » et à vérifier l'indicateur dans le terminal client.

Conclusion

Répétons brièvement les principales idées auxquelles vous devez prêter attention lors de la création d'un indicateur personnalisé à partir d'un autre indicateur.

Lors de l'amélioration d'un indicateur, vous devez spécifier correctement le nombre de tampons et le nombre de tampons à tracer (les propriétés indicator_buffers, indicator_plots) ; vous devez déterminer les propriétés de nouveaux tampons (les propriétés indicator_label, indicator_type, indicator_color, indicator_style, indicator_width). Lors de l'appel de la fonction SetIndexBufer() pour les nouveaux tampons, vous devez spécifier la valeur correcte du troisième paramètre (INDICATOR_DATA or INDICATOR_CALCULATIONS) ; et spécifier correctement les valeurs du premier paramètre (indice de tampon) ; effectuer la réindexation des tampons si nécessaire.

Lors de la création d'un nouvel indicateur à l'aide d'un autre indicateur personnalisé, vous devez correctement transmettre les paramètres vers la fonction iCustom(), et remplir la structure des paramètres lors de l'utilisation de la fonction IndicatorCreate(). Ici, vous devez également surveiller la spécification correcte des paramètres lors de l'appel de la fonction SetIndexBuffer() ; et le plus important est de ne pas oublier d'effectuer l'appel de la fonction SetIndexBuffer() pour les nouveaux tampons.

Chaque fois que vous travaillez avec des indicateurs, vous devez faire attention à déterminer une série de calcul de barres - utilisez les valeurs des variables prev_calculated, rates_total, begin. MetaEditor vous aidera à traiter les autres erreurs qui peuvent apparaître lors de la programmation (les messages d'erreur qui apparaissent lors de la compilation sont affichés dans l'onglet « Erreurs »).

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

Fichiers joints |
tsis.mq5 (7.59 KB)
tsiscdicreate.mq5 (3.46 KB)
tsiscdicust.mq5 (3.11 KB)
20 signaux de trade en MQL5 20 signaux de trade en MQL5
Cet article vous apprendra comment recevoir les signaux de trade nécessaires au fonctionnement d'un système de trading. Les exemples de formation de 20 signaux de trade sont donnés ici en tant que fonctions personnalisées distinctes qui peuvent être utilisées lors du développement d'Expert Advisors. Pour votre aisance, toutes les fonctions utilisées dans l'article sont regroupées dans un seul fichier d'inclusion mqh qui peut être facilement connecté à un futur Expert Advisor.
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.
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.
Création d'un panneau d'information à l'aide des classes de bibliothèque standard et de l'API Google Chart Création d'un panneau d'information à l'aide des classes de bibliothèque standard et de l'API Google Chart
Le langage de programmation MQL5 cible principalement la création de systèmes de trading automatisés et d'instruments complexes d'analyses techniques. Mais en dehors de cela, cela nous permet de créer des systèmes d'information intéressants pour suivre les situations de marché, et fournit une connexion retour avec le trader. L'article décrit les composants de la bibliothèque standard MQL5 et montre des exemples de leur utilisation pratique pour atteindre ces objectifs. Il montre également un exemple d'utilisation de l'API Google Chart pour la création de graphiques.