Nuevo enfoque a la interpretación de la divergencia clásica e inversa

Alexander Lasygin | 16 noviembre, 2017


Introducción

En la mayoría de los casos, los traders recurren a los métodos clásicos del análisis técnico del mercado. No obstante, muchos métodos y enfoques que son diferentes también tienen derecho a existir. En este artículo, yo propongo estudiar un método no estándar de cómo buscar e interpretar las divergencias. Nosotros crearemos una estrategia comercial a base de este enfoque.

Definición de la divergencia/convergencia

El movimiento en el mercado continua hasta que sus participantes tengan el deseo y los medios para eso. De ello se desprende que tarde o temprano llega el momento cuando todos los participantes ya se encuentran en el mercado, y no hay nadie quien puede seguir moviendo el precio. Semejantes situaciones no es una cosa de otro mundo en el mercado. Dependiendo de la dirección de la tendencia, se llaman la sobrecompra o la sobreventa.

La sobrecompra es una situación en los mercados financieros, mercados de valores o de futuros, que surge cuando todos los que querían comprar activos, ya los compraron, y no hay nadie quien podía seguir moviendo el precio.

La sobreventa es una situación inversa, cuando todos los que querían vender activos, ya los vendieron, y no hay nadie quien podía seguir moviendo el precio.

La sobrecompra/sobreventa no aparece de nada. Se sabe que el movimiento del precio es ondulatorio. Los traders rastrean el cambio del precio comparando su gráfico con el gráfico de indicadores u osciladores. Cuando el comportamiento del indicador se diferencia de la dirección del movimiento del precio, se forma la convergencia en el mercado bajista o la divergencia en el mercado alcista.

Tipos de divergencias

Diferentes investigadores clasifican la divergencia/convergencia de maneras diferentes. Nos basaremos en su subdivisión en dos tipos principales: la clásica y la oculta.

    Divergencia clásica

    Para identificar una divergencia clásica, basta con comparar los momentos de la actualización de los extremos del precio con los mismos momentos en el gráfico del indicador. Si el gráfico del precio ha actualizado otra vez su máximo o mínimo, y el indicador no ha podido hacer eso, entonces se trata de la divergencia. El mercado está sobrecomprado (sobrevendido), y es inconveniente intentar abrir las transacciones en la dirección de la tendencia actual.

    Hay muchas publicaciones sobre la divergencia clásica. Dependiendo de las características, se puede dividirla en tres subclases:

    • Clase A.Se encuentra con más frecuencia que las demás. Cuando el precio del activo actualiza de nuevo su extremo, el indicador empieza a dar la vuelta indicando al trader en la divergencia y la posibilidad de una próxima reversión.
    • Clase B. Parece a la clase A a excepción de que el precio del activo no puede romper el extremo, dibuja el patrón de reversión «pico doble» / «valle doble», mientras que el indicador no ha alcanzado sus extremos.
    • Clase C. El precio actualiza el pico o el valle, y el indicador dibuja el pico doble (valle doble).

    La divergencia (convergencia) puede repetirse consecutivamente varias veces, combinando varias clases y creando así un modelo de reversión más fuerte. Cada clase debe ser analizada individualmente en cada determinado caso. No se puede decir unívocamente cuál de ellas es más fuerte o débil. Las razones de eso serán consideradas más abajo.

    Divergencia oculta

    Este tipo de divergencia también está dividido en subclases:

    • Los máximos descendientes del precio junto con los máximos ascendientes del oscilador indican en la confirmación de la tendencia bajista.
    • Los mínimos ascendientes del precio y los mínimos descendientes del oscilador confirman una tendencia alcista.


    En la imagen de arriba, podemos observar claramente un mercado alcista, pero el indicador MACD muestra nuevo mínimo que no se confirma por el gráfico del precio. Esta discrepancia indica en la presencia de una divergencia alcista oculta, y señaliza sobre el reforzamiento de la tendencia alcista.

    Indicadores y osciladores para buscar la divergencia/convergencia. ¿Cómo funciona eso?

    ¿Qué indicadores pueden mostrar la divergencia y convergencia? Un indicador del análisis técnico debe saber determinar los niveles de la demanda y oferta, así como rastrear el momentum. A estos indicadores les pertenecen los osciladores, estocástico, RSI, CCI etc., así como el indicador de tendencia con elementos del oscilador— MACD. El MACD puede interpretarse como una divergencia y convergencia de las medias móviles. Este indicador rastrea eficazmente las discrepancias en el movimiento del precio y su momentum. Muchos traders basan sus decisiones de divergencia y convergencia usando este indicador.

    Por tanto, sería un error recomendar alguna determinada herramienta para trabajar con la divergencia. Cada trader elige por sí mismo un indicador de tal manera que corresponda a su estrategia comercial y no sobrecargue el gráfico del precio. Es decir, la única recomendación es la siguiente: repase la lista de indicadores, pruebe cada uno de ellos, elija uno y opere usando sus señales, sin prestar atención en los demás factores.

    También se puede detectar una divergencia sin usar indicadores, además, no es difícil. En primer lugar, Usted tiene que comprender los principios de la formación de la divergencia.

    El momentum desempeña un papel importante en la formación de la divergencia. O sea, nosotros comprendemos que si después de un fuerte movimiento del mercado, la amplitud del movimiento posterior va a bajar, eso será una señal para su formación.


    La imagen de arriba nos muestra este ejemplo. Cuando se forma un mínimo nuevo, se puede notar que el tamaño de la onda nueva es menor que el tamaño de la anterior. Eso nos permite suponer que surge una divergencia.

    Abajo se muestra la misma parte del mercado con el indicador RSI para confirmar esta suposición.


    Y aunque no es tan difícil determinar una divergencia, este método no puede considerarse completo si el uso de los indicadores. No vemos las líneas de divergencia/convergencia. Por eso yo propongo considerar varios indicadores que se utilizan con más frecuencia para identificar este patrón.

    Oscilador RSI

    El oscilador RSI tiene las zonas >-100 y <+100, denominadas las zonas de sobreventa y sobrecompra, respectivamente. Las señales que aparecen cuando el indicador se encuentra en estas zonas ya se consideran fuertes, y si esta señal es una divergencia, su fuerza se aumenta considerablemente.

    A las desventajas de este método les pertenece el hecho de que el indicador es muy sensible a las fluctuaciones del precio. Eso hace difícil la identificación de los picos y valles. Es necesario analizar el gráfico de precios. Eso lleva al retardo en la detección de señales.

    Oscilador Stochastic

    Para el oscilador se utilizan las configuraciones estándar:

    • Período %K: 5
    • Período %D: 3
    • Retardo: 3

    El oscilador Stochastic, igual como RSI, tiene las zonas de sobrecompra y sobreventa. La divergencia o la convergencia en estas zonas aumenta considerablemente las posibilidades de conseguir el resultado positivo de la transacción.

    La desventaja de esta herramienta es la aparición frecuente de las divergencias, y como consecuencia, la formación de señales falsas. Todas las señales se debe interpretar como advertencias sobre unos posibles cambios, por eso es necesario usar las técnicas adicionales para determinar los puntos de entrada en el mercado.

    Oscilador MACD

    El MACD es un oscilador bastante interesante que puede hacer muchas cosas, entre esas, ayudar en la búsqueda de la divergencia. Este indicador se usa con las configuraciones estándar:

    • EMA rápida: 12
    • EMA lenta: 26
    • MACD SMA: 9


    Una de las reglas para detectar la divergencia usando este indicador es la siguiente: las barras del oscilador no deben cruzar el nivel cero. En la imagen de abajo, vemos que la divergencia no es obvia en esta situación, y nuestra probabilidad de realizar una transacción rentable tiende a cero.

    A diferencia de los indicadores anteriores, éste genera menos señales, pero dado que es de tendencia, él avisa sobre unos cambios globales en el mercado. A pesar de todas sus ventajas, también requiere la confirmación para entrar en el mercado por el análisis Price Action o patrones de velas.

    Indicador Volumes (volumen)

    El volumen es otra característica importante. Una de las señales de reversión más potente es la reversión (convergencia) del precio y volumen (volumes). La idea es la siguiente:

    El movimiento alcista continuaba hasta que en el mercado se inyectaban nuevos volúmenes. Cuando el máximo se rompe, observamos una reducción del volumen, lo que significa que los compradores han dejado de inyectar el dinero en el mercado. De ello se desprende que el precio está sobrecomprado e irá para abajo. Esta situación se muestra en la imagen de abajo.

    En este contexto, me parece que el indicador OBV es el más interesante. Proporciona buenas señales para entrar en el mercado precisamente a base de esta divergencia oculta.

    No obstante, la divergencia clásica en OBV suele indicar sólo en la ralentización y transición a la consolidación.


    Reglas para determinar la divergencia/convergencia y trader con ella

    Vamos a hablar de los errores que los traders cometen frecuentemente cuando intentan encontrar una divergencia/convergencia y realizar una transacción usando este patrón.

    • La presencia de la tendencia es obligatoria, ya que la divergencia no trabaja en el flat.
    • A la hora de trabajar con las divergencias, confirme sus entradas usando los patrones de PriceAction o velas japonesas.
    • No cree que ha encontrado una señal de 100%. Siempre hay una probabilidad de un error. Por eso, cuando opera en el mercado, siga todas las reglas generales para ejecutar las operaciones.
    • Para determinar la divergencia, no utilice las velas construidas a base de los indicadores de noticias. Debido a una alta volatilidad durante las publicaciones de noticias, estas velas con mucha frecuencia generan las señales falsas.
    • La divergencia que se busca tiene que ser explícita. Tiene que estar seguro de que no sólo Usted ve la señal, sino también los demás participantes del mercado. Sólo en este caso, la probabilidad de tomar una decisión correcta se aumenta.
    • Analice sólo los picos y los valles más cercanos. Eso da una comprensión más clara de la situación. Para los indicadores de tendencia, como MACD, la intersección del nivel cero puede debilitar considerablemente la señal o incluso cancelarla.

    Nuevo enfoque

    Más arriba hemos considerado las reglas principales y comunes para usar y construir el patrón «Divergencia». Ahora hablaremos de su uso no estándar en el trading. En nuestro trabajo, no sólo nos apartaremos de las reglas estándar, sino vamos a usar un indicador no típico para estos propósitos.

    Vamos a llevar a cabo nuestro experimento a base de una herramienta clásica —indicador de Bill Williams, Accelerator Oscillator. Su elección no ha sido casual. Este indicador va a cambiar la dirección antes del cambio de la fuerza de movimiento, y ella, en su lugar, va a cambiar la dirección antes del cambio del precio. AO es una señal de confirmación incipiente, lo que nos da unas ventajas evidentes. Tenemos la posibilidad de recibir las señales sobre la discrepancia antes y con más frecuencia. Normalmente, esta solución lleva al aumento de la «basura», pero en nuestro caso, eso nos da más señales de entrada en el mercado y las señales de ralentización más tempranas.

    Más arriba hemos considerado las reglas principales y comunes para usar y construir la divergencia. Ahora hablaremos de su uso no estándar en el trading. En nuestro trabajo, seguiremos las reglas comunes, pero vamos a usar un modo inusual para determinar los puntos de entrada.

    Puesto que el objetivo principal de la creación de esta herramienta es la búsqueda de la divergencia, introduciremos sólo un parámetro en las variables (número de barras a calcular que son necesarias para detectar la divergencia).

    #property indicator_separate_window
    //---- Para calcular y dibujar el indicador se usa un búfer
    #property indicator_buffers 2
    //---- Se usa sólo una construcción gráfica
    #property indicator_plots 1
    //---- El indicador se dibuja como una línea
    #property indicator_type1 DRAW_COLOR_HISTOGRAM
    //---- El color de la línea del indicador es azul
    #property indicator_color1 Green,Red
    //----
    #property indicator_width1 2
    //---- La línea del indicador es una curva continua
    #property indicator_style1 STYLE_SOLID
    //---- Visualización de la etiqueta del indicador
    #property indicator_label1 "AC_Div"
    //+------------------------------------------------------------------+
    input int Bars_Calculated=1000;
    //+------------------------------------------------------------------+
    string shortname="";
    double AC_buff[];
    double Color_buff[];
    int wid;
    int Handle_AC;
    //---
    #define DATA_LIMIT 37
    

    El indicador será inicializado con los presentes parámetros del histograma multicolor.

    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
     {
    //---- Conversión de los arrays dinámicos en el búfer de indicador
     SetIndexBuffer(0,AC_buff,INDICATOR_DATA);
     SetIndexBuffer(1,Color_buff,INDICATOR_COLOR_INDEX);
    //---- Establecimiento de la posición desde la cual se empieza el dibujado del indicador
     PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,DATA_LIMIT);
    //---- Inicialización de la variable para el nombre corto del indicador
     shortname="Accelerator_Divergence";
    //---- Creación del nombre para mostrar en una ventana separada y en la descripción emergente
     IndicatorSetString(INDICATOR_SHORTNAME,shortname);
    //---- Definición de la precisión para visualizar valores del indicador
     IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
    //---- Deshabilitar el dibujado de valores vacíos
     PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
     PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
    //--- Formamos el handle del indicador Accelerator
     Handle_AC=iAC(NULL,0);
    //--- Buscamos el número de la subventana del indicador
     wid=ChartWindowFind(0,shortname);
    //---
     return(INIT_SUCCEEDED);
     }
    

    La función para el cálculo principal del indicador va a componerse de dos partes.

    La primera parte es el mismo indicador.

    //---- Declaración de las variable locales
     int limit,bar,pos;
    //---- Comprueba si el número de las barras es suficiente para el cálculo
     if(rates_total<DATA_LIMIT)
     return(0);
     int barsCalculated=MathMin(Bars_Calculated,rates_total);
    //+------ Establecemos la dirección de la indexación del array ---------------------+
     ArraySetAsSeries(close,true);
     ArraySetAsSeries(AC_buff,true);
     ArraySetAsSeries(low,true);
     ArraySetAsSeries(high,true);
     ArraySetAsSeries(Color_buff,true);
     ArraySetAsSeries(time,true);
    //+--- Determinamos el número de las barras necesarias para el cálculo ----------+
     limit=rates_total-DATA_LIMIT-1;
     if(prev_calculated>0) limit=rates_total-prev_calculated;
     pos=limit;
     if(pos>barsCalculated)pos=limit;
     int to_copy;
     if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
     else
     {
     to_copy=rates_total-prev_calculated;
     if(prev_calculated>0) to_copy++;
     }
    //---
     if(IsStopped()) return(0); //Checking for stop flag
    //+----- Formamos el array principal ----------------------------------+
     if(CopyBuffer(Handle_AC,0,0,to_copy,AC_buff)<=0)
     {
     Print("getting Accelerator Handle is failed! Error",GetLastError());
     return(0);
     }
    //+---------- Coloreamos el histograma ------------------------------+
     for(bar=limit; bar>=0 && !IsStopped(); bar--)
     {
     Color_buff[bar]=0.0;
     if(AC_buff[bar]<AC_buff[bar+1])Color_buff[bar] =1.0;
     if(AC_buff[bar]>AC_buff[bar+1])Color_buff[bar] =0.0;
     }
    

    La segunda parte incluye la búsqueda de las discrepancias.

    //+----------- Detectamos las discrepancias UP -------------------------------+
     int bars=barsCalculated;
     for(bar=pos; bar>=0 && !IsStopped(); bar--)
     {
     int l=bar+2;
     if(Extremum(AC_buff[l+1],AC_buff[l],AC_buff[l-1])<0)
     {
     int i=l;
     int counted=LastPeak(l,bars,AC_buff);
     if(counted!=-1)
     {
     if(AC_buff[i]<AC_buff[counted] && high[i]>high[counted])
     {
     DrawPriceTrendLine(time[i],time[counted],high[i],high[counted],Red,STYLE_SOLID);
     DrawIndicatorTrendLine(time[i],time[counted],AC_buff[i],AC_buff[counted],Red,STYLE_SOLID);
     }
    
     if(AC_buff[i]>AC_buff[counted] && high[i]<high[counted])
     {
     DrawPriceTrendLine(time[i],time[counted],high[i],high[counted],Red,STYLE_DOT);
     DrawIndicatorTrendLine(time[i],time[counted],AC_buff[i],AC_buff[counted],Red,STYLE_DOT);
     }
     }
     }
    //+----------- Detectamos las discrepancias DN -------------------------------+
     if(Extremum(AC_buff[l+1],AC_buff[l],AC_buff[l-1])>0)
     {
     int i=l;
     int counted=LastTrough(l,bars,AC_buff);
     if(counted!=-1)
     {
     if(AC_buff[i]>AC_buff[counted] && low[i]<low[counted])
     {
     DrawPriceTrendLine(time[i],time[counted],low[i],low[counted],Green,STYLE_SOLID);
     DrawIndicatorTrendLine(time[i],time[counted],AC_buff[i],AC_buff[counted],Green,STYLE_SOLID);
     }
     if(AC_buff[i]<AC_buff[counted] && low[i]>low[counted])
     {
     DrawPriceTrendLine(time[i],time[counted],low[i],low[counted],Green,STYLE_DOT);
     DrawIndicatorTrendLine(time[i],time[counted],AC_buff[i],AC_buff[counted],Green,STYLE_DOT);
     }
     }
     }
     }
    

    Para reducir el código, las construcciones gráficas y la función de la búsqueda de los extremos se proporcionan separadamente.

    //+----- Búsqueda del segundo extremo UP --------------------------------+
    int LastPeak(int l,int bar,double &buf[]) 
     {
     for(int i=l+5; i<bar-2; i++)
     if(Extremum(buf[i+1],buf[i],buf[i-1])<0)return (i);
     return (-1);
     }
    //+------ Búsqueda del segundo extremo DN -------------------------------+
    int LastTrough(int l,int bar,double &buf[])
     {
     for(int i=l+5; i<bar-2; i++)
     if(Extremum(buf[i+1],buf[i],buf[i-1])> 0)return (i);
     return (-1);
     }
    //+-- Búsqueda de los extremos --------------------------------------------+
    int Extremum(double a,double b,double c)
     {
     if((a-b)*(b-c)<0)
     {
     if(c>b && b<0) return(1); //extremo DN
     if(c<b && b>0) return(-1);//extremo UP
     }
     return(0);
     }
    //+------ Creamos los objetos en el gráfico del precio ---------------------------+
    void DrawPriceTrendLine(datetime T_0,
     datetime T_1,
     double P_0,
     double P_1,
     color color_0,
     int style)
     {
     string name_2=shortname+DoubleToString(T_0,0);
     string name_0;
     name_0=shortname+"Line_Sn"+ColorToString(color_0);
    //--- 
     if(ObjectFind(0,name_2)<0)
     drawLineS(name_2,T_0,T_1,P_0,P_1,color_0,style,0,true,false,0);
    //+-----------+
     if(style==STYLE_DOT)
     drawLineS(name_0,T_1,T_0,P_1,P_0,clrAqua,0,3,true,true,0);
     }
    //+------ Creamos los objetos en la ventana del indicador -------------------------+
    void DrawIndicatorTrendLine(datetime T_0,
     datetime T_1,
     double P_0,
     double P_1,
     color color_0,
     int style)
     {
     string name_1,name_0;
     int window= wid;
     name_1 = shortname+DoubleToString(T_0+wid,0);
     if(ObjectFind(0,name_1)<0)
     drawLineS(name_1,T_0,T_1,P_0,P_1,color_0,style,0,false,false,window);
    //---
     if(style==STYLE_SOLID)
     {
     name_0=shortname+"Line_Pn"+ColorToString(color_0);
     drawLineS(name_0,T_1,T_0,P_1,P_0,clrMagenta,style,2,true,true,window);
     }
     }
    //+------------------------------------------------------------------+
    void drawLineS(string name,
     datetime t0,
     datetime t1,
     double p0,
     double p1,
     color clr,
     int style,
     int width,
     bool back,
     bool ray,
     int window)
     {
     ObjectDelete(0,name);
     ObjectCreate(0,name,OBJ_TREND,window,t0,p0,t1,p1,0,0);
     ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,ray);
     ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
     ObjectSetInteger(0,name,OBJPROP_STYLE,style);
     ObjectSetInteger(0,name,OBJPROP_WIDTH,width);
     ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
     ObjectSetInteger(0,name,OBJPROP_BACK,back);
     }
    //+------------------------------------------------------------------+
    
    

    Para la conveniencia del análisis visual, usaremos la línea continua para la divergencia clásica, y la línea punteada, para la oculta. El color rojo se usa para las divergencias bajistas, y el verde, para las alcistas. Los rayos gruesos se usan para mostrar las últimas divergencias ocultas alcistas y bajistas en el gráfico de precios y las divergencias clásicas en la ventana del indicador. Luego, explicaremos para qué hacemos eso. El indicador tendrá el siguiente aspecto:

    Principios básicos de la estrategia

    El análisis de los gráficos del precio y del indicador ha demostrado que la línea extendida de la divergencia inversa en el gráfico del precio y la clásica en el del indicador actúan como una especie de los niveles inclinados del soporte (resistencia). La ruptura firme de estas líneas caracteriza el futuro comportamiento del mercado a largo y corto plazo.

    El ejemplo de la ruptura de las líneas de soporte formadas por la divergencia oculta se muestra en el gráfico del precio:


    En el siguiente ejemplo, las barras del histograma rompen las líneas de la divergencia clásica en la ventana del indicador:

    Después de la ruptura, las líneas a menudo cambian su finalidad. Es decir, el nivel de soporte roto se convierte en el de resistencia:

    Nuestra estrategia va a basarse en estas regularidades en el comportamiento.


    Reglas del trading

    Usted puede tradear usando tanto las órdenes pendientes, como las órdenes de mercado. El timeframe y la hora no tienen un significado importante. La regla principal consiste en la ruptura segura de las líneas. Cuando tradeamos con las órdenes pendientes, las colocamos en el máximo (mínimo) de la vela que se rompe, o la vela en la que se forma la barra del histograma. Además, debe tener la dirección de la ruptura. En otras palabras, si la ruptura va hacia arriba, la vela debe cerrarse en buy, y viceversa. 

    En la imagen de abajo, la divergencia oculta se rompe con seguridad en el gráfico del precio: hemos obtenido la señal de apertura de una posición larga que se confirma más tarde. Además, vemos que la línea de la divergencia clásica está rota en la ventana del indicador: obtenemos la señal de apertura de una posición corta, pero ella no se confirma a continuación.


    La siguiente imagen muestra otra situación: la señal de compra se forma cuando la línea de la divergencia clásica se rompe en la ventana del indicador. A continuación, esta señal se confirma.

    A continuación, tenemos otro ejemplo interesante. Dos señales aparecen simultáneamente en una vela: la señal de compra y la señal de venta. En este caso, podemos comprobar los valores del oscilador. Pero incluso si los hemos ignorado, vemos que se activado sólo una orden, con lo cual hemos confirmado la transacción de venta. Luego, ha aparecido otra señal para la posición corta, lo que ha intensificado la señal anterior. Eso nos ha permitido añadir fondos a la transacción y aumentar el beneficio.


    Es una señal clásica de venta:

    A continuación, vemos una señal de venta (cancelada luego por los valores del oscilador) y dos señales de compra.


    Colocamos los Stop Loss debajo del extremo local cercano. El Take Profit se coloca en los niveles de soporte/resistencia. Si tradeamos contra la tendencia, nuestras líneas pueden servir de estos niveles. Pero en este caso, hay que tener cuidado, porque la situación del mercado puede cambiar bruscamente, y probablemente habrá que ajustar el nivel del Take Profit.

    En los timeframes pequeños (М1-М15), el precio a menudo vuelve a la línea después de la ruptura, formando así el patrón 1-2-3 que intensifica la señal. Por eso, si el mercado no está muy activo, es mejor entrar en estos timeframes después de que el precio rompa los extremos de la vela de ruptura. Claro que no vamos a olvidar de la versión clásica de la interpretación de la divergencia. Aunque aquí el oscilador no es tan importante como en otras estrategias, y se utiliza principalmente para las construcciones, es deseable tomar en cuenta su comportamiento durante el trading. El indicador AO forma parte de muchas estrategias. Su combinación con el enfoque descrito puede aumentar considerablemente su eficacia.

    Para comprobar la viabilidad de nuestra estrategia, escribiremos un EA que tradea usando las órdenes pendientes. El problema principal consiste en el hecho de que no podemos usar la llamada simple al indicador dentro del EA para eso. En este caso, nuestro indicador no va a dibujar ningunas construcciones en la subventana. Pero como trabajamos precisamente con las construcciones gráficas, tenderemos que insertar una parte del código desde el indicador en el EA.

    input double InpLots =0.1;           // Lots
    input int InpTakeProfit =150;        // Take Profit (in pips)
    input int InpStopLoss =60;           // StopLoss (in pips)
    input int InpTrailingStop =25;       // Trailing Stop Level (in pips)
    input int InpOffset =5;              // Distance from the price (in pips)
    input int InpDellOorder =30;         // Order removal distance (in pips)
    //---
    int ExtTimeOut=10;                   // tiempo entre las operaciones comerciales en segundos
    int barsCalculated=1000;
    datetime t=0;
    datetime time[];
    
    

    Completaremos las variables conocidas Lots, TakeProfit, StopLoss y TrailingStop con otras dos, Offset y DellOorder. La primera de ellas establece la distancia (pip) entre nuestra orden y el máximo (mínimo) de la vela de ruptura. Si la orden todavía no se ha activado, y el precio se mueve en la dirección opuesta de nosotros, en la distancia DellOorder (pip), eliminamos la orden.

    Puesto que este EA no es original, discutiremos los momentos de mayor importancia. No vamos a usar nada para la filtración de las transacciones, pero de cualquier forma, introduciremos pequeñas modificaciones en el código original.

    //+------------------------------------------------------------------+
    //| Cálculo principal                                                |
    //+------------------------------------------------------------------+
     for(int bar=1; bar>0 && !IsStopped() && t!=time[0]; bar--)
     {
     int l=bar+1;
     int p1=0,p2=0;
     //+----------- Detectamos las discrepancias UP ---------------------+
     if(Extremum(m_buff_ind[l+1],m_buff_ind[l],m_buff_ind[l-1])<0)
     {
     int i=l;
     int counted=LastPeak(l,bars,m_buff_ind);
     if(counted!=-1)
     {
     if(m_buff_ind[i]<m_buff_ind[counted] && high[i]>high[counted] && !d1)
     { drawLine("Buy_1",time[i],time[counted],m_buff_ind[i],m_buff_ind[counted],Red,1); d1=true;}
     //---
     if(m_buff_ind[i]>m_buff_ind[counted] && high[i]<high[counted] && !d2)
     {
     p1=ArrayMaximum(high,i-1,5);p2=ArrayMaximum(high,counted-2,5);
     drawLine("Buy_2",time[p1],time[p2],high[p1],high[p2],Red,0);d2=true;
     }
     }
     }
     //+----------- Detectamos las discrepancias DN -------------------------------+
     if(Extremum(m_buff_ind[l+1],m_buff_ind[l],m_buff_ind[l-1])>0)
     {
     int i=l;
     int counted=LastTrough(l,bars,m_buff_ind);
     if(counted!=-1)
     {
     if(m_buff_ind[i]>m_buff_ind[counted] && low[i]<low[counted] && !d3)
     { drawLine("Sell_1",time[i],time[counted],m_buff_ind[i],m_buff_ind[counted],Green,1);d3=true;}
     //---
     if(m_buff_ind[i]<m_buff_ind[counted] && low[i]>low[counted] && !d4)
     {
     p1=ArrayMinimum(low,i-1,5);p2=ArrayMinimum(low,counted-2,5);
     drawLine("Sell_2",time[p1],time[p2],low[p1],low[p2],Green,0);d4=true;
     }
     }
     }
     if(d1 && d2 && d3 && d4)break;
     t=time[0];
     }
    //---
     }
    

    Nosotros comprendemos que el extremo del indicador no será necesariamente igual como en el gráfico del precio. Por eso, para corregir un poco las distorsiones de las construcciones relacionadas con eso en nuestro gráfico, hemos añadido dos funciones ArrayMinimum y ArrayMaximum (marcadas en color). Estas funciones permiten identificar el máximo y el mínimo en la parte del gráfico del precio, donde se ha formado el extremo del indicador. Además, para eliminar pequeñas fluctuaciones del indicador alrededor de la línea cero y las señales falsas relacionadas con ello, hemos modificado la fórmula de la determinación de los extremos. Ahora, ella toma en consideración sólo los valores del indicador que tienen el potencial común (positivos o negativos).

    //+-- Búsqueda de los extremos --------------------------------------------+
    int Extremum(double a,double b,double c)
     {
     if(((a-b)*(b-c)<0) && ((a>0 && b>0 && c>0) || (a<0 && b<0 && c<0)))
     {
     if(c>b && b<0) return(1); //DN экстремум
     if(c<b && b>0) return(-1);//UP экстремум
     }
     return(0);
     }
    //+------
    

    Para determinar el valor de la línea en una determinada coordenada temporal, usaremos la función estándar ObjectGetValueByTime. Va a usarse varias veces. Por motivos de conveniencia, será añadida separadamente.

    //+----------------------------------------------------------------------------+
    //|Devuelve el valor del precio para la hora especificada del objeto indicado  |
    //+----------------------------------------------------------------------------+
    double CSampleExpert::ValueByTime(string label,int i)
     {
     double p=0.0;
    //---
     p=ObjectGetValueByTime(0,label,time[i],0);
     return(p);
     }
    //+------------------------------------------------------------------+
    

    Como ya hemos dicho, no vamos a tener ningunos filtros especiales. Nuestro objetivo no consiste en la creación de un EA completamente funcional: sólo queremos evaluar si la estrategia tiene derecho a la existencia. Por esa razón, nuestro módulo de señales será bastante simple. Nosotros sólo determinamos si nuestra línea está rota en la dirección necesaria, y a dónde se mueve el precio (indicador) en este momento.

    //+------------------------------------------------------------------+
    //| Comprobar las condiciones de la apertura de una posición corta   |
    //+------------------------------------------------------------------+
    bool CSampleExpert::ShortOpened(void)
     {
     bool res=false;
    //---
     double pp1=EMPTY_VALUE,pp2=EMPTY_VALUE,pp3=EMPTY_VALUE,
     pp4=EMPTY_VALUE,pp5=EMPTY_VALUE,pp6=EMPTY_VALUE;
    //---
     if(ObjectFind(0,"Sell_2")!=-1)
     {
     pp1=ValueByTime("Sell_2",1);
     pp2=ValueByTime("Sell_2",2);
     pp3=ValueByTime("Sell_2",3);
     }
     if(ObjectFind(0,"Sell_1")!=-1)
     {
     pp4=ValueByTime("Sell_1",1);
     pp5=ValueByTime("Sell_1",2);
     pp6=ValueByTime("Sell_1",3);
     }
    //--- Comprobar las posibilidades de la posición corta (SELL) 
     if((pp1!=EMPTY_VALUE && close[1]<pp1 && close[2]>pp2&&close[0]<close[1])||
     (pp4!=EMPTY_VALUE && m_ind_1>m_ind_0 && ((m_ind_1<pp4 && m_ind_2>pp5) ||(m_ind_2<pp5 && m_ind_3>pp6))))
     {
     //--- En cualquier caso, tenemos que salir del EA
     res=true;
     }
    //--- Resultado
     return(res);
     }
    //+------------------------------------------------------------------+
    
    

    Arriba se muestra la variante de la entrada en las posiciones cortas. El bloque de la entrada en las posiciones largas es similar.

    Después recibir la señal (nuestra línea está rota), colocamos la orden correspondiente a la distancia InpOffset desde el extremo de la vela, que ha sido el máximo o el mínimo cerca de la vela de ruptura. Si esta misma vela es de ruptura, la orden se coloca directamente en ella. 

    //+------------------------------------------------------------------+
    //| Abrir la posición sellstop                                       |
    //+------------------------------------------------------------------+
    bool CSampleExpert::OpenSellStop(void)
     {
     bool res=false;
    //--- Buscamos bar con el low mínimo entre las velas cercanas
     int i=ArrayMinimum(low,0,3);
    //---
     if(ShortOpened())
     {
     double offset=InpOffset;                          // Distancia desde low de la vela para colocar la orden, en puntos
     double limit_price=m_symbol.Bid();
     double price=low[i]-offset*m_adjusted_point;;
     double tp =price-m_take_profit;
     double sl =price+m_stop_losse;
     //--- Comprobar la presencia de fondos en el balance de la cuenta
     if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_SELL_STOP,InpLots,price)<0.0)
     printf("No tenemos dinero. Margen libre = %f",m_account.FreeMargin());
     else
     {
     //--- Abrimos la posición
     if(m_trade.OrderOpen(Symbol(),ORDER_TYPE_SELL_STOP,InpLots,limit_price,price,sl,tp))
     {res=true; printf("Position by %s to be opened",Symbol());}
     else
     {
     printf("Error de la apertura de la posición SELL STOP %s : '%s'",Symbol(),m_trade.ResultComment());
     printf("Abrir parámetros: precio=%f,TP=%f",price,tp);
     }
     }
     }
    //--- Resultado
     return(res);
     }
    //+------------------------------------------------------------------+
    

    Si nuestra orden no se ha activado y el precio se ha alejado de ella a la distancia que supera InpDellOorder, la eliminamos.

    //+------------------------------------------------------------------+
    //| Eliminamos las órdenes innecesarias                              |
    //+------------------------------------------------------------------+
    bool CSampleExpert::DelOrder(ulong ticket,string type)
     {
     bool res=false;
     if(m_trade.OrderDelete(ticket))
     printf("Position by %s to be opened",Symbol());
     else
     {
     res=true;// Establecemos la bandera que indica que la orden no ha sido eliminada
     printf("Fallo al eliminar la orden"+type+" %s : '%s'",Symbol(),m_trade.ResultComment());
     }
     return(res);
     }
    //+------------------------------------------------------------------+
    

    Volvamos a nuestro objetivo principal, es decir, a la evaluación de la estrategia. La dificultad de la evaluación de las estrategias que trabajan con las construcciones gráficas en el Probador de Estrategias consiste en el hecho de que eso es posible únicamente en el modo de la visualización. No puede tratarse de ninguna optimización en modo automático. Este proceso es sumamente complicado y requiere mucho tiempo. Por eso, iniciaremos el EA en GBPUSDH1, partiendo desde el principio de 2017. Usamos los ajustes predefinidos.

    Obtenemos el siguiente resultado:




    Es difícil llamar este método de evaluación completamente objetivo. No obstante, el resultado obtenido da a entender que la estrategia tiene potencia. En el futuro, después de las mejoras realizadas, ella puede ocupar su lugar entre otras estrategias. 


    Conclusión

    Aunque el enfoque descrito nos ha permitido crear una estrategia bastante viable, tampoco excluye la aplicación de otras herramientas dentro de ella. Entre las desventajas de esta estrategia se puede mencionar una incorrecta construcción de las líneas de indicador que ocurre a veces ocasionalmente, y la necesidad de corregirlas manualmente. Eso hace difícil automatizar la estratgia, y por consecuencia, analizarla. Sin embargo, vemos que no sólo los modelos clásicos tienen derecho a la existencia.

    Programas usados en el artículo:

    #NombreTipo Descripción 
    1Accelerator_DivIndicador

    El indicador que determina la divergencia/convergencia explícita u oculta a base del indicador Accelerator

    2TestExpertAsesor Experto

    Asesor Experto para probar la estrategia