English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Embarquement sur de nouveaux rails : Indicateurs personnalisés dans MQL5

Embarquement sur de nouveaux rails : Indicateurs personnalisés dans MQL5

MetaTrader 5Exemples | 22 décembre 2021, 16:08
189 0
TheXpert
TheXpert

Introduction

Enfin, nous avons l'opportunité d'essayer le nouveau terminal de trading - MetaTrader 5. Sans aucun doute, il est remarquable et possède de nombreuses nouvelles fonctionnalités par rapport à son prédécesseur. Les avantages importants de cette plateforme entre autres sont :

  • Langage essentiellement modifié permettant maintenant d'utiliser la programmation orientée objet, tout en permettant toujours d'utiliser les riches avantages de la programmation structurelle.
  • La vitesse d'exécution du code, qui est maintenant beaucoup plus rapide que dans MetaTrader 4.
  • Augmentation essentielle des possibilités d'affichage des informations nécessaires.

Je ne vais pas lister toutes les nouvelles possibilités et fonctionnalités du nouveau terminal et du nouveau langage. Elles sont nombreuses, et certaines nouveautés méritent d'être discutées dans un article séparé. De plus, il n'y a aucun code d’écrit avec une programmation orientée objet, c'est un sujet trop sérieux pour être simplement mentionné dans un contexte comme des avantages supplémentaires pour les développeurs.

Dans cet article, nous examinerons les indicateurs, leur structure, dessin, types et leurs détails de programmation, par rapport à MQL4.

Il n'y a rien de compliqué dans cet article, de plus, tout ce qui est considéré ici peut être vérifié directement dans le terminal à l'aide des fichiers joints.

J'espère que cet article sera utile aussi bien aux débutants qu'aux développeurs expérimentés, peut-être que certains d'entre eux découvriront une nouvelle matière à apprendre ici.

 

La structure générale

La structure générale de l'indicateur par rapport au MQL4 n'a pas changé.

Comme précédemment, il existe trois fonctions - pour l'initialisation, pour le traitement des données et pour la désinitialisation de l'indicateur.

Comme précédemment, de nombreux paramètres d'indicateur peuvent être définis par des propriétés (mot clé #property). La plupart d'entre eux sont conçus spécifiquement pour les indicateurs. Les propriétés et les paramètres d'entrée comme précédemment, sont définis dans un contexte global.

À titre d'exemple, considérons l'implémentation de la coloration personnalisée de l'indicateur RSI. Voici la version tronquée, la version complète se trouve dans le fichier Color_RSI.mq5.

Considérons les parties du code.

//--- group of data properties
#property copyright "TheXpert"
#property link      "theforexpert@gmail.com"
#property version   "1.00"
//--- description of the indicator should not exceed 511 symbols in total
//--- including newline symbols
#property description "      "
#property description "Demonstration of the indicator creation"
#property description "by the example of RSI coloring"

Les propriétés spécifiées ci-dessus s'affichent dans le panneau d'informations de l'indicateur (onglet « Common » des propriétés). On dirait :

//--- indicator properties
#property indicator_separate_window // the indicator will be displayed in a separate subwindow
#property indicator_buffers 2       // number of used buffers
#property indicator_plots   1       // number of displayed buffers
//--- plot 1
#property indicator_color1 clrDarkSalmon, clrDeepSkyBlue // use 2 colors
#property indicator_type1  DRAW_COLOR_LINE               // and the special color display type

Ces properties sont les propriétés de l'indicateur. La description des autres propriétés se trouve dans la section de l'aide.

//---- buffers
double Values[];                 // buffer of values
double ValuesPainting[];         // buffer of color indices
//--- indicator input parameters
input string             _1           = "RSI parameters";
input int                RSIPeriod    = 5;
input int                SmoothPeriod = 5;
input ENUM_APPLIED_PRICE AppliedPrice = PRICE_CLOSE;
input string             _2           = "Color settings";
input color              Down         = clrDarkSalmon;
input color              Up           = clrDeepSkyBlue;
//--- variable for storing the indicator handle
int RSIHandle;

Voici les paramètres d'entrée de l'indicateur et les variables globales (à ne pas confondre avec les variables globales du terminal client). Les paramètres d'entrée de l'indicateur sont spécifiés avec l'identifiant input.

Maintenant, il est possible de définir une énumération pour le paramètre d'entrée, il est parfois utile d'éviter la sélection incorrecte des paramètres.

Par exemple, le paramètre AppliedPrice sera affiché dans une liste déroulante avec des valeurs valides possibles.

Ainsi, toutes les énumérations, y compris celles définies par l'utilisateur, seront affichées dans la même liste déroulante. Par exemple, le paramètre suivant

//...
enum DayOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

input DayOfWeek Day;

//...

s'affichera comme suit :

int OnInit()
  {
//--- bind indicator buffers
//--- Values serves as a display buffer
   SetIndexBuffer(0,Values,INDICATOR_DATA);
//--- ValuesPainting serves as the buffer for storing colors
   SetIndexBuffer(1,ValuesPainting,INDICATOR_COLOR_INDEX);
//--- Set the start of drawing Values buffer
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,RSIPeriod);
//--- Set the indicator name
   IndicatorSetString(INDICATOR_SHORTNAME,"Color RSI("+string(RSIPeriod)+")");
//--- Set an empty value for plots
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//--- Set buffer colors
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Down);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,Up);
//--- Receive indicator handles
   RSIHandle=iRSI(NULL,0,RSIPeriod,AppliedPrice);
//--- Set the sequence of buffer indexation
   ArraySetAsSeries(Values,true);
   ArraySetAsSeries(ValuesPainting,true);
//--- successful execution
   return(0);
  }

OnInitest la fonction d'initialisation de l'indicateur.           | Ici, nous configurons les marges indicatrices et leurs propriétés, et définissons les variables d'indicateur qui ne peuvent pas être définies dans les propriétés ou doivent être définies dynamiquement. Il y a également une initialisation initiale des données, y compris l'affectation des descripteurs nécessaires aux indicateurs.

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[])
  {
//--- number of bars for calculation
   int toCount=(int)MathMin(rates_total,rates_total-prev_calculated+1);
//--- try to copy iRSI indicator data
   if(CopyBuffer(RSIHandle,0,0,toCount,Values)==-1)
     {
      Print("Data copy error, №",GetLastError());
      //--- return command for recalculation of the indicator values
      return(0);
     }
//--- coloring. Yer, now it has become that easy
   for(int i=toCount-2;i>=0;--i)
     {
      //--- coloring the first line
      if(Values[i+1]!=EMPTY_VALUE && Values[i]>Values[i+1])
         ValuesPainting[i]=1;
      else
         ValuesPainting[i]=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

OnCalculate est la fonction de calcul des données. Cette fonction peut être de deux sortes. Voici sa forme standard. Voici les détails.

Fonction :

//--- this function usage in not obligatory
/*
void OnDeinit()
{

}
*/

OnDeinit est la fonction de désinitialisation de l'indicateur. Il est souvent nécessaire de libérer les ressources, par exemple les descripteurs de fichiers. Pour les autres cas, cette fonction n'est pas nécessaire.

 

Deux concepts d'indicateurs

Le premier est standard, le même que celui auquel nous nous sommes habitués en MQL4, mais sous une forme légèrement modifiée. La fonction OnCalculate est utilisée à la place de la fonction Start.

Pour la forme standard, elle se présente comme suit :

int OnCalculate(const int rates_total,      // Arrays size
                const int prev_calculated,  // Bars processed on the previous call
                const datetime& time[],     // Data for the current chart and timeframe...
                const double& open[],
                const double& high[],       
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
{
   return rates_total;
}

Afin de réduire la quantité de code destiné à la copie des données, les données du graphique sont directement transmises sous forme de tableaux aux paramètres de la fonction. De plus, le nombre de barres disponibles est passé en premier paramètre de la fonction, le nombre de barres traitées après le dernier appel ou 0 (zéro) est passé en second paramètre.

La valeur 0 (zéro) peut être transmise au premier appel de l'indicateur, ainsi que lors du chargement de données nouvelles ou manquantes. Ce paramètre est un remplacement (alternatif ou équivalent - à vous de choisir) pour IndicatorCounted(), ce qui n’est pas pratique pour de nombreux développeurs.

Le deuxième concept est le remplacement et l'expansion des fonctions de type i<…>OnArray, similaires à celles de MQL4. Il existe un indicateur de ce type dans les exemples de terminaux - Moyenne mobile personnalisée. Ce type d'indicateurs est destiné à un traitement de données dépendant du choix de l'utilisateur, y compris les indicateurs personnalisés.

La fonction de traitement des données pour les indicateurs de ce type ressemble à ce qui suit :

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

Le dernier paramètre de la fonction est la donnée sélectionnée par l'utilisateur pour être traitées. Si vous voulez appliquer un indicateur avec beaucoup de tampons, le premier tampon indicateur sera transmis pour le traitement des données.

Les données de premier indicateur signifient que l'indicateur sera appliqué au premier indicateur attaché à la fenêtre sélectionnée du graphique.

Les données du premier indicateur signifient que cet indicateur sera appliqué au dernier indicateur attaché à la fenêtre sélectionnée du graphique.

Ces indicateurs peuvent être utilisés pour assembler tout le paquet d'empilement. Par exemple, en utilisant l'indicateur de la moyenne mobile personnalisée, il est possible d'obtenir le triple lissage en imposant le premier indicateur aux données nécessaires, le second au premier et le troisième au deuxième :

Il existe de nombreux indicateurs standard qui mettent en œuvre ce concept particulier. Par conséquent, lorsque vous voyez l'invite pour le paramètre de fonction applied_price_or_handle :

il indique que l'indicateur est mis en application de la manière dont il peut être calculé sur les données utilisateur - le descripteur de ces données doit être transmis en tant que paramètre applied_price_or_handle.

De la même manière, il est possible d'organiser le traitement des données directement dans le code indicateur :

  {
   //...
   RSIHandle = iRSI(NULL, 0, RSIPeriod, AppliedPrice);
   SmoothHandle = iMA(NULL, 0, SmoothPeriod, 0, MODE_EMA, RSIHandle);
   //...
  }

Il existe une autre nouvelle application de ce concept - la capacité d'écrire des indicateurs de service universel. Un exemple d'un tel indicateur est joint dans le fichier Direction_Brush.mq5.

Les résultats sont présentés sur le graphique supérieur. La coloration de direction dans ce cas est séparée en tant qu'entité indépendante et mise en application dans l'autre indicateur.

Certes, leur universalité est limitée, puisqu'elles ne sont applicables que pour la marge zéro de l'indicateur. Néanmoins, je pense que des indicateurs de ce type pourraient être utiles.

De l'autre côté, lorsque vous écrivez un indicateur personnalisé, vous devez en tenir compte, car le traitement principal de l'information dans la marge zéro permettra d'éviter d'implémenter une machine multifonctionnelle dans un indicateur. La plupart des autres actions peuvent être entreprises et exécutées dans les indicateurs de services externes. Tout ce que vous aurez à faire est de joindre les indicateurs de service avec la fonctionnalité requise pour votre personnalisation.

Le domaine d'application n'est pas si étroit qu'il n'y paraît à première vue :

  • colorier les caractéristiques de l'indicateur (sommets, directions, niveaux, segments, etc.), y compris la visualisation des tons ;
  • différents signaux dans différentes conditions;
  • collecter et afficher des statistiques - par exemple, la distribution des données ;
  • construction d'indicateurs universels pouvant être calculés pour une marge - par exemple, moyennes mobiles, zigzag.

Les fonctionnalités mentionnées ci-dessus ne constituent pas la liste exhaustive de la mise en application du concept. Je pense que beaucoup d'autres mises en application efficaces seront trouvées plus tard.

 

Accès aux données

Les principes d'accès aux données ont changé dans MQL5. Maintenant, le travail s’effectue directement dans les tableaux, et par conséquent, la vitesse de calcul a considérablement augmenté. Maintenant, il n'est pas nécessaire de créer un tableau et d’appeler la fonction iCustom pour chaque valeur. Par contre, c'est possible d'obtenir le nombre de données nécessaires en appelant une fonction, et puis d’utiliser directement les données demandées copiées dans un tableau local spécifié.

La copie des données est réalisée à l'aide de la fonction système CopyBuffer. Vous pouvez trouver la description de la fonction dans la section de l'aide.

Le nombre maximal de données à copier pour les tableaux indicateur et statique (avec une taille prédéfinie) est déterminé par la taille du tableau. La taille du tableau dynamique peut être modifiée si le nombre de données copiées dépasse sa taille.

En outre, il existe des fonctions spéciales pour accéder aux données historiques :

Fonction Description
CopyBuffer Obtient les données d'une mémoire tampon indiquée d'un certain indicateur dans la quantité nécessaire.
CopyRates Obtient les données historiques de la structure MqlRates d'une période de symbole spécifiée en quantité spécifiée dans le tableau rates_array.
CopyTime La fonction obtient les données historiques time_array de l'heure d'ouverture de la barre pour la paire symbole-période spécifiée dans la quantité spécifiée.
CopyOpen La fonction obtient dans open_array les données historiques des prix d'ouverture des barres pour la paire symbole-période sélectionnée dans la quantité spécifiée.
CopyHigh La fonction obtient dans high_array les données historiques des prix des barres les plus élevées pour la paire symbole-période sélectionnée dans la quantité spécifiée.
CopyLow La fonction obtient dans low_array les données historiques des prix minimaux des barres pour la paire symbole-période sélectionnée dans la quantité spécifiée.
CopyClose La fonction obtient dans close_array les données historiques des prix de clôture des barres pour la paire symbole-période sélectionnée dans la quantité spécifiée.
CopyTickVolume La fonction obtient dans volume_array les données historiques des volumes de traits pour la paire symbole-période sélectionnée dans la quantité spécifiée.
CopyRealVolume La fonction entre dans volume_array les données historiques des volumes trading pour la paire symbole-période sélectionnée dans la quantité spécifiée.
CopySpread La fonction obtient dans spread_array les données historiques des valeurs de propagation pour la paire symbole-période sélectionnée dans la quantité spécifiée.

Les détails peuvent être trouvés dans la section de l'aide.

Ces données sont transmises sous format unique d'indicateur, pour l'autre, elles doivent s’approprier leur propre format.

En raison du fait que le type du tableau de données historiques n'est pas nécessairement double, il est recommandé de n'utiliser que des mémoires tampons dynamiques non indicatrices pour leur stockage.

Il existe également un autre détail non documenté - si le nombre de données copiées est égal à 0 (zéro), la fonction CopyBuffer générera une erreur avec le code №4003, donc le nombre de données à copier ne doit pas être inférieur à 1 (un) élément.

 

Les tampons indicateurs

Le nombre des tampons n'est pas limité.

Maintenant, vous n'avez pas à penser comment adapter les informations correctement, comment effectuer les calculs intermédiaires efficacement, en travaillant sur la création de l'indicateur de cluster.

Mais il ne faut pas oublier que le stockage des tampons nécessite de la mémoire. Par conséquent, si vous spécifiez une profondeur historique de terminal d'environ 1 000 000 de barres et attachez l'indicateur de cluster « épais » au graphique des minutes, ne soyez pas surpris de voir le terminal consommer des Go de mémoire.

L'essence du tampon a également subi quelques changements. La quantité de tampons utilisés est spécifiée dans les propriétés internes.

#property indicator_buffers 2       // buffers used

Cette valeur doit correspondre au nombre total de tampons.

Le nombre de tampons affichés est défini par les propriétés :

#property indicator_plots 1         // buffers displeyed

Voici quelques détails. La plupart des styles de dessin n'ont besoin que d'un seul tampon INDICATOR_DATA pour le dessin. Cependant, certains styles nécessitent plusieurs tampons d'indicateurs pour le dessin.

Nous nous référons aux styles de dessin suivants :

  • DRAW_HISTOGRAM2 - requiert deux tampons indicateurs (HistogramSample.mq5)

  • DRAW_FILLING - requiert deux tampons indicateurs (CrossMa.mq5)

  • DRAW_CANDLES - requiert quatre tampons indicateurs (CandleSample.mq5)

  • DRAW_BARS - requiert quatre tampons indicateurs (BarsSample.mq5)

Tous les types ci-dessus, sauf le style DRAW_FILLING (qui requiert pas de couleur), a des analogues colorés.

Tous les tampons d'indicateurs sont désormais divisés en 3 types :

  • INDICATOR_DATA - tampons, dont les données sont affichées sur le graphique. Ces tampons sont destinés au dessin et à l'utilisation d’ iCustom. Ils doivent être enregistrés en premier. Dans le cas de leur ordre arbitraire (incorrect), le code sera compilé avec succès et il sera dessiné lorsqu'il est appliqué à un graphique, cependant, très probablement, de manière incorrecte.

  • INDICATOR_COLOR_INDEX - tampons pour un stockage de couleurs. Ils sont nécessaires pour stocker les indices de tampon de couleur de type INDICATOR_DATA, ayant l'un des types de couleur spéciaux (#property indicator_typeN). Un tel tampon (nous nommons son tampon de couleur) doit être enregistré juste après le tampon principal, qui l'utilise.

  • INDICATOR_CALCULATIONS - les tampons d'un tel type sont destinés à stocker les résultats des calculs auxiliaires. Ils ne sont pas affichés sur le graphique.

int OnInit()
{
   // ...
   SetIndexBuffer(0, V2, INDICATOR_DATA);
   SetIndexBuffer(1, V2C,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, V4, INDICATOR_DATA);
   SetIndexBuffer(3, V4C,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(4, V1, INDICATOR_CALCULATIONS);
   SetIndexBuffer(5, V3, INDICATOR_CALCULATIONS);

   // ...
   return 0;
}

Il existe également certaines fonctionnalités lorsque l'on se réfère aux indicateurs via iCustom.

  • Les tampons pour le dessin (ceux qui sont affichés sur le graphique) sont disponible pour la lecture. Le numéro de tampon (indice) doit correspondre à celui pour lequel le tampon est enregistré.
  • Les tampons pour un stockage de couleur peuvent être disponibles pour la lecture, mais pas toujours. Par exemple, dans le code ci-dessus, le tampon V2C peut lire et obtenir les valeurs nécessaires, mais le tampon V4C n'est pas disponible.
  • Les tampons pour les calculs intermédiaires ne sont pas disponibles, comme c'était dans MQL4. Si vous voulez avoir un accès garanti au tampon de données externes, déclarez-le comme INDICATOR_DATA.

Dans le cas de la requête au tampon inaccessible, l'erreur 4806 Les données demandées sont introuvables ») sera générée.

Considérons les tampons de couleur en détail.

Dans MQL4, pour chaque couleur, il était nécessaire de créer un tampon séparé, mais maintenant en utilisant les styles de couleurs, vous pouvez spécifier jusqu'à 63 couleurs pour un seul tampon. Dans certains cas, cela permettra d'optimiser le nombre de tampons utilisés, et ainsi que d'économiser l'utilisation de la mémoire. Cela ouvre également de nouvelles possibilités d'écriture d'indicateurs, en particulier, l'utilisation de la visualisation des tons.

De plus, cette innovation dans certains cas, simplifie grandement la logique de l'application de plusieurs couleurs par rapport au MQL4. L’ exemple le plus évident - séparation des tendances par couleurs. Dans MQL4, pour le cas très économique (à partir de cas corrects) de la mise en application, il a fallu trois (3) tampons et lune programmation non triviale.

Maintenant, c'est plus facile que jamais. Voici les exemples de code, la mise en application complète se trouve dans le fichier Color_RSI.mq5.

#property indicator_color1 clrDarkSalmon, clrDeepSkyBlue // use 2 colors
#property indicator_type1  DRAW_COLOR_LINE               // and the special color display type
//---- buffers
double Values[];                 // buffer of values
double ValuesPainting[];         // buffer of color indices
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- bind indicator buffers
//--- Values serves as a display buffer
   SetIndexBuffer(0,Values,INDICATOR_DATA);
//--- ValuesPainting serves as the buffer for storing colors
   SetIndexBuffer(1,ValuesPainting,INDICATOR_COLOR_INDEX);
//...
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(/*...*/)
  {
//--- number of bars for calculation
   int toCount=(int)MathMin(rates_total,rates_total-prev_calculated+1);
//--- try to copy iRSI indicator data
   if(CopyBuffer(RSIHandle,0,0,toCount,Values)==-1)
     {
      Print("Data copy error, №",GetLastError());
      //--- return command for recalculation of the indicator values
      return(0);
     }
//--- coloring. Yer, now it has become that easy
   for(int i=toCount-2;i>=0;--i)
     {
      //--- coloring the first line
      if(Values[i+1]!=EMPTY_VALUE && Values[i]>Values[i+1])
         ValuesPainting[i]=1;
      else
         ValuesPainting[i]=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Un peu plus de code, et nous obtenons ce qui suit :

On devrait noter certains détails lors de l'utilisation de types de couleurs pour le dessin.

Pour les tampons de couleur, lors de l'utilisation d'un schéma de définition de couleur dynamique, le nombre maximal de couleurs est limité par le nombre de couleurs défini dans la propriété indicator_colorN. Par exemple,

#property indicator_color1 clrDarkSalmon, clrDeepSkyBlue // use 2 colors

Le schéma de couleurs du tampon contiendra au maximum deux couleurs, même si vous définissez dynamiquement un plus grand nombre de couleurs (à l'aide de PlotIndexSetInteger).

Par conséquent, le nombre requis de couleurs doit être écrit en une seule ligne - ligne de définition de propriétés. Ensuite, elles peuvent être modifiées dynamiquement. La couleur la plus courte que j'ai découverte - « Rouge ». Cependant, vous pouvez toujours effectuer les opérations suivantes :

En lieu et place de

#property indicator_color1  clrRed, clrRed, clrRed, clrRed, clrRed, clrRed, clrRed, clrRed, //…

vous pouvez écrire :

#define C clrRed
#property indicator_color1  C, C, C, C, C, C, C, C, C, C, C, C, C, C, //…

Le nombre maximum de couleurs pour un tampon est de 63. Lorsque le nombre de couleurs supérieur au tampon maximal (défini par la propriété indicator_colorN) n’est pas affiché.

Voici un exemple de visualisation des tons, en utilisant le nombre maximum de couleurs :

En général, les possibilités de dessin ont considérablement augmenté, et c'est très bien.

 

Tableaux

Lors de la référence directe aux données de tableau par indices, il faut désigner le type de classement des données - propriété AsSeries. Il ne peut pas être défini pour certains types de tableaux.

Ce drapeau ne peut pas être défini pour les tableaux multidimensionnels et statiques. Pour les types de tableaux qui sont transmis à la fonction OnCalculate, il est possible de définir un tel drapeau.

La copie de données à l'aide de la fonction CopyBuffer ne dépend pas de la propriété AsSeries, mais sa mise en application est différente pour différents tampons.

Pour les tampons d'indicateurs, il est nécessaire de copier toute la profondeur de l'historique disponible. Il faut s'en souvenir.

Pour les tableaux dynamiques et statiques (avec une taille prédéfinie), la copie des données est effectuée du présent vers le passé.

La fonction CopyBuffer modifie la taille des tampons pour les tampons dynamiques (à l'exception des indicateurs) pour la taille nécessaire.

Il n'est pas recommandé d'utiliser les tableaux statiques pour la copie de données.

En général, je vous conseille de toujours vérifier, comment vous copiez les données et comment vous les traitez. Le moyen le plus simple et le plus sûr est :

  • de définir la propriété AsSeries pour tous les tampons utilisés pour le stockage des données historiques.
  • de prendre en compte les structures tampons pour les différents tampons.
  • de toujours vérifier la valeur de la variable _LastError (dernier code d'erreur).

En outre, je conseille fortement d'étudier l'aide de la fonction CopyBuffer et de toutes les fonctions liées à la propriété AsSeries.

 

IndicatorCounted

Maintenant, les débats sur la nécessité de la fonction IndicatorCounted tomberont dans l'oubli, car cette valeur est définie directement par nous comme valeur retour de l'appel de fonction précédent.

int OnCalculate(const int rates_total,      // array size
                const int prev_calculated,  // bars processed after last call
                //...)
  {
   return rates_total;
  }

Le plus souvent, il suffit de retourner la valeur rates_total qui contient le nombre de barres de l'appel de fonction en cours.

Cependant, si les données de prix ont été modifiées depuis le dernier appel OnCalculate() (par exemple, les données historiques ont été chargées ou les blancs de données historiques ont été remplis), alors la valeur du paramètre d'entrée prev_calculated

sera mis à 0 (zéro) par le terminal client.

En outre, si la fonction OnCalculate renvoie zéro, les valeurs de l'indicateur ne sont pas affichées dans la DataWindow du terminal client. Par conséquent, si vous voulez voir l'indicateur et effectuer un recalcul complet pendant le processus de chargement de l'historique ou après un défaut de connexion, retournez à 1 au lieu de 0.

L'autre fonctionnalité utile qui a été ajoutée est de déterminer combien de barres ont été calculées pour l’ indicateur Il est plus utile pour les Expert Advisors qui effectuent des calculs sur des données volumineuses. La fonction est BarsCalculated, et ses détails peuvent être trouvés dans la section de l'aide.

Cette fonction a une autre application utile. Si l'indicateur n'a pas été chargé, son chargement peut prendre un certain temps - le temps entre la création du descripteur de l'indicateur et son utilisation pour les calculs.

Ce temps est nécessaire à l'initialisation et à son pré-calcul initial. Cela dépend de la vitesse de calcul et des détails de l'indicateur.

Pendant ce temps, l'appel de la fonction CopyBuffer génère l'erreur 4806 - « Les données demandées sont introuvables »..

La fonction BarsCalculated peut servir dans la détermination de la disponibilité des données de l'indicateur à copies:

//--- number of bars for calculation
   int toCount=rates_total-(int)MathMax(prev_calculated-1,0);
//--- try to copy iWPR indicator data
   int copied=CopyBuffer(WPRHandle,0,0,toCount,Values);
   int err=GetLastError();
//--- check coying result
   if(copied==-1)
     {
      //--- if error number is 4806, the data simply have not been uploaded yet
      if(err==4806)
        {
         //--- wait till the data is uploaded
         for(int i=0;i<1000;++i)
            if(BarsCalculated(WPRHandle)>0)
               break;
         //--- try to copy iWPR indicator data again
         copied=CopyBuffer(WPRHandle,0,0,rates_total,Values);
         err=GetLastError();
        }
     }
//--- check coying result
   if(copied==-1)
     {
      Print("Error when trying to get WPR values, last error is ",err," bars ",rates_total);
      return(0);
     }
//...

 

Sommaire

En conclusion, je voudrais dire qu’il n’y a que quelques-uns des détails qui ont été examinés dans cet article. Mais j'espère que les aspects fondamentaux sont présentés ici.

Ce serait super si cet article pouvait être une référence utile en cette matière, où vous pourriez toujours regarder et trouver des informations détaillées.

Si vous avez trouvé des erreurs dans cet article, ou avez découvert quelque chose d'important, veuillez m'en informer et j'essaierai de le corriger et d'améliorer l'article dès que possible.

Je prévois de décrire les changements récents, en plus de cela, j'espère que certaines des informations utiles apparaîtront dans les commentaires.

C'est pour cette raison qu’il faudrait en faire une lecture attentive.

 

Annexe

  • Color.mqh - fichier d'inclusion, copiez ce fichier dans le dossier MQL5/Include. Ce fichier est nécessaire pour l'indicateur Toned_WPR.
  • Color.mq5 - bibliothèque, copiez ce fichier dans le dossier MQL5/Libraries. Ce fichier est nécessaire pour l'indicateur Toned_WPR.

Tous les fichiers ci-dessus sont des indicateurs.

 

Remerciements

Encore une fois, je tiens à remercier Mr. Victor Rustamov (granit77) pour la lecture du manuscrit, les discussions utiles et les conseils pertinents.


Traduit de l’anglais par MetaQuotes Ltd.
Article original : https://www.mql5.com/en/articles/5

Fichiers joints |
crossma.mq5 (2.47 KB)
candlesample.mq5 (2.31 KB)
barssample.mq5 (2.3 KB)
color.mq5 (4.28 KB)
color.mqh (0.99 KB)
toned_wpr.mq5 (4.65 KB)
color_rsi.mq5 (5.57 KB)
MQL5 : Créez votre propre indicateur MQL5 : Créez votre propre indicateur
Qu’est-ce qu’un indicateur? C’est un ensemble de valeurs calculées que nous voulons afficher à l’écran de manière pratique. Les ensembles de valeurs sont représentés dans les programmes sous forme de tableaux. Ainsi, la création d’un indicateur signifie écrire un algorithme qui gère certains tableaux (tableaux de prix) et enregistre les résultats de la manipulation sur d’autres tableaux (valeurs d’indicateur). En décrivant la création de True Strength Index, l’auteur montre comment écrire des indicateurs dans MQL5.
Voici les nouveaux MetaTrader 5 et MQL5 Voici les nouveaux MetaTrader 5 et MQL5
Ceci n'est qu'un bref aperçu de MetaTrader 5. Je ne peux pas décrire toutes les nouvelles fonctionnalités du système sur une période aussi courte - les tests ont commencé le 09.09.2009. C'est une date symbolique, et je suis sûr que ce sera un chiffre porte-bonheur. Quelques jours se sont écoulés depuis que j'ai obtenu la version bêta du terminal MetaTrader 5 et MQL5. Je n'ai pas réussi à essayer toutes ses fonctionnalités, mais je suis déjà impressionné.
Appliquer un indicateur à un autre Appliquer un indicateur à un autre
Lors de l'écriture d'un indicateur qui utilise la forme abrégée de l'appel de fonction OnCalculate(), vous pourriez manquer le fait qu'un indicateur peut être calculé non seulement par les données de prix, mais également par les données d'un autre indicateur (qu'il s'agisse du type intégré ou personnalisé). Vous souhaitez améliorer un indicateur pour sa bonne application aux données de l'autre indicateur ? Dans cet article, nous passerons en revue toutes les étapes requises pour une telle modification.
Utilisez les canaux MQL5.community et les discussions de groupe Utilisez les canaux MQL5.community et les discussions de groupe
Le site MQL5.com rassemble des traders du monde entier. Les utilisateurs publient des articles, partagent des codes gratuits, vendent des produits sur le Market, effectuent des commandes auprès des Freelance et copient des signaux de trading. Vous pouvez communiquer avec eux sur le Forum, dans les chats des traders et dans les canaux MetaTrader.