Testando o desempenho do cálculo das médias móveis no MQL5
Introdução
O uso de médias móveis é uma prática comum na análise de séries de tempo do mercado, em programação de Expert Advisors e indicadores. é o método de suavização dos dados de preço mais popular. Na nova versão da linguagem MQL há uma dúzia de algoritmos de média móvel disponíveis.
Qual é a diferença entre eles? O cálculo é dependente de velocidade em certos algoritmos das médias móveis? Qual algoritmo é o mais rápido?
A velocidade do cálculo das médias móveis aumentou no MetaTrader 5 em comparação com o MetaTrader 4? Parecem haver muitas dessas questões surgindo. Então vamos considerar a maioria delas.
Claro, a velocidade de uma nova plataforma é impressionante, mas é melhor verificar experimentalmente.
1. Condições de teste
A velocidade do cálculo é dependente de muitos fatores. Portanto, os dados que foram combinados como resultados, em outras condições de teste seriam diferentes. Em outras palavras, os valores absolutos de desempenho serão diferentes, mas valores relativos devem ser semelhantes (para uma determinada plataforma).
Devido ao fato de que a função iMA no MQL5 não retorna os resultados de cálculo por si (ela retorna um handle do indicador), testaremos a velocidade de duas funções: iMA e CopyBuffer.
- CPU: Core i7 965
- Símbolo: "EURUSD"
- Tamanho dos dados do preço: 10000 elementos
- Terminal do cliente: autônomo, o número máximo de barras no gráfico é configurado para 10000
- Modelos de médias móveis: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
- A precisão da velocidade de cálculo é limitada a dois dígitos significantes
- O número possível de chamadas das funções das médias móveis: 7
2. Como nós testamos
Para medir o tempo do cálculo das médias móveis nós possuímos a função GetTickCount(), que opera em milissegundos. Essa precisão não é o suficiente, então nós precisamos organizar alguns ciclos para melhorar a qualidade das medições.
No entanto, se nós repetirmos o ciclo muitas vezes com o mesmo cálculo e as mesmas entradas de dados, os resultados serão distorcidos. A razão para esse fato é a seguinte: a função iMA cria uma cópia do indicador técnico correspondente no cache global do terminal do cliente. Se a cópia de um indicador (com os mesmos parâmetros) já está presente no cache global, a nova cópia não é criada, o contador de referência da cópia do indicador é aumentado.
Em outras palavras, todo o indicador de memória de armazenamento (buffer) é calculado apenas uma vez na primeira chamada, e em todas as chamadas subsequentes ele só toma os valores prontos, calculando novamente apenas os dados novos.
Então, o loop deve ser organizado no caminho, quando os parâmetros de entrada do indicador forem únicos durante o ciclo. Selecionamos três destes parâmetros: período de média; cronograma e preço aplicado.
Parâmetro | Gama de valores |
---|---|
Período de média | de 1 a 100 |
Cronograma | М1, М5, М15, М30 |
Preço aplicado | PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED |
Tabela 1. Tabela 1.
Calcularemos os valores da média móvel para o arranjo com 10000 elementos utilizando sete diferentes métodos de chamada (ver detalhes na seção 4).
3. Os resultados do estudo
Combinamos todos os resultados na tabela 1, o desempenho calculado é estimado utilizando o tempo de cálculo (ver tabela 1) em segundos. O programa calcula 100х4х7=2800 tipos de médias móveis, e nós determinamos o tempo de cálculo para o arranjo de preço com 10 000 elementos. O tempo de cálculo do passo único (ciclo) é aproximadamente igual ao tempo total dividido por 2800. Por exemplo, para o caso 1 e modo SMA ele é igual a ~ 0,0028/2800.
Modo | MODE_SMA | MODE_EMA | MODE_SMMA | MODE_LWMA | Plataforma |
---|---|---|---|---|---|
0 (ver seção 4.1) |
0,0041 | 0,0040 | 0,0043 | 0,0041 | MetaTrader 4 |
1 (ver seção 4.2) | 0,0028 | 0,00023 | 0,00027 | 0,0045 | MetaTrader 5 |
2 (ver seção 4.3) | 0,0029 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
3 (ver seção 4.4) | 0,0998 | 0,0997 | 0,0998 | 0,0998 | MetaTrader 5 |
4 (ver seção 4.5) | 0,0996 | 0,0996 | 0,0996 | 0,0996 | MetaTrader 5 |
5 (ver seção 4.6) | 0,0030 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
6 (ver seção 4.7) | 0,000140 | 0,000121 | 0,000117 | 0,0035 | MetaTrader 5 |
Tabela 2. Os resultados
O significado de casos de teste serão considerados adiante (seções 4.1-4.7). Vamos estimar o quadro completo de cálculo do desempenho da média móvel.
Por conveniência, os resultados são apresentados em gráficos (ver figuras 1-5). O tipo de chamada da média móvel é apresentado nos eixos X (ver tabela 2), os valores nos eixos Y são apresentados em escala logarítmica multiplicados por -1 de forma que os valores maiores significassem desempenho mais rápido. Cada modelo de cálculo (SMA, EMA, SMMA, LWMA) corresponde a uma coluna do gráfico.
Figura 1. Os resultados do teste de desempenho para diferentes algoritmos de média móvel
Pode-se ver a diferença significante no cálculo da velocidade para diferentes casos de cálculo de média móvel. O que isso quer dizer? Os diversos algoritmos para cálculo da média móvel, fornecidos pelos desenvolvedores do MQL5 possuem diferentes desempenhos de cálculo: há um algoritmo mais rápido (caso 6) e métodos mais lentos (casos 3 e 4). Então, é necessário escolher os algorítimos corretos ao escrever programas no MQL5, que usa média móveis.
O cálculo de tempo de cada um dos modelos de médias móveis (0-6) é apresentado em detalhes nas figuras seguintes, ver tabela 2.
Figura 2. O desempenho de cálculo de MA do modo MODE_SMA
Figura 3. O desempenho de cálculo de MA do modo MODE_EMA
Figura 4. O desempenho de cálculo de MA do modo MODE_SMMA
Figura 5. O desempenho de cálculo de MA do modo MODE_LWMA
é interessante comprar o cálculo de desempenho das duas plataformas: MetaTrader 4 e MetaTrader 5. Os resultados são apresentados na tabela 2 caso nº. 0 (MQL4) e caso nº. 2 (MQL5).
Por conveniência, vamos combinar os resultados do cálculo do indicador padrão IMA em um gráfico e tabela separados (ver figura 6). O cálculo do tempo do teste é apresentado nos eixos Y.
Figura 6. Gráfico comparativo do desempenho de cálculo do MetaTrader 4 и MetaTrader 5
Conclusões:
- A nova plataforma do MetaTrader 5 é 40% mais rápida do que a do MetaTrader 4 anterior.
- O desempenho mais rápido foi alcançado para os modelos SMA, EMA, e SMMA (caso nº. 6), para LWMA (casos nº. 2 e nº. 5).
- Para os casos de teste, quando o indicador padrão iMA é utilizado, o desempenho de cálculo para diferentes modelos é praticamente o mesmo. Não é a verdade para as funções da biblioteca MovingAverages.mqh. Para modelos diferentes o desempenho difere por quase uma ordem de (0,00023~0,0045).
- Os resultados apresentados correspondem a um "início frio", não há nenhum dado pré-calculado no cache global do terminal do cliente.
4. Estudos de casos
Os desenvolvedores do MQL5 recomendam o seguinte método para obter os valores dos indicadores técnicos padrão:
//---- 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 }
Esse método é descrito em detalhes no artigo "MQL5 para novatos: Guia para utilizar indicadores técnicos em conselheiros experientes".
Para testar o desempenho de cálculo das médias móveis, é melhor usar o script, porque é capaz de realizar todos os cálculos sem aguardar os eventos (por exemplo, novo evento de tick, etc.).
é necessário criar um programa universal separado para todos os casos de teste, então, criaremos um script separado para cada caso de cálculo MA.
Então vamos considerar em detalhes os casos dos cálculos da média móvel.
4,1. Caso nº. 1
Neste caso nós medimos o cálculo do desempenho do indicador técnico iMA do MQL4. Os cálculos foram realizados no MetaTrader 4 e realizados com todos os dados.
Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 2, 5) |
O código desse caso é o seguinte (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); } }
Observação: Esse código não funcionará no MetaTrader 5 porque está escrito em MQL4. Ele deve ser executado em um terminal do cliente do MetaTrader 4.
4,2. Caso nº. 1
Nesse caso nós realizamos o cálculo de 4 modelos: nº. 1(SMA), nº. 2(EMA), nº. 3(SMMA) e nº. 4(LWMA) utilizando as funções da biblioteca MovingAverages.mqh.
O cálculo é realizado com todos os arranjos de dados.
Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 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); } }
Observação. Nós planejamos utilizar os diversos tipos de dados da biblioteca no arranjo, mas para a simplicidade, utilizamos apenas um arranjo com dados de preços próximos (não afeta o desempenho dos cálculos).
4,3. Caso nº. 2
Neste caso, usamos o indicador técnico padrão iMA e teste nº 5.
O cálculo é realizado com todos os arranjos de dados.
Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 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 nº. 3
No caso nº. 3 as classes trabalhando com indicadores das classes da biblioteca padrão são utilizadas.
A cópia de dados com relação aos elementos é utilizada. O cálculo é realizado com todos os arranjos de dados.
Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 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 nº. 4
No caso nº. 4 as classes trabalhando com indicadores das classes da biblioteca padrão são utilizadas.
O arranjo do indicador do buffer é copiado completamente. O cálculo é realizado com todos os arranjos de dados.
Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 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 nº. 5
O teste nº 8 é usado: o handle do indicador é criado usando a função IndicatorCreate.
O cálculo é realizado com todos os arranjos de dados.Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 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 nº. 6
Nesse caso nós realizamos o cálculo de 4 modelos: №9(SMA), №10(EMA), №11(SMMA) и №12(LWMA) usando as funções da biblioteca MovingAverages.mqh (o buffer funciona como iMAOnArray do MQL4).
O cálculo é realizado com todos os arranjos de dados.
Modelo | Resultado | Melhor resultado |
---|---|---|
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 (casos 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); }
Observação. Nós planejamos utilizar os diversos tipos de dados da biblioteca no arranjo, mas para a simplicidade, utilizamos apenas um arranjo com dados de preços próximos (não afeta o desempenho dos cálculos).
5. Saída dos resultados
Para a saída dos resultados e verificação das médias móveis, utilizei a função 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]); }
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); //---
Observe, que a classificação do arranjo é diferente antes e depois dos cálculos.
IMPORTANTE. O sinalizador AsSeries é configurado como falso durante os cálculos e é configurado para verdadeiro quando imprimindo os resultados.
6. Investigações adicionais
Para responder as perguntas sobre o efeito dos parâmetros iniciais no desempenho do cálculo, algumas medições adicionais foram feitas.
Que eu me lembre, o caso nº 6 tem a melhor performance, então nós iremos usá-lo.
Parâmetros de teste:
Modo | Cronograma | Período de média |
---|---|---|
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 |
Tabela 3. Investigações adicionais
Código fonte dos testes:
//+------------------------------------------------------------------+ //| 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); }
Para os testes adicionais, usaremos o programa autotest, sua interface de usuário gráfica é apresentada na Fig. 7.
Figura 7. O programa autotest para a verificação automatizada
Resultados: (os eixos X possuem escala de tempo logarítmica)
Figura 8. O parâmetro Cronograma (Y) e o desempenho do cálculo das médias móveis (X)
Figura 9. O parâmetro Período (Y) e o desempenho do cálculo das médias móveis (X)
As conclusões dos resultados de investigações adicionais:
- O parâmetro cronograma não é importante, ele não afeta o cálculo do desempenho (ver a figura 8).
- O período não é um parâmetro importante para o desempenho do cálculo das médias móveis para os modelos SMA, EMA e SMMA. Mas em contraste, ele significativamente (de 0,00373 segundos para ,145 segundos) desacelera os cálculos do modelo LWMA (ver a figura 9).
Conclusão
A escolha incorreta do algoritmo das médias móveis é capaz de reduzir o desempenho de cálculo dos seus programas.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/106
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso