Download MetaTrader 5

Testing Performance of Moving Averages Calculation in MQL5

23 July 2010, 10:04
Sergey Pavlov
0
4 343


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.

Testing conditions:
  • 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_SMAMODE_EMAMODE_SMMAMODE_LWMAPlatform
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

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 2. The MA calculation performance of the MODE_SMA mode

Figure 3. The MA calculation performance of the MODE_EMA mode

Figure 3. The MA calculation performance of the MODE_EMA mode

Figure 4. The MA calculation performance of the MODE_SMMA mode

Figure 4. The MA calculation performance of the MODE_SMMA mode

Figure 5. The MA calculation performance of the MODE_LWMA 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

Figure 6. Comparative chart of MetaTrader 4 и MetaTrader 5 calculation performance

Conclusions:

  1. The new MetaTrader 5 platform is 40% faster than previous  MetaTrader 4.
  2. The fastest perfromance has been achieved for the SMA, EMA, and SMMA models (case №6), for LWMA (cases №2 and №5).
  3. 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).
  4. 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.

ModelResultBest 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
 ResultBest result
MODE_SMA
0,0028
0,000140 (case 6)
MODE_EMA
0,00023
0,000121 (case 6)
MODE_SMMA
0,000270,000117 (case 6)
MODE_LWMA
0,00450,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.

ModelResultBest 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.

ModelResultBest 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.

ModelResultBest 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.
ModelResultBest 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.

ModelResultBest 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
М121
6
М134
7
М155
8
М189
9
М1233
10
М1377
11
М1610
12
М1987

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

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 8. The Timeframe parameter (Y) and Moving Averages calculation performance (X)

Figure 9. The Period 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:

  1. The timeframe parameter isn't important, it doesn't affect on the calculation performance (see fig. 8).
  2. 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 Software Corp.
Original article: https://www.mql5.com/ru/articles/106

Attached files |
autotest__1.zip (10.86 KB)
Step on New Rails: Custom Indicators in MQL5 Step on New Rails: Custom Indicators in MQL5

I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.

Here Comes the New MetaTrader 5 and MQL5 Here Comes the New MetaTrader 5 and MQL5

This is just a brief review of MetaTrader 5. I can't describe all the system's new features for such a short time period - the testing started on 2009.09.09. This is a symbolical date, and I am sure it will be a lucky number. A few days have passed since I got the beta version of the MetaTrader 5 terminal and MQL5. I haven't managed to try all its features, but I am already impressed.

False trigger protection for Trading Robot False trigger protection for Trading Robot

Profitability of trading systems is defined not only by logic and precision of analyzing the financial instrument dynamics, but also by the quality of the performance algorithm of this logic. False trigger is typical for low quality performance of the main logic of a trading robot. Ways of solving the specified problem are considered in this article.

Using text files for storing input parameters of Expert Advisors, indicators and scripts Using text files for storing input parameters of Expert Advisors, indicators and scripts

The article describes the application of text files for storing dynamic objects, arrays and other variables used as properties of Expert Advisors, indicators and scripts. The files serve as a convenient addition to the functionality of standard tools offered by MQL languages.