English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Gestion des événements dans MQL5 : Modification de la période  MA à la volée

Gestion des événements dans MQL5 : Modification de la période MA à la volée

MetaTrader 5Indicateurs | 15 novembre 2021, 15:01
156 0
Sceptic Philozoff
Sceptic Philozoff

Introduction

Ce court article est consacré à l'une des nouvelles fonctionnalités MQL5 de la plateforme MetaTrader 5, élaborée par MetaQuotes Software Corp. Peut-être que cet article est légèrement en retard (il aurait dû être publié en septembre-octobre 2009 - alors il serait opportun), mais il n'y avait pas d'articles similaires sur ce sujet. De plus, à cette époque, il n'y avait pas de telles possibilités pour gérer les événements dans les indicateurs.

Imaginez que nous ayons un indicateur de prix simple appliqué à un graphique (dans ce cas, il s'agit de la Moyenne Mobile, c'est-à-dire MA), et dont nous souhaitons modifier sa période de lissage. Dans la plate-forme MT4, nous avions les options suivantes :

  • En MetaEditor, vous pouvez éditer le paramètre d'entrée expert (extern), responsable de la période MA, puis compiler le fichier source.
  • Sans passer à MetaEditor, directement dans la fenêtre du terminal, vous pouvez ouvrir la boîte de dialogue Propriétés de l'indicateur et y modifier le paramètre d'entrée correspondant.
  • Vous pouvez ouvrir la bibliothèque API Win32, trouver des fonctions de capture de messages, puis ajuster le code de l'indicateur pour qu'il réponde aux événements depuis le clavier.

Comme nous le savons, le désir du minimum d'efforts est le plus grand moteur de progrès. Désormais, grâce à une nouvelle plate-forme MT5, qui permet la gestion des événements d'indicateurs initiés par l'utilisateur, nous pouvons ignorer les possibilités ci-dessus et modifier les paramètres d’ indicateur en appuyant simplement sur une touche. Cet article couvre l’implémentation technique de cette solution de problème.

Affectation des tâches et problèmes

Le code source de l'indicateur, utilisé dans nos expériences, est livré avec Client Terminal. Le fichier de code source inchangé (Custom Moving Average.mq5) est joint à la fin de cet article.

Pour l'instant nous n'analyserons pas le code source et surtout les modifications par rapport à son MQL4 d'origine. Oui, à certains endroits, cela a beaucoup changé, et ce n'est pas toujours évident. Les explications correspondantes, liées à la restructuration de la partie de base du calcul, se trouvent sur le forum et dans l'aide en ligne.

Néanmoins, la partie principale de l'indicateur en MQL4 est restée inchangée. Au moins 80% de toutes les modifications de code, destinées à résoudre notre problème, ont été effectuées sur la base de l'idée de fonctions de calcul d'indicateur comme les "boîtes noires".

Un exemple de ce que nous souhaitons réaliser ressemble à ceci. Admettons que nous ayons appliqué cet indicateur à un graphique et qu'à un moment donné, il affiche une MA exponentielle (EMA) avec un décalage de zéro et une période de 10. Notre objectif est d'augmenter la période de lissage de la MA simple (SMA) de 3 (jusqu'à 13), et de la décaler de 5 barres vers la droite. La séquence d'action admise est la suivante :

  • Appuyez plusieurs fois sur la touche TAB pour changer le MA affiché d'exponentiel à simple (changement de type MA).
  • Appuyez trois fois sur la touche fléchée UP de la partie principale du clavier pour augmenter la période simple de MA par 3.
  • Appuyer 5 fois sur la touche fléchée UP (8) du pavé numérique pour décaler MA de 5 barres vers la droite.

La première et la plus évidente des solutions consiste à insérer la fonction OnChartEvent() dans le code indicateur et à écrire le gestionnaire d'événements de touche. Selon la liste des modifications dans le terminal client MetaTrader 4 builds 245 et 246 https://www.mql5.com/en/forum/53/page1/#comment_2655,

Terminal Client MetaTrader 5 build 245 et 246

MQL5: a ajouté de la possibilité de gérer les événements par des indicateurs personnalisés, similaire à celui des Expert Advisors.

Donc, maintenant, nous n'avons aucun souci avec l'ajout de nouveaux gestionnaires d'événements dans l'indicateur. Mais pour cela nous devons encore modifier légèrement son code.

Premièrement, en MQL5, l'état des paramètres externes de l'indicateur a changé : vous ne pouvez pas les modifier dans le code. La seule façon de les modifier est via la boîte de dialogue Propriétés dans le terminal client. Généralement, en cas de besoin urgent de les modifier, cette restriction est facilement contournée : il suffit de copier les valeurs des paramètres externes dans les nouvelles variables globales de l'indicateur, et tous les calculs sont effectués comme si ces nouvelles variables étaient en fait les paramètres externes de l'indicateur. En revanche, dans ce cas s'en va la faisabilité des paramètres externes, dont les valeurs ne peuvent que tromper les utilisateurs. Maintenant, ces paramètres ne sont tout simplement plus nécessaires.

Ainsi, il n'y a pas de paramètres externes (d'entrée) dans l'indicateur. Les variables jouant le rôle de paramètres externes, seront désormais les Variables Globales Terminales ou TGV, pour faire court. Si vous voulez voir le TGV, responsable des anciens paramètres externes de l'indicateur, vous pouvez simplement appuyer sur la touche F3 dans le terminal. Je ne trouve pas d'autre moyen simple de contrôler les paramètres de l'indicateur.

Deuxièmement (et c'est important), lors de toute modification dans les paramètres externes de l'indicateur, nous devons recalculer toutes ses valeurs tout au long de l'historique, à nouveau et à partir de zéro. En d'autres termes, nous devrons effectuer des calculs, qui ne sont généralement effectués qu'au tout premier démarrage de l'indicateur. L'optimisation des calculs de l'indicateur demeure, mais maintenant elle devient plus subtile.

Plusieurs parties de code de la première version de l'indicateur modifié s trouvent ci-dessous. Le code complet est joint à la fin de cet article.

 

Version « standard » : la description des modifications dans le code source de l'indicateur standard

Les paramètres externes ne sont plus externes, mais simplement des variables globales

Tous les paramètres externes de l'indicateur ont perdu leur modificateur d'entrée. Généralement, je ne pouvais même pas les rendre globales, mais j'ai décidé de le faire par tradition :

int              MA_Period   = 13;
int              MA_Shift    =  0;
ENUM_MA_METHOD   MA_Method   =  0;
int              Updated     =  0;     /// Indicates whether the indicator has updated after changing it's values

Les trois premières options - sont la période, le décalage et le type de MA, et la quatrième - Mis à jour - est responsable de l'optimisation des calculs, lors de la modification des paramètres MA. Les explications se trouvent en quelques lignes ci-dessous. 

Codes clés virtuelles

Saisissez les codes des clés virtuelles :

#define KEY_UP             38
#define KEY_DOWN           40
#define KEY_NUMLOCK_DOWN   98
#define KEY_NUMLOCK_UP    104
#define KEY_TAB             9

Il s'agit des codes des touches « flèche vers le haut » et « flèche vers le bas », des flèches similaires sur le clavier numérique (touche « 8 » et « 2 »), ainsi que la touche TAB. Les mêmes codes (avec d'autres noms de constantes VK_XXX) existent en fait dans le fichier <MT5dir>\MQL5\Include\VirtualKeys.mqh, mais dans ce cas j'ai décidé de le laisser tel quel.


Petite correction de code en fonction, calcul de la moyenne mobile pondérée linéaire (LWMA)

J'ai fait un petit ajustement dans la fonction CalculateLWMA() : dans la version originale, la variable de somme de poids était déclarée à l'aide du modificateur statique. Apparemment, la seule raison pour laquelle les développeurs ont fait cela était la nécessité de le pré-calculer lors du premier appel de cette fonction. De plus, dans le code, cette variable reste inchangée. Voici le code original de cette fonction, dans lequel les parties liées au calcul et à l'utilisation de la somme des poids sont marquées par des commentaires :

void CalculateLWMA(int rates_total,int prev_calculated,int begin,const double &price[])
  {
   int              i,limit;
   static int     weightsum;                       // <-- using weightsum
   double               sum;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)                          // <-- using weightsum
     {
      weightsum=0;                                 // <-- using  weightsum
      limit=InpMAPeriod+begin;                     // <-- using weightsum
      //--- set empty value for first limit bars
      for(i=0;i<limit;i++) ExtLineBuffer[i]=0.0;
      //--- calculate first visible value
      double firstValue=0;
      for(i=begin;i<limit;i++)                     // <-- using weightsum
        {
         int k=i-begin+1;                          // <-- using weightsum
         weightsum+=k;                             // <-- using weightsum
         firstValue+=k*price[i];
        }
      firstValue/=(double)weightsum;
      ExtLineBuffer[limit-1]=firstValue;
     }
   else limit=prev_calculated-1;
//--- main loop
   for(i=limit;i<rates_total;i++)
     {
      sum=0;
      for(int j=0;j<InpMAPeriod;j++) sum+=(InpMAPeriod-j)*price[i-j];
      ExtLineBuffer[i]=sum/weightsum;              // <-- using weightsum
      }
//---
  }

Auparavant, cette variante fonctionnait assez bien, mais lorsque j'ai exécuté le tandem "indicateur + conseiller" (ceci est mentionné à la fin de cet article), dans ce type même de MA, des problèmes sont survenus. Le principal était causé par les circonstances décrites ci-dessus, c'est-à-dire que la somme des poids était la variable statique : cette variable augmentait constamment car à chaque modification de paramètre MA à la volée, il était nécessaire de le recalculer à partir de zéro.

Le moyen le plus simple de calculer directement et immédiatement la valeur de la somme des poids (elle est égale à la somme des entiers de 1 à la période MA - à cet effet, il existe une formule simple pour la somme de la progression arithmétique), et en même temps de nier son statut en statique, ce que j'ai fait. Maintenant, au lieu de déclarer la somme de poids précédente à l'aide du modificateur statique, nous la déclarons sans lui, initialisons simplement avec la valeur "correcte" et supprimons ainsi la boucle initiale de "l'accumulation de variables".

int weightsum = MA_Period *( MA_Period + 1 ) / 2;

Maintenant, tout fonctionne correctement.


Fonction OnCalculate() en tant que gestionnaire

J'ai dû faire beaucoup de changements dans la fonction OnCalculate(), et donc je cite ici complètement son code.

int OnCalculate(const int rates_total,
                const int prev_calculated,            /// Mathemat: full recalculation!
                const int begin,                      /// Mathemat: full recalculation!
                const double &price[])
  {
//--- check for bars count
   if(rates_total<MA_Period-1+begin)
      return(0);// not enough bars for calculation
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
      ArrayInitialize(LineBuffer,0);
//--- sets first bar from what index will be draw
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,MA_Period-1+begin);

//--- calculation (Mthmt - optimized by Mathemat)

   if( GlobalVariableGet( "Updated" ) == 1 )
   {
      if(MA_Method==MODE_EMA)  CalculateEMA(       rates_total,prev_calculated,begin,price);
      if(MA_Method==MODE_LWMA) CalculateLWMA_Mthmt(rates_total,prev_calculated,begin,price);
      if(MA_Method==MODE_SMMA) CalculateSmoothedMA(rates_total,prev_calculated,begin,price);
      if(MA_Method==MODE_SMA)  CalculateSimpleMA(  rates_total,prev_calculated,begin,price);
   }
   else
   {
      OnInit( );                 /// Mthmt
      if(MA_Method==MODE_EMA)  CalculateEMA(       rates_total,0,0,price);
      if(MA_Method==MODE_LWMA) CalculateLWMA_Mthmt(rates_total,0,0,price);
      if(MA_Method==MODE_SMMA) CalculateSmoothedMA(rates_total,0,0,price);
      if(MA_Method==MODE_SMA)  CalculateSimpleMA(  rates_total,0,0,price);
      GlobalVariableSet( "Updated", 1 );
      Updated = 1;
   }
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

La principale modification concerne le besoin perçu d'un calcul complet de l'indicateur "à partir de zéro": il est évident que si la manipulation du clavier d'un utilisateur a modifié la période MA de 13 à 14, toutes les optimisations précédentes de ses calculs sont déjà obsolètes, et nous devons calculer à nouveau MA. Cela se produit lorsque la variable mise à jour a la valeur 0 (TGV s’est modifié après avoir appuyé sur la touche rapide , mais la coche, qui redessine l'indicateur, n'est pas encore venue).

Cependant, en plus, auparavant, nous devions appeler explicitement la fonction OnInit(), car nous devions modifier le nom abrégé de l'indicateur, qui sera affiché lorsqu'un curseur survolera la ligne. Après le calcul initial de la MA, le TGV mis à jour est défini sur 1, ce qui ouvre la voie au calcul optimisé de l'indicateur - jusqu'à ce que vous ne souhaitiez plus modifier un paramètre d'indicateur à la volée.


Gestionnaire OnChartEvent()

Vous trouverez ci-dessous un code simple du gestionnaire OnChartEvent() :

void OnChartEvent( const int          id,
                   const long    &lparam,
                   const double  &dparam,
                   const string  &sparam )
{
   if( id == CHARTEVENT_KEYDOWN )
      switch( lparam )
      {
         case( KEY_TAB          ):  changeTerminalGlobalVar( "MA_Method",  1 ); 
                                    GlobalVariableSet( "Updated",  0 );
                                    Updated = 0;
                                    break;
         
         case( KEY_UP           ):  changeTerminalGlobalVar( "MA_Period",  1 ); 
                                    GlobalVariableSet( "Updated",  0 );
                                    Updated = 0;
                                    break;
         case( KEY_DOWN         ):  changeTerminalGlobalVar( "MA_Period", -1 ); 
                                    GlobalVariableSet( "Updated",  0 );
                                    Updated = 0;
                                    break;
         
         case( KEY_NUMLOCK_UP   ):  changeTerminalGlobalVar( "MA_Shift",   1 ); 
                                    GlobalVariableSet( "Updated",  0 );
                                    Updated = 0;
                                    break;
         case( KEY_NUMLOCK_DOWN ):  changeTerminalGlobalVar( "MA_Shift",  -1 ); 
                                    GlobalVariableSet( "Updated",  0 );
                                    Updated = 0;
                                    break;
      }
      
      return;
}//+------------------------------------------------------------------+      

Le gestionnaire fonctionne de la manière suivante : vous appuyez sur la touche de raccourci, son code virtuel est défini, puis la fonction auxiliaire changeTerminalGlobalVar() est lancée et modifie correctement le TGV souhaité. Après cela, le drapeau mis à jour est remis à zéro, en attendant la coche, qui lancera OnCalculate() et redessinera l'indicateur "à partir de zéro".


Fonction auxiliaire qui change "correctement" le TGV

Et, enfin, le code de la fonction changeTerminalGlobalVar(), utilisé dans le gestionnaire OnChartEvent() :

void changeTerminalGlobalVar( string name, int dir = 0 )
{
   int var = GlobalVariableGet( name );
   int newparam = var + dir;
   if( name == "MA_Period" )
   {
      if( newparam > 0 )       /// Possible period is valid for MA
      {
         GlobalVariableSet( name, newparam ); 
         MA_Period = newparam;     /// Don't forget to change the global variable    
      }   
      else                       /// we do not change the period, because MA period is equal to 1 minimum
      {   
         GlobalVariableSet( name, 1 );     
         MA_Period = 1;     /// Don't forget to change the global variable 
      }   
   }   
      
   if( name == "MA_Method" )    /// Here when you call the 'dir' it is always equal to 1, the dir value is not important    
   {
      newparam = ( var + 1 ) % 4;
      GlobalVariableSet( name, newparam );  
      MA_Method = newparam;
   }      

   if( name == "MA_Shift" )
   {
      GlobalVariableSet( name, newparam );     
      MA_Shift = newparam;
   }      

   ChartRedraw( );
   return;
}//+------------------------------------------------------------------+

L'objectif principal de cette fonction - le calcul correct de nouveaux paramètres MA en tenant compte des "limitations physiques". Évidemment, on ne peut pas faire en sorte que la période MA soit inférieure à 1, le décalage MA peut être aléatoire, mais le type MA est le nombre de 0 à 3, correspondant à un numéro de membre conditionnel dans l'énumération ENUM_MA_METHOD.

 

Vérification. Cela fonctionne, mais "au grade C". Ce que nous pouvons faire?

OK, appliquons notre indicateur au graphique et commençons à appuyer sporadiquement sur les touches de raccourci, qui modifient les paramètres MA. Oui, tout fonctionne correctement, mais il y a un fait désagréable : les TGV changent immédiatement (vous pouvez le vérifier en appelant le TGV à l'aide de la touche F3), mais MA ne redessine pas toujours immédiatement, mais uniquement à l'arrivée du nouveau tick. Si nous avons une session américaine avec le flux de ticks actif, alors nous pouvons à peine remarquer le retard. Mais si cela se produit la nuit, pendant le calme, on peut attendre le re-dessinage plusieurs minutes. Quoi de neuf?

Eh bien, comme on dit, ce que vous écrivez, vous l'aurez ainsi. Avant de construire 245 dans les indicateurs, il n'y avait qu'un seul "point d'entrée" - la fonction OnCalculate(). Bien sûr, je ne parle pas des fonctions OnInit() et OnDeinit(), qui assurent les calculs initiaux, l'initialisation et l'achèvement de l'indicateur. Il existe maintenant plusieurs points d'entrée et ils sont connectés aux nouveaux événements Timer et ChartEventévènements.

Cependant, les nouveaux gestionnaires ne font que ce qu'ils comportent et ne sont pas formellement associés au gestionnaire OnCalculate(). Alors, que pouvons-nous faire avec notre gestionnaire "alien" OnChartEvent() pour le faire fonctionner "correctement", c'est-à-dire qu'il permettrait de redessiner immédiatement la MA ?

En général, il existe plusieurs façons d’implémenter cette exigence :

  • "Matryoshka" (appel OnCalculate() dans OnChartEvent()) : insérez l'appel de la fonction OnCalculate() dans ce gestionnaire, en pré-remplissant tous ses paramètres. Vu que le gestionnaire OnChartEvent() implique de modifier au moins un paramètre MA, alors il affectera tout son historique, c'est à dire qu'il faudra le recalculer à nouveau "à zéro", sans optimisation des calculs.
  • "Tick artificiel" qui transfère le contrôle au début de la fonction OnCalculate(), qui modifie le tampon graphique. Apparemment, il n'y a pas de méthodes "légitimes", comme en témoigne la documentation MT5 (bien que j'ai peut-être pas cherché aussi complètement). Si vous êtes intéressé, vous pouvez rechercher quelque chose comme « API », « PostMessageA », etc. Par conséquent, nous ne prenons pas en compte cette variante ici, car elle ne garantit pas que les fonctionnalités non documentées ne changeront pas un jour. Je n'ai aucun doute que cela puisse être réalisé.

 

« Matriochka » fonctionne !

Il s'avère que nous avons déjà fait la chose la plus importante. Vous trouverez ci-dessous un code de fonction très simple. Vous pouvez simplement insérer son appel directement devant l'opérateur de retour du gestionnaire OnChartEvent().

int OnCalculate_Void()
{
   const int rates_total = Bars( _Symbol, PERIOD_CURRENT );
   CopyClose( _Symbol, PERIOD_CURRENT, 0, rates_total, _price );
   OnCalculate( rates_total, 0, 0, _price );
   return( 1 );
}//+------------------------------------------------------------------+

Après avoir compilé et appliqué l'indicateur au graphique, nous constatons qu'en général le code fonctionne rapidement et indépendamment de l'arrivée des ticks.

L'inconvénient de cette implémentation est que les prix de clôture sont exactement copiés dans le tableau price[]. Si vous le souhaitez, la fonction CopyClose() peut être remplacée par ce que nous souhaitons en définissant le champ "Appliquer à" dans l'onglet "Paramètres" de la boîte de dialogue des propriétés de l'indicateur. Si le prix actuel sera basique (Open, High, Bas, Close), alors nous avons déjà la fonction correspondante CopyXXXX(). Dans le cas de prix plus compliqués (Moyen, Typique ou Pondéré), nous devons calculer le tableau autrement.

Je ne sais pas si nous n'avons pas besoin de la fonction CopyClose(), qui copie l'intégralité de l'historique du tableau. Par contre, cette fonction est assez rapide lorsque l'historique n'est pas trop chargé. La vérification de l'indicateur sur EURUSD H1 avec l'historique avant 1999 (environ 700 mille barres) a indiqué que l'indicateur traite des calculs et n’affiche aucun ralentissement. Sur un tel historique, les éventuels ralentissements peuvent être causés non pas par la fonction CopyXXXX(), mais par la nécessité de recalculer l'indicateur plus compliqué depuis le début de l'historique (ceci est obligatoire).


Plusieurs constatations et conclusion

Quoi de mieux - un seul fichier indicateur ou tandem « indicateur + conseiller » ?

En fait, cette question n'est pas si simple. D'une part, il est bon d'avoir un seul fichier d'indicateurs, car toutes les fonctions, y compris les gestionnaires d'événements, sont concentrées au même endroit.

D'un autre côté, imaginons qu'il y ait 3 ou 4 indicateurs appliqués au graphique avec un Expert Advisor - cette situation n'est pas rare. De plus, admettons que chaque indicateur soit équipé de son propre gestionnaire d'événements, en plus du OnCalculate() standard. Pour éviter toute confusion avec le traitement des événements dans cette "crue hétéroclite", il est plus raisonnable de concentrer tous les gestionnaires d'événements, désormais autorisés dans les indicateurs, en un seul endroit - dans Expert Advisor.

Depuis longtemps, les développeurs de logiciels ont décidé de nous offrir la possibilité de traiter les événements de l'indicateur : à partir de la version bêta non publique du 09.09.09 (lorsque l'indicateur est considéré comme "pur calcul & entité mathématique" et ne doit pas être contaminé par des caractéristiques qui entravent la vitesse de calcul) ont passé exactement 5 mois. Probablement, la "pureté de l'idée" doit souffrir - et maintenant un véritable chaos de fantasmes de programmeurs sera déclenché. Mais l'équilibre est toujours quelque part entre au milieu d’ une idée pure, mais limitée, et pas si propre, mais une capacité plus puissante.

En septembre-octobre 2009, alors que le numéro de build de la version bêta de MT5 n'a même pas atteint 200, j'ai écrit et débogué le code du tandem "Expert Adviser + Indicator", qui permettait de gérer les paramètres MA à la volée, mais " au grade C" : il n'a été mis à jour qu'après l'arrivée des ticks, mais pas immédiatement. À l'époque, ce tandem était la seule solution possible, et maintenant il est peu probable qu'il soit intéressant pour qui que ce soit.

Je ne pouvais pas alors penser à la manière d'amener la fonctionnalité d'indicateur au "grade B", c'est-à-dire tel qu'il est présenté dans la dernière version. Maintenant, j’ai le plaisir de vous offrir une solution plus pratique à tous ceux qui peuvent être intéressés.


Ci-joint ma courte vidéo, démontrant le travail de notre création. Le changement en douceur de la courbe MA (seule la période change - elle augmente d'abord, puis diminue) est même éblouissante d'une certaine manière. C'est Matryoshka (semblable au célèbre ensemble de poupées russes).


Bien sûr, de telles astuces ne sont utiles que lorsque le calcul de l'indicateur lui-même à partir de zéro ne prend pas trop de temps. L'AMM simple, contenue dans cet indicateur, répond à cette exigence.


Un aspect glissant

Rappelez-vous que les anciens paramètres externes de l'indicateur sont désormais les variables globales terminales (TGV), que vous pouvez voir en appuyant sur la touche F3. Admettons que vous ayez ouvert la boîte de dialogue Variables globales et modifié l'un des TGV (par exemple, la période MA). Vous vous attendez à ce que cette modification se reflète immédiatement dans l'indicateur sur le graphique.

Actuellement dans le terminal il n'y a pas d'événement, correspondant à l'édition TGV faite par l'utilisateur (par exemple, CHARTEVENT_GLOBALVAR_ENDEDIT). De plus, je pense que nous ne pouvons pas désactiver la modification TGV dans la boîte de dialogue Variables globales. Par conséquent, ici, nous ne pouvons compter sur aucun événement, à l'exception du tick. Que va-t-il se passer en vrai ?

Si vous ne touchez pas le clavier ,alors même sur le prochain tick, la mise à jour sera «erronée» : La variable mise à jour n’était pas réglée à zéro et en conséquence le seul calcul d’indicateur «optimisé»(correspondant à la valeur précédente de la variable changée TGV) sera effectué. Dans ce cas, pour rétablir la justice, nous ne pouvons conseiller qu'une seule chose : après avoir édité TGV vous devez au moins appuyer une fois sur la touche de raccourci, qui modifie le TGV, définit le Updated = 0 et provoque un recalcul complet de l'indicateur.

Tous les utilisateurs et développeurs potentiels doivent garder ce fait à l'esprit.


Fichiers joints du code source et de la vidéo

Enfin, je joins les fichiers de code source. Explication:

  1. Moyenne Mobile Personnalisée.mq5 - Fichier de code source MA, livré avec MT5.
  2. MyMA_ind_with_ChartEvent.mq5 - Implémentation initiale ("C grade") : l'indicateur ne se met à jour qu'après l'arrivée des ticks.
  3. MyMA_ind_with_ChartEvent_Matryoshka.mq5 - la deuxième variante (peut-être, "note B") : l'indicateur se met à jour immédiatement, sans attendre l'arrivée des ticks.

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

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.
MQL5: Analyse et traitement des rapports de la Commodity Futures Trading Commission (CFTC) dans MetaTrader 5 MQL5: Analyse et traitement des rapports de la Commodity Futures Trading Commission (CFTC) dans MetaTrader 5
Dans cet article, nous allons élaborer un outil d’analyse des rapports CFTC. Nous allons résoudre le problème suivant: élaborer un indicateur, qui permet d’utiliser les données du rapport CFTC directement à partir des fichiers de données fournis par la Commission sans traitement intermédiaire et conversion. En outre, il peut être utilisé à différentes fins: pour tracer les données en tant qu’indicateur, pour procéder avec les données dans les autres indicateurs, dans les scripts pour l’analyse automatisée, dans les Expert Advisors pour l’utilisation dans les stratégies de trading.
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.
Implémentation pratique des Filtres Numériques dans MQL5 pour les débutants Implémentation pratique des Filtres Numériques dans MQL5 pour les débutants
L'idée du filtrage des signaux numériques a été largement discutée sur des sujets de forum concernant la création de systèmes de trading. Et il serait imprudent de ne pas créer un code standard de filtres numériques en MQL5. Dans cet article, l'auteur décrit la transformation du code d'un simple indicateur SMA de son article "Indicateurs Personnalisés dans MQL5 pour les Débutants" en code de filtre numérique plus compliqué et universel. Cet article est une suite logique de l'article précédent. Il explique également comment remplacer le texte dans le code et comment corriger les erreurs de programmation.