English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
calcul de moyenne des Séries de Prix pour les Calculs Intermédiaires Sans Utiliser de Tampons Supplémentaires

calcul de moyenne des Séries de Prix pour les Calculs Intermédiaires Sans Utiliser de Tampons Supplémentaires

MetaTrader 5Indicateurs | 17 novembre 2021, 16:43
177 0
Nikolay Kositsin
Nikolay Kositsin

Introduction

Dans mon article "Les Principes du Calcul Économique des Indicateurs", j'ai conduit des tests raisonnablement concluants qui prouvent le fait que chaque appel d'un indicateur personnalisé ou technique dans un code n'est pas le moyen le plus optimal d'effectuer des calculs intermédiaires dans un indicateur élaboré.

La vitesse d'exécution finale peut sembler beaucoup plus faible, comparée à ce que nous aurions si nous placions le code des calculs intermédiaires directement dans notre indicateur.

Ce genre d'approche pour écrire un code serait très attrayant, s'il était assez simple. En fait, cela semble être une importante complication d'un code avec la description de tampons supplémentaires utilisés pour stocker des résultats intermédiaires de calcul.

Malgré la variété des calculs intermédiaires, ceux qui sont le plus nécessaires sont différents des algorithmes de moyennage. Dans la plupart des cas, pour eux, nous pouvons utiliser des fonctions personnalisées simples et universelles qui simplifient considérablement la tâche d'écriture d'un tel code. Le processus de création de ces fonctions et de leur fonctionnement seront décrits dans cet article.


1. L'Idée Générale des Fonctions de calcul de moyenne qui Fonctionnent avec une Barre

L'approche classique du calcul de moyenne sur une barre actuelle consiste en un tampon d'indicateur intermédiaire, que nous remplissons avec les informations requises, puis sélectionnons une plage de valeurs précédentes, qui est égale à la période de calcul de moyenne, et calculons la valeur moyenne.

La procédure de traitement de cette sélection se présente comme suit :

SmoothVar(bar) = Function(Var(bar - (n-1)), Var(bar - (n-2)), ......... Var(bar)) 

Où :

  • SmoothVar(bar) — paramètre moyenné ;
  • bar — numéro d'une barre pour laquelle le calcul est effectué ;
  • Var(bar - (n-1)) — paramètres moyens avec un décalage sur (n-1) barres ;
  • n — nombre de barres pour la calcul de moyenne.

Une telle approche de calcul de moyenne, dans notre cas, conduit à l'apparition de deux cycles de calcul. Dans le premier cycle, les données sont calculées et mises dans un tampon intermédiaire. Au deuxième cycle, le calcul de la moyenne à l'aide d'un autre cycle de recherche supplémentaire de cellules du tampon indicateur est effectué sur la base de la formule suggérée ci-dessus. Ce calcul semblera beaucoup plus facile si nous accumulons la sélection de données intermédiaires au sein de la fonction elle-même. Dans ce cas, la fonction de calcul de moyenne ressemblera à ceci :

SmoothVar(bar) = Function(Var(bar), bar)

Une nouvelle valeur Var(barre) est écrite dans la sélection de valeurs à l'intérieur de la fonction sur une barre actuelle, et les valeurs de Var(bar - n) qui deviennent inutiles sont supprimées de la sélection. Avec cette approche, un code de calcul de moyenne semble assez trivial et ne nécessite pas de tampons d'indicateurs supplémentaires. À l'intérieur de la fonction, le tableau stocke la quantité exacte de données nécessaires au calcul d'une barre, et non l'intégralité des données de l'historique.

Dans ce cas, il n'y a également qu'un seul cycle de calcul des données. A noter que pour appeler cette fonction de calcul de moyenne sur une barre courante, il faut d'abord l'appeler sur toutes les barres précédentes !


2. La Calcul de Moyenne Classique comme exemple de mise en œuvre d'une fonction qui opère avec une barre

De telles fonctions de calcul de moyenne doivent comporter des variables qui ne doivent pas perdre leurs valeurs entre les appels de ces fonctions. De plus, le calcul de moyenne de type unique avec différents paramètres peut être utilisé plusieurs fois dans un code ; par conséquent, pour éviter un conflit d'utilisation des ressources de mémoire partagée, nous devons implémenter ces fonctions en tant que classes ; et c'est ce que j'ai fait.

Les algorithmes de moyennage classique sont décrits dans la classe CMoving_Average :

class CMoving_Average : public CMovSeriesTools
  {
public:  
   double    MASeries  (uint begin,               // Index of start of reliable bars
                       uint prev_calculated,      // Amount of history in bars at a previous tick
                       uint rates_total,          // Amount of history in bars at a current tick
                       int Length,               // Period of averaging
                       ENUM_MA_METHOD MA_Method, // Method of averaging (MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA)
                       double series,              // Value of price series calculated for the bar with the 'bar' number
                       uint bar,                   // Bar index
                       bool set                  // Direction of indexing of arrays.
                      );

   double    SMASeries (uint begin,          // Index of start of reliable bars
                       uint prev_calculated,// Amount of history in bars at a previous tick
                       uint rates_total,     // Amount of history in bars at a current tick
                       int Length,            // Period of averaging
                       double series,         // Value of price series calculated for the bar with the 'bar' number
                       uint bar,              // Bar index
                       bool set              // Direction of indexing of arrays.
                      );
                        
   double    EMASeries (uint begin,            // Index of start of reliable bars
                       uint prev_calculated, // Amount of history in bars at a previous tick
                       uint rates_total,     // Amount of history in bars at a current tick
                       double Length,         // Period of averaging
                       double series,        // Value of price series calculated for the bar with the 'bar' number
                       uint bar,              // Bar index
                       bool set              // Direction of indexing of arrays.
                      );
                        
   double    SMMASeries(uint begin,              // Index of start of reliable bars
                         uint prev_calculated, // Amount of history in bars at a previous tick
                         uint rates_total,     // Amount of history in bars at a current tick
                         int Length,            // Period of averaging
                         double series,         // Value of price series calculated for the bar with the 'bar' number
                         uint bar,              // Bar index
                         bool set              // Direction of indexing of arrays.
                      );

   double    LWMASeries(uint begin,               // Index of start of reliable bars
                         uint prev_calculated, // Amount of history in bars at a previous tick
                         uint rates_total,      // Amount of history in bars at a current tick
                         int Length,             // Period of averaging
                         double series,          // Value of price series calculated the bar with the 'bar' number
                         uint bar,               // Bar index
                         bool set               // Direction of indexing of arrays.
                        );

protected:
   double            m_SeriesArray[];
   int               m_Size_, m_count, m_weight;
   double            m_Moving, m_MOVING, m_Pr;
   double            m_sum, m_SUM, m_lsum, m_LSUM;
  };

Cette classe est dérivée de la classe de base CMovSeriesTools qui comporte des fonctions-méthodes protégées et supplémentaires et une vérification de l'exactitude de la période des moyennes mobiles.

La classe de base comporte un code universel supplémentaire qui est utilisé dans toutes les classes que je suggère, et il ne sert à rien de le copier plusieurs fois dans les classes dérivées. Dans les tâches appliquées d'utilisation du calcul de moyenne, les membres de classe protégés ne sont pas utilisés sous une forme explicite, suspendons donc leur vue d'ensemble pour le moment.

La classe CMoving_Average se compose de cinq fonctions de calcul de moyenne de type unique, dont les noms parlent d'elles-mêmes, et elles n'ont pas besoin d'être décrites en détail.

La première fonction MASeries() est une collection intégrale de quatre autres fonctions qui permettent de sélectionner un algorithme de calcul de moyenne à l'aide du paramètre MA_Method. Le code des algorithmes de calcul de moyenne sont optimisés pour des performances maximales, et c'est la raison pour laquelle les principaux paramètres de fonctions (Longueur, série, barre) sont complétés par des paramètres supplémentaires begin, prev_calculated, rates_total et set, dont le but est absolument identique aux variables indicatrices au même nom.

Le paramètre « set » définit le drapeau d'indexation des éléments d'une série de prix « série »dans les fonctions de calcul de la calcul de moyenne pour être le même que les tableaux de variables.

Nous devons considérer que toutes les fonctions de calcul de calcul de moyenne de cette classe ont le paramètre Longueur fixe et qu'il ne peut pas être modifié lorsque le code du programme est en cours d'exécution ! La fonction EMASeries() de la classe CMoving_Average a ce paramètre de type double !

Maintenant que nous nous sommes familiarisés avec la classe CMoving_Average, nous pouvons commencer à l'utiliser dans les indicateurs. Pour ce faire, à l'aide de la directive #include ajoutez le contenu du fichier MASeries_Cls.mqh sur le périmètre global au code de l'indicateur que vous élaborez::

#include <MASeries_Cls.mqh> 

Ensuite, vous devez déterminer le nombre nécessaire de procédures d calcul de moyenne dans le code indicateur, puis dans la partie OnCalculate() (avant les opérateurs de boucle et les accolades) déclarer les variables statiques de la classe CMoving_Average en fonction du nombre requis de procédures de moyennage. Il doit y avoir une variable distincte de la classe et une cellule distincte dans le tableau de la classe pour chaque procédure de calcul de calcul de moyenne.

//---- declaration of variables of the class CMoving_Average из файла MASeries_Cls.mqh
static CMoving_Average MA1, MA2, MA3, MA4;

Les variables de la classe dans la fonction OnCalculate() sont déclarées comme statiques, car leurs valeurs doivent être conservées entre les appels de cette fonction. Maintenant, nous pouvons commencer à travailler avec le calcul de moyenne elle-même. À titre d'exemple, je vais montrer quatre procédures consécutives de calcul de moyenne des séries de prix - SMA/EMA/SMMA/LWMA (l'indicateur MAx4.mq5) :

//---- The main cycle of indicator calculation 
for(bar = first; bar < rates_total; bar++) 
 {
  //----+ Four calls of the function MASeries.  
  ma1_ = MA1.MASeries(start1, prev_calculated, rates_total, Length1, MODE_SMA,  price[bar], bar, false);
  ma2_ = MA2.MASeries(start2, prev_calculated, rates_total, Length2, MODE_EMA,  ma1_,       bar, false);
  ma3_ = MA3.MASeries(start3, prev_calculated, rates_total, Length3, MODE_SMMA, ma2_,       bar, false);
  ma4_ = MA4.MASeries(start4, prev_calculated, rates_total, Length4, MODE_LWMA, ma3_,       bar, false);
  //----       
  MAx4[bar] = ma4_ + dPriceShift;
 }

Le résultat de chaque calcul précédent de moyenne (à l'exception du dernier) est utilisé dans l'algorithme de calcul de moyenne suivant, et le résultat final est transmis au tampon indicateur.

Je pense que la partie la plus cruciale de ce code est une initialisation préliminaire très prudente des variables d'index qui indiquent le début de barres fiables. Dans cette situation, il ressemblera à ce qui suit :

//---- Initialization of variables of start of reliable information
start1 = 0 + begin;
start2 = Length1 + begin;
start3 = Length1 + begin; // the previous EMA averaging doesn't change the start of reliable information
start4 = Length1 + Length3 + begin;

Notez que dans cette situation, l'algorithme de calcul de moyenne LWMA est le dernier et il n'affecte rien ; mais si ce n'était pas le dernier, alors le décalage de début d'information fiable serait égal à Longueur4+1, pas à Longueur4 !

Je souhaite ajouter, si le code précédent n'indique pas clairement à partir de quel numéro les informations fiables commencent, prenez un plus grand nombre, puis diminuez-le expérimentalement si nécessaire.


3. Comparaison de l'indicateur créé à l'aide de classes avec ses analogues utilisant des indicateurs techniques et personnalisés

Il serait très intéressant de comparer les performances de l'indicateur créé MAx4.mq5 avec son analogue identique (iMAx4.mq5) qui utilise l'indicateur technique iMA().

Eh bien, dès que nous aurons décidé de faire le test, il sera raisonnable de tester un autre indicateur (MAx3x1.mq5) similaire à MAx4.mq5, mais ayant le premier calcul de moyenne effectué en utilisant l'appel de l'indicateur technique iMA() et le trois autres utilisant la classe CMoving_Average. Et dès que l'ensemble standard d'indicateurs du terminal client comprend l'indicateur Custom Moving Average.mq5, j'ai créé un autre indicateur analogue sur ses bases à des fins de test (cMAx4.mq5).

Pour l'analyse à venir que j'ai préparée pour le test Expert Advisors : MAx4_Test.mq5, iMAx4_Test.mq5, MAx3x1_Test.mq5 et cMAx4_Test.mq5 respectivement. Les conditions de réalisation de ces tests ont été décrites en détail dans l'article " Les Principes de Calcul Économique des Indicateurs" Dans cet article, je ne vais pas décrire les détails du test, mais je vais montrer les résultats finaux de l'exécution des quatre Expert Advisor dans le testeur de stratégie au cours des 12 derniers mois sur EURUSD Н4 avec modélisation de chaque coche et la valeur des paramètres d'entrée « période » de tous les EA égale à 500.

Fig.1 Le résultat du test des indicateurs 

Les pires résultats de nos tests sont affichés par l'indicateur qui appelle des indicateurs personnalisés ; par conséquent, cette variante d'écriture d'un code ne peut être recommandée qu'aux paresseux ! Bien sûr, un autre "leader" arrivant en dernier mais basé sur des appels d'indicateurs techniques présente de bien meilleurs résultats, cependant, ils sont trop loin d'un idéal.

Le vrai leader des tests est l'indicateur élaboré à l'aide de classes !

L'hybride qui utilise des classes et des indicateurs techniques a pris la deuxième place, mais cela n'arrive pas toujours ; si le moment du test d'un indicateur est crucial, alors il vaut mieux vérifier personnellement ces variantes pour chaque situation.

Présentation des classes de calcul de calcul de moyenne mises en œuvre

№  Algorithme Nom de classe Nom de fichier Décalage du début des barres fiables
Après avoir appliqué un algorithme
Possibilité de dynamique
Modification de la longueur du paramètre
   1  calcul de moyenne classique  CMoving_Average  MASeries_Cls.mqh Longueur/0/Longueur/Longueur + 1 (SMA/EMA/SMMA/LWMA) Aucun
   2  Déviation Standard   CStdDeviation  StdDevSeries_Cls.mqh Longueur Aucun
   3  Lissage JMA  CJJMA  JJMASeries_Cls.mqh 30 Oui
   4  Lissage T3  CT3  T3Series_Cls.mqh 0 Oui
   5  Lissage Ultra-linéaire  CJurX  JurXSeries_Cls.mqh 0 Oui
   6  Lissage de Tushar Chande   CCMO  CMOSeries_Cls.mqh Longueur Aucun
   7  Lissage de Kaufman  CAMA  AMASeries_Cls.mqh Longueur Aucun
   8  calcul de moyenne parabolique  CParMA  ParMASeries_Cls.mqh Longueur Aucun
   9  Vitesse de Modification  CMomentum  MomSeries_Cls.mqh                                             Longueur                               Aucun
  10  Vitesse de Modification Normalisée  CnMomentum  nMomSeries_Cls.mqh                                             Longueur                               Aucun
  11  Taux de Modification  CROC  ROCSeries_Cls.mqh                                             Longueur                               Aucun

La classe CMoving_Average décrite précédemment comprend cinq algorithmes de calcul moyenne.

La classe CCMO comporte des algorithmes de calcul moyenne et d'oscillateur.

Les autres classes comprennent des algorithmes simples de calcul de moyenne L'idéologie d'utilisation de l'une des classes suggérées est absolument la même que la procédure d'utilisation de la classe CMoving_Average décrite ci-dessus. Le code de tous les algorithmes de calcul de moyenne (sauf celui parabolique) est optimisé pour une vitesse d'exécution maximale. Le code de calcul de moyenne parabolique n'a pas été optimisé, en raison de la complexité de ce processus. Les trois derniers algorithmes ne représentent pas un calcul de moyenne. Je les ai ajoutés en raison de leur grande popularité et de leur compatibilité avec les travaux d'analystes techniques populaires.

Pour une meilleure compréhension des informations, il est préférable de représenter les algorithmes de calcul de moyenne dans des fichiers .mqh séparés ; et pour une utilisation pratique, la meilleure variante est de les avoir dans un seul fichier.

Pour une utilisation dans les indicateurs, toutes les classes suggérées sont compressées dans le seul fichier SmoothAlgorithms.mqh. En plus de cela, le fichier est complété par les fonctions du fichier iPriceSeries.mqh. Seule la fonction PriceSeries() est utilisée dans les exemples de cet article :

double PriceSeries
 (
  uint applied_price,  // Price constant
  uint   bar,          // Index of shift for a specified number of periods back or forward
                          // relatively to a current bar.
  const double& Open [],
  const double& Low  [],
  const double& High [],
  const double& Close[]
 )

Cette fonction est destinée à travailler avec des indicateurs basés sur l'utilisation du deuxième type d'appel de la fonction OnCalculate().

L'idée principale de la création de cette fonction est d'étendre l'ensemble des suites de durée de prix de l'énumération ENUM_APPLIED_PRICE avec des variantes personnalisées. La fonction renvoie la valeur d'une suites de durée de prix par son nombre qui varie de 1 à 11.


4. Exemples Pratiques d’Implémentation d'un Code de Programme à l'aide des Classes de Calcul de Moyenne

S'il suffit de montrer un autre exemple d'utilisation des autres classes, pour s’assurer que tout se fait de la même manière qu'avec le calcul quadruple de moyenne. Je vais montrer une variante d'implémentation de la fonction OnCalculate() dans un analogue de l'indicateur CCI en utilisant les classes CJJMA et CJurX (JCCX.mq5)

int OnCalculate(const int rates_total,       // amount of history in bars on a current tick
              const int prev_calculated,   // amount of history in bars on a previous tick
              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[]
             )
  {
//----+   
   //---- Checking whether there are enough bars for calculation
   if (rates_total < 0) return(0);
    
   //---- Declaration of variables  with floating point  
   double price_, jma, up_cci, dn_cci, up_jccx, dn_jccx, jccx;
   //----+ Declaration of integer variables
   int first, bar;
   
   //---- calculation of start number 'first' for the cycle of recalculation of bars
   if (prev_calculated == 0) // checking for the first start of calculation of indicator
        first = 0;           // starting number for calculation of all bars
   else first = prev_calculated - 1; // starting number for calculation of new bars
   
   //---- declaration of variables of the class CJurX from the file SmoothAlgorithms.mqh
   static CJurX Jur1, Jur2;
   //---- declaration of variables of the class CJMA from the file SmoothAlgorithms.mqh
   static CJJMA JMA;
   
   //---- Main cycle of calculation of the indicator
   for(bar = first; bar < rates_total; bar++)
    {
     //----+ Calling the PriceSeries function to get the input price price_
     price_ = PriceSeries(IPC, bar, open, low, high, close); 

     //----+ One call of the JJMASeries function to get JMA
     jma = JMA.JJMASeries(0, prev_calculated, rates_total, 0, JMAPhase, JMALength, price_, bar, false); 

     //----+ Determine the deviation of price from the value of JMA
     up_cci = price_ - jma;         
     dn_cci = MathAbs(up_cci);

     //----+ Two calls of the JurXSeries function.  
     up_jccx = Jur1.JurXSeries(30, prev_calculated, rates_total, 0, JurXLength, up_cci, bar, false);
     dn_jccx = Jur2.JurXSeries(30, prev_calculated, rates_total, 0, JurXLength, dn_cci, bar, false); 

     //---- Preventing zero divide in empty values
     if (dn_jccx == 0) jccx = EMPTY_VALUE;
     else
      {
       jccx = up_jccx / dn_jccx;
       
       //---- Limitation of the indicator from the top and from the bottom
       if (jccx > +1)jccx = +1;
       if (jccx < -1)jccx = -1;
      }

     //---- Loading the obtained value to the indicator buffer
     JCCX[bar] = jccx;
    }
//----+     
   return(rates_total);
  }

Fig.2 L'indicateur JCCX 

Mais cette fois j'ai ajouté les classes appropriées d'un autre fichier sur la portée globale dans le code de l'indicateur :

#include <SmoothAlgorithms.mqh>

Maintenant, je veux attirer votre attention sur autre chose. Le problème est qu'un grand nombre d'indicateurs peuvent être représentés sous forme de fonctions d'une barre, ce qui savent travailler en utilisant des classes.

Par exemple, il serait intéressant de dessiner la chaîne Bollinger sur la base de la moyenne mobile Vidya de Tushar Chande. Dans ce cas, deux classes CCMO et CStdDeviation sont utilisées. En utilisant la première classe, nous obtenons la valeur de la moyenne mobile VIDYA ; et en utilisant la seconde, nous calculons la valeur de l'écart type de la série de prix pour la moyenne mobile.

Après cela, nous utilisons cet écart pour le calcul des limites supérieure et inférieure du canal :

//+------------------------------------------------------------------+
// Description of the classes CStdDeviation{}; and CCMO{};           | 
//+------------------------------------------------------------------+ 
#include <SmoothAlgorithms.mqh> 
//+==================================================================+
//|  The algorithm of getting the Bollinger channel from             |
//|  the moving average VIDYA                                        |
//+==================================================================+
class CVidyaBands
{
public:
  double VidyaBandsSeries(uint begin,                // number of the start of reliable calculation of bars
                         uint prev_calculated,      // amount of history on a previous tick in bars
                         uint rates_total,          // amount of history on a current tick in bars
                         int CMO_period,            // the period of averaging of the oscillator CMO
                         double EMA_period,         // the period of averaging of EMA
                         ENUM_MA_METHOD MA_Method, // the type of averaging
                         int BBLength,             // the period of averaging of the Bollinger channel
                         double deviation,          // Deviation
                         double series,             // Value of the price series calculated for a bar with the number 'bar'
                         uint bar,                  // Bar index
                         bool set,                  // Direction of indexing of arrays
                         double& DnMovSeries,       // Value of the lower border of the channel for a current bar
                         double& MovSeries,         // Value of the middle line of the channel for a current bar
                         double& UpMovSeries        // Value of the upper border of the channel for a current bar 
                        ) 
   {
//----+
    //----+ Calculation of the middle line    
    MovSeries = m_VIDYA.VIDYASeries(begin, prev_calculated, rates_total, 
                                    CMO_period, EMA_period, series, bar, set); 
    //----+ Calculation of the Bollinger channel
    double StdDev = m_STD.StdDevSeries(begin+CMO_period+1, prev_calculated, rates_total, 
                                      BBLength, deviation, series, MovSeries, bar, set);
    DnMovSeries = MovSeries - StdDev;
    UpMovSeries = MovSeries + StdDev;
//----+
    return(StdDev); 
   }

  protected:
    //---- declaration of variables of the classes CCMO and CStdDeviation
    CCMO           m_VIDYA;
    CStdDeviation  m_STD;
};

Donc, nous avons une classe simple et petite!

Les trois derniers paramètres d'entrée de la fonction VidyaBandsSeries() transmettent les valeurs nécessaires du canal via un lien.

Je voudrais noter que dans ce cas, vous ne pouvez pas déclarer les variables de classes dans la fonction VidyaBandsSeries() et les rendre statiques, car les variables statiques dans les classes indiquent autre chose. C'est pourquoi cette déclaration doit être faite sur la portée globale de la classe :

protected: 
  //---- declaration of variables of the classes CCMO and CStdDeviation 
  CCMO           m_VIDYA; 
  CStdDeviation  m_STD;

Dans un canal de Bollinger normal, la période de calcul de moyenne mobile et la période de calcul de moyenne du canal lui-même sont toujours égales.

Dans cette classe, j'ai séparé ces paramètres pour vous donner plus de liberté (EMA_period et BBLength). L'indicateur lui-même (VidyaBBands.mq5) réalisé sur la base de cette classe est si simple à utiliser la classe CVidyaBands dont nous n'avons pas besoin d'analyser son code dans l'article.

Ces classes de fonctions indicatrices doivent être placées dans un fichier mqh séparé. J'ai placé ces fonctions dans le fichier IndicatorsAlgorithms.mqh.

Fig.3 L'indicateur VidyaBBands 


5. Comparer les performances d'un indicateur qui utilise des classes avec un autre qui n'en utilise pas 

Tout d'abord, je souhaite savoir comment l'utilisation de classes lors de l'écriture du code d'un indicateur diminue ses performances ?

Pour cela, le code de l'indicateur JJMA.mq5 a été écrit sans utiliser les classes (JMA.mq5), puis il a été testé dans les mêmes conditions que lors du test précédent. Les résultats finaux des tests n'affichent pas une grande différence:

Fig.4 Les résultats des tests des indicateurs JMA et JJMA 

Bien sûr, il y a des frais supplémentaires pour l'utilisation des cours, mais ils ne sont pas importants par rapport aux avantages qu'ils offrent. 


6. Avantages de l'utilisation des classes de calcul de calcul de moyenne

Un avantage de l'utilisation de ces algorithmes, qui est vraiment convaincant, est que le remplacement des appels d'indicateurs techniques et personnalisés conduit à une forte augmentation des performances du code élaboré et décrit ci-dessus.

Un autre avantage pratique de ces classes est la grande commodité de leur utilisation. Par exemple, tout ce qui est décrit dans le livre populaire de William Blau « Momentum, Direction and Divergence » apparaît comme un véritable terrain d'expérimentation pour ce type d'approche de rédaction d'indicateurs. Le code des indicateurs sort au maximum compressé, compréhensible et souvent constitué d'un seul cycle de recalcul des barres.

Vous pouvez facilement élaborer n'importe quel indicateur - classique ou technique, en utilisant les méthodes alternatives de calcul de moyenne. Une assez grande variété d'algorithmes de calcul de calcul de moyenne offre de larges possibilités pour créer des systèmes commerciaux non traditionnels, souvent avec une détection précoce des tendances et un plus petit nombre de faux déclenchements.


7. Quelques recommandations sur l'utilisation des algorithmes de calcul de calcul de moyenne dans un code d'indicateur spécifique

Un rapide coup d'œil à n'importe quel indicateur développé à l'aide des différents algorithmes de calcul de calcul de moyenne décrits ici est suffisant pour comprendre à quel point ces algorithmes sont différents.

 

  Fig. 5 Les calcul de moyennes mobiles qui utilisent différents algorithmes de calcul de moyenne

Par conséquent, il serait raisonnable de supposer que tous les algorithmes suggérés ne sont pas également bons dans toutes les situations. Bien qu'il soit difficile de déterminer une limite stricte d'utilisation de l'un ou l'autre algorithme, il est possible de vous fournir quelques recommandations générales sur leur utilisation.

Par exemple, les algorithmes de Tushar Chande et Kaufman sont destinés à déterminer des situations de tendance et ne conviennent pas à un lissage supplémentaire à des fins de filtrage du bruit. Par conséquent, il est préférable d'entrer des séries de prix non traitées ou des valeurs d'indicateurs sans faire la calcul de moyenne de ces algorithmes. Voici le résultat du traitement des valeurs de l'indicateur Momentum à l'aide de l'algorithme de Kaufman (l'indicateur 4c_Momentum_AMA.mq5)

Fig.6 Le résultat du traitement des valeurs de l'indicateur Momentum en utilisant l'algorithme de Kaufman 

Je pense que les algorithmes de calcul de moyenne classique n'ont pas besoin de recommandations particulières. Leur champ d'application est assez large. Partout où ces algorithmes sont utilisés, vous pouvez utiliser avec succès les quatre algorithmes de gauche (JMA, T3, ultra-linéaire et parabolique). Voici un exemple de l'indicateur MACD où EMA et SMA sont remplacés par le calcul de moyenne JMA (l'indicateur JMACD.mq5) :

  Fig.7 Le graphe MACD utilisant le calcul de moyenne JMA

Et voici le résultat du lissage de l'indicateur calculé au lieu de changer son algorithme de calcul de moyenne pour une meilleure qualité de détermination de la tendance actuelle (l'indicateur JMomentum.mq5) :

Fig.8 Le résultat du lissage JMA de l'indicateur Momentum

Ce n'est pas une surprise que l’attitude des marchés change constamment ; par conséquent, il serait naïf de penser que vous pouvez trouver le seul et unique algorithme idéal pour une certaine partie du marché financier maintenant et pour toujours ! Hélas! Rien dans ce monde ne dure éternellement ! Néanmoins, comme pour moi par exemple, sur ce marché en perpétuelle évolution j'utilise souvent les indicateurs de tendances rapides et à moyen terme comme JFATL.mq5 et J2JMA.mq5. Je suis assez satisfait des prévisions sur leur base.

Une autre chose que je souhaite ajouter. Les algorithmes de calcul de moyenne sont réutilisables. De bons résultats peuvent être obtenus en appliquant des calcul de moyennes répétées à des valeurs déjà moyennées. En fait, dans cet article, j'ai entamé l’analyse du processus d'élaboration de l'indicateur à partir de celui-ci (l'indicateur MAx4.mq5).


8. L'idée générale de composer le code des algorithmes de calcul de moyenne

Et maintenant, au terme de l'article, je voudrais attirer votre attention sur le mécanisme des fonctions de calcul de moyenne elles-mêmes.

Tout d'abord, la plupart des algorithmes de calcul de moyenne comportent des tableaux dynamiques de variables de type m_SeriesArray[] pour stocker les valeurs du paramètre d'entrée 'series'..

Dès que l’ information importante pour le calcul apparaît, vous devez allouer la mémoire pour ce tableau pour une fois. Cela se fait à l'aide de la fonction SeriesArrayResize() de la classe CMovSeriesTools.

//----+ Changing the size of the array of variables
if(bar==begin && !SeriesArrayResize(__FUNCTION__, Length, m_SeriesArray, m_Size_))
   return(EMPTY_VALUE);

Ensuite, sur chaque barre, vous devez écrire la valeur actuelle de la série de prix « série » à la valeur la plus ancienne du tableau et mémoriser le numéro de sa position dans la variable m_count. Cela se fait à l'aide de la fonction Recount_ArrayZeroPos() de la classe CMovSeriesTools.

//----+ transposition and initialization of cells of the array m_SeriesArray 
Recount_ArrayZeroPos(m_count, Length_, prev_calculated, series, bar, m_SeriesArray);

Et maintenant, si nous devons trouver un élément avec un décalage relatif par rapport à l'élément courant, nous devons utiliser la fonction Recount_ArrayNumber() de la classe CMovSeriesTools :

for(iii=1; iii<=Length; iii++, rrr--)
   {
    kkk = Recount_ArrayNumber(m_count, Length_, iii);
    m_sum += m_SeriesArray[kkk] * rrr;
    m_lsum += m_SeriesArray[kkk];
    m_weight += iii;
   }

D’habitude, dans de telles situations, l'élément le plus récent est écrit à une position zéro et les autres (sauf le plus ancien) sont préalablement écrasés sur les positions suivantes à tour de rôle ; cependant, cela n'économise pas les ressources informatiques, et l'approche plus complexe décrite ci-dessus semble être plus rationnelle !

En plus des algorithmes de calcul de moyenne, les corps de ces fonctions comportent les appels de fonctions utilisées pour déterminer des positions des barres par rapport au début du calcul des barres :

//----+ Checking the start of reliable calculation of bars
if(BarCheck1(begin, bar, set)) return(EMPTY_VALUE);

le moment où il y a suffisamment d'informations pour démarrer l'initialisation des variables :

//----+ Initialization of zero
if(BarCheck2(begin, bar, set, Length))

et des situations où la dernière barre est clôturée :

//----+ Saving values of the variables 
if(BarCheck4(rates_total, bar, set))

ou non-clôturée :

//----+ Restoring values of the variables
if(BarCheck5(rates_total, bar, set))

La première vérification détermine une situation dans laquelle il n'y a pas assez de barres pour que la fonction de calcul de moyenne fonctionne, et elle renvoie un résultat vide. Une fois que le deuxième contrôle est passé avec succès et qu'il y a suffisamment de données pour le premier calcul, l'initialisation des variables est effectuée une fois. Deux dernières vérifications sont nécessaires pour le bon traitement multiple des valeurs sur la barre courante non-clôturée Je l'ai déjà décrit dans mon article consacré à l'optimisation d'un code de programme.

Et maintenant, quelques mots sur l'optimisation du code de programme de ces fonctions pour des performances maximales. Par exemple, l'algorithme SMA implique de faire la calcul de moyenne des valeurs sélectionnées d'une période d'une série de prix sur chaque barre. Ces valeurs sont littéralement additionnées et divisées par la période sur chaque barre.

Mais la différence entre la somme sur la barre précédente et la somme sur la barre actuelle est que la première est additionnée à la valeur de la série de prix avec un décalage sur une période par rapport à la période actuelle et la seconde - avec la valeur actuelle . Par conséquent, il serait très rationnel de ne calculer une telle somme qu'une seule fois lors de l'initialisation des fonctions, puis d'ajouter sur chaque barre uniquement les nouvelles valeurs de la série de prix à cette somme et d'en soustraire les valeurs les plus anciennes. C'est exactement ce qui se fait dans une telle fonction.


Conclusion

Suggérée dans l’article portant les implémentations des algorithmes de calcul de moyenne utilisant les classes sont simples, de type unique et universelles, vous n'aurez donc aucune difficulté à les étudier.

Les archives jointes à l'article comportent de nombreux exemples pour mieux comprendre cette approche d'écriture de code d'indicateurs. Dans l'archive Include__en.zip toutes les classes sont réparties dans des fichiers. L'archive Include_en.zip ne comporte que deux fichiers suffisants pour compiler tous les indicateurs de l'archive Indicators.zip. Les Expert Advisors à tester sont dans l'archive Experts.zip.


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

Fichiers joints |
experts-en.zip (3.88 KB)
include__en.zip (40.84 KB)
include-en.zip (17.82 KB)
indicators_en.zip (90.93 KB)
Construire un Analyseur de Spectre Construire un Analyseur de Spectre
Cet article est destiné à familiariser ses lecteurs avec une variante possible d'utilisation des objets graphiques du langage MQL5. Il analyse un indicateur, qui met implémente un panel de gestion d'un analyseur de spectre simple utilisant les objets graphiques. L'article est destiné aux lecteurs familiarisés avec les bases de MQL5.
Créez votre propre Veille du Marché en utilisant les classes de bibliothèque standard Créez votre propre Veille du Marché en utilisant les classes de bibliothèque standard
Le nouveau terminal client MetaTrader 5 et le langage MQL5 offrent de nouvelles opportunités pour présenter des informations visuelles au trader. Dans cet article, nous proposons un ensemble de classes universel et extensible, qui gère tout le travail d'organisation de l'affichage des informations textuelles arbitraires sur le graphique. L'exemple de l'indicateur Veille du Marché est présenté.
Indicateurs et Systèmes de Trading de William Blau en MQL5. partie 1: Indicateurs Indicateurs et Systèmes de Trading de William Blau en MQL5. partie 1: Indicateurs
L'article présente les indicateurs, décrits dans le livre de William Blau "Dynamique, Direction, and Divergence". L'approche de William Blau nous permet d'estimer rapidement et avec précision les fluctuations de la courbe des prix, de déterminer la tendance des mouvements de prix et des tournants, et d'éliminer le bruit des prix. Pendant ce temps, nous sommes également en mesure de détecter les états de surachat/survente du marché et des signaux indiquant la fin d'une tendance et l'inversion du mouvement des prix.
L'exemple simple de création d'un indicateur à l'aide d'une logique floue L'exemple simple de création d'un indicateur à l'aide d'une logique floue
L’article est consacré à l’application pratique du concept de logique floue pour l’analyse des marchés financiers. Nous proposons l’exemple de l’indicateur générant des signaux basés sur deux règles floues fondées sur l’indicateur Enveloppes. L’indicateur développé utilise plusieurs tampons d’indicateurs: 7 tampons pour les calculs, 5 tampons pour l’affichage des graphiques et 2 tampons de couleur.