
Tester la performance du Calcul des Moyennes Mobiles dans MQL5
Introduction
L'utilisation de Moyennes Mobiles est une pratique courante dans l'analyse des séries chronologiques de marché, dans les indicateurs et la programmation des Expert Advisors. C'est la méthode de lissage des données de prix la plus populaire. Dans la nouvelle version du langage MQL, une douzaine d'algorithmes de Moyenne Mobile est disponible.
C'est la différence entre eux ? Vraiment, la vitesse de calcul dépend-elle de certains algorithmes de Moyennes Mobiles ? Quel algorithme est le plus rapide ?
La vitesse de calcul des Moyennes Mobiles a-t-elle augmenté dans MetaTrader 5 par rapport à MetaTrader 4 ? Il y a beaucoup de telles questions qui surgissent. Alors, considérons la plupart d'entre elles.
Bien sûr, la vitesse d'une nouvelle plateforme est impressionnante, mais il vaut mieux la vérifier expérimentalement.
1. Conditions de test
La vitesse de calcul dépend de nombreux facteurs. Par conséquent, les données obtenues à la suite de cette recherche, dans d'autres conditions d'essai, seraient différentes. En d'autres termes, les valeurs absolues de performance seront différentes, mais les valeurs relatives devraient être similaires (pour une certaine plate-forme).
Du fait que la fonction iMA dans MQL5 ne renvoie pas elle-même les résultats du calcul (elle renvoie la poignée d'un indicateur), nous allons tester la vitesse de deux fonctions : iMA et CopyBuffer.
- Processeur Core i7 965
- Symbole "EURUSD"
- Taille des données de prix : 10000 éléments
- Terminal client : autonome, le nombre maximum de barres dans le graphique est fixé à 10000
- Modèles de Moyenne Mobile : MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
- La précision de la vitesse de calcul est limitée à deux chiffres significatifs
- Le nombre d'appels possibles des fonctions Moyennes Mobiles : 7
2. Comment nous avons testé
Pour mesurer le temps de calcul des Moyennes Mobiles, nous avons la fonction GetTickCount(), qui opère en millisecondes. Cette précision n'est pas suffisante, il faut donc organiser des cycles pour améliorer la qualité des mesures.
Cependant, si nous répétons la boucle plusieurs fois avec le même calcul et les mêmes données d'entrée, les résultats seront faussés. La raison de ce fait est la suivante : la fonction iMA crée une copie de l'indicateur technique correspondant dans le cache global du terminal client. Si la copie d'un indicateur (avec les mêmes paramètres) est déjà présente dans le cache global, la nouvelle copie n'est pas créée, le compteur de référence de la copie de l'indicateur est augmenté.
En d'autres termes, l'ensemble de l'indicateur de tampon est calculé une seule fois au premier appel, et à tous les appels suivants, il ne prend que les valeurs prêtes, il ne recalcule que les nouvelles données.
Par conséquent, la boucle doit être organisée de la manière, lorsque les paramètres d'entrée de l'indicateur sont uniques durant le cycle. Nous avons sélectionné trois de ces paramètres : période de moyennage ; délai et prix appliqué.
Paramètre | Fourchette des valeurs |
---|---|
Période de moyenne | de 1 à 100 |
Délai | М1, М5, М15, М30 |
Prix appliqué | PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED |
Tableau1. Les fourchettes de paramètres d'entrée
Nous allons calculer les valeurs de moyenne mobile pour le tableau avec 10000 éléments en utilisant les sept méthodes d'appel différentes (voir les détails dans la section 4).
3. Les conclusions de l'étude
Nous avons combiné tous les résultats dans le tableau 1, la performance de calcul est estimée en utilisant le temps de calcul (voir tableau 1) en secondes. Le programme calcule 100х4х7=2800 types de Moyennes Mobiles, et nous déterminons le temps de calcul pour le tableau des prix avec 10 000 éléments. Le temps de calcul du seul passage (cycle) est environ égal au temps total, divisé par 2800. Par exemple, pour le cas 1 et le mode SMA, il est égal à ~ 0,0028/2800.
Mode | MODE_SMA | MODE_EMA | MODE_SMMA | MODE_LWMA | Plateforme |
---|---|---|---|---|---|
0 (voir paragraphe 4.1) | 0,0041 | 0,0040 | 0,0043 | 0,0041 | MetaTrader 4 |
1 (voir paragraphe 4.2) | 0,0028 | 0,00023 | 0,00027 | 0,0045 | MetaTrader 5 |
2 (voir paragraphe 4.3) | 0,0029 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
3 (voir paragraphe 4.4) | 0,0998 | 0,0997 | 0,0998 | 0,0998 | MetaTrader 5 |
4 (voir paragraphe 4.5) | 0,0996 | 0,0996 | 0,0996 | 0,0996 | MetaTrader 5 |
5 (voir paragraphe 4.6) | 0,0030 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
6 (voir paragraphe 4.7) | 0,000140 | 0,000121 | 0,000117 | 0,0035 | MetaTrader 5 |
Tableau2. Les résultats
La signification des cas de test sera examinée plus en détail (paragraphes 4.1-4.7). Estimons l'ensemble de la performance de calcul de la Moyenne Mobile.
Pour plus de commodité, les résultats sont présentés sous forme de graphiques (voir figures 1-5). Le type d'appel de la Moyenne Mobile est présenté sur les axes X (voir tableau 2), les valeurs sur les axes Y sont présentées en échelle logarithmique multipliée par -1, donc les valeurs les plus élevées signifient des performances plus rapides. Chacun des modèles de calcul (SMA, EMA, SMMA, LWMA) correspond à une colonne du graphique.
Figure 1. Les résultats des tests de performance pour différents algorithmes de Moyenne Mobile
On peut voir une différence considérable de vitesse de calcul pour les différents cas de calcul des Moyennes Mobiles. Qu'est-ce que ça veut dire? Les différents algorithmes de calcul des Moyennes Mobiles, fournis par les développeurs de MQL5, ont des performances de calcul différentes : il existe un algorithme rapide (cas 6) et des méthodes plus lentes (cas 3 et 4). Il est donc nécessaire de choisir les bons algorithmes lors de l'écriture de programmes en MQL5, qui utilise les Moyennes Mobiles.
Le temps de calcul de chaque modèle de Moyennes Mobiles (0-6) est présenté en détail sur les figures suivantes, voir tableau 2.
Figure 2. La performance de calcul MA du mode MODE_SMA
Figure 3. la performance de calcul MA du mode MODE_EMA
Figure 4. la performance de calcul MA du mode MODE_SMMA
Figure 5. La performance de calcul MA du mode MODE_LWMA
Il est intéressant de comparer la performance de calcul de deux plateformes : MetaTrader 4 et MetaTrader 5. Les résultats sont présentés dans le tableau 2, cas №0 (MQL4) et cas №2 (MQL5).
Pour plus de commodité, combinons les résultats des calculs de l'indicateur standard iMA dans un graphique et un tableau séparés (voir fig. 6). Le temps de calcul du test est présenté en axes Y.
Figure 6. Tableau comparatif de performance de calcul de MetaTrader 4 et MetaTrader 5
Conclusion :
- La nouvelle plateforme MetaTrader 5 est 40% plus rapide que la précédente MetaTrader 4.
- La performance la plus rapide a été obtenue pour les modèles SMA, EMA et SMMA (cas №6), pour LWMA (cas №2 et №5).
- Pour les cas de test, lorsque l'indicateur standard iMA est utilisé, la performance de calcul des différents modèles sont quasiment identiques. Ce n'est pas vrai pour les fonctions de la bibliothèque MovingAverages.mqh. Pour différents modèles, la performance diffèrent de presque un ordre (0,00023 ~ 0,0045).
- Le résultat présenté correspond au "démarrage à froid", il n'y a pas de données précalculées dans le cache global du terminal client.
4. Études de cas
Les développeurs MQL5 recommandent la méthode suivante pour obtenir les valeurs des indicateurs techniques standard :
//---- indicator buffers double MA[]; // array for iMA indicator values //---- handles for indicators int MA_handle; // handle of the iMA indicator //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- creating handle of the iMA indicator MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE); //--- print message if there was an error if(MA_handle<0) { Print("The iMA object is not created: MA_handle= ",INVALID_HANDLE); Print("Runtime error = ",GetLastError()); //--- forced termination of program return(-1); } return(0); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- filling the MA[] array with current values of the iMA indicator //--- we will copy 100 elements, or return if there was an error if(CopyBuffer(MA_handle,0,0,100,MA)<=0) return; //--- set ordering of MA[] as timeseries ArraySetAsSeries(MA,true); //--- here you can do anything with these data }
Cette méthode est décrite en détail dans l'article "MQL5 for Newbies : Guide d'utilisation des indicateurs techniques dans Expert Advisors".
Pour tester la performance de calcul des Moyennes Mobiles, il est préférable d'utiliser le script, car il est capable d'effectuer tous les calculs sans attendre les événements (par exemple, nouvel événement tick, etc.).
Il n'est pas nécessaire de créer un programme universel séparé pour tous les cas de test, nous allons donc créer un script séparé pour chaque cas de calcul MA.
Examinons donc en détail chacun des cas de calculs de Moyenne Mobile.
4.1. Cas №0
Dans ce cas, nous avons mesuré la performance de calcul de l'indicateur technique iMA de MQL4. Les calculs sont effectués dans MetaTrader4 et menées sur toutes les données.
Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,0041 | 0,000140 (cas 6) |
MODE_EMA | 0,0040 | 0,000121 (cas 6) |
MODE_SMMA | 0,0043 | 0,000117 (cas 6): |
MODE_LWMA | 0,0041 | 0,0029 (cas 2, 5) |
Le code de ce cas est le suivant (MQL4) :
int M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; int P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[]; double time; int count=10000; int startGTC,endGTC; int m,p; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { if(ArrayResize(buf,count)<0) return(-1); Print("START "); startGTC=GetTickCount(); //---- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test0(); } } } //---- endGTC=GetTickCount(); time=endGTC-startGTC; Print("Total time [msec] ",time); time=time/1000/m/p/periodMA; Print("Performance [sec] ",DoubleToStr(time, 10)); return(0); } //+------------------------------------------------------------------+ void Test0() { //--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA for(int i=0;i<count;i++) { buf[i]=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p],i); } }
Note: Ce code ne fonctionnera pas dans MetaTrader 5, car il est écrit en MQL4. Il doit être exécuté sur le terminal client MetaTrader 4.
4.2. Cas №1
Dans ce cas, nous avons effectué le calcul de 4 modèles : №1(SMA), №2(EMA), №3(SMMA) et №4(LWMA) en utilisant les fonctions de la bibliothèque MovingAverages.mqh.
Le calcul est effectué sur l'ensemble du tableau de données.
Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,0028 | 0,000140 (cas 6) |
MODE_EMA | 0,00023 | 0,000121 (cas 6) |
MODE_SMMA | 0,00027 | 0,000117 (cas 6): |
MODE_LWMA | 0,0045 | 0,0029 (cas 2 et 5) |
#include <MovingAverages.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[],close[]; double time; int count=10000; int startGTC,endGTC; int m,p; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { if(ArrayResize(buf,count)<0) return(-1); ArraySetAsSeries(buf,false); ArraySetAsSeries(close,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { CopyClose(_Symbol,M[m],0,count,close); for(periodMA=1;periodMA<=100;periodMA++) { Test1(); // the test is here } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test1() { for(int i=0;i<count;i++) { buf[i]=SimpleMA(i,periodMA,close); } } //+------------------------------------------------------------------+ void Test2() { buf[0]=close[0]; for(int i=1;i<count;i++) { buf[i]=ExponentialMA(i,periodMA,buf[i-1],close); } } //+------------------------------------------------------------------+ void Test3() { buf[0]=close[0]; for(int i=1;i<count;i++) { buf[i]=SmoothedMA(i,periodMA,buf[i-1],close); } } //+------------------------------------------------------------------+ void Test4() { for(int i=0;i<count;i++) { buf[i]=LinearWeightedMA(i,periodMA,close); } }
Note: Nous avons prévu d'utiliser les différents types de données dans le tableau, mais pour la simplicité, nous avons utilisé un seul tableau avec clôture des données de prix (cela n'affecte pas la performance des calculs).
4.3. Cas №2
Dans ce cas, nous avons utilisé l'indicateur technique standard iMA et le test №5.
Le calcul est effectué sur l'ensemble du tableau de données.
Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,0029 | 0,000140 (cas 6) |
MODE_EMA | 0,0029 | 0,000121 (cas 6) |
MODE_SMMA | 0,0029 | 0,000117 (cas 6): |
MODE_LWMA | 0,0029 | 0,0029 (cas 2 et 5) |
ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double time; int count=10000; int startGTC,endGTC; int m,p; double MA[]; // array for the iMA indicator int MA_handle; // handle of the iMA indicator //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test5(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test5() { //--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA MA_handle=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p]); while(BarsCalculated(MA_handle)<count){} CopyBuffer(MA_handle,0,0,count,MA); }
4.4. Cas №3
Dans le cas №3, les classes fonctionnant avec les indicateurs des classes de la bibliothèque standard sont utilisées.
La copie de données élément par élément est utilisée. Le calcul est effectué sur l'ensemble du tableau de données.
Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,0998 | 0,000140 (cas 6) |
MODE_EMA | 0,0997 | 0,000121 (cas 6) |
MODE_SMMA | 0,0998 | 0,000117 (cas 6): |
MODE_LWMA | 0,0998 | 0,0029 (cas 2 et 5) |
#include <Indicators\Trend.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[]; double time; int count=10000; int startGTC,endGTC; int m,p; CiMA objMA; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { if(ArrayResize(buf,count)<0) return(-1); ArraySetAsSeries(buf,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test6(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test6() { //--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]); objMA.BuffSize(count); objMA.Refresh(1); for(int i=0;i<count;i++) { buf[i]=objMA.Main(i); } }
4.5. Cas №4
Dans le cas №4, les classes fonctionnant avec des indicateurs des classes de bibliothèque standard sont utilisées.
Le tableau du tampon indicateur est copié dans son ensemble. Le calcul est effectué sur l'ensemble du tableau de données.
Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,0996 | 0,000140 (cas 6) |
MODE_EMA | 0,0996 | 0,000121 (cas 6) |
MODE_SMMA | 0,0996 | 0,000117 (cas 6): |
MODE_LWMA | 0,0996 | 0,0029 (cas 2, 5) |
#include <Indicators\Trend.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[]; double time; int count=10000; int startGTC,endGTC; int m,p; CiMA objMA; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { if(ArrayResize(buf,count)<0) return(-1); ArraySetAsSeries(buf,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test7(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test7() { //--- Models: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]); objMA.BuffSize(count); objMA.Refresh(1); objMA.GetData(0,count,0,buf); }
4.6. Cas №5
Le test №8 est utilisé : la poignée de l'indicateur est créée à l'aide de la fonction IndicatorCreate.
Le calcul est effectué sur l'ensemble du tableau de données.Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,0030 | 0,000140 (cas 6) |
MODE_EMA | 0,0029 | 0,000121 (cas 6) |
MODE_SMMA | 0,0029 | 0,000117 (cas 6): |
MODE_LWMA | 0,0029 | 0,0029 (cas 2 et 5) |
ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double time; int count=10000; int startGTC,endGTC; int m,p; double MA[]; // array for the iMA indicator int MA_handle; // handle of the iMA indicator MqlParam params[]; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { ArrayResize(params,4); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test8(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test8() { //--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA //--- set ma_period params[0].type =TYPE_INT; params[0].integer_value=periodMA; //--- set ma_shift params[1].type =TYPE_INT; params[1].integer_value=0; //--- set ma_method params[2].type =TYPE_INT; params[2].integer_value=MODE_SMA; //--- set applied_price params[3].type =TYPE_INT; params[3].integer_value=P[p]; //--- create MA MA_handle=IndicatorCreate(NULL,M[m],IND_MA,4,params); while(BarsCalculated(MA_handle)<count){} CopyBuffer(MA_handle,0,0,count,MA); }
4.7. Cas №6
Dans ce cas, nous avons effectué le calcul de 4 modèles : №9(SMA), №10(EMA), №11(SMMA) и №12(LWMA) en utilisant les fonctions de la bibliothèque MovingAverages.mqh (les fonctions de tampon comme iMAOnArray de MQL4) .
Le calcul est effectué sur l'ensemble du tableau de données.
Modèle | Résultat | Meilleur résultat |
---|---|---|
MODE_SMA | 0,000140 | 0,000140 (cas 6) |
MODE_EMA | 0,000121 | 0,000121 (cas 6) |
MODE_SMMA | 0,000117 | 0,000117 (cas 6): |
MODE_LWMA | 0,00350 | 0,0029 (cas 2 et 5) |
#include <MovingAverages.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[],arr[]; double close[]; double time; int count=10000,total; int startGTC,endGTC; int m,p; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { CopyClose(_Symbol,_Period,0,count,close); total=ArrayCopy(arr,close); if(ArrayResize(buf,total)<0) return(-1); //--- ArraySetAsSeries(close,false); ArraySetAsSeries(arr,false); ArraySetAsSeries(buf,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { CopyClose(_Symbol,M[m],0,count,close); total=ArrayCopy(arr,close); for(periodMA=1;periodMA<=100;periodMA++) { Test9(); // the test is here } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test9() { SimpleMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ void Test10() { ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ void Test11() { SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ void Test12() { LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf); }
Note: Nous avons prévu d'utiliser plusieurs types de données dans le tableau, mais pour plus de simplicité, nous n'avons utilisé qu'un seul tableau avec des données de prix de clôture (cela n'affecte pas la performance des calculs).
5. Sortie des résultats
Pour la sortie des résultats et la vérification des Moyennes Mobiles, j'ai utilisé la fonction PrintTest :
void PrintTest(const int position, const double &price[]) { Print("Total time [msec] ",(endGTC-startGTC)); Print("Performance [sec] ",time); Print(position," - array element = ",price[position]); }
Elle peut être appelée comme suit (la position de la barre et le tableau de données sont des paramètres de la fonction) :
//--- ArraySetAsSeries(buf,false); ArraySetAsSeries(close,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- Output of results ArraySetAsSeries(buf,true); ArraySetAsSeries(close,true); PrintTest(0,buf); PrintTest(0,close); //---
Notez que l'indexation des tableaux est différente avant et après les calculs.
IMPORTANT. L'indicateur AsSeries est défini comme faux durant les calculs et défini comme vrai lors de l’impression des résultats.
6. Enquêtes supplémentaires
Pour répondre à la question sur l'effet des paramètres initiaux sur la performance du calcul, quelques mesures supplémentaires ont été effectuées.
Comme nous nous en souvenons, le boîtier №6 présente la meilleure performance, nous allons donc l'utiliser.
Paramètres de test
Mode | Délai | Période de moyenne |
---|---|---|
1 | М1 | 144 |
2 | М5 | 144 |
3 | М15 | 144 |
4 | М30 | 144 |
5 | М1 | 21 |
6 | М1 | 34 |
7 | М1 | 55 |
8 | М1 | 89 |
9 | М1 | 233 |
10 | М1 | 377 |
11 | М1 | 610 |
12 | М1 | 987 |
Tableau3 Enquêtes complémentaires
Code source des tests :
//+------------------------------------------------------------------+ //| Test_SMA Model: MODE_SMA | //+------------------------------------------------------------------+ void Test_SMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); SimpleMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ //| Test_EMA Model: MODE_EMA | //+------------------------------------------------------------------+ void Test_EMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ //| Test_SMMA Model: MODE_SMMA | //+------------------------------------------------------------------+ void Test_SMMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ //| Test_LWMA Model: MODE_LWMA | //+------------------------------------------------------------------+ void Test_LWMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf); }
Pour les tests supplémentaires, nous utiliserons le programme d'autotest, son interface utilisateur graphique est présentée à la Fig. 7.
Figure 7. Le programme d'autotest pour les tests automatisés
Résultats: (les axes X ont une échelle de temps logarithmique)
Figure 8. Le paramètre Délai (Y) et la performance de calcul des Moyennes Mobiles (X)
Figure 9. Le paramètre Période (Y) et la performance de calcul des Moyennes Mobiles (X)
Les conclusions des résultats d'enquêtes complémentaires:
- Le paramètre délai n'est pas important, il n'affecte pas la performance de calcul (voir fig. 8).
- La durée n'est pas un paramètre important pour la performance du calcul des Moyennes Mobiles pour les modèles SMA, EMA et SMMA. Mais en revanche, elle ralentit considérablement (de 0,00373 seconde à 0,145 seconde) les calculs pour le modèle LWMA (voir. fig. 9).
Conclusion
Le mauvais choix de l'algorithme des Moyennes Mobiles est en mesure de réduire la performance de calcul de vos programmes.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/106





- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation