Test delle Prestazioni del Calcolo delle Medie Mobili in MQL5
Introduzione
L'uso delle Medie Mobili è una pratica comune nell'analisi delle time serie di mercato, negli indicatori e nella programmazione degli Expert Advisor. È il metodo più popolare dello smoothing dei dati sui prezzi. Nella nuova versione del linguaggio MQL sono disponibili una dozzina di algoritmi Moving Average.
Questa è la differenza tra loro? Davvero, la velocità di calcolo dipende da un determinato algoritmo delle Medie Mobili? Quale algoritmo è più veloce?
La velocità di calcolo delle Medie Mobili è aumentata in MetaTrader 5 rispetto a MetaTrader 4? Tante domande simili appaiono. Quindi, consideriamo la maggior parte di loro.
Certo, la velocità di una nuova piattaforma è impressionante, ma è meglio verificarla sperimentalmente.
1. Condizioni di prova
La velocità di calcolo dipende da molti fattori. Pertanto, i dati che sono stati ottenuti a seguito di questa ricerca, sarebbero diversi in altre condizioni di test. In altre parole, i valori assoluti delle prestazioni saranno diversi, ma i valori relativi dovrebbero essere simili (per una determinata piattaforma).
A causa del fatto che la funzionei MA in MQL5 non restituisce i risultati del calcolo stesso (restituisce l'handle di un indicatore), testeremo la velocità di due funzioni: iMA e CopyBuffer.
- CPU: Core i7 965
- Simbolo: "EURUSD"
- Dimensione dati prezzo: 10000 elementi
- Terminale client: autonomo, il numero massimo di barre nel chart è fissato a 10000
- Modelli di media mobile: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
- La precisione della velocità di calcolo è limitata a due cifre significative
- Il numero possibile di chiamate delle funzioni delle Medie Mobili: 7
2. Come abbiamo effettuato il test
Per misurare il tempo del calcolo delle medie mobili abbiamo la funzione GetTickCount(), che opera in millisecondi. Questa precisione non è sufficiente, quindi è necessario organizzare alcuni cicli per migliorare la qualità delle misurazioni.
Tuttavia, se ripeteremo il ciclo molte volte con lo stesso calcolo e gli stessi dati di input, i risultati saranno distorti. La ragione di questo fatto è la seguente: la funzione iMA crea una copia dell'indicatore tecnico corrispondente nella cache globale del terminale client. Se la copia di un indicatore (con gli stessi parametri) è già presente nella cache globale, la nuova copia non viene creata, viene incrementato il contatore di riferimento della copia dell'indicatore.
In altre parole, l'intero indicatore del buffer viene calcolato solo una volta alla prima chiamata, e a tutte le chiamate successive prende solo i valori pronti, ricalcola solo i nuovi dati.
Pertanto il ciclo dovrebbe essere organizzato nel modo in cui i parametri di input dell'indicatore sono unici durante il ciclo. Abbiamo selezionato tre di questi parametri: periodo della media; timeframe e prezzo applicato.
Parametro | Gamma dei valori |
---|---|
Periodo della media | da 1 a 100 |
Timeframe | М1, М5, М15, М30 |
Prezzo applicato | PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED |
Tabella 1. Le gamme dei parametri di input
Calcoleremo i valori della media mobile per l'array con 10000 elementi utilizzando i sette diversi metodi di chiamata (vedi dettagli nella sezione 4).
3. I risultati dello studio
Abbiamo unito tutti i risultati nella tabella 1, le prestazioni di calcolo sono stimate utilizzando il tempo di calcolo (vedi tabella 1) in secondi. Il programma calcola 100х4х7=2800 tipi di medie mobili e determiniamo il tempo di calcolo per l'array dei prezzi con 10.000 elementi. Il tempo di calcolo del singolo passaggio (ciclo) è approssimativamente uguale al tempo totale, diviso per 2800. Ad esempio, per il caso 1 e la modalità SMA è pari a ~ 0,0028/2800.
Modalità | MODE_SMA | MODE_EMA | MODE_SMMA | MODE_LWMA | Piattaforma |
---|---|---|---|---|---|
0 (vedi sezione 4.1) | 0,0041 | 0,0040 | 0,0043 | 0,0041 | MetaTrader 4 |
1 (vedi sezione 4.2) | 0,0028 | 0,00023 | 0,00027 | 0,0045 | MetaTrader 5 |
2 (vedi sezione 4.3) | 0,0029 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
3 (vedi paragrafo 4.4) | 0,0998 | 0,0997 | 0,0998 | 0,0998 | MetaTrader 5 |
4 (vedi sezione 4.5) | 0,0996 | 0,0996 | 0,0996 | 0,0996 | MetaTrader 5 |
5 (vedi sezione 4.6) | 0,0030 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
6 (vedi sezione 4.7) | 0,000140 | 0,000121 | 0,000117 | 0,0035 | MetaTrader 5 |
Tabella 2 I risultati
Il significato dei casi dei test sarà considerato ulteriormente (sezioni 4.1-4.7). Stimiamo l'intero quadro delle prestazioni di calcolo della Media Mobile.
Per comodità, i risultati sono presentati sotto forma di grafici (vedi figure 1-5). Il tipo di chiamata di Moving Average è presentato sugli assi X (vedi tabella 2), i valori sugli assi Y sono presentati in scala logaritmica moltiplicata per -1, quindi i valori più grandi indicano le prestazioni più veloci. Ciascuno dei modelli di calcolo (SMA, EMA, SMMA, LWMA) corrisponde a una colonna del grafico.
Figura 1. I risultati del test delle prestazioni per diversi algoritmi della Media Mobile
Si può notare una differenza significativa nella velocità di calcolo per i diversi casi del calcolo delle Medie Mobili. Cosa significa? I diversi algoritmi di calcolo delle Medie Mobili, forniti dagli sviluppatori MQL5, hanno prestazioni di calcolo differenti: c'è un algoritmo veloce (caso 6) e metodi più lenti (casi 3 e 4). Quindi, è necessario scegliere gli algoritmi corretti quando si scrivono programmi in MQL5, che utilizza le Medie Mobili.
Il tempo di calcolo di ciascun modello delle Medie Mobili (0-6) è presentato in dettaglio nelle figure seguenti, vedere la tabella 2.
Figura 2. Le prestazioni di calcolo MA della modalità MODE_SMA
Figura 3. Le prestazioni di calcolo MA della modalità MODE_EMA
Figura 4. Le prestazioni di calcolo MA della modalità MODE_SMMA
Figura 5. Le prestazioni di calcolo MA della modalità MODE_LWMA
È interessante confrontare le prestazioni di calcolo di due piattaforme: MetaTrader 4 e MetaTrader 5. I risultati sono presentati nella Tabella 2, caso №0 (MQL4) e caso №2 (MQL5).
Per comodità, uniamo i risultati del calcolo dell'indicatore standard iMA in un grafico e una tabella separati (vedi fig. 6). Il tempo di calcolo del test è presentato sugli assi Y.
Figura 6. Grafico comparativo di MetaTrader 4 e prestazioni di calcolo MetaTrader 5
Conclusioni:
- La nuova piattaforma MetaTrader 5 è più veloce del 40% rispetto alla precedente MetaTrader 4.
- La prestazione più veloce è stata ottenuta per i modelli SMA, EMA e SMMA (caso №6), per LWMA (casi №2 e №5).
- Per i casi di test, quando viene utilizzato l'indicatore standard iMA, le prestazioni di calcolo dei diversi modelli sono praticamente identiche. Non è lo stesso per le funzioni della libreria MovingAverages.mqh. Per i diversi modelli le prestazioni differiscono di quasi un ordine (0.00023~0,0045).
- I risultati presentati corrispondono a "cold start", non ci sono dati precalcolati nella cache globale del client terminal.
4. Casi Studio
Gli sviluppatori MQL5 consigliano il seguente metodo per ottenere i valori degli indicatori tecnici 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 }
Questo metodo è descritto in dettaglio nell'articolo "MQL5 for Newbies: Guide to Using Technical Indicators in Expert Advisors".
Per testare le prestazioni di calcolo delle medie mobili, è meglio utilizzare lo script, perché è in grado di eseguire tutti i calcoli senza attendere gli eventi (ad esempio, nuovo evento tick, ecc.).
Non è necessario creare un programma universale separato per tutti i casi di test, quindi creeremo uno script separato per ogni caso di calcolo MA.
Quindi, consideriamo in dettaglio ciascuno dei casi di calcolo della Media Mobile.
4.1. Caso №0
In questo caso abbiamo misurato le prestazioni di calcolo dell'indicatore tecnico iMA di MQL4. I calcoli vengono eseguiti in MetaTrader4 ed eseguiti su tutti i dati.
Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,0041 | 0,000140 (caso 6) |
MODE_EMA | 0,0040 | 0,000121 (caso 6) |
MODE_SMMA | 0,0043 | 0,000117 (caso 6) |
MODE_LWMA | 0,0041 | 0,0029 (casi 2, 5) |
Il codice di questo caso è il seguente (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); } }
Nota: Questo codice non funzionerà in MetaTrader 5, perché è scritto in MQL4. Dovrebbe essere eseguito sul terminale client MetaTrader 4.
4.2. Caso №1
In questo caso abbiamo eseguito il calcolo di 4 modelli: №1(SMA), №2(EMA), 3(SMMA) e №4(LWMA) utilizzando le funzioni della libreria MovingAverages.mqh.
Il calcolo viene eseguito su tutta la matrice di dati.
Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,0028 | 0,000140 (caso 6) |
MODE_EMA | 0,00023 | 0,000121 (caso 6) |
MODE_SMMA | 0,00027 | 0,000117 (caso 6) |
MODE_LWMA | 0,0045 | 0,0029 (casi 2 e 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); } }
Nota.Abbiamo deciso di utilizzare i diversi tipi di dati nell’array ma per semplicità abbiamo utilizzato un solo array con i dati sui prezzi di chiusura (non influisce sull'esecuzione dei calcoli).
4.3. Caso №2
In questo caso abbiamo utilizzato l'indicatore tecnico standard iMA e il test №5.
Il calcolo viene eseguito su tutta la matrice di dati.
Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,0029 | 0,000140 (caso 6) |
MODE_EMA | 0,0029 | 0,000121 (caso 6) |
MODE_SMMA | 0,0029 | 0,000117 (caso 6) |
MODE_LWMA | 0,0029 | 0,0029 (casi 2 e 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. Caso №3
Nel caso №3 vengono utilizzate le classi che lavorano con gli indicatori delle classi della libreria Standard.
Viene utilizzata la copia dei dati elementwise. Il calcolo viene eseguito su tutta la matrice di dati.
Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,0998 | 0,000140 (caso 6) |
MODE_EMA | 0,0997 | 0,000121 (caso 6) |
MODE_SMMA | 0,0998 | 0,000117 (caso 6) |
MODE_LWMA | 0,0998 | 0,0029 (casi 2 e 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. Caso №4
Nel caso №4 vengono utilizzate le classi che lavorano con gli indicatori delle classi della libreria Standard.
L'array del buffer dell'indicatore viene copiato nel suo insieme. Il calcolo viene eseguito su tutta la matrice di dati.
Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,0996 | 0,000140 (caso 6) |
MODE_EMA | 0,0996 | 0,000121 (caso 6) |
MODE_SMMA | 0,0996 | 0,000117 (caso 6) |
MODE_LWMA | 0,0996 | 0,0029 (casi 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. Caso №5
Viene utilizzato il test №8: l'handle dell'indicatore viene creato utilizzando la funzione IndicatorCreate.
Il calcolo viene eseguito su tutta la matrice di dati.Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,0030 | 0,000140 (caso 6) |
MODE_EMA | 0,0029 | 0,000121 (caso 6) |
MODE_SMMA | 0,0029 | 0,000117 (caso 6) |
MODE_LWMA | 0,0029 | 0,0029 (casi 2 e 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. Caso 6
In questo caso abbiamo eseguito il calcolo di 4 modelli: №9(SMA), №10(EMA), №11(SMMA) e №12(LWMA) utilizzando le funzioni della libreria MovingAverages.mqh (il buffer funziona come iMAOnArray da MQL4) .
Il calcolo viene eseguito su tutta la matrice di dati.
Modello | Risultato | Miglior risultato |
---|---|---|
MODE_SMA | 0,000140 | 0,000140 (caso 6) |
MODE_EMA | 0,000121 | 0,000121 (caso 6) |
MODE_SMMA | 0,000117 | 0,000117 (caso 6) |
MODE_LWMA | 0,00350 | 0,0029 (casi 2 e 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); }
Nota.Abbiamo pianificato di utilizzare i diversi tipi di dati nell'array, ma per semplicità abbiamo utilizzato un solo array con i dati sui prezzi di chiusura (non influisce sulle prestazioni dei calcoli).
5. Output dei Risultati
Per l'output dei risultati e la verifica delle medie mobili, ho utilizzato la funzione 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]); }
Può essere chiamato, come segue (la posizione della barra e l'array dei dati sono parametri della funzione):
//--- 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); //---
Si noti che l'indicizzazione dell'array è diversa prima e dopo i calcoli.
IMPORTANTE. Il flag AsSeries è impostato su false durante i calcoli e su true durante la stampa dei risultati.
6. Ulteriori Analisi
Per rispondere alla domanda sull'effetto dei parametri iniziali sulle prestazioni di calcolo, sono state effettuate alcune misurazioni aggiuntive.
Come ricordiamo, il caso №6 ha le migliori prestazioni, quindi lo useremo.
Test parametri
Modalità | Timeframe | Periodo della media |
---|---|---|
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 |
Tabella 3. Ulteriori analisi
Codice sorgente dei test:
//+------------------------------------------------------------------+ //| 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); }
Per i test aggiuntivi utilizzeremo il programma di autotest, la sua interfaccia utente grafica è presentata nella Fig. 7.
Figura 7. Il programma di autotest per i test automatizzati
Risultati: (l'asse X ha una scala temporale logaritmica)
Figura 8. Il parametro Timeframe (Y) e le prestazioni di calcolo delle Medie Mobili (X)
Figura 9. Il parametro Period (Y) e le prestazioni di calcolo delle Medie Mobili (X)
Le conclusioni dei risultati di ulteriori analisi:
- Il parametro timeframe non è importante, non influisce sulle prestazioni di calcolo (vedi fig. 8).
- Il periodo non è un parametro importante per l'esecuzione del calcolo delle medie mobili per i modelli SMA, EMA e SMMA. Ma al contrario, rallenta significativamente i calcoli (da 0,00373 secondi a 0,145 secondi) per il modello LWMA (vedi fig. 9).
Conclusione
La scelta errata dell'algoritmo delle medie mobili è in grado di ridurre le prestazioni di calcolo dei tuoi programmi.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/106
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso