Moving Mini-Max (Minimax móvil): un nuevo indicador de análisis técnico y su implementación en MQL5

investeo | 4 abril, 2014


Introducción

Existe una disciplina llamada "Finanzas cuantitativas", que permite estudiar los modelos de fijación de precios de derivados financieros, mediante métodos de física teórica y matemáticos.

Recientemente he leído una publicación que describe un nuevo indicador de análisis técnico que combina algunos conceptos de la física cuántica y la aplica a las finanzas. Me interesó y decidí que quería enseñar cómo implementar indicadores en MQL5, basados en artículos científicos.

El artículo original sobre Moving Mini-Max [2] lo ha escrito Z.K. Silagadze, un físico cuántico del Instituto Budker de Física Nuclear y de la Universidad Estatal de Novosibirsk. Los enlaces hacia la publicación, así como el código fuente en MQL5 están disponibles al final del artículo.


El indicador

Nunca pensé que algún día escribiría sobre este tema, sin embargo, voy a explicar lo que es un túnel cuántico. Sin querer ofender, voy a suponer que la mayoría de los lectores no están muy familiarizados con el tema, así que lo voy a explicar en términos sencillos. En primer lugar, vamos a definir en una sola frase el concepto del análisis técnico de las series de tiempo financieras. Estamos buscando principalmente:

La idea original del indicador Moving Mini-Max es encontrar los máximos y mínimos en el gráfico mediante la analogía con la partícula cuántica alfa que trata de escaparse de un núcleo. El problema procede de la teoría de la desintegración alfa de George Gamov [1].

Una imagen vale más que mil palabras, así que adjunto este pequeño gráfico.

 Fig. 1 Bola cuántica imaginaria en un gráfico de series de tiempo

Figura 1. Bola cuántica imaginaria en un gráfico de precios de Forex

Imagínese una bola lanzada desde lo alto de una colina o en nuestro caso desde el último máximo del gráfico de las series de tiempo. En la mecánica clásica rebotará contra los obstáculos y puede que no llegue a pararse en el obstáculo más importante, ya que puede quedarse bloqueada en alguna parte del camino.

Pero según la mecánica cuántica y la teoría de la desintegración alfa una bola puede tener una probabilidad muy pequeña, pero no nula, de tunelización (tunneling) entre las barreras encontrando su camino hasta la parte inferior del fondo y oscilar ahí.

Esto es parecido a encontrar un mínimo local en el gráfico de los precios. El trabajo de Z.K. Silagadze [2] propone que para reducir la complejidad del cálculo, en lugar de resolver los problemas de la mecánica cuántica, basta con simular el comportamiento cuántico. Voy a presentar la base matemática propuesta en el trabajo original, y más adelante la implementación en MQL5.

Vamos a considerar que   son las series de tiempo de alguna ventana de tiempo. El Moving Mini-Max es una transformación no linear de las series de tiempo: 

uSi

Donde la definición de  y  es la siguiente:

 

Como puede observar es una relación recurrente, es decir, el i-ésimo elemento depende del elemento i-1. Las series de Moving Mini-Max satisfacen las condiciones de normalización, es decir, la suma de todos los elementos es igual a uno.

 

Las probabilidades de tunelización de una bola cuántica se llaman probabilidades de transición, ya que imitan las probabilidades de cruce a través de las estrechas barreras de las series de precios, o los pequeños obstáculos imaginarios en el descenso:


con

 

El parámetro m representa el ancho de la ventana de suavizado que simula la (inversa) masa de la bola cuántica y su capacidad de pasar a través de los pequeños obstáculos. Alternativamente, se puede construir el Moving Mini-Max d(si) que enfatiza los máximos locales poniendo el signo negativo al parámetro que se asigna a la función exp(). 

 


La implementación

Después de haber leído acerca de las bases matemáticas del indicador, podemos implementarlo en MQL5. La mejor manera de hacerlo es contemplar las ecuaciones anteriores. Si presta atención a las variables m y n verá que el indicador necesita una matriz de series de precios de n+2m elementos para una ventana Mini-Max y el tamaño del desfase que tendrá será de m barras.

Esto se debe al cálculo de los índices S i+k y S i-k en las variables Q. Se incrementa la variable i  de 1 a n y k de 1 a m, por tanto, tenemos que comenzar a partir del buffer n+2m. Esto se puede conseguir llamando al código:

double S[];
ArrayResize(S,n+2*m);
CopyClose(Symbol(),0,0,n+2*m,S);

Este declarará una matriz doble, cambiará su tamaño a n+2m y copia los valores del cierre de las últimas barras n+2m a partir del símbolo actual del gráfico, comenzando por la última barra.

El siguiente paso es el cálculo de los valores de Q. Si lee cuidadosamente la definición, se dará cuenta que para el i-ésimo elemento analizado de las series de precios, tenemos que sumar los resultados m de la función exp() con las variables de los valores del precio. De modo que tenemos que escribir un bucle que va de 1 a n para calcular todos los valores de Q:

void calcQii()
  {
   int i,k;

   for(i=0; i<n; i++)
     {
      double sqiip1=0;
      double sqiim1=0;
      double dqiip1=0;
      double dqiim1=0;

      for(k=0; k<m; k++)
        {
         sqiip1 += MathExp(2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i]));
         sqiim1 += MathExp(2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i]));

         dqiip1 += MathExp(-2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i]));
         dqiim1 += MathExp(-2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i]));       
        }
      sQiip1[i] = sqiip1;
      sQiim1[i] = sqiim1;
      dQiip1[i] = dqiip1;
      dQiim1[i] = dqiim1;

     }
  }

Como puede observar, la función calcQii calcula el i-ésimo valor de Q y Q` para la ventana del precio observado de tamaño n. La matriz S almacena los valores del precio y se usan sQiip1, sQiim1, dQiip1, dQiim1 como variables de cálculo intermedio de Q y Q'.

Se calculan las probabilidades en base a las variables Q y Q`, por tanto, podemos escribir otra función que recorre las matrices sQii y dQii mediante un bucle de 1 a n :

void calcPii()
  {
   int i;

   for(i=0; i<n; i++)
     {
      sPiip1[i] = sQiip1[i] / (sQiip1[i] + sQiim1[i]);
      sPiim1[i] = sQiim1[i] / (sQiip1[i] + sQiim1[i]);
      dPiip1[i] = dQiip1[i] / (dQiip1[i] + dQiim1[i]);
      dPiim1[i] = dQiim1[i] / (dQiip1[i] + dQiim1[i]);
     }
  }

Solo falta calcular los elementos uSi y más adelante dSi y colocar los resultados en las matrices uSi y dSi: 

void calcui()
  {
   int i;

   sui[0] = 1;
   dui[0] = 1;

   for(i=1; i<n; i++) 
     {
      sui[i] = (sPiim1[i]/sPiip1[i])*sui[i-1];
      dui[i] = (dPiim1[i]/dPiip1[i])*dui[i-1];
     }

   double uSum = 0;
   double dSum = 0;

   ArrayInitialize(uSi, 0.0);
   ArrayInitialize(dSi, 0.0);
   
   for(i=0; i<n; i++) { uSum+=sui[i]; dSum+=dui[i]; }
   for(i=0; i<n; i++) { uSi[n-1-i] = sui[i] / uSum; dSi[n-1-i] = dui[i] / dSum; }
 
  }

Para comprobar la normalización de las condiciones, podemos añadir las siguientes líneas:

   double result=0;
   for(i=0; i<n; i++) { /* Print("i = "+i+" uSi = "+uSi[i]); */ result+=uSi[i]; }

   Print("Result = "+ DoubleToString(result));

Después de llevar a cabo los cálculos, tenemos que mostrarlos en la ventana del indicador. Para hacerlo, tenemos que declarar por lo menos dos buffers de indicador, uno para la matriz uSi y el otro para dSi, y definir el tipo de indicador como DRAW_LINE. 

    #property indicator_separate_window

    #property indicator_buffers 2
    #property indicator_plots 2
    #property indicator_type1 DRAW_LINE
    #property indicator_type2 DRAW_LINE
    #property indicator_color1 SeaGreen
    #property indicator_color2 BlueViolet

A continuación, llamando a la función SetIndexBuffer(), indicamos que hay que mostrar las matrices uSi y dSi como INDICATOR_DATA:

   SetIndexBuffer(0,uSi,INDICATOR_DATA);
   SetIndexBuffer(1,dSi,INDICATOR_DATA);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   PlotIndexSetInteger(0,PLOT_SHIFT,-(m-1));
   PlotIndexSetInteger(1,PLOT_SHIFT,-(m-1));

Fig. 2 El indicador Moving Mini-Max

 Figura 2. El indicador Moving Mini-Max implementado 

Las posibles aplicaciones del indicador que se describen en este artículo son la identificación de las líneas de soporte y resistencia y la identificación de los patrones de gráficos mediante el suavizado inherente del indicador. En cuanto a las líneas de soporte y resistencia, se forman mediante el cruce de Moving Mini-Max de las series del precio y de Moving Mini-Max de su promedio móvil.

Si el precio atraviesa el máximo local y cruza el promedio móvil, tenemos una resistencia. Después de su implementación, he observado que algunas señales falsas afectan al método, pero adjunto el código fuente como referencia acerca del modo de colocar las líneas mediante la librería ChartObjectsLines.mqh: 

void SR()
{
   // if price goes through local maximum and crosses a moving average draw resistance
   int i, cnt=0;
   int rCnt=CopyClose(Symbol(),0,0,n+2*m,S);
      
   for (i=n-2; i>=0; i--)
      if (uSi[i]<uSi_MA[i] && uSi[i+1]>=uSi_MA[i+1]) 
      {
      Print("Resistance at " + i);
      CChartObjectHLine *line=new CChartObjectHLine();
      line.Create(0, "MiniMaxResistanceLine:"+IntegerToString(cnt), 0, S[i]);
      line.Color(LightSkyBlue);
      line.Width(1);
      line.Background(true);
      line.Selectable(false);
      cnt++;
      }
   // if price goes through local minimum and crosses a moving average draw support

   for (i=n-2; i>=0; i--)
      if (dSi[i]<dSi_MA[i] && dSi[i+1]>=dSi_MA[i+1]) 
      {
      Print("Support at " + i);
      CChartObjectHLine *line=new CChartObjectHLine();
      line.Create(0, "MiniMaxSupportLine:"+IntegerToString(cnt), 0, S[i]);
      line.Color(Tomato);
      line.Width(1);
      line.Background(true);
      line.Selectable(false);
      cnt++;
      }
}

Un dato interesante del indicador es que he observado que reconoce bastante bien los máximos y mínimos locales de la tendencia a corto plazo para una ventana de tiempo concreta. Es suficiente para filtrar la propagación entre las lecturas máximas y mínimas de Moving Mini-Max y marcarlas como el principio de una tendencia a corto plazo alcista o bajista.

Podemos aprovechar este comportamiento en base a otros indicadores y a la gestión del dinero para crear un Expert Advisor más rentable.

Para marcar las lecturas máximas en la ventana de tiempo actual, podemos utilizar buffers de indicador adicionales para mostrar las flechas hacia arriba y hacia abajo cada vez que la propagación es mayor. Además de hacer un indicador más atractivo, he decidido usar una nueva característica de MQL5: el histograma a color. Se colorean las tendencias bajistas y alcistas con colores distintos, y se señala el cambio de tendencia con una barra amarilla. 

Con el fin de usar el histograma a color entre dos buffers, necesitamos 2 buffers de datos y un buffer para los índices de los colores. Observe cómo se definen los dibujos. Hay 5 buffers de indicador en total y se definen tres colores para el histograma a color.

//+------------------------------------------------------------------+
//|                                                MovingMiniMax.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2011, Investeo.pl"
#property link        "http://Investeo.pl"

#property description "Moving Mini-Max indicator"
#property description "proposed by Z.K. Silagadze"
#property description "from Budker Institute of Nuclear Physics"
#property description "and Novosibirsk State University"
#property description "Original paper can be downloaded from:"
#property description "http://arxiv.org/abs/0802.0984"

#property version     "0.6"
#property indicator_separate_window

#property indicator_buffers 5
#property indicator_plots 3

#property indicator_type1 DRAW_COLOR_HISTOGRAM2
#property indicator_type2 DRAW_ARROW
#property indicator_type3 DRAW_ARROW

#property indicator_color1 Chartreuse, OrangeRed, Yellow
#property indicator_color2 RoyalBlue
#property indicator_color3 RoyalBlue

#property indicator_width1 5
#property indicator_width2 4
#property indicator_width3 4

Tenga en cuenta que el histograma cuenta con dos buffers de tipo INDICATOR_DATA y un buffer INDICATOR_COLOR_INDEX. Hay que configurar los buffers exactamente en el siguiente orden, primero los buffers de datos y después se define el buffer de los índices de color.

   SetIndexBuffer(0,uSi,INDICATOR_DATA);
   SetIndexBuffer(1,dSi,INDICATOR_DATA);
   SetIndexBuffer(2,trend,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(3,upArrows,INDICATOR_DATA);
   SetIndexBuffer(4,dnArrows,INDICATOR_DATA);
   
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0);
   
   PlotIndexSetInteger(1,PLOT_ARROW,234);
   PlotIndexSetInteger(2,PLOT_ARROW,233); 

Los buffers 1, 2 y 3 son para el histograma a color, los buffers 3 y 4 son para mostrar las flechas.

A continuación se muestra el algoritmo del coloreado:

   if (upind<dnind) 
    { 
      for (i=0; i<upind; i++) trend[i]=0;
      for (i=upind; i<dnind; i++) trend[i]=1;
      for (i=dnind; i<n; i++) trend[i]=0 ;
    } else
    {
      for (i=0; i<dnind; i++) trend[i]=1;
      for (i=dnind; i<upind; i++) trend[i]=0;
      for (i=upind; i<n; i++) trend[i]=1;
   }
   
   trend[upind] = 2;
   trend[dnind] = 2;

 Esta es una captura de pantalla del resultado final:

Figura 3. Versión final del indicador Moving Mini-Max

Figura 3. Versión final del indicador Moving Mini-Max

Hay que recordar que los valores para la tendencia bajista y alcista se calculan para una determinada ventana de tiempo cada vez que llega una nueva barra, siendo este el motivo por el cual el indicador se llama Moving Mini-Max.

Aunque se retrasa de m barras, proporciona una buena visión general de la tendencia en la ventana de tiempo actual y una interpretación acerca del "pulso" del mercado.

Estoy convencido de que este indicador puede ser rentable.

 

Conclusión

He presentado la base matemática de un nuevo indicador de análisis técnico y su implementación en MQL5

El trabajo original de Z.K. Silagadze está disponible en http://arxiv.org/abs/0802.0984. El código fuente adjunto está disponible para su descarga.

Espero que en un futuro pueda presentar unos indicadores técnicos más interesantes con su implementación en MQL5

 

Referencias:

1. G.Gamov, Teoría de la desintegración alfa.
2. Z.K. Silagadze, Moving Mini-Max - a new indicator for technical analysis (un nuevo indicador para el análisis técnico).