Testing Performance of Moving Averages Calculation in MQL5
Introduction
The use of Moving Averages is a common practice in analysis of market time series, in indicators and Expert Advisors programming. It's the most popular price data smoothing method. In new version of MQL language there is a dozen of Moving Average algorithms are available.
That's the difference between them? Really, does the calculation speed dependent on certain algorithm of Moving Averages? Which algorithm is faster?
Does the calculation speed of Moving Averages has increased in MetaTrader 5 compared with MetaTrader 4? There is a lot of such questions appear. So, let's consider most of them.
Of course, the speed of a new platform is impressive, but it's better to check it experimentally.
1. Testing conditions
The calculation speed is dependent on many factors. Therefore, the data that were obtained as a results of this research, in other testing conditions would be different. In other words, the absolute values of performance will be different, but relative values should be similar (for a certiain platform).
Because of the fact that the iMA function in MQL5 doesn't return the calculation results itself (it returns an indicator's handle), we will test the speed of two functions: iMA and CopyBuffer.
- CPU: Core i7 965
- Symbol: "EURUSD"
- Price data size: 10000 elements
- Client terminal: autonomous, the maximum number of bars in the chart is set to 10000
- Moving average models: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
- The accuracy of calculation speed is limited to two significant digits
- The possible number of calls of the Moving Averages functions: 7
2. How we tested
To measure the time of the moving averages calculation we have the GetTickCount() function, which operates in milliseconds. This accuracy is not enough, so we need to organize some cycles to improve the quality of measurements.
However, if we will repeat the loop many times with the same calculation and same input data, the results will be distorted. The reason of this fact is the following: the iMA function creates a copy of the corresponding technical indicator in the global cache of the client terminal. If the copy of an indicator ( with the same parameters) is already present in the global cache, the new copy is not created, the reference counter of the indicator's copy is increased.
In other words, the entire buffer indicator is calculated just once at the first call, and at all subsequent calls it just takes the ready values, it recalculates only the new data.
Therefore the loop should be organized the way, when input parameters of the indicator are unique during the cycle. We have selected three such parameters: averaging period; timeframe and applied price.
Parameter | Range of the values |
---|---|
Averaging period | from 1 to 100 |
Timeframe | М1, М5, М15, М30 |
Applied price | PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED |
Table 1. The ranges of input parameters
We will calculate the values of moving average for the array with 10000 elements using the seven different call methods (see details in section 4).
3. The results of the study
We have combined all results in Table 1, the calculation performance is estimated using the calculation time (see table 1) in seconds. The program calculates 100х4х7=2800 types of moving averages, and we determine the calculation time for the price array with 10 000 elements. The calculation time of the single pass (cycle) is approximately equal to total time, divided by 2800. For example, for the case 1 and SMA mode it equal to ~ 0,0028/2800.
Mode | MODE_SMA | MODE_EMA | MODE_SMMA | MODE_LWMA | Platform |
---|---|---|---|---|---|
0 (see section 4.1) |
0,0041 | 0,0040 | 0,0043 | 0,0041 | MetaTrader 4 |
1 (see section 4.2) | 0,0028 | 0,00023 | 0,00027 | 0,0045 | MetaTrader 5 |
2 (see section 4.3) | 0,0029 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
3 (see section 4.4) | 0,0998 | 0,0997 | 0,0998 | 0,0998 | MetaTrader 5 |
4 (see section 4.5) | 0,0996 | 0,0996 | 0,0996 | 0,0996 | MetaTrader 5 |
5 (see section 4.6) | 0,0030 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
6 (see section 4.7) | 0,000140 | 0,000121 | 0,000117 | 0,0035 | MetaTrader 5 |
Table 2. The results
The meaning of testing cases will be considered further (sections 4.1-4.7). Let's estimate the whole picture of calculation performance of Moving Average.
For convience, the results are presented at charts (see figures 1-5). The calling type of Moving Average is presented at X axes (see table 2), the values at Y axes are presented in logarithmic scale multiplied by -1, so the larger values means faster performance. Each of the calculation model (SMA, EMA, SMMA, LWMA) corresponds to a column on the chart.
Figure 1. The performance test results for different Moving Average algorithms
One can see a significant difference in calculation speed for the different cases of the Moving Averages calculation. What does it mean? The several algorithms of Moving Averages calculation, provided by MQL5 developers have different calculation performance: there is a fast algorithm (case 6) and slower methods (cases 3 and 4). So, it's necessary to choose the correct algorithms when writing programs in MQL5, which uses Moving Averages.
The calculation time of each Moving Averages models (0-6) is presented in details on the following figures, see table 2.
Figure 2. The MA calculation performance of the MODE_SMA mode
Figure 3. The MA calculation performance of the MODE_EMA mode
Figure 4. The MA calculation performance of the MODE_SMMA mode
Figure 5. The MA calculation performance of the MODE_LWMA mode
It's interesting to compare the calculation performance of two platforms: MetaTrader 4 and MetaTrader 5. The results are presented in Table 2, case №0 (MQL4) and case №2 (MQL5).
For convience, let's combine the calculation results of iMA standard indicator into a separate chart and table (see fig. 6). The calculation time of the test is presented at Y axes.
Figure 6. Comparative chart of MetaTrader 4 и MetaTrader 5 calculation performance
Conclusions:
- The new MetaTrader 5 platform is 40% faster than previous MetaTrader 4.
- The fastest perfromance has been achieved for the SMA, EMA, and SMMA models (case №6), for LWMA (cases №2 and №5).
- For test cases, when the standard indicator iMA is used,
the calculation performance of different models is practically identical. It's not true for the MovingAverages.mqh library functions. For different models the performance differ by almost an order (0,00023~0,0045).
- The results presented is corresponds to "cold start", there isn't any precalculated data in the global cache of the client terminal.
4. Case Studies
The MQL5 developers recommend the following method for getting the values of standard technical indicators:
//---- 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 }
This method is described in details in the article "MQL5 for Newbies: Guide to Using Technical Indicators in Expert Advisors".
For testing of the calculation performance of moving averages, it's beter to use the script, because it's able perform all the calculations without waiting of the events (for example, new tick event, etc.).
It isn't necessary to create a separate universal program for all test cases, therefore we will create a separate script for every case of MA calculation.
So, let's consider in details each of the cases of Moving Average calculations.
4.1. Case №0
In this case we measured the calculation performance of technical indicator iMA of MQL4. The calculations is perfomed in MetaTrader4 and carried out on all the data.
Model | Result | Best result |
---|---|---|
MODE_SMA | 0,0041 | 0,000140 (case 6) |
MODE_EMA | 0,0040 | 0,000121 (case 6) |
MODE_SMMA | 0,0043 | 0,000117 (case 6) |
MODE_LWMA | 0,0041 | 0,0029 (cases 2, 5) |
The code of this case is the following (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: This code will not work in MetaTrader 5, because it written in MQL4. It should be executed at MetaTrader 4 client terminal.
4.2. Case №1
In this case we have performed calculation of 4 models: №1(SMA), №2(EMA), №3(SMMA) и №4(LWMA) using the MovingAverages.mqh library functions.
The calculation is carried out on all the data array.
Model | Result | Best result |
---|---|---|
MODE_SMA | 0,0028 | 0,000140 (case 6) |
MODE_EMA | 0,00023 | 0,000121 (case 6) |
MODE_SMMA | 0,00027 | 0,000117 (case 6) |
MODE_LWMA | 0,0045 | 0,0029 (cases 2 and 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. We have planned to use the several types of data in the array, but for the simplicity, we have used only one array with close prices data (it doesn't affect on the performance of calculations).
4.3. Case №2
In this case we have used the iMA standard technical indicator and test №5.
The calculation is carried out on all the data array.
Model | Result | Best result |
---|---|---|
MODE_SMA | 0,0029 | 0,000140 (case 6) |
MODE_EMA | 0,0029 | 0,000121 (case 6) |
MODE_SMMA | 0,0029 | 0,000117 (case 6) |
MODE_LWMA | 0,0029 | 0,0029 (cases 2 and 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. Case №3
In case №3 the classes working with indicators of the Standard library classes are used.
The elementwise data copying is used. The calculation is carried out on all the data array.
Model | Result | Best result |
---|---|---|
MODE_SMA | 0,0998 | 0,000140 (case 6) |
MODE_EMA | 0,0997 | 0,000121 (case 6) |
MODE_SMMA | 0,0998 | 0,000117 (case 6) |
MODE_LWMA | 0,0998 | 0,0029 (cases 2 and 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. Case №4
In case №4 the classes working with indicators of the Standard library classes are used.
The indicator buffer's array is copied as a whole. The calculation is carried out on all the data array.
Model | Result | Best result |
---|---|---|
MODE_SMA | 0,0996 | 0,000140 (case 6) |
MODE_EMA | 0,0996 | 0,000121 (case 6) |
MODE_SMMA | 0,0996 | 0,000117 (case 6) |
MODE_LWMA | 0,0996 | 0,0029 (cases 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. Case №5
The test №8 is used: the indicator handle is created using the IndicatorCreate function.
The calculation is carried out on all the data array.Model | Result | Best result |
---|---|---|
MODE_SMA | 0,0030 | 0,000140 (case 6) |
MODE_EMA | 0,0029 | 0,000121 (case 6) |
MODE_SMMA | 0,0029 | 0,000117 (case 6) |
MODE_LWMA | 0,0029 | 0,0029 (cases 2 and 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. Case №6
In this case we have performed calculation of 4 models: №9(SMA), №10(EMA), №11(SMMA) и №12(LWMA) using the MovingAverages.mqh library functions (the buffer functions like iMAOnArray from MQL4).
The calculation is carried out on all the data array.
Model | Result | Best result |
---|---|---|
MODE_SMA | 0,000140 | 0,000140 (case 6) |
MODE_EMA | 0,000121 | 0,000121 (case 6) |
MODE_SMMA | 0,000117 | 0,000117 (case 6) |
MODE_LWMA | 0,00350 | 0,0029 (cases 2 and 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. We have planned to use the several types of data in the array, but for the simplicity, we have used only one array with close prices data (it doesn't affect on the performance of calculations).
5. Output of the Results
For the output of the results and checking of the moving averages, I used the PrintTest function:
void PrintTest(const int position, const double &price[]) { Print("Total time [msec] ",(endGTC-startGTC)); Print("Performance [sec] ",time); Print(position," - array element = ",price[position]); }
It can be called, as follows (the bar position and data array are parameters of the function):
//--- 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); //---
Note, that array indexing are differ before and after the calculations.
IMPORTANT. The AsSeries flag is set to false during the calculations and it set to true when printing the results.
6. Additional Investigations
To answer the question about the effect of initial parameters on the performance of calculation, some additional measurements have done.
As we remember, the case №6 has best performance, so we will use it.
Testing parameters:
Mode | Timeframe | Averaging period |
---|---|---|
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 |
Table 3. Additional investigations
Source code of the 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); }
For the additional tests we will use the autotest program, its graphic user interface is presented at Fig. 7.
Figure 7. The autotest program for the aurtomated testing
Results: (the X axes has a logarithmic time scale)
Figure 8. The Timeframe parameter (Y) and Moving Averages calculation performance (X)
Figure 9. The Period parameter (Y) and Moving Averages calculation performance (X)
The conclusions of the results of additional investigations:
- The timeframe parameter isn't important, it doesn't affect on the calculation performance (see fig. 8).
- The period isn't important parameter for the performance of moving averages calculation for the models SMA, EMA and SMMA. But in contrast, it significantly (from 0,00373 seconds to 0,145 seconds) slows the calculations for the LWMA model (see fig. 9).
Conclusion
The incorrect choice of the moving averages algorithm is able to reduce calculation performance of your programs.
Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/106
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use