English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Création d'un indicateur avec plusieurs tampons d'indicateurs pour les débutants

Création d'un indicateur avec plusieurs tampons d'indicateurs pour les débutants

MetaTrader 5Exemples | 16 novembre 2021, 15:16
267 0
Nikolay Kositsin
Nikolay Kositsin

Introduction

Dans mes articles précédents «Indicateurs personnalisés dans MQL5 pour les débutants» et «Implémentation Pratique des Fichiers Numériques dans MQL5 pour lesDébutants», je me suis concentré en détail sur la structure de l’indicateur avec un tampon d’indicateur.

Évidemment, une telle méthode peut être largement appliquée pour écrire des indicateurs personnalisés, mais la vie réelle peut à peine se limiter à leur utilisation, et il est donc temps d’aborder des méthodes plus complexes de construction du code de l’indicateur. Heureusement, les capacités de MQL5 sont vraiment inépuisables et ne sont limitées que par la RAM de nos PC.


L’indicateur Aroon comme exemple de doublement de code

La formule de cet indicateur contient deux composantes: les indicateurs haussiers et baissiers, qui sont tracés dans une fenêtre graphique distincte:

TAUREAUX = (1 - (bar - SHIFT(MAX(HIGH(), AroonPeriod)))/AroonPeriod) * 100
OURS = (1 - (bar - SHIFT(MIN (LOW (), AroonPeriod)))/AroonPeriod) * 100

Avec :

  • BULLS - la force du taureau;
  • OURS - la force de l’ours;
  • SHIFT() - fonction de détermination de la position de l’indice de la barre;
  • MAX() - fonction de recherche du maximum sur la période AroonPeriod;
  • MIN() - fonction de recherche du minimum sur la période AroonPeriod;
  • HIGH() et LOW() - les tableaux de prix pertinents;

Dès les formules de l’indicateur, nous pouvons conclure que pour construire un indicateur, nous ne devons avoir que deux tampons d’indicateurs, la structure de l’indicateur différera très peu de la structure du SMA_1.mq5, considéré dans l’article précédent.

Pratiquement, il s’agit simplement du même code dupliqué, avec différents nombres de tampons d’indicateurs. Ouvrons donc le code de cet indicateur dans le MetaEditor et enregistrons-le sous Aroon.mq5. Maintenant, dans les 11 premières lignes du code, qui se rapportent au droit d’auteur et à son numéro de version, nous allons uniquement remplacer le nom de l’indicateur:

//+------------------------------------------------------------------+
//|                                                        Aroon.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
//---- copyright
#property copyright "2010, MetaQuotes Software Corp."
//---- link to the author's site
#property link      "http://www.mql5.com"
//---- version number
#property version   "1.00"

Ensuite, dans la 12ème ligne de code, nous devons modifier le tracé de l’indicateur de la fenêtre de graphique de base à la fenêtre séparée:

//---- plot indicator in the separate window
#property indicator_separate_window

Étant donné que cet indicateur dispose d’ une plage de valeurs complètement différente, son tracé sera effectué dans une fenêtre séparée.

Après cela, dans les 4 lignes suivantes du code (les propriétés générales de l’indicateur), nous modifions le nombre de tampons d’indicateur utilisés à deux:

//---- two buffers are used
#property indicator_buffers 2
//---- two plots are used 
#property indicator_plots   2

Les 10 lignes de code suivantes sont liées au traçage de l’indicateur à partir d’un tampon d’indicateur spécifique, son étiquette doit être dupliquée, après quoi, nous devons remplacer tous les index de 1 à 2. Nous devons également modifier toutes les étiquettes des tampons d’indicateurs:

//+----------------------------------------------+
//| bullish strength indicator parameters        |
//+----------------------------------------------+
//---- drawing style = line
#property indicator_type1   DRAW_LINE
//---- drawing color = Lime
#property indicator_color1  Lime
//---- line style = solid line
#property indicator_style1  STYLE_SOLID
//---- line width = 1
#property indicator_width1  1
//---- label of the BullsAroon indicator
#property indicator_label1  "BullsAroon"
//+----------------------------------------------+
//|  bearish strength indicator parameters       |
//+----------------------------------------------+
//---- drawing style = line
#property indicator_type2   DRAW_LINE
//---- drawing color = Red
#property indicator_color2  Red
//---- line style = solid line
#property indicator_style2  STYLE_SOLID
//---- line width = 1
#property indicator_width2  1
//---- label of the BearsAroon indicator
#property indicator_label2  "BearsAroon"

Cet indicateur utilise trois niveaux horizontaux avec les valeurs de 30, 50 et 70.

Afin de tracer ces niveaux, nous devons ajouter cinq lignes de code supplémentaires au code de l’indicateur.

//+----------------------------------------------+
//| Horizontal levels                            |
//+----------------------------------------------+
#property indicator_level1 70.0
#property indicator_level2 50.0
#property indicator_level3 30.0
#property indicator_levelcolor Gray
#property indicator_levelstyle STYLE_DASHDOTDOT

Pour les paramètres d’entrée de l’indicateur, par rapport à l’indicateur précédent, tout reste le même, à l’exception de légères modifications dans les titres:

//+----------------------------------------------+
//| Indicator input parameters                   |
//+----------------------------------------------+
input int AroonPeriod = 9; // Period 
input int AroonShift = 0// Horizontal shift of the indicator in bars 

 Maintenant, cependant, il y aura deux tableaux, qui seront utilisés comme tampons d’indicateurs, et ils auront des noms appropriés:

//--- declare the dynamic arrays used further as indicator buffers
double BullsAroonBuffer[];
double BearsAroonBuffer[]; 

Nous procédons dans une toute même affaire avec le code de la fonction OnInit().

Tout d’abord, nous modifions les lignes de code du zéroième tampon:

//--- set BullsAroonBuffer dynamic array as indicator buffer 
SetIndexBuffer(0, BullsAroonBuffer, INDICATOR_DATA);
//--- horizontal shift (AroonShift) of the indicator 1
PlotIndexSetInteger(0, PLOT_SHIFT, AroonShift);
//--- plot draw begin (AroonPeriod) of the indicator 1
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, AroonPeriod);
//--- label shown in DataWindow
PlotIndexSetString(0, PLOT_LABEL, "BearsAroon"); 

Après cela, copiez le code entier dans le presse-papiers Windows et collez-le juste après le même code.

Ensuite, dans le code collé, nous modifions le numéro du tampon d’indicateur de 0 à 1, modifions le nom du tableau d’indicateurs et l’étiquette de l’indicateur:

//--- set BearsAroonBuffer dynamic array as indicator buffer 
SetIndexBuffer(1, BearsAroonBuffer, INDICATOR_DATA); 
//--- horizontal shift (AroonShift) of the indicator 2 
PlotIndexSetInteger(1, PLOT_SHIFT, AroonShift); 
//--- plot draw begin (AroonPeriod) of the indicator 2 
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, AroonPeriod); 
//--- label shown in DataWindow 
PlotIndexSetString(1, PLOT_LABEL, "BullsAroon");  

Le nom abrégé de l’indicateur a également subi de légères modifications :

//--- initialization of the variable for a short indicator name
string shortname;
StringConcatenate(shortname, "Aroon(", AroonPeriod, ", ", AroonShift, ")"); 

Maintenant, examinons la précision du traçage de l’indicateur. La plage réelle de l’indicateur est comprise entre 0 et 100, et cette plage est affichée tout le temps.

Dans cette situation, il est tout à fait possible d’utiliser uniquement les valeurs entières de l’indicateur, tracées sur le graphique. Pour cette raison, nous utilisons 0 pour les nombres après la virgule, pour le tracé de l’indicateur:

//--- set accuracy of drawing of indicator values
IndicatorSetInteger(INDICATOR_DIGITS, 0);

Dans l’indicateur SMA_1.mq5, nous avons utilisé la première forme de l’appel de fonction OnCalculate().

Il ne convient pas à l’indicateur Aroon, en raison de son absence de tableaux de prix élevés et bas. Ces tableaux sont disponibles dans la deuxième forme d’appel de cette fonction. Et, par conséquent, il est nécessaire de modifier l’en-tête de la fonction:

int OnCalculate( 
                const int rates_total,    // total bars on the current tick
                const int prev_calculated,// total bars on the previous tick
                const datetime& time[],
                const double& open[],    
                const double& high[],     // price array of the maximum prices for the indicator calculations
                const double& low[],      // price array of the minimum prices for the indicator calculations
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[]
              )

Après cette modification, l’utilisation du paramètre begin a perdu tout son sens, il doit donc être supprimé du code!

Le code de calcul des limites des modifications de variables du cycle de fonctionnement, la vérification des données pour la suffisance du calcul, est pratiquement resté inchangé.

//--- checking the number of bars
if (rates_total < AroonPeriod - 1) return(0);
   
//--- declare the local variables 
int first, bar;
double BULLS, BEARS; 

//--- calculation of the first (staring index) for the main loop
if (prev_calculated == 0)          // checking for the first call of the OnCalculate function
    first = AroonPeriod - 1;       // starting index for calculating all of the bars 
else first = prev_calculated - 1// starting index for calculating new bars

Cependant, certains problèmes surgissent avec les algorithmes de calcul des valeurs des indicateurs. Le problème est que MQL5 ne dispose pas des fonctions intégrées pour déterminer les indices du maximum et du minimum, pour la période à partir de la barre actuelle, dans la direction de l’indice décroissant.

Une façon de sortir de cette situation est d’écrire ces fonctions nous-mêmes. Heureusement, de telles fonctions existent déjà dans l’indicateur ZigZag.mq5 dans le dossier se trouvant dans « MetaTrader5\MQL5\Indicators\Examples ».

Le moyen le plus simple de s’en sortir - est de sélectionner le code de ces fonctions dans l’indicateur ZigZag.mq5, de les copier dans le presse-papiers Windows et de les coller dans notre code, par exemple, juste après la description de la fonction OnInit(), au niveau global:

//+------------------------------------------------------------------+
//|  searching index of the highest bar                              |
//+------------------------------------------------------------------+
int iHighest(const double &array[], // array for searching for the index of the maximum element
             int count,            // number of the elements in the array (in the decreasing order), 
             int startPos          // starting index
             )                     
  {
//---+
   int index = startPos;
   
   //---- checking the starting index
   if (startPos < 0)
     {
      Print("Incorrect value in the function iHighest, startPos = ", startPos);
      return (0);
     } 
   //---- checking the startPos values
   if (startPos - count < 0) count = startPos;
    
   double max = array[startPos];
   
   //---- index search
   for(int i = startPos; i > startPos - count; i--)
     {
      if(array[i] > max)
        {
         index = i;
         max = array[i];
        }
     }
//---+ return of the index of the largest bar
   return(index);
  }
//+------------------------------------------------------------------+
//|  searching index of the lowest bar                               |
//+------------------------------------------------------------------+
int iLowest(
            const double &array[], // array for searching for the index of the maximum element
            int count,            // number of the elements in the array (in the decreasing order),
            int startPos          // starting index
            ) 
{
//---+
   int index = startPos;
   
   //--- checking the stating index
   if (startPos < 0)
     {
      Print("Incorrect value in the iLowest function, startPos = ",startPos);
      return(0);
     }
     
   //--- checking the startPos value
   if (startPos - count < 0) count = startPos;
    
   double min = array[startPos];
   
   //--- index search
   for(int i = startPos; i > startPos - count; i--)
     {
      if (array[i] < min)
        {
         index = i;
         min = array[i];
        }
     }
//---+ return of the index of the smallest bar
   return(index);
  }

Après cela, le code de la fonction OnCalculate() sera le suivant :

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate( const int rates_total,    // total number of bars on the current tick
               const int prev_calculated,// number of calculated bars on the previous tick
               const datetime& time[],
               const double& open[],    
               const double& high[],     // price array for the maximum price for the indicator calculation
               const double& low[],      // price array for the minimum price for the indicator calculation
               const double& close[],
               const long& tick_volume[],
               const long& volume[],
               const int& spread[]
             )
  {
//---+   
   //--- checking the number of bars
   if (rates_total < AroonPeriod - 1)
    return(0);
   
   //--- declare the local variables 
   int first, bar;
   double BULLS, BEARS;
   
   //--- calculation of the starting bar number
   if (prev_calculated == 0// checking for the first start of the indicator calculation
     first = AroonPeriod - 1; // starting number for the calculation of all of the bars

   else first = prev_calculated - 1; // starting number for the calculation of new bars

   //--- main loop
   for(bar = first; bar < rates_total; bar++)
    {
     //--- calculation of values
     BULLS = 100 - (bar - iHighest(high, AroonPeriod, bar) + 0.5) * 100 / AroonPeriod;
     BEARS = 100 - (bar - iLowest (low,  AroonPeriod, bar) + 0.5) * 100 / AroonPeriod;

     //--- filling the indicator buffers with the calculated values 
     BullsAroonBuffer[bar] = BULLS;
     BearsAroonBuffer[bar] = BEARS;
    }
//---+     
   return(rates_total);
  }
//+------------------------------------------------------------------+

Pour la symétrie des axes, j’ai légèrement corrigé dans le code, en ajoutant le décalage vertical de l’indicateur, par rapport à l’indicateur d’origine, en utilisant la valeur de 0,5.

Voici les résultats des travaux de cet indicateur sur le graphique :                                                                              

Pour trouver la position de l’élément avec les valeurs maximales ou minimales sur une distance ne dépassant pas AroonPeriod de la barre actuelle, nous pouvons utiliser les fonctions ArrayMaximum() et ArrayMinimum() intégrées de MQL5, qui recherchent également les extremums, mais ces fonctions effectuent la recherche en utilisant l’ordre croissant.

Cependant, la recherche doit être menée dans l’ordre décroissant des index. Dans ce cas, la solution la plus simple consiste à modifier la direction de l’indexation dans les tampons d’indicateur et de prix, à l’aide de la fonction ArraySetAsSeries().

Mais nous devons également modifier la direction de l’ordre des barres dans la boucle de calcul et modifier l’algorithme du premier calcul de variable.

Dans ce cas, la fonction OnCalculate() résultante ressemblera à ceci :

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(
                const int rates_total,    // total number of bars on the current tick
                const int prev_calculated,// number of calculated bars on the previous tick
                const datetime& time[],
                const double& open[],    
                const double& high[],     // price array for the maximum price for the indicator calculation
                const double& low[],      // price array for the minimum price for the indicator calculation
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[]
              )
  {
//---+   
   //--- checking the number of bars
   if (rates_total < AroonPeriod - 1)
    return(0);
    
   //--- set indexation as timeseries
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low,  true);
   ArraySetAsSeries(BullsAroonBuffer, true);
   ArraySetAsSeries(BearsAroonBuffer, true);
   
   //--- declare the local variables 
   int limit, bar;
   double BULLS, BEARS;
   
   //--- calculation of the starting bar index
   if (prev_calculated == 0)                      // check for the first call of OnCalculate function
       limit = rates_total - AroonPeriod - 1// starting index for the calculation of all of the bars
   else limit = rates_total - prev_calculated; // starting index for the calculation of new bars
   
   //--- main loop
   for(bar = limit; bar >= 0; bar--)
    {
     //--- calculation of the indicator values
     BULLS = 100 + (bar - ArrayMaximum(high, bar, AroonPeriod) - 0.5) * 100 / AroonPeriod;
     BEARS = 100 + (bar - ArrayMinimum(low,  bar, AroonPeriod) - 0.5) * 100 / AroonPeriod;

     //--- filling the indicator buffers with the calculated values 
     BullsAroonBuffer[bar] = BULLS;
     BearsAroonBuffer[bar] = BEARS;
    }
//----+     
   return(rates_total);
  }
//+------------------------------------------------------------------+

J’ai modifié le nom de la variable « first » en « limit », c’est plus approprié dans ce cas.

Dans ce cas, le code de la boucle principale est similaire à celui qui a été fait dans MQL4. Ainsi, ce style d’écriture de la fonction OnCalculate() peut être utilisé pour la conversion d’indicateurs de MQL4 en MQL5 avec un minimum de modifications du code.


Conclusion

Alors, c’est fait! L’indicateur est rédigé, et même en deux versions.

Pour un cas de la bonne façon conservatrice et intelligente de résoudre de tels problèmes, les solutions s’avèrent légèrement plus compliquées que la construction d’un jouet utilisant le constructeur Lego pour enfants.

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

Fichiers joints |
sma_1.mq5 (3.92 KB)
aroon.mq5 (8.04 KB)
aroons.mq5 (6.28 KB)
zigzag.mq5 (9.17 KB)
MQL pour "Nuls" : Comment Concevoir et Construire des Classes d'Objets MQL pour "Nuls" : Comment Concevoir et Construire des Classes d'Objets
En créant un échantillon de programme de conception visuelle, nous montrons comment concevoir et construire des classes dans MQL5. L'article est écrit pour les programmeurs débutants, qui travaillent sur des applications MT5. Nous proposons une technologie simple et facilement intelligible pour créer des classes, sans avoir besoin de s'immerger profondément dans la théorie de la programmation orientée-objet.
Interaction MetaTrader 5 et MATLAB Interaction MetaTrader 5 et MATLAB
Cet article couvre les détails de l'interaction entre MetaTrader 5 et le package mathématique MatLab. Il indique le mécanisme de conversion des données, le processus d’élaboration d'une bibliothèque universelle pour interagir avec le bureau MatLab. Il couvre également l'utilisation des DLL générées par l'environnement MatLab. Cet article est destiné aux lecteurs expérimentés, connaissant C++ et MQL5.
Algorithmes Génétiques - C'est Facile ! Algorithmes Génétiques - C'est Facile !
Dans cet article, l'auteur parle de calculs évolutifs à l'aide d'un algorithme génétique personnellement élaboré . Il démontre le fonctionnement de l'algorithme, à l'aide d'exemples, et fournit des recommandations pratiques pour son utilisation.
Création d’un indicateur avec des Options de Contrôle Graphique Création d’un indicateur avec des Options de Contrôle Graphique
Ceux qui sont familiers avec les attitudes du marché, connaissent l’indicateur MACD (son nom complet est Moyenne Mobile de Convergence / Divergence) - l’outil puissant pour analyser le mouvement des prix, utilisé par les traders dès les premiers moments d’apparition des méthodes d’analyse informatique. Dans cet article, nous examinerons les éventuelles modifications de MACD et les implémenterons dans un seul indicateur avec la possibilité de basculer graphiquement entre les modifications.