Pruebas de rendimiento computacional de los promedios móviles en MQL5
Introducción
El uso de los Promedios móviles es una práctica muy común en el análisis de las series de tiempo del mercado, en los indicadores y en la programación de los Expert Advisors. Es el método de suavizado de datos de precios más conocido. En la nueva versión de MQL hay disponible una docena de algoritmos de Promedios móviles.
¿Cuál es la diferencia entre ellos? ¿Depende de verdad la velocidad de cálculo de ciertos algoritmos de promedios móviles? ¿Cuál es el algoritmo más rápido?
¿Ha incrementado la velocidad computacional de los Promedios móviles en MetaTrader5 en comparación con MetaTrader4? Surgen muchas preguntas. Así que, vamos a tratar de responder a la mayoría de ellas.
Por supuesto, la velocidad de la nueva plataforma es impresionante, pero lo mejor es comprobarlo experimentalmente.
1. Condiciones de las pruebas
La velocidad de cálculo depende de muchos factores. En consecuencia, los datos obtenidos como resultados de este estudio serían distintos en otras condiciones de prueba. En otras palabras, los valores absolutos del rendimiento serán distintos, pero los valores relativos deberían ser parecidos (para cierta plataforma).
Puesto que en MQL5 la función iMA no devuelve los resultados del cálculo directamente (devuelve el identificador del indicador), vamos a probar la velocidad de dos funciones: iMA y CopyBuffer.
- CPU: Core i7 965
- Símbolo: "EURUSD"
- Tamaño de los datos del precio: 10.0000 elementos
- Terminal de cliente: autónomo, se establece el número máximo de barras en el gráfico a 10.000
- Modelos de promedios móviles: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
- La precisión de la velocidad de cálculo se limita a 2 cifras significativas.
- El número de llamadas posibles de las funciones de los promedios móviles: 7
2. Cómo hemos realizado las pruebas
Para medir el tiempo de computación de los promedios móviles, disponemos de la función GetTickCount(), que opera en milisegundos. Esta precisión no es suficiente, por lo que tenemos que poner algunos bucles para mejorar la calidad de las medidas.
Sin embargo, si repetimos el mismo bucle varias veces con el mismo cálculo y los mismos datos de entrada, los resultados se pueden distorsionar. Esto se debe a lo siguiente: la función iMA crea una copia del indicador técnico correspondiente en el caché global del terminal de cliente. Si ya existe la copia de un indicador (con los mismos parámetros) en el caché global, no se crea una nueva copia y se incrementa el contador de referencia de copias del indicador.
En otras palabras, se calcula el indicador del buffer entero solo una vez a la primera llamada, y en todas las llamadas siguientes toma únicamente los valores ya preparados, solo recalcula los nuevos datos.
Por lo tanto, se debe organizar el bucle correctamente, cuando los parámetros de entrada del indicador son únicos durante un ciclo. Hemos elegido tres de estos parámetros: el período promedio, la periodicidad y el precio aplicado.
Parámetro |
Rango de valores |
---|---|
Período promedio |
de 1 a 100 |
Periodicidad |
М1, М5, М15, М30 |
Precio aplicado |
PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED |
Tabla 1. Los rangos de los parámetros de entrada
Vamos a calcular los valores del promedio móvil para una matriz con 10.000 elementos, mediante siete métodos de llamada distintos (ver los detalles en la sección 4).
3. Los resultados del estudio
Hemos combinado todos los resultados en la Tabla 1, se hace la estimación del rendimiento del cálculo mediante el tiempo del cálculo (ver la Tabla 1) en segundos. El programa calcula 100x4x7=2800 tipos de promedios móviles, y determinamos el tiempo de cálculo para la matriz del precio con 10.000 elementos. El tiempo de cálculo de una única pasada (ciclo) es aproximadamente igual al tiempo total dividido entre 2800. Por ejemplo, para el caso 1 y el modo SMA es igual a ~ 0,0028/2800.
Modo |
MODE_SMA | MODE_EMA | MODE_SMMA | MODE_LWMA | Plataforma |
---|---|---|---|---|---|
0 (ver sección 4.1) |
0,0041 | 0,0040 | 0,0043 | 0,0041 | MetaTrader 4 |
1 (ver sección 4.2) | 0,0028 | 0,00023 | 0,00027 | 0,0045 | MetaTrader 5 |
2 (ver sección 4.3) | 0,0029 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
3 (ver sección 4.4) | 0,0998 | 0,0997 | 0,0998 | 0,0998 | MetaTrader 5 |
4 (ver sección 4.5) | 0,0996 | 0,0996 | 0,0996 | 0,0996 | MetaTrader 5 |
5 (ver sección 4.6) | 0,0030 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
6 (ver sección 4.7) | 0,000140 | 0,000121 | 0,000117 | 0,0035 | MetaTrader 5 |
Tabla 2. Los resultados:
Veremos el significado de los casos de las pruebas más adelante (secciones 4.1-4.7). Vamos a evaluar el rendimiento del cálculo de los promedios móviles en todo su conjunto.
Para mayor comodidad, se presentan los resultados en gráficos (ver figuras de 1 a 5). El eje X representa el tipo de llamada del Promedio móvil (ver tabla 2), los valores del eje Y están representados en una escala logarítmica y multiplicados por -1, de modo que mayor sea valor más rápido será el rendimiento. Cada modelo de cálculo (SMA, EMA, SMMA, LWMA) corresponde a una columna en el gráfico.
Figura 1. Resultados de las pruebas de rendimiento para distintos algoritmos de Promedios móviles.
Se puede observar una diferencia relevante en la velocidad computacional para los distintos casos de cálculo de los promedios móviles. ¿Qué significa esto? Los distintos algoritmos de cálculo de Promedios móviles, proporcionados por los desarrolladores de MQL5 tienen un rendimiento computacional distinto: hay un algoritmo muy rápido (caso 6) y otros más lentos (casos 3 y 4). Por lo tanto, hay que elegir los algoritmos adecuados a la hora de escribir programas en MQL5, y que utilizen Promedios móviles.
Se representa en detalle el tiempo de cálculo de cada modelo de Promedios móviles (0-6) en las siguientes figuras, ver la tabla 2.
Figura 2. Cálculo del rendimiento computacional del promedio móvil del modo MODE_SMA
Figura 3. Cálculo del rendimiento computacional del promedio móvil del modo MODE_EMA
Figura 4. Cálculo del rendimiento computacional del promedio móvil del modo MODE_SMMA
Figura 5. Cálculo del rendimiento computacional del promedio móvil del modo MODE_LWMA
Es interesante comparar el rendimiento del cálculo de las dos plataformas. MetaTrader 4 y MetaTrader 5. Se representan los resultados en la tabla 2, caso nº 0 (MQL4) y caso nº 2 (MQL5).
Por comodidad, vamos a combinar los resultados de los cálculos del indicador estándar iMA en tablas y gráficos separados (ver la figura 6). El eje Y representa el tiempo de cálculo de las pruebas.
Figura 6. Comparativa del rendimiento del cálculo entre MetaTrader 4 y MetaTrader 5
Conclusiones:
- La nueva plataforma MetaTrader 5 es 40% más rápida que MetaTrader 4.
- Se han alcanzado los rendimientos más rápidos con los modelos SMA, EMA y SMMA (caso nº 6), para LWMA (casos nº 2 y nº 5).
- Cuando se utiliza el indicador estándar iMA en las distintas pruebas, el rendimiento del cálculo para los distintos modelos es prácticamente idéntico. No es el caso con las funciones de la librería MovingAverages.mqh. La diferencia de rendimiento es del orden de (0,00023~0,0045) para los distintos modelos.
- Los resultados presentados corresponden a un "arranque en frío" (cold start), no hay ningún dato precalculado en el caché global del terminal de cliente.
4. Estudios de caso
Los desarrolladores de MQL5 recomiendan el siguiente método para obtener los valores de los indicadores técnicos estándar:
//---- 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 }
En el artículo"MQL5 para principiantes: Guía para el uso de indicadores técnicos en Expert Advisors", se describe en detalle este método .
Para probar el rendimiento computacional de los promedios móviles, es mejor utilizar el script, puesto que puede llevar a cabo todos los cálculos sin esperar los eventos (por ejemplo, el evento de un nuevo tick, etc.).
No es necesario crear un programa universal separado para todos los casos de las pruebas, por lo tanto vamos a crear un script separado para cada caso de cálculo de Promedio móvil.
Vamos a ver en detalle cada caso de cálculo del Promedio móvil.
4.1. Caso nº 0
En este caso hemos medido el rendimiento de computación del indicador técnico iMA con MQL4. Se realizan los cálculos en MetaTrader 4 y se llevan a cabo con todos los datos.
Modelo | Resultado | Mejor 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 y 5) |
A continuación está el código de este caso (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: Este código no va a funcionar con MetaTrader 5, ya que fue escrito en MQL4. Hay que ejecutarlo en el terminal de cliente de MetaTrader.
4.2. Caso nº 1
En este caso hemos realizado los cálculos de 4 modelos: nº 1(SMA), nº 2(EMA), nº3(SMMA) y nº 4(LWMA) mediante las funciones de la librería MovingAverages.mqh.
Se lleva a cabo el cálculo con todos los datos de la matriz.
Modelo |
Resultado | Mejor 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 y 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. Nuestra idea era utilizar distintos tipos de datos en la matriz, pero para simplificar, hemos utilizado una única matriz con los datos de los precios de cierre (no afecta al rendimiento de de los cálculos).
4.3. Caso nº 2
En este caso hemos utilizado el indicador técnico estándar iMA y la prueba nº 5.
Se lleva a cabo el cálculo con todos los datos de la matriz.
Modelo | Resultado | Mejor 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 y 5) |
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
En el caso nº 3, se utilizan las clases que manejan los indicadores de la Librería estándar.
Se copian los datos elemento por elemento. Se lleva a cabo el cálculo con todos los datos de la matriz.
Modelo | Resultado | Mejor 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 y 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
En el caso nº 4, se utilizan las clases que manejan los indicadores de la Librería estándar.
Se copia toda la matriz del buffer del indicador. Se lleva a cabo el cálculo con todos los datos de la matriz.
Modelo | Resultado | Mejor 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 y 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
Se utiliza la prueba nº8: se crea el identificador del indicador mediante la función IndicatorCreate.
Se lleva a cabo el cálculo con todos los datos de la matriz.Modelo | Resultado | Mejor 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 y 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
En este caso hemos realizado los cálculos de 4 modelos: nº 9(SMA), nº 10(EMA), nº 11(SMMA) y nº 12(LWMA) mediante la librería de funciones MovingAverages.mqh (las funciones de buffers como iMAOnArray de MQL4).
Se lleva a cabo el cálculo con todos los datos de la matriz.
Modelo | Resultado | Mejor 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 y 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. Nuestra idea era utilizar distintos tipos de datos en la matriz, pero para simplificar, hemos utilizado una única matriz con los datos de los precios de cierre (no afecta al rendimiento de los cálculos).
5. La salida de los resultados
Para la salida de los resultados y la comprobación de los promedios móviles, he recurrido a la función 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]); }
Se le puede llamar, de la siguiente manera (la posición de la barra y la matriz de datos son parámetros de la función):
//--- 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); //---
Tenga en cuenta que los índices de la matriz son distintos antes y después de los cálculos.
IMPORTANTE. Se establece la señal de AsSeries en false durante los cálculos y en true al mostrar los resultados.
6. Estudios adicionales
Para poder responder a la pregunta sobre la influencia de los parámetros iniciales en el rendimiento del cálculo, hacen falta algunas medidas adicionales.
Como recordaremos, el caso nº 6 presenta el mejor rendimiento, así que lo vamos a utilizar.
Parámetros de las pruebas:
Modo |
Periodicidad |
Período promedio |
---|---|---|
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 |
Tabla 3. Estudios adicionales
Código fuente de las pruebas:
//+------------------------------------------------------------------+ //| 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); }
Vamos a utilizar el programa de prueba automática "autotest" para las pruebas adicionales, se muestra su interfaz gráfica en la figura 7.
Figura 7. El programa autotest para las pruebas automáticas
Resultados: (los ejes X tienen una escala de tiempo logarítmica)
Figura 8. El parámetro de periodicidad (Y) y el rendimiento de computación de los Promedios móviles (X)
Figura 9. El parámetro período (Y) y el rendimiento de computación de los Promedios móviles (X)
Las conclusiones de los resultados de los estudios adicionales:
- La periodicidad no es un parámetro importante, no afecta al rendimiento de los cálculos (ver figura 8).
- El periodo no es un parámetro importante para el rendimiento de computación de los promedios móviles para los modelos SMA, EMA y SMMA. Sin embrago, ralentiza de manera significativa los cálculos (de 0,00373 segundos a 0,145 segundos) para el modelo LWMA (ver figura 9).
Conclusión
Una elección errónea del algoritmo de los promedios móviles pude reducir el rendimiento de los cálculos de tus programas.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/106
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso