English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
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

MetaTrader 5Exemples | 15 novembre 2021, 14:43
172 0
Nikolay Kositsin
Nikolay Kositsin

Introduction

Ainsi, dans mon article précédent, j'ai effectué une analyse de code d'un indicateur simple et j'ai légèrement couvert l'interaction de cet indicateur avec le terminal client MetaTrader 5. Maintenant, avant d'aller plus loin, nous devrions examiner de plus près les résultats de la compilation experte dans l'onglet "Erreurs" de la fenêtre "Boîte à outils" de MetaEditor. De là, vous pouvez entamer une étude plus approfondie du code de l'indicateur SMA, que j'avais proposé plus tôt.

Erreurs de compilation des indicateurs

Dans notre situation, lors de la compilation de l'une des deux versions du code, en cas d'absence de modification, le processus de compilation est assez fluide avec le résultat attendu :


Il n'y a pas d'erreurs, et avec le fichier indicateur avec l'extension .mq5 est apparu le fichier similaire avec l'extension .ex5.

En règle générale, lorsque vous travaillez avec le code, vous ne pouvez pas échapper aux erreurs. que les programmeurs commettent souvent À cette fin, MetaEditor dispose d'un mécanisme intégré pour vérifier le code compilé pour toutes sortes d'erreurs, et lorsqu'il les trouvera, il donnera une liste complète des erreurs générées.

Pour détecter l'emplacement d'une erreur, vous pouvez simplement double-cliquer sur la ligne appropriée avec le contenu de l'erreur dans la fenêtre "Boîte à outils". Dans la plupart des cas, le compilateur indiquera avec précision la ligne de code où l'erreur a été trouvée, en utilisant l'icône appropriée.

Vous devriez considérer une chose. Une erreur dans le code peut générer toute une série d'erreurs de compilation. Ainsi, pour supprimer la série d'erreurs, il suffit d'aller à la première ligne où le compilateur a trouvé une erreur, et de corriger le code. Tout naturellement, il peut y avoir beaucoup de telles séries d'erreurs de compilation. Ainsi, après avoir corrigé une erreur dans le code, nous devons la recompiler à nouveau, et si le compilateur trouve des erreurs, nous devons rechercher la première ligne dans l'onglet "Erreurs" de la fenêtre "Boîte à outils":

Peut-être que la méthode la plus efficace pour comprendre cela aura un impact significatif et destructeur sur notre code afin d'étudier comment le compilateur réagira aux erreurs consciemment commises. La technique est assez simple - faites l'erreur dans une partie particulière du code, appuyez sur le bouton "Compiler" dans MetaEditor et observez le résultat de la compilation. Ce sera encore mieux si vous vous rappelez intuitivement d'un tel résultat d'impact destructeur sur le code. Dans tous les cas, cela peut être utile dans la pratique ultérieure, lorsque vous travaillez avec du code MQL5.

Voici la liste d’éventuelles modifications destructrices dans le code source de l'indicateur :

  1. Faire un espace dans n'importe quel opérateur ou variable.
  2. Effacer un point-virgule ";" signe.
  3. Ajout d'un ";" signe dans différentes parties du code.
  4. Suppression d'un opérateur.
  5. Supprimer ou ajouter un support ou une parenthèse.
  6. Suppression d'un signe de virgule ",."
  7. Ajout d'un paramètre d'entrée supplémentaire dans la fonction OnCalculate().
  8. Diviser une variable par zéro.
  9. Remplacement d'un signe "==" par "=" dans la ligne d'opérateur "if".
  10. Changer le sens de l'échelon dans une variable de bar++ à bar--.

Naturellement, le compilateur ne trouve pas toujours la place avec une erreur là où elle est commise. C'est pourquoi ce travail préliminaire mérite d'être fait afin de comprendre comment gérer de telles situations. Eh bien, encore une explication concernant les erreurs - le compilateur MetaEditor ne détermine que les erreurs du langage MQL5 lui-même, et dans la plupart des cas, il ne trouve pas les erreurs logiques de programmation !

Votre vocabulaire MQL5

Si vous écoutez un individu en particulier, alors, avec toute la richesse de toute langue humaine, il s'avère qu'il n'utilise qu'une infime partie des outils exprimant ses pensées et ses besoins. Dans la plupart des situations, il s'avère que le vocabulaire réellement utilisé est nettement plus petit que celui disponible. Le même principe peut être appliqué à MQL5. Dans un premier temps, tout en maîtrisant le langage MQL5, vous devez vous habituer aux opérateurs et expressions les plus couramment utilisés de ce langage de programmation. Et au fur et à mesure que vous apprenez ce langage, vous pouvez progressivement élargir les limites de votre vocabulaire actuel.

Par exemple, vous pouvez utiliser quatre types de variables (int, double, bool, string), l'opérateur conditionnel if-else, l'opérateur de boucle for, l'opérateur composé {} et l'opérateur de return. Vous devez également apprendre à utiliser un point-virgule ";" et une virgule ",". Il serait peut-être sage d'apprendre les fonctions mathématiques et trigonométriques. Ces outils sont plus que suffisants pour s’entraîner et mettre en pratique vos premières compétences en programmation !

Affinement supplémentaire des indicateurs

Les capacités MQL5 d'indicateur de raffinage, affichées dans le terminal client MetaTrader, sont assez simples et standard. Ils sont constitués d'opérateurs de niveau global :

//---- Indicator's author
#property copyright "2010, MetaQuotes Software Corp."
//---- Author's web-site link
#property link      "https://www.mql5.com"
//---- Indicator version number
#property version   "1.00"
//---- Drawing the indicator in the main window
#property indicator_chart_window
//---- One buffer is used for calculating and drawing the indicator
#property indicator_buffers 1
//---- Only one graphical plotting is used
#property indicator_plots   1
//---- Drawing the indicator as line
#property indicator_type1   DRAW_LINE
//---- Red is used as indicator's line color
#property indicator_color1  Red
//---- Indicator line is continuous curve
#property indicator_style1  STYLE_SOLID
//---- Indicator line thickness is equal to 1
#property indicator_width1  1
//---- Displaying indicator's label
#property indicator_label1  "SMA"

Et des appels de fonction de OnInit() :

//---- Variable initialization for indicator's short name
   string shortname;
   StringConcatenate(shortname,"FATL(",FATLShift,")");
//--- Creating labels to display in Data Window
   PlotIndexSetString(0,PLOT_LABEL,shortname);
//--- Creating name to display in a separate window and in tool-tip
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
//--- Defining accuracy of displaying indicator's values
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//--- Prohibition of displaying blank values
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
La fonction StringConcatenate() assemble la chaîne du nom de l'indicateur à l'aide de cette formule :
   shortname = shortname + "SMA(" + MAPeriod + "," + MAShift + ")";

Selon les recommandations de l'article Appliquer un indicateur à un autre, cela ne ferait pas de mal d'ajouter l'appel de la fonction PlotIndexSetInteger() dans OnCalculate() :

//---- Calculating the 'first' starting number for the bars recalculation loop
   if(prev_calculated==0)        // Checking the first start of the indicator calculation
     {
      first=FATLPeriod-1+begin;  // Starting number for calculation of all bars
      //--- Increasing the start of data position by 'begin' bars, because the 
      //    calculations are based on data of another indicator
      if(begin>0)
         PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin+FATLPeriod);
     }
   else first=prev_calculated-1; // Starting number for calculation of new bars
Il est naturel qu'après l'inclusion de ces lignes de code supplémentaires, notre indicateur ait légèrement augmenté en taille et soit devenu un peu plus compliqué, mais il a maintenant une interface plus conviviale.

Le résultat du travail précédent comme modèle pour la création de nouveaux indicateurs

Tout cela est certes intéressant, mais il y a une question tout à fait naturelle - pourquoi inventer la roue et répéter le code d'indicateur, qui est déjà disponible dans Client Terminal en deux versions ? Sous la forme d'indicateur technique Moving Average.mq5 et d'indicateur personnalisé Moving Average.mq5. La réponse est simple. Pour apprendre à écrire rapidement du code d'indicateurs similaires, en utilisant simplement mon code d'indicateur SMA proposé précédemment comme modèle, économisant ainsi autant que possible vos ressources intellectuelles ! Par exemple, vous pouvez essayer d'écrire du code en MQL5 pour un filtre numérique, tel que FATL à partir de Finware.

En général, la formule de calcul du filtre numérique est :

FILTRE = SOMME (K(i) * FERMER (i), FilterPeriod)

Où :

  • SUM — la somme.
  • K(i) — le coefficient de pondération.
  • CLOSE (i) — Le prix de clôture de la barre courante ;
  • FilterPeriod — le nombre de barres pour la moyenne. 

Cette formule ne diffère pas beaucoup de la formule de l'indicateur SMA :

SMA = SOMME ((1 / MAperiod ) * FERMER (i), MAperiod)

La différence est que la période, sur laquelle sont effectués les calculs avec un filtre numérique, est strictement fixe et est individuelle pour un filtre numérique spécifique, ainsi que des coefficients de pondération K(i). Les coefficients de pondération eux-mêmes et la période du filtre numérique sont calculés à l'aide d'algorithmes spécialisés. L'analyse de ces algorithmes dépasse le cadre de cet article, nous nous limiterons donc à utiliser des valeurs prêtes pour le filtre numérique FATL. Ceux qui sont intéressés par l'idée du filtrage de signal numérique peuvent visiter le site Web Digital Methods Generator (en russe). La formule d'une variante de l'indicateur FATL dans MQL4 n'est pas un secret :

     FATL =  0.4360409450 * Close[bar + 0]
           + 0.3658689069 * Close[bar + 1]
           + 0.2460452079 * Close[bar + 2]
           + 0.1104506886 * Close[bar + 3]
           - 0.0054034585 * Close[bar + 4]
           - 0.0760367731 * Close[bar + 5]
           - 0.0933058722 * Close[bar + 6]
           - 0.0670110374 * Close[bar + 7]
           - 0.0190795053 * Close[bar + 8]
           + 0.0259609206 * Close[bar + 9]
           + 0.0502044896 * Close[bar + 10]
           + 0.0477818607 * Close[bar + 11]
           + 0.0249252327 * Close[bar + 12]
           - 0.0047706151 * Close[bar + 13]
           - 0.0272432537 * Close[bar + 14]
           - 0.0338917071 * Close[bar + 15]
           - 0.0244141482 * Close[bar + 16]
           - 0.0055774838 * Close[bar + 17]
           + 0.0128149838 * Close[bar + 18]
           + 0.0226522218 * Close[bar + 19]
           + 0.0208778257 * Close[bar + 20]
           + 0.0100299086 * Close[bar + 21]
           - 0.0036771622 * Close[bar + 22]
           - 0.0136744850 * Close[bar + 23]
           - 0.0160483392 * Close[bar + 24]
           - 0.0108597376 * Close[bar + 25]
           - 0.0016060704 * Close[bar + 26]
           + 0.0069480557 * Close[bar + 27]
           + 0.0110573605 * Close[bar + 28]
           + 0.0095711419 * Close[bar + 29]
           + 0.0040444064 * Close[bar + 30]
           - 0.0023824623 * Close[bar + 31]
           - 0.0067093714 * Close[bar + 32]
           - 0.0072003400 * Close[bar + 33]
           - 0.0047717710 * Close[bar + 34]
           + 0.0005541115 * Close[bar + 35]
           + 0.0007860160 * Close[bar + 36]
           + 0.0130129076 * Close[bar + 37]
           + 0.0040364019 * Close[bar + 38]; 

Dans MQL5, les barres des tampons d'indicateurs sont calculées dans le sens opposé à celui de MQL4. Ainsi, pour utiliser cette formule dans les indicateurs MQL5, nous devons remplacer l'opération d'augmentation à l'intérieur des parenthèses par l'opération de diminution. En raison de l'absence du tableau de séries chronologiques Close[] dans MQL5, nous devons également le remplacer par une variante plus appropriée - price[]. Il est tout à fait naturel d'automatiser cette tâche en utilisant la commande de menu suivante dans MetaEditor :

Le Close [bar + expression régulièrement rencontrée doit être remplacée par price [bar - :

Dans cette boîte de dialogue, cliquez sur le bouton "Remplacer tout". En conséquence, nous obtenons la formule requise pour le calcul de l'indicateur FATL dans MQL5 :

     FATL =  0.4360409450 * price[bar - 0]
           + 0.3658689069 * price[bar - 1]
           + 0.2460452079 * price[bar - 2]
           + 0.1104506886 * price[bar - 3]
           - 0.0054034585 * price[bar - 4]
           - 0.0760367731 * price[bar - 5]
           - 0.0933058722 * price[bar - 6]
           - 0.0670110374 * price[bar - 7]
           - 0.0190795053 * price[bar - 8]
           + 0.0259609206 * price[bar - 9]
           + 0.0502044896 * price[bar - 10]
           + 0.0477818607 * price[bar - 11]
           + 0.0249252327 * price[bar - 12]
           - 0.0047706151 * price[bar - 13]
           - 0.0272432537 * price[bar - 14]
           - 0.0338917071 * price[bar - 15]
           - 0.0244141482 * price[bar - 16]
           - 0.0055774838 * price[bar - 17]
           + 0.0128149838 * price[bar - 18]
           + 0.0226522218 * price[bar - 19]
           + 0.0208778257 * price[bar - 20]
           + 0.0100299086 * price[bar - 21]
           - 0.0036771622 * price[bar - 22]
           - 0.0136744850 * price[bar - 23]
           - 0.0160483392 * price[bar - 24]
           - 0.0108597376 * price[bar - 25]
           - 0.0016060704 * price[bar - 26]
           + 0.0069480557 * price[bar - 27]
           + 0.0110573605 * price[bar - 28]
           + 0.0095711419 * price[bar - 29]
           + 0.0040444064 * price[bar - 30]
           - 0.0023824623 * price[bar - 31]
           - 0.0067093714 * price[bar - 32]
           - 0.0072003400 * price[bar - 33]
           - 0.0047717710 * price[bar - 34]
           + 0.0005541115 * price[bar - 35]
           + 0.0007860160 * price[bar - 36]
           + 0.0130129076 * price[bar - 37]
           + 0.0040364019 * price[bar - 38];

On peut maintenant entamer le codage l'indicateur, dont l'algorithme de calcul vient d'être considéré. Pour ce faire, ouvrez tout d'abord l'indicateur SMA_1_en.mq5 dans MetaEditor et enregistrez-le sous FATL_en.mq5. Le modèle d'indicateur est prêt et nous devons maintenant remplacer l'algorithme de calcul de l'indicateur et apporter quelques modifications aux variables, principalement superficielles. Vous devez sélectionner le bloc entier de la dernière formule mentionnée pour le calcul du filtre FATL et le copier dans le presse-papiers Windows. Ensuite, maintenant dans le code indicateur FATL.mq5, supprimez tout le code à l'intérieur de l'opérateur de boucle, à l'exception de la dernière initialisation du tampon indicateur :

//---- Main loop of indicator calculation
   for(bar=first; bar<rates_total; bar++)
     {
     


      //---- Indicator buffer's cell initialization with FATL value
      ExtLineBuffer[bar]=FATL;
     }

A la place de ce code supprimé, nous collerons l'algorithme de calcul du filtre numérique FATL à partir du presse-papiers de Windows. Ensuite, nous devrions remplacer le mot SMA par un FATL plus approprié, en utilisant la procédure de remplacement que j'ai décrite ci-dessus. Absolument la même chose, nous devons remplacer les noms des variables d'entrée MAPeriod et MAShift par FATLPeriod et FATLShft respectivement. La variable FATLPeriod doit être supprimée des variables externes, car elle a une valeur fixe égale à 39. Pour la même raison, elle doit être supprimée de l'opérateur StringConcatenate() dans la fonction OnInit(). Maintenant, il n'y a plus besoin de la variable locale iii, elle peut donc être supprimée. Et enfin, vous pouvez changer la couleur de la ligne indicatrice en bleu et rendre la ligne elle-même un peu plus épaisse.

Après ces manipulations simples avec le code SMA_1_en.mq5 on obtient le code indicateur souhaité FATL_en.mq5 :

//+------------------------------------------------------------------+
//|                                                      Fatl_en.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
//---- Indicator's author
#property copyright "2010, MetaQuotes Software Corp."
//---- Author's web-site link
#property link      "https://www.mql5.com"
//---- Indicator version number
#property version   "1.00"
//---- Drawing the indicator in the main window
#property indicator_chart_window
//---- One buffer is used for calculating and drawing the indicator
#property indicator_buffers 1
//---- Only one graphical plotting is used
#property indicator_plots   1
//---- Drawing the indicator as line
#property indicator_type1   DRAW_LINE
//---- Blue is used as indicator's line color
#property indicator_color1  Blue
//---- Indicator line is continuous curve
#property indicator_style1  STYLE_SOLID
//---- Indicator line thickness is equal to 2
#property indicator_width1  2
//---- Displaying indicator's label
#property indicator_label1  "FATL"

//---- Input parameters of indicator
input int FATLShift=0; // FATL horizontal shift in bars

//---- Declaring and initializing a variable to store the number of calculated bars
int FATLPeriod=39;

//---- Declaration of dynamic array, which will be 
//     used later as indicator buffer
double ExtLineBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+  
void OnInit()
  {
//----+
//---- Transformation of ExtLineBuffer dynamic array into indicator buffer
   SetIndexBuffer(0,ExtLineBuffer,INDICATOR_DATA);
//---- Horizontal shift of indicator by FATLShift
   PlotIndexSetInteger(0,PLOT_SHIFT,FATLShift);
//---- Setting the position from which the drawing of indicator will start
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,FATLPeriod);
//---- Variable initialization for indicator's short name
   string shortname;
   StringConcatenate(shortname,"FATL(",FATLShift,")");
//--- Creating labels to display in Data Window
   PlotIndexSetString(0,PLOT_LABEL,shortname);
//--- Creating name to display in a separate window and in tool-tip
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
//--- Defining accuracy of displaying indicator's values
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//--- Prohibition of displaying blank values
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//----+
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(
                const int rates_total,     // amount of history in bars at the current tick
                const int prev_calculated, // amount of history in bars at the previous tick
                const int begin,           // beginning number of reliable count of bars
                const double &price[]      // price array for indicator calculation
                )
  {
//----+   
//---- Check if the number of bars is sufficient for calculation
   if(rates_total<FATLPeriod-1+begin)
      return(0);

//---- Declaring local variables
   int first,bar;
   double Sum,FATL;

//---- Calculating the 'first' starting number for the bars recalculation loop
   if(prev_calculated==0)        // Checking the first start of the indicator calculation
     {
      first=FATLPeriod-1+begin;  // Starting number for calculation of all bars
      //--- Increasing the start of data position by 'begin' bars, because the 
      //    calculations are based on data of another indicator
      if(begin>0)
         PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin+FATLPeriod);
     }
   else first=prev_calculated-1; // Starting number for calculation of new bars

//---- Main loop of indicator calculation
   for(bar=first; bar<rates_total; bar++)
     {
      //---- 
      FATL=0.4360409450*price[bar-0]
           + 0.3658689069 * price[bar - 1]
           + 0.2460452079 * price[bar - 2]
           + 0.1104506886 * price[bar - 3]
           - 0.0054034585 * price[bar - 4]
           - 0.0760367731 * price[bar - 5]
           - 0.0933058722 * price[bar - 6]
           - 0.0670110374 * price[bar - 7]
           - 0.0190795053 * price[bar - 8]
           + 0.0259609206 * price[bar - 9]
           + 0.0502044896 * price[bar - 10]
           + 0.0477818607 * price[bar - 11]
           + 0.0249252327 * price[bar - 12]
           - 0.0047706151 * price[bar - 13]
           - 0.0272432537 * price[bar - 14]
           - 0.0338917071 * price[bar - 15]
           - 0.0244141482 * price[bar - 16]
           - 0.0055774838 * price[bar - 17]
           + 0.0128149838 * price[bar - 18]
           + 0.0226522218 * price[bar - 19]
           + 0.0208778257 * price[bar - 20]
           + 0.0100299086 * price[bar - 21]
           - 0.0036771622 * price[bar - 22]
           - 0.0136744850 * price[bar - 23]
           - 0.0160483392 * price[bar - 24]
           - 0.0108597376 * price[bar - 25]
           - 0.0016060704 * price[bar - 26]
           + 0.0069480557 * price[bar - 27]
           + 0.0110573605 * price[bar - 28]
           + 0.0095711419 * price[bar - 29]
           + 0.0040444064 * price[bar - 30]
           - 0.0023824623 * price[bar - 31]
           - 0.0067093714 * price[bar - 32]
           - 0.0072003400 * price[bar - 33]
           - 0.0047717710 * price[bar - 34]
           + 0.0005541115 * price[bar - 35]
           + 0.0007860160 * price[bar - 36]
           + 0.0130129076 * price[bar - 37]
           + 0.0040364019 * price[bar - 38];

      //---- Indicator buffer's cell initialization with FATL value
      ExtLineBuffer[bar]=FATL;
     }
//----+     
   return(rates_total);
  }
//+------------------------------------------------------------------+

Après avoir compilé l'indicateur, il peut être testé sur le graphique dans le terminal client :

Il est naturel que le code subséquent de l'indicateur FATL puisse être utilisé comme modèle pour construire d'autres filtres similaires. Mais maintenant, le problème est beaucoup plus facile. Dans notre code, il suffit de remplacer la formule de calcul du filtre, de remplacer le mot FATL par DIGFILTER, et d'initialiser (maintenant) la variable DIGFILTERPeriod avec la dimension requise du filtre numérique.

Solution courante pour créer des filtres numériques dans le Terminal Client

L'indicateur, que nous venons d'évoquer, est une variante unique pour résoudre le problème général du filtrage numérique du signal. Ce serait bien d'avoir un indicateur, qui représente une solution courante, permettant de construire n'importe quel filtre numérique en utilisant un seul indicateur. Ce problème a été résolu il y a longtemps pour le terminal client MetaTrader 4 en utilisant le module DF.dll par Sergei Ilyuhin. Ainsi, il serait facile de l'utiliser pour résoudre notre problème dans le terminal client MetaTrader 5. Dans ce module, la fonction DigitalFilter() est introduite :

DigitalFilter(int FType, int P1, int D1, int A1, int P2, int D2, int A2, double Ripple, int Delay, double& array[]); 

eIle vous permet de recevoir les coefficients du filtre numérique sous forme de tableau array[]. La fonction écrit les coefficients du filtre numérique dans ce tableau avec une taille de 1500 en utilisant la référence (le signe '&' après la déclaration de ce type de variable dans ce tableau). La fonction accepte les valeurs de dix paramètres d'entrée et renvoie la taille du filtre numérique. Donc, c'est tout à fait suffisant pour construire le filtre numérique universel. Tout le problème se résume à organiser l'importation de DLL dans l'indicateur existant au niveau global, obtenant le tableau de coefficients dans le bloc de code d'initialisation de l'indicateur, et sur la base de ces coefficients exécuter le calcul universel de filtre dans OnCalculate(). Les variables d'entrée de la fonction DigitalFilter() doivent être placées dans les variables d'entrée de l'indicateur. Nous allons le faire tout de suite.

L'importation du fichier DF.dll ne pose aucune difficulté Ceux ne sont que trois lignes de code :

//---- DLL import
#import "DF.dll"
int DigitalFilter(int FType, int P1, int D1, int A1, int P2, int D2, int A2, double Ripple, int Delay, double& array[]); 
#import

Après cela, nous ferons fonctionner toutes les variables externes de DigitalFilter() en tant que variables d'entrée de l'indicateur :

//---- Input parameters of indicator
input FType_ FType=LPF;     //Filter Type
                            //0 - Low-Pass Filter (FATL / SATL / KGLP), 1 - High-Pass Filter (KGHP), 
                            //2 - Band-Pass Filter (RBCI / KGBP), 3 - Band-Stop Filter (KGBS)
input int    P1 = 28;       //Cut-off period 1, in bars
input int    D1 = 19;       //Transient process cut-off period 1, in bars
input int    A1 = 40;       //Fading in delay band 1, in dB
input int    P2 = 0;        //Cut-off period 2, in bars
input int    D2 = 0;        //Transient process cut-off period 2, in bars
input int    A2 = 0;        //Fading in delay band 2, in dB
input int    Delay=0;       //Delay, in bars
input double Ripple=0.08;   //Beats in bandwidth, in dB
input int    FILTERShift=0; //Moving Average horizontal shift, in bars

Au niveau global, nous déclarerons la variable FILTERPeriod sans initialisation :

//---- Declaring and initializing a variable to store the number of calculated bars
int FILTERPeriod;

Au niveau global, nous déclarerons un tableau dynamique pour stocker les coefficients de filtre :

//---- Declaration of dynamic array, which will be 
//     used later as indicator buffer
double FILTERTable[];

Passons maintenant au bloc de la fonction OnInit(). Il n'est pas tout à fait logique d'utiliser le tableau FILTERTable[] comme paramètre de la fonction DigitalFilter(). Pour cela, nous lui attribuerons une taille allant jusqu'à 1500 éléments, dont dans le bloc fonction OnCalculate(), seuls 100 à 200 seront utilisés. Dans une telle situation, il serait préférable d'utiliser un tableau Array[1500] déclaré localement dans la fonction OnInit(). La quantité nécessaire de données de ce tableau sera écrite dans le tableau FILTERTable[]. Après avoir quitté la fonction OnInit(), le grand tableau Array[] sera détruit et les données nécessaires resteront dans le tableau FILTERTable[], qui aura une taille égale à la longueur du filtre numérique FILTERPeriod. Voici la variante de code utilisée à cette fin :

//---- Calculation of digital filter coefficients and determining the size of FILTERTable[] buffer
   double Array[1500];
   FILTERPeriod=DigitalFilter(FType,P1,D1,A1,P2,D2,A2,Ripple,Delay,Array);
//----  Changing the size of FILTERTable[] buffer for required number of digital filter coefficients
   if(FILTERPeriod<=0)
     {
      Print("Input parameters are incorrect. Indicator can't operate!");
      return;
     }
//---- Copying data from temporary array with size of 1500 to the main array with size of FILTERPeriod
   ArrayCopy(FILTERTable,Array,0,0,FILTERPeriod);

Dans la fonction OnCalculate(), le code de calcul du filtre est assez simple :

      //---- Digital filter calculation formula
      FILTER=0.0;
      for(iii = 0; iii<FILTERPeriod; iii++)
         FILTER+= FILTERTable[iii] * price[bar - iii];

La version finale de ce code indicateur est présentée dans le fichier DFilter_en.mq5. L'interface de cet indicateur peut être légèrement améliorée. Le fait que la variable d'entrée de l'indicateur prenne des valeurs de 0 à 3.

input int FType = 0; //Тип фильтра
                     //0 - ФНЧ (FATL/SATL/KGLP), 1 - ФВЧ (KGHP), 2 - полосовой (RBCI/KGBP), 3 - режекторный (KGBS)

Ces valeurs sont beaucoup plus faciles perçues non pas sous forme numérique, mais comme les noms du filtre : 0 - Filtre passe-bas (FATL/SATL/KGLP), 1 - Filtre passe-haut (KGHP), 2 - Filtre passe-bande (RBCI/KGBP), 3 - Filtre coupe-bande (KGBS). Pour un tel cas dans MQL5, il existe un type spécial de variables, appelées énumérations. Dans notre cas, nous devons déclarer et initialiser l'énumération avant les paramètres d'entrée de l'indicateur :

//---- Declaration and initialization of digital filters types
enum FType_ //Filter Type
  {
   LPF, //Low-Pass Filter (FATL/SATL/KGLP)
   HPF, //High-Pass Filter (KGHP)
   BPF, //Band-Pass Filter (RBCI/KGBP)
   BSF, //Band-Stop Filter (KGBS)
  };

Après cela, nous devons remplacer le type de variable utilisée dans la déclaration du paramètre externe de l'indicateur :

input FType_ FType = LPF; //Filter Type

En conséquence, le choix des valeurs de ce paramètre dans la boîte de dialogue de l'indicateur ressemble à ceci :

Comme dans la déclaration d'énumération, les constantes nommées sont suivies de commentaires sur une seule ligne, puis elles doivent être choisies comme paramètres d'entrée. Nous avons maintenant la version finale du code source du filtre numérique universel :

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2010, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
/*
 * <<< DIGITAL FILTERS FOR METATRADER 5 >>> *
 *
 * DF.dll file should be placed in "\MetaTrader 5\MQL5\Libraries\" folder.
 * DF.dll requires three additional DLLs, containing a block of mathematical 
 * processing - bdsp.dll, lapack.dll, mkl_support.dll.
 * These DLLs must be installed in "C:\Windows\System32\" folder for 
 * Windows 32-bit operating systems or in "C:\Windows\SysWOW64\" folder 
 * for Windows 64-bit operating systems.
 *
 * Before using, make sure that:
 * 
 * 1. "Allow DLL import" option is enabled in Client Terminal settings 
 *    (Tools->Options->Expert Advisors tab).
 * 2. In "C:\Windows\System32\" or in "C:\Windows\SysWOW64\" folders the
 *    Bdsp.dll, lapack.dll and mkl_support.dll auxiliary math libraries are present.
 *
 * Description of input parameters:
 * 
 * Ftype  - Filter Type: 0 - Low-Pass Filter (FATL/SATL/KGLP), 1 - High-Pass Filter (KGHP),
 *          2 - Band-Pass Filter (RBCI / KGBP), 3 - Band-Stop Filter (KGBS)
 * P1     - Cut-off period P1, in bars
 * D1     - Transient process cut-off period D1, in bars
 * A1     - Fading in delay band A1, in dB
 * P2     - Cut-off period P2, in bars
 * D2     - Transient process cut-off period D2, in bars
 * A2     - Fading in delay band A2, in dB
 * Ripple - Beats in bandwidth, in dB
 * Delay  - Delay, in bars
 *
 * For Low-Pass Filter and HPF the values of P2, D2, A2 are ignored
 *
 * Conditions:
 * Low-Pass Filter:                       P1>D1
 * High-Pass Filter:                      P1<D1
 * Band-Pass Filter and Band-Stop Filter: D2>P2>P1>D1
 */
//+------------------------------------------------------------------+
//|      Digital Low Pass (FATL/SATL, KGLP) Filter    DFilter_en.mq5 | 
//|                    Digital Filter: Copyright (c) Sergey Ilyukhin |
//|                           Moscow, qpo@mail.ru  http://fx.qrz.ru/ |
//|                              MQL5 CODE: 2010,   Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+
//---- Indicator's author
#property copyright "2005, Sergey Ilyukhin, Moscow"
//---- Author's web-site link
#property link      "http://fx.qrz.ru/"
//---- Indicator version number
#property version   "1.00"
//---- Drawing the indicator in main window
#property indicator_chart_window
//---- One buffer is used for calculating and drawing the indicator
#property indicator_buffers 1
//---- Only one graphical plotting is used
#property indicator_plots   1
//---- Drawing the indicator as line
#property indicator_type1   DRAW_LINE
//---- Blue is used as indicator's line color
#property indicator_color1  DarkViolet
//---- Indicator line is continuous curve
#property indicator_style1  STYLE_SOLID
//---- Indicator line thickness is equal to 2
#property indicator_width1  2
//---- Displaying indicator's label
#property indicator_label1  "DFilter"
//---- Declaration and initialization of digital filters types
enum FType_ //Filter Type
  {
   LPF, //Low-Pass Filter (FATL/SATL/KGLP)
   HPF, //High-Pass Filter (KGHP)
   BPF, //Band-Pass Filter (RBCI/KGBP)
   BSF, //Band-Stop Filter (KGBS)
  };

//---- Input parameters of indicator
input FType_ FType=LPF;     //Filter Type
                            //0 - Low-Pass Filter (FATL / SATL / KGLP), 1 - High-Pass Filter (KGHP), 
                            //2 - Band-Pass Filter (RBCI / KGBP), 3 - Band-Stop Filter (KGBS)
input int    P1 = 28;       //Cut-off period 1, in bars
input int    D1 = 19;       //Transient process cut-off period 1, in bars
input int    A1 = 40;       //Fading in delay band 1, in dB
input int    P2 = 0;        //Cut-off period 2, in bars
input int    D2 = 0;        //Transient process cut-off period 2, in bars
input int    A2 = 0;        //Fading in delay band 2, in dB
input int    Delay=0;       //Delay, in bars
input double Ripple=0.08;   //Beats in bandwidth, in dB
input int    FILTERShift=0; //Moving Average horizontal shift, in bars

//---- DLL Import
#import "DF.dll"
int DigitalFilter(int FType,int P1,int D1,int A1,int P2,int D2,int A2,double Ripple,int Delay,double &array[]);
#import

//---- Declaring and initializing a variable to store the number of calculated bars
int FILTERPeriod;

//---- Declaration of dynamic array, which will be 
//     used later as indicator buffer
double ExtLineBuffer[];

//---- Declaring and initializing an array for the digital filter coefficients
double FILTERTable[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+  
void OnInit()
  {
//----+
//---- Transformation of ExtLineBuffer dynamic array into indicator buffer
   SetIndexBuffer(0,ExtLineBuffer,INDICATOR_DATA);
//---- Horizontal shift of indicator by FILTERShift
   PlotIndexSetInteger(0,PLOT_SHIFT,FILTERShift);
//---- Setting the position from which the drawing of indicator will start
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,FILTERPeriod);
//---- Variable initialization for indicator's short name
   string shortname;
   StringConcatenate(shortname,"FILTER(",FILTERShift,")");
//---- Creating label to display in Data Window
   PlotIndexSetString(0,PLOT_LABEL,shortname);
//---- Creating name to display in a separate window and in tool-tip
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
//---- Defining accuracy of displaying indicator's values
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//---- Prohibition of empty values plotting
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//---- Calculation of digital filter coefficients and determining the size of FILTERTable[] buffer
   double Array[1500];
   FILTERPeriod=DigitalFilter(FType,P1,D1,A1,P2,D2,A2,Ripple,Delay,Array);
//----  Changing the size of FILTERTable[] buffer for required number of digital filter coefficients
   if(FILTERPeriod<=0)
     {
      Print("Input parameters are incorrect. Indicator can't operate!");
      return;
     }
//---- Copying data from temporary array with size of 1500 to the main array with size of FILTERPeriod
   ArrayCopy(FILTERTable,Array,0,0,FILTERPeriod);
//----+
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(
                const int rates_total,     // amount of history in bars at the current tick
                const int prev_calculated, // amount of history in bars at the previous tick
                const int begin,           // beginning number of reliable count of bars
                const double &price[]      // price array for indicator calculation
                )
  {
//----+   
//---- Check if the number of bars is sufficient for calculation
   if(rates_total<FILTERPeriod-1+begin)
      return(0);

//---- Declaring local variables
   int first,bar,iii;
   double Sum,FILTER;

//---- Calculating the 'first' starting number for the bars recalculation loop
   if(prev_calculated==0)         // Checking the first start of the indicator calculation
     {
      first=FILTERPeriod-1+begin; // Starting number for calculation of all bars
      //---- Increasing the start of data position by 'begin' bars, 
      //     because the calculations are based on data of another indicator
      if(begin>0)
         PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,begin+FILTERPeriod);
     }
   else first=prev_calculated-1;  // Starting number for calculation of new bars

//---- Main loop of indicator calculation
   for(bar=first; bar<rates_total; bar++)
     {
      //---- Digital filter calculation formula
      FILTER=0.0;
      for(iii = 0; iii<FILTERPeriod; iii++)
         FILTER+= FILTERTable[iii] * price[bar - iii];

      //---- Indicator buffer's cell initialization with FILTER value
      ExtLineBuffer[bar]=FILTER;
     }
//----+     
   return(rates_total);
  }
//+------------------------------------------------------------------+
L'implémentation MQL5 d'un tel filtre numérique universel uniquement au moyen du terminal client élimine complètement le besoin de tout filtre numérique de la société FinWare. C'est une commodité considérable, qui ouvre de nouvelles perspectives dans l'utilisation de ces indicateurs.

Conclusion

Après toutes ces manipulations avec du code, il a obtenu beaucoup de détails. Mais à regarder de plus près ces détails de ce processus, tout fonctionne de manière parfaitement logique et compréhensible, si nous commençons par l'analyse des choses les plus simples et continuons à faire une transition significative et délibérée du simple au complexe.

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

Fichiers joints |
dll.rar (1302.47 KB)
sma__en.mq5 (3.56 KB)
sma_1_en.mq5 (4.51 KB)
fatl_en.mq5 (6.08 KB)
dfilter_0_en.mq5 (8.17 KB)
dfilter_en.mq5 (8.42 KB)
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.
Comment exporter des cotations de МetaTrader 5 vers des applications .NET à l'aide des services WCF Comment exporter des cotations de МetaTrader 5 vers des applications .NET à l'aide des services WCF
Vous souhaitez organiser l'exportation des cotations de MetaTrader 5 vers votre propre application ? La jonction MQL5-DLL permet de créer de telles solutions ! Cet article vous indiquera l'un des moyens d'exporter des cotations de MetaTrader 5 vers des applications écrites en .NET. Pour moi, il était plus intéressant, rationnel et facile d'implémenter l'export de cotations en utilisant cette même plateforme. Malheureusement, la version 5 ne prend toujours pas en charge .NET, donc comme autrefois, nous utiliserons la dll win32 avec la prise en charge de .NET comme couche intermédiaire.
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
Admettons qu'un simple indicateur MA (Moyenne mobile) avec la période 13 soit appliqué à un graphique. Et nous souhaitons modifier la période à 20, mais nous ne souhaitons pas aller dans la boîte de dialogue des propriétés de l'indicateur et éditer le nombre 13 à 20 : tout simplement fatigué de ces actions fastidieuses avec la souris et le clavier. Et surtout nous ne souhaitons pas ouvrir le code indicateur et le modifier. Nous souhaitons faire tout cela d'une simple pression sur un bouton - "flèches vers le haut" à côté du pavé numérique. Dans cet article, je vais décrire comment le faire.
Dessiner les Émissions de l'Indicateur en MQL5 Dessiner les Émissions de l'Indicateur en MQL5
Dans cet article, nous allons traiter l'émission d'indicateurs - une nouvelle approche de l'étude de marché. Le calcul de l'émission est basé sur l'intersection de différents indicateurs : de plus en plus de points de couleurs et de formes différentes apparaissent après chaque tick. Ils forment de nombreux groupes comme des nébuleuses, des nuages, des pistes, des lignes, des arcs, etc. Ces formes contribuent à détecter les ressorts et les forces invisibles qui affectent le mouvement des prix du marché.