Descargar MetaTrader 5

Los principios del cálculo económico de los indicadores

25 febrero 2014, 10:56
Nikolay Kositsin
0
557

Introducción

La idea de preservar los recursos en uno u otro segmento de las actividades prácticas de la gente, es quizás uno de los temas más importantes y urgentes en el camino hacia el desarrollo humano y el progreso. En este sentido, la programación en MQL5 no es una excepción. Por supuesto, si se limita el rango de las tareas al trading visual, muchos defectos de programación pueden pasar inadvertidos.

Pero todo lo que se refiere al trading automatizado, requiere la máxima eficiencia en la escritura del código, de lo contrario, el proceso de la prueba y la optimización de los robots de trading se puede extender muchísimo en el tiempo, de modo que sería prácticamente imposible esperar hasta que se completen. La idea de crear algo de valor en este tipo de situación parece bastante difícil.

Así que antes de embarcarse en la implementación de estrategias de trading, tendría sentido familiarizarse más con estos detalles de programación, que afectan el tiempo de pruebas y de optimización de los Expert Advisors. Y puesto que la mayoría de los Expert Advisors contienen las indicaciones del usuario en su código, supongo entonces que deberíamos empezar con ellos.

En general, no hay muchos puntos relevantes a tener en cuenta durante la implementación de los indicadores, por lo tanto, lo más lógico sería simplemente revisar cada uno ordenadamente.

El recálculo de los ticks en cada indicador, que no hayan sido calculados, de las nuevas barras en los indicadores clásicos.

La esencia misma de los indicadores clásicos, como RSI, ADX, ATR, CCI, etc., está en las barras cerradas, el cálculo de estos indicadores se puede hacer solo una vez, y después, solo se puede hacer con las barras nuevas. La única excepción es la barra abierta actual, donde se hace el cálculo con cada tick, hasta que se cierre la barra.

La manera más sencilla de averiguar si es conveniente calcular los indicadores en las barra no calculadas, es hacer una comparación en el probador de estrategias, los resultados de dichos indicadores (optimizados) con los indicadores (sin optimizar) calculados en todas las barras, todo el tiempo.

Esto se hace de forma sencilla: Se crea un Expert Advisor mediante las funciones OnInit() y OnTick(). Lo que hay que hacer es escribir la llamada en el Expert Advisor de la versión requerida del indicador optimizado o sin optimizar, y contemplar la ejecución en el probador de estrategias de dichos Expert Advisors en ambos casos. A modo de ejemplo, voy a utilizar el indicador SMA.mq5 de mi artículo "Indicadores personalizados para principiantes en MQL5", en el cual voy a sustituir algunas líneas.  

   if (prev_calculated == 0) // if this is the first start, then make a recalculation of all existing bars
    first = MAPeriod - 1 + begin;
   else first = prev_calculated - 1; // on all subsequent starts, make calculations only on newly appeared bars

por 

   first = MAPeriod -  1  + Begin;  / / On all ticks the bars are being recalculated 

Como resultado, voy a obtener una versión no optimizada del código de programación (SMA !!!!!!. mq5), que, a diferencia de la original, va a recalcular todos sus valores con cada tick. Estrictamente hablando, el código del Expert Advisor es prácticamente el mismo en ambas versiones, por lo tanto, voy a proporcionar solo una de ellas (SMA_Test.mq5)

//+------------------------------------------------------------------+
//|                                                     SMA_Test.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
int Handle;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//----+
   //----+ Obtaining the indicator handle
   Handle = iCustom(Symbol(), 0, "SMA");
   if (Handle == INVALID_HANDLE)
     Print(" Not able to obtain the indicator handle SMA");
//----+
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----+
    //--- Release the indicator handle
    IndicatorRelease(Handle);
//----+   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//----+
   double SMA[1];
   //----+ Using the indicator handle, copy the values of the indicator 
                   // buffer in a specially prepared for this statistical array
   CopyBuffer(Handle, 0, 0, 1, SMA);
//----+
  }
//+------------------------------------------------------------------+

Ahora podemos empezar las pruebas. Cabe destacar que en todas las pruebas de este artículo, vamos a utilizar un modo de simulación de cambios de barras, que es lo más cercano posible a la realidad -"Todos los ticks" (Every tick).

Fig. 1 Configuración de las pruebas del Expert Advisor SMA_Test 

Este es el resultado de la ejecución de un indicador optimizado en el probador de estrategias.

Fig. 2 El resultado de las pruebas del Expert Advisor SMA_Test 

El color rojo indica el intervalo de tiempo elegido para la prueba. ¡No se puede decir que es mucho tiempo! Pero sí que tenemos que esperar mucho tiempo para completar la prueba del indicador SMA !!!!!!. mq5.

Fig. 3 El resultado de las pruebas del Expert Advisor SMA !!!!!!_ Test 

Básicamente, el tiempo de procesamiento de la prueba en este caso supera el tiempo de la prueba anterior con más de 500 veces. Y esto a pesar de haber elegido un período suficientemente corto para la prueba. Sin embargo, durante la prueba del Expert Advisor podemos soportar estos costes computacionales tan elevados, es mejor olvidar la optimización de sus parámetros.

Y por lo tanto, esta es la evidencia más elocuente de que la escritura económica del código, no es solo un pasatiempo para los profesionales en el campo de la programación, sino más bien un enfoque muy específico para escribir el código.

Hay un sitio web Overclockers.ru dedicado completamente a la aceleración de los PCs para maximizar su rendimiento. Esta práctica consiste básicamente en el uso de componentes mucho más caros para aumentar la velocidad de la CPU y la memoria RAM.

Después de hacer esto, hay que utilizar sistemas de enfriamiento por agua, o incluso procesadores de inmersión en nitrógeno líquido, para esta CPU sobre acelerada. Gracias a estos procedimientos se puede duplicar o incluso triplicar el rendimiento del PC.

Otra alternativa, la escritura eficiente del código nos puede a menudo ayudar a conseguir muchas cosas, haciendo un pequeño esfuerzo. Por supuesto, este método no es capaz de convertir un Celleron300A en un Core 2 Quad Q6600, pero sí que nos permite hacer funcionar un PC estándar doméstico con un rendimiento parecido al de los ordenadores de gama superior.

Recálculo repetido de la barra cerrada actual en algunos indicadores, no del todo clásicos

Sería genial si este método de optimización del código del programa fuera adecuado para todos los indicadores indiscriminadamente. Pero, lamentablemente, no es el caso. Hay un conjunto de indicadores, que con dicho enfoque empiezan a calcular normalmente solo una vez, durante la carga del indicador en los datos del historial que ya existen.

Y los valores resultan ser completamente incorrectos en todas las barras que hayan surgido después de cargar el indicador. La razón principal por la que esto ocurre es que algunas variables del código del indicador dependen de estos indicadores, que tienen las mismas variables después del cálculo del indicador en la barra anterior. Se ve así:

                                                                                                                                                                                                                           

SomeVariable(bar) = Function(SomeVariable(bar - 1))

 

donde:

  • SomeVariable() -el valor de alguna variable para alguna barra;
  • bar -número de barra, en la que se hace el cálculo.

Por motivos obvios, en el código real, tantas dependencias tienen una forma funcional poco clara. Pero la esencia no cambia, por ejemplo, para la parte del código de T3 móvil (indicador no optimizado -T3 !!!!!!. mq5), lo más relevante para nosotros es lo siguiente:

   e1 = w1 * series + w2 * e1;
   e2 = w1 * e1 + w2 * e2;
   e3 = w1 * e2 + w2 * e3;
   e4 = w1 * e3 + w2 * e4;
   e5 = w1 * e4 + w2 * e5;
   e6 = w1 * e5 + w2 * e6;
   //----  
   T3 = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;

Las variables e1, e2, e3, e4, e5 y e6 tienen precisamente tanta dependencia, que implican el uso de este código para el cálculo de cada barra nueva ¡solo una vez! Pero la barra actual, mediante un cálculo parecido, será omitida repetidamente hasta su cierre.

Y los valores de estas variables en la barra actual van a cambiar todo el tiempo, aunque para la barra actual, antes de cambiar, deben ser los resultantes del cálculo de la barra anterior.

Por consiguiente, se deben almacenar los valores de estas variables de la barra anterior (en relación a la barra actual) en variables estáticas y enviarlas para reutilizarlas en el siguiente cambio de barra, en la cual se deben almacenar otra vez los penúltimos valores de las variables e1, e2, e3, e4, e5 y e6.

El código adicional que lleva a cabo los procesamientos de estos valores es bastante sencillo. En primer lugar, hay que declarar la variables locales estáticas para almacenar los valores en la función OnCalculate()

   //---- declare the static variables for storing the valid values of the coefficients
   static double e1_, e2_, e3_, e4_, e5_, e6_;

Después de esto, se hace la memorización de los valores de las variables en el bucle de la barra actual antes de hacer cualquier cálculo, justo cuando el número de las nuevas barras que aparecen sea superior a cero:

     //---- memorize the values of variables before the run on the current bar
     if (rates_total != prev_calculated && bar == rates_total - 1)
      {
       e1_ = e1;
       e2_ = e2;
       e3_ = e3;
       e4_ = e4;
       e5_ = e5;
       e6_ = e6;
      }

Y después del bloque del operador del ciclo, se recuperan los valores de las variables mediante una transformación inversa:

   //---- restore the values of the variables
   e1 = e1_;
   e2 = e2_;
   e3 = e3_;
   e4 = e4_;
   e5 = e5_;
   e6 = e6_;

Por supuesto, la primera inicialización de los coeficientes calculados se hace ahora solo una vez, en el primer inicio de la función OnCalculate(), y ahora la inicialización no se hace solo para los propios coeficientes, sino también para las correspondientes variables estáticas.

//---- calculating the starting number first for the cycle of recalculation of bars
   if (prev_calculated == 0) // verification of the first start of the indicator calculation
    {
     first = begin; // the starting number for calculating all of the bars
     //---- the starting initialization of calculated coefficients
     e1_ = price[first];
     e2_ = price[first];
     e3_ = price[first];
     e4_ = price[first];
     e5_ = price[first];
     e6_ = price[first];
    }

Como resultado, el indicador final T3.mq5 empieza a hacer los cálculos de la manera más eficiente. Todo lo que no es importante, pero no siempre resulta fácil identificar las dependencias funcionales parecidas. En este caso, se pueden memorizar los valores de todas las variables de los indicadores en variables estáticas, y ser recuperadas del mismo modo.

Y solo después, podemos empezar a averiguar cuáles son las variables que realmente tienen que ser recuperadas y cuáles no. Para hacer esto, hay que coger los gráficos de la versión optimizada y sin optimizar del indicador, y comparar su trabajo, y gradualmente ir quitando de la lista de recuperación una variable a la vez. Al final, nos quedamos únicamente con estas variables, que realmente hay que recuperar.

Naturalmente, he proporcionado esta versión de lógica para trabajar con el código del programa de los indicadores comunes, en los cuales hay un recuento de la barra actual y de las nuevas barras que van apareciendo. Para los indicadores, que vamos a ver y retocar en el futuro, no vamos a ser capaces de crear un método estándar y muy sencillo de optimización de código parecido, debido a las características únicas de estos indicadores. Y la mayoría de los escritores experimentados de Expert Advisors no lo consideran necesario. Por lo tanto, podemos considerar el análisis detallado de estos indicadores terminado.

Características de las llamadas de los indicadores, que puede hacer MQL5 -código excesivamente lento 

Parece que ya hemos acabado la tarea, tenemos un indicador optimizado, que cuenta las barra de la manera más eficiente, y ahora basta con escribir pocas líneas de código, y llamar a este indicador desde el Expert Advisor o el código del indicador para obtener los valores calculados desde el buffer del indicador.

Pero esto no es tan fácil como lo parece desde un planteamiento formal, sin molestarse en averiguar qué tipo de operaciones hay detrás de estas pocas líneas de código.

Los detalles de la obtención de los valores desde el usuario y los indicadores técnicos, así como desde las series de tiempo de MQL5, se hace copiando los datos en las matrices de variables de los usuarios. Esto puede llevar a la creación de datos completamente innecesarios, para las cuentas actuales.

La forma más fácil de comprobar todo esto en una recepción especifica de datos, procede de algunos indicadores técnicos. A modo de ejemplo, podemos utilizar el iAMA móvil y construir a partir de este indicador técnico, un indicador personalizado AMkA.

Para copiar los datos vamos a utilizar la primera versión de llamada de funciones CopyBuffer (), con una petición a la posición de inicio y el número de elementos que hay que copiar. En el indicador AMkA, el incremento móvil en la barra actual se procesa mediante el indicador técnico Desviación estándar, y luego, para obtener las señales de trading, se compara este incremento con valor total de las desviaciones estándar procesadas.

Por lo tanto, en el caso más sencillo para la implementación del indicador AMkA, debemos primero crear un indicador, el buffer de este indicador contiene el valor del Incremento móvil (indicador dAMA). Y luego, en otro indicador, mediante el identificador de indicador con los incrementos AMA, obtenemos el valor resultante, procesado con el indicador Desviación estándar.

Ya ha sido examinado en detalle el proceso de creación de indicadores similares en varios artículos sobre estos temas, así que no lo voy a tratar, y voy a analizar solo los detalles de acceso a los buffers de indicadores correspondientes al indicador que recibe la llamada, en el código de otro indicador.

En los inmensos recursos que hay en Internet, ya hemos visto la aparición de ejemplos en MQL5, en los cuales los autores copian literalmente todo el contenido de los buffers del indicador en matrices dinámicas intermedias. Y después de esto, todos los valores, uno por uno, se envían los buffers del indicador final a partir de estas matrices intermedias, mediante el operador de bucle.

Para resolver nuestro problema, este método parece muy sencillo

   if (CopyBuffer(AMA_Handle, 0, 0, rates_total, Array) <= 0) return(0);
   ArrayCopy(AMA_Buffer, Array, 0, 0, WHOLE_ARRAY);

(Indicador dAMA !!!!!!. mq5) O así 

   if (CopyBuffer(AMA_Handle, 0, 0, rates_total, Array) <= 0) return(0);
   
   for(bar = 0; bar < rates_total; bar++)
    {
     AMA_Buffer[bar] = Array[bar];
     /*
      here is the code of indicator calculations
    */     
    }

Pero, ¿cuál es el precio de una solución tan sencilla? Para empezar, estaría bien entender mejor cuál va a ser el camino de actuación más lógico. En primer lugar, no existe ninguna necesidad justificada de utilizar la matriz intermedia Array [], y los datos deben ser copiados directamente al buffer de indicador AMA [].

En segundo lugar, es necesario copiar los valores a cada tick del indicador en solo tres casos:

  • a partir de las nuevas barras que surgen,
  • a partir de la barras cerradas,
  • a partir de las barras abiertas actuales.

Ya existen los valores restantes del buffer del indicador, y no tiene sentido reescribirlos varias veces. 

//--- calculation of the required number of copied data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)// verification for the first start of indicator calculation
        to_copy = rates_total - begin; // calculated number of all bars
   else to_copy = rates_total - prev_calculated + 1; // calculated number of only new bars

//--- copy the reappearing data into the indicator buffer AMA_Buffer[]
   if (CopyBuffer(AMA_Handle, 0, 0, to_copy, AMA_Buffer) <= 0)
    return(0); 

 Es normal que en este caso el código final será un poco más complejo (indicador dAMA.mq5), pero ahora podemos utilizar la metodología que había propuesto al principio de este artículo, para llevar a cabo las pruebas en ambos casos, y sacar las conclusiones pertinentes. Esta vez, vamos a aumentar el intervalo de la prueba a un año.

Fig. 4 Configuración de las pruebas del Expert Advisor dAMA_Test
 

Finalmente, y después de hacer la prueba, obtenemos en el diario del probador de estrategias el tiempo necesario de la prueba del Expert Advisor dAMA_Test

Fig. 5 El resultado de las pruebas del Expert Advisor dAMA_Test

El tiempo de la prueba es de 43,937 ms, y está dentro de unos límites razonables. Desafortunadamente, no se puede decir lo mismo de los tiempos de prueba obtenidos con el Expert Advisor dAMA !!!!!!_ Test

Fig. 6 El resultado de las pruebas del Expert Advisor dAMA !!!!!!_ Test
  

El tiempo de la prueba es de 960.625 ms, que es 20 veces más que en el caso anterior. La conclusión parece bastante obvia. Hay que escribir el código de manera más eficiente, de modo que no lleve a cabo ningún cálculo innecesario.
El indicador AMkA, construido a partir de los principios descritos antes, no demuestra nada nuevo, de modo que en este caso voy a tratar solamente la copia de los datos.

//---- declaring local arrays
   double dAMA_Array[], StdDev_Array[];
//---- indexation of elements in arrays just like in time series
   ArraySetAsSeries(dAMA_Array, true);
   ArraySetAsSeries(StdDev_Array, true);

//--- calculation of the number of copied data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)// verification of the first start of indicator calculation
        to_copy = rates_total - begin; // calculated number of all bars
   else to_copy = rates_total - prev_calculated + 1; // calculated number of only new bars
   
//--- copy the newly appeared data into the indicator buffer and local dynamic arrays
   if(CopyBuffer(dAMAHandle,   1, 0, to_copy, AMABuffer   ) <= 0) return(0);
   if(CopyBuffer(dAMAHandle,   0, 0, to_copy, dAMA_Array  ) <= 0) return(0);
   if(CopyBuffer(StdDevHandle, 0, 0, to_copy, StdDev_Array) <= 0) return(0);

Se hace todo de un modo completamente análogo, salvo que ahora los datos se copian en un buffer de indicador único y dos matrices dinámicas declaradas localmente para los cálculos intermedios. 

La implementación de todos los cálculos del indicador dentro del indicador, como una de las formas de optimización 

Todo esto es muy interesante, pero una estructura tan compleja de llamadas sucesivas del usuario y los indicadores técnicos parece un poco extraña. Y hay que comprobarla de alguna manera. Pero para hacer esto, no estaría de más disponer del código del indicador AMkA, que se encuentra dentro del indicador del usuario, y no puede llamar a otros indicadores.

Para un programador que ha captado la idea del proceso de escritura de indicadores en MQL5, este problema no le supondría muchos esfuerzo. En primer lugar, se escribe el código del indicador del usuario AMA.mq5, y luego se añaden los elementos necesarios del código para la implementación del indicador AMkA_.mq5. Recibimos un segundo bucle largo de cálculos del indicador, en el cual la matriz del usuario se carga con los incrementos del indicador AMA,

   //---- the main cycle of calculating the AMkA indicator
   for(bar = first; bar < rates_total; bar++)
    {
     //---- load the increments of the AMA indicator into the array for intermediate calculations
     for(iii = 0; iii < ama_period; iii++)
      dAMA[iii] = AMABuffer[bar - iii - 0] - AMABuffer[bar - iii - 1]; 

Se utiliza este indicador después para mejorar las operaciones, de manera similar para el cálculo del indicador técnico StDev, basado en los datos del indicador dAMA.mq5.

     //---- find the simple average of increments of AMA
     Sum = 0.0;
     for(iii = 0; iii < ama_period; iii++)
      Sum += dAMA[iii];
     SMAdif = Sum / ama_period;
     
     //---- find the sum of the square differences of increments and the average
     Sum = 0.0;
     for(iii = 0; iii < ama_period; iii++)
      Sum += MathPow(dAMA[iii] - SMAdif, 2);
     
     //---- determine the final value of the meansquare deviation of StDev from the increment of AMA
     StDev = MathSqrt(Sum / ama_period);

Lo que queda del código es exactamente similar a lo del código del indicador AMkA.mq5, y no nos interesa para nada. Ahora podemos empezar a probar los indicadores AMkA_.mq5 y AMkA.mq5 con la ayuda de los Expert Advisors AMkA__Test.mq5 y AMkA_Test.mq5.

No surgen dificultades con las pruebas del indicador AMkA_.mq5, y el tiempo de la prueba está dentro de los límites aceptables.

Fig. 7 El resultado de las pruebas del Expert Advisor AMkA__Test
 

Pero el indicador AMkA.mq5 era increíblemente lento

Fig. 8 El resultado de las pruebas del Expert Advisor AMkA_Test
 

Por el resultado obtenido, es siete veces más lento que su "hermano". ¿Qué otros comentarios pueden haber? La conclusión es bastante obvia: esta implementación tan compleja, que consiste en varias llamadas consecutivas de los indicadores, el uno a partir del otro, no es muy prudente y es adecuada únicamente para las pruebas preliminares.

Obviamente, se han obtenido estos resultados en una versión de prueba del terminal de cliente, y es difícil decir ahora qué pasará en el futuro. Pero para el próximo campeonato de robots de trading, se puede afirmar con toda claridad que se trata de un tema relevante y eficiente.

Algunas características de llamar a los indicadores a partir de los Expert Advisors

Todo lo que se refiere a la optimización del acceso a los datos del usuario y los indicadores técnicos en el código de programación de los indicadores, se puede de la misma manera aplicar a la optimización del acceso a los datos del usuario y los indicadores técnicos en el código de programación de los Expert Advisors. Además de lo que ya hemos visto, el Expert Advisor dispone de otro factor, que puede afectar considerablemente a las pruebas y la optimización de los sistemas de trading.

En general, un gran número de Expert Advisors procesa los datos del indicador únicamente cuando hay un cambio de barra, por esta razón, en estos Expert Advisors no es necesario llamar a la función CopyBuffer () con cada tick.

En este caso, los Expert Advisors solo tendrán que obtener los datos de los buffers del indicador durante los cambios de barras. De este modo, las llamadas de los indicadores tienen que estar ubicadas en el bloque entre paréntesis, cuyo acceso está permitido solo una vez por cada cambio de barra, si todos los datos necesarios del buffer del indicador se copian correctamente en las matrices para los cálculos intermedios.

Lo mejor para tal filtro es una función de usuario, que devuelve una unidad lógica al tiempo, cuando cambia la barra actual. El archivo IsNewBar.mqh contiene mi versión, muy genérica, de esta función:

bool IsNewBar
            (
             int Number, // Number of call to the function IsNewBar in the program code of the expert Advisor
             string symbol, // The chart symbol on which the data calculation is done
             ENUM_TIMEFRAMES timeframe // Timeframe of the chart on which the data calculation is done
            )

Está sería la función al utilizarla en el código del Expert Advisor.

    //---- declaration of a static variable - array for storing the values of the AMA indicator
    static double AMA_Array[3];

    //---- calling up the AMA indicator for copying its values into the AMA_Array array
    if (IsNewBar(0, Symbol(), 0))
     {
      CopyBuffer(AMA_Handle, 0, 1, 3, AMA_Array); 
     }

Pero en este caso, es más razonable de manera distinta. Lo cierto es que cuando se llama a CopyBuffer (), no se pueden copiar los datos en la matriz AMA_Array [], y en tal caso, vas a tener que llamar a esta función con cada tick, mientras no haya una opción que permita copiar los datos, y que se implementa mediante un filtro algo complicado

   //---- declaration of a static variable - array for storing values of the AMA indicator
   static double AMA_Array[3];
    
   //---- declaration of the static variable for storing the results of copying the data from the AMA indicator
   static bool Recount;

   //---- calling up the AMA indicator for copying its values into the AMA_Array array
   if (IsNewBar(0, Symbol(), 0) || Recount)
     {
      if (CopyBuffer(AMA_Handle, 0, 1, 3, AMA_Array) < 0)
       {
        Recount = true; // attempt of data copying was unsuccessful 
        return; // exit the function OnTick()
       }
      
      //---- All operations of copying from the indicator buffers are successfully completed
           // there is no need for returning to this block until the next bar change
      Recount = false;
     }

Ahora que han quedado claros los detalles de la llamada de la función de copiado de los valores del indicador en el código del Expert Advisor, podemos comprobar los beneficios de la aplicación de la función IsNewBar () en los Expert Advisors.

Así que disponemos de dos opciones de Expert Advisors para probarlas en el probador de estrategias, la primera es AMA_Test.ex5. Copia los datos a partir del buffer del indicador a cada tick.

Fig. 9 El resultado de las pruebas con el Expert Advisor AMA_Test

La segunda es IsNewBar_AMA_Test.mq5, y copia los datos solo durante el cambio de barra.

Fig. 10 El resultado de las pruebas con el Expert Advisor IsNewBar_AMA_Test

¡Sí! Los resultados de las pruebas son algo decepcionantes. Demuestran que la llamada a la función IsNewBar () a cada tick es mucho más costosa que copiar los datos en tres celdas de la matriz del usuario. 

Me gustaría llamar su atención sobre otro aspecto importante, pero al parecer una parte poco visible del indicador. Lo cierto es que si conseguimos el identificador del indicador en la función OnInit (), independientemente de si copiamos o no los datos a partir de este indicador en la función OnTick(), sus cálculos en las barras no calculadas aún y las barras actuales, se seguirán haciendo en cada tick.

Por lo tanto, si nuestro Expert Advisor no requiere los valores del indicador contados a partir de la barra abierta actual, entonces es mejor, en términos de ahorro del tiempo, desactivar el cálculo de estos valores. Esto se hace fácilmente -restamos uno al extremo derecho del bucle principal del recuento de las barras en el indicador, este es el bucle en el indicador AMA.mq5 antes de ser modificado

   //---- main cycle of indicator calculation
   for(bar = first; bar < rates_total; bar++)

Se queda así después de la modificación  

   //---- main cycle of indicator calculation
   for(bar = first; bar < rates_total - 1; bar++)

El indicator AMA_Ex.mq5. Ahora puede probar este indicador (Expert Advisor AMA_Ex_Test.mq5)

Fig. 11 El resultado de las pruebas con el Expert Advisor AMA_Ex_Test 

Por supuesto, este resultado es un 21% mejor que el resultado obtenido en la prueba del indicador AMA, que no está tan mal, pero pensándolo bien, este resultado podría ser mucho mejor.

Conclusión

En definitiva, la eficiencia del código de un programa es un parámetro bastante objetivo. La eficiencia puede ser medida, lógicamente analizada y en ciertas situaciones, significativamente aumentada. Los métodos para lograr esto no son muy complicados. Todo lo que hace falta es algo de paciencia y hacer más prácticas, lo que afecta directamente la rentabilidad de los sistemas de trading automatizado. 


Traducción del ruso hecha por MetaQuotes Software Corp.
Artículo original: https://www.mql5.com/ru/articles/109

Archivos adjuntos |
mql5.zip (23.38 KB)
Pruebas de rendimiento computacional de los promedios móviles en MQL5 Pruebas de rendimiento computacional de los promedios móviles en MQL5

Desde la creación del primer indicador de Promedio móvil, surgieron muchos indicadores. Muchos de ellos utilizan los mismos métodos de suavizado, pero no se han estudiado los rendimientos de los distintos algoritmos de los promedios móviles. En este artículo, vamos a examinar distintas maneras de utilizar los Promedios móviles en MQL5 y comparar su rendimiento.

Creación de un Expert Advisor que opera con varios instrumentos Creación de un Expert Advisor que opera con varios instrumentos

El concepto de diversificación de activos en los mercados financieros es bastante antiguo, y siempre ha atraído a los operadores principiantes. En este artículo, el autor propone un enfoque muy simplificado para la implementación de un Expert Advisor multidivisa, para una introducción inicial a este tipo de estrategias de trading.

El uso de ORDER_MAGIC para el trading con distintos Expert Advisors con un solo instrumento El uso de ORDER_MAGIC para el trading con distintos Expert Advisors con un solo instrumento

Este artículo aborda cuestiones de codificación de la información, mediante la identificación mágica (magic-identification), así como la división, la agrupación y la sincronización del trading automatizado de distintos Expert Advisors. Este artículo puede resultar interesante para los principiantes, como para los traders más experimentados, ya que aborda la cuestión de las posiciones virtuales, que pueden ser muy útiles en la implementación de sistemas complejos de sincronización de los Expert Advisors y de varias estrategias.

Uso de MetaTrader 5 como proveedor de señales comerciales para MetaTrader 4 Uso de MetaTrader 5 como proveedor de señales comerciales para MetaTrader 4

En este artículo se discuten las particularidades del uso de MetaTrader 5 como proveedor de señales comerciales para MetaTrader 4. Ustedes conocerán cómo crear un sencillo proveedor de señales desde MetaTrader 5 y cómo conectarlo a varios terminales MetaTrader 4. Además, conocerán cómo copiar en tiempo real las transacciones de los participantes de Automated Trading Championship a su cuenta real en MetaTrader 4.