English Русский 中文 Deutsch 日本語 Português
Indicador de líneas de tendencia según el enfoque de T. Demark

Indicador de líneas de tendencia según el enfoque de T. Demark

MetaTrader 4Ejemplos | 16 noviembre 2015, 10:01
2 163 0
Genkov
Genkov

Introducción

La lucha entre los compradores ("osos") y los vendedores ("toros") se pone de manifiesto por medio de las líneas de tendencia. Thomas Demark desarrolló unos métodos para elegir de forma objetiva dos puntos de la línea TD de la tendencia (aquí puede encontrar información detallada sobre la estrategia de análisis técnico de T. Demark).

Según T. Demark, lo más importante para un trader es el estado actual del mercado. En consecuencia, en el indicador que sugiere, la dirección de la tendencia actual se dibuja con una línea sólida gruesa. Analizando pues el estado del mercado se puede conocer la dirección de la tendencia inmediatamente anterior, que se dibuja con una línea de puntos fina.


Características del código MQL4 del indicador sugerido


Se utilizan cuatro búferes. Dos son para el código de las flechas de dirección de las líneas, y los otros dos son para el alargamiento del la línea TD hacia la izquierda.

Los búferes del indicador pintan de color "aqua" las primeras diez barras (a la izquierda del segundo punto TD).

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Chartreuse
#property indicator_color2 Tomato
#property indicator_color3 Aqua
#property indicator_color4 Aqua
 
// ----- búferes del indicador
double   TrendUpBuffer[];
double   TrendDownBuffer[];
double   TrendLineBufferUp[];
double   TrendLineBufferDown[];

Inicializar las funciones de cálculo y visualización del indicador.

int init()
  {
//---- indicadores
   SetIndexStyle(0,DRAW_ARROW);        // tipo y estilo de la línea del indicador
   SetIndexArrow(0,236);               // icono de la línea del indicador
   SetIndexBuffer(0,TrendUpBuffer);    // declaración del array unidimensional
   SetIndexEmptyValue(0,0.0);          // tamaño del valor vacío del indicador
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,238);
   SetIndexBuffer(1,TrendDownBuffer);
   SetIndexEmptyValue(1,0.0);
   SetIndexStyle(2,DRAW_LINE);         
   SetIndexBuffer(2,TrendLineBufferUp);    // línea creciente
   SetIndexEmptyValue(2,0.0);           
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,TrendLineBufferDown);  // línea decreciente
   SetIndexEmptyValue(3,0.0);
//----
   return(0);

La desinicialización se puede dejar vacía por defecto.

int deinit()
  {
  //  DelObj1();  
  //  DelObj2();
  return(0);
  }

Crear la función que elimina el objeto con el nombre especificado.

  void DelObj1()
  {
  ObjectDelete("TrDdown"); // Borrar el objeto con el nombre especificado. 
  }
  void DelObj2()
  {
  ObjectDelete("TrDup");
  }

Por conveniencia, buscaremos los puntos de comprobación en ciclos separados por picos y valles. Comenzamos la búsqueda en la barra 2; tenemos que compararla con la barra derecha (no cero) para confirmar la veracidad de la línea de tendencia.

Comprobemos pues la condición #1 (el precio de la barra Max debe ser mayor que los precios de las barras derecha e izquierda).

   for(int i=2;i<48;i++) // 48 horas - 2 días  // i es el índice de la barra a comprobar
    {
     if(High[i]>High[i+1]&&High[i]>High[i-1]) 
      {

Comprobemos ahora la condición #2 (el precio máximo tiene que ser mayor que el precio de cierre de i+2).

Si se cumplen las condiciones #1 y #2, incrementamos el contador de coincidencias.

      if(High[i]>Close[i+2])  
       { 
        U++; // contador de coincidencias de las condiciones 1 y 2
        if(U==1)
         {

A continuación calculamos los siguientes valores:

         // El precio del primer punto de comprobación cuando se cumplen las condiciones #1 y #2
         TD_up[1]=High[i];  
         index_up_1=i;                               // índice del primer punto de comprobación
         Pr_up_Cl_1=Close[i-1]; // el precio de cierre de la barra siguiente al punto de comprobación
         time_up_1=iTime(NULL,0,index_up_1);          // la hora del primer punto de comprobación

Aquí podemos insertar este código de verificación para controlar el programa en ejecución:

         // de este modo controlamos el procesamiento de las operaciones
         Time_up_1=TimeToStr(time_up_1,TIME_DATE|TIME_MINUTES); 
         Print("  Precio del primer punto de comprobación = ",TD_up[1],"  ;  index = ",
               index_up_1,"  time = ",Time_up_1);

Como el contador se ha disparado una vez, descubrimos el segundo punto en las iteraciones siguientes.

          }  
          if(U==2)
           { 
           // El precio del segundo punto de comprobación cuando se cumplen las condiciones #1 y #2
           TD_up[2]=High[i]; 
           index_up_2=i;            // el índice del segundo punto de comprobación
           time_up_2=iTime(NULL,0,index_up_2);// la hora del segundo punto de comprobación

Aquí podemos insertar este código de verificación para controlar el programa en ejecución:

           Time_up_2=TimeToStr(time_up_2,TIME_DATE|TIME_MINUTES); 
           Print("  Precio del segundo punto de comprobación = ",TD_up[2],"  ;  index = ",
                 index_up_2,"  time = ",Time_up_2);

Ahora que tenemos dos puntos de comprobación TD podemos comprobar la condición de tendencia bajista; es decir, el precio del primer punto de comprobación tiene que ser menor que el del segundo.

           // condición de tendencia bajista (el punto TD derecho debe ser menor que el izquierdo)
           if((U==2 && TD_up[1]<TD_up[2])==false) 
             {  
              Print(" Las condiciones de tendencia bajista no se cumplen "); 
              U--; TD_up[2]=0.0; index_up_2=0; time_up_2=0;  continue; 
              }

Si la condición no se cumple disminuimos el contador en uno, y asignamos cero a los valores del precio, el índice y la hora, y repetimos de nuevo el ciclo en búsqueda de un segundo punto de comprobación. Si la condición se satisface, calculamos la velocidad de caída de la línea TD.

            else
             { 
              Print(" Se satisfacen las condiciones de tendencia bajista ");
              // cálculo de la velocidad de caída de TD_max
              V_up=(TD_up[2]-TD_up[1])/(index_up_2-index_up_1);// velocidad (pips/barra)
              // el valor calculado de TD-line en las primeras barras
              Pr_Tr_up_1=TD_up[1]-V_up;
              // si restamos el producto de la velocidad de la línea TD
              // del precio del primer punto de comprobación, obtendremos el precio de 
              Pr_Tr_up_0=TD_up[1]-(index_up_1*V_up);           // tendencia bajista en la barra "0"

Comprobemos ahora la condición #3 (para el último precio máximo, el precio de cierre de la siguiente barra a la derecha debe ser menor que el valor calculado de la velocidad de caída de la línea TD). Con esta condición se satisface la tendencia bajista.

              // comprobación de la condición #3 (para el último precio máximo,
              // el precio de cierre de la siguiente barra a la derecha debe ser menor
              // que el valor calculado de la velocidad de caída de la línea TD)
              if((Pr_up_Cl_1< Pr_Tr_up_1)==false)
               {
                Print(" Las condiciones de tendencia bajista no se cumplen");
                i=index_up_1+2; TD_up[1]=0.0; TD_up[2]=0.0; time_up_1=0; 
                time_up_2=0; index_up_1=50; index_up_2=50; U=0; continue;
                }

Si la condición #3 de tendencia bajista no se cumple, entonces comenzamos de nuevo la búsqueda de puntos Td. Para ello, debemos establecer a cero los valores de las variables obtenidas anteriormente, y comenzar la búsqueda en la barra situada dos barras a la izquierda del primer valor encontrado del primer punto de comprobación.


Si la condición se cumple, memorizamos los valores de las variables calculadas para dibujar la línea de tendencia.

             else
               { // si se cumple la condición #3, la tendencia existe
               Print("  Se satisfacen las condiciones de tendencia bajista ");
               // memorizamos los valores de las variables para dibujar la línea de tendencia
                TDu1=TD_up[1];  // precio del primer punto
                T_u1=time_up_1; // hora del primer punto
                TDu2=TD_up[2];  // precio del segundo punto
                T_u2=time_up_2; // precio del segundo punto
                TrendDownBuffer[index_up_1]=TDu1+5*Point;// poner la flecha hacia abajo

Ahora vamos a llenar el búfer con 10 valores de la línea de tendencia, a la izquierda del segundo punto de comprobación:

                // precios de 10 barras de la línea de tendencia a la izquierda del punto TD
                for(int k=index_up_2;k<index_up_2+10;k++) 
                TrendLineBufferDown[k]=Pr_Tr_up_0+k*V_up;
                Print("  salimos del ciclo de búsqueda porque se han encontrado 2 puntos TD");   
                break;      
                }

Insertar las llaves que faltan.

               } 
              } 
             }  
            } 
//==================================================================================+

Si se cumple la condición, la línea de tendencia se trazará 10 barras a la izquierda del segundo punto de comprobación. Esta línea se va a dibujar a la derecha con la función ObjectCreate(). Con este objetivo, al final del programa hay un bloque que dibuja líneas de tendencia.

En dicho bloque, los dos primeros operadores controlan el grosor de la línea TD (STYLE_SOLID), habiendo en esta fase solo una línea de tendencia. Dibujamos la línea descendente y salimos del ciclo de búsqueda de picos para puntos TD, borrando la línea anterior.

Con el razonamiento descrito escribimos el código de la línea creciente.

//==================================================================================+
   // puntos mínimos   
   for(int j=2;j<48;j++) // 48 horas - 2 días  // j es el índice de la barra a comprobar
    { 
     // comprobemos la condición #1 (el precio de la barra debe ser menor que los precios de las barras izquierda y derecha) 
     if(Low[j]<Low[j+1]&&Low[j]<Low[j-1])
      {
       // comprobemos la condición #2 (el precio mínimo Low[j] debe ser menor que el
       // precio de cierre Close[j+2]
       if(Low[j]<Close[j+2])
        { 
         D++;  // contador de coincidencias de las condiciones primera y segunda
         if(D==1)
          { 
           TD_down[1]=Low[j]; 
           index_down_1=j;
           Pr_down_Cl_1=Close[j-1]; 
           time_down_1=iTime(NULL,0,j);
           
           Time_down_1=TimeToStr(time_down_1,TIME_DATE|TIME_MINUTES);            
           Print(" Precio D del primer punto de comprobación ",TD_down[1]," ; index ",index_down_1,
           " ; Cierre a la derecha ",Pr_down_Cl_1,"  ; ",Time_down_1);           
           } 
           if(D==2)
            { 
             TD_down[2]=Low[j]; 
             index_down_2=j; 
             time_down_2=iTime(NULL,0,j);
             
             Time_down_2=TimeToStr(time_down_2,TIME_DATE|TIME_MINUTES);
             Print(" Precio D del segundo punto de comprobación ",TD_down[2]," index ",index_down_2,
                   "  time ",Time_down_2);             
             // condición de tendencia alcista (el punto mínimo derecho debe ser superior al izquierdo)
             if((D==2 && TD_down[1]>TD_down[2])==false)
              {
                 Print(" Las condiciones de tendencia alcista no se satisfacen "); 
                 D--;   TD_down[2]=0.0;  continue; 
                 } 
                else 
            { 
             Print(" Las condiciones de tendencia alcista se satisfacen");            
             // cálculo de la velocidad de subida de TD_min
             V_down=(TD_down[1]-TD_down[2])/(index_down_2-index_down_1);
             // el valor calculado de la línea en la primera barra a la derecha de Min
             Pr_Tr_down_1=TD_down[1]+V_down;
             } 
             // comprobemos la condición #3 (para el último precio mínimo,
             // el precio de cierre de la siguiente barra debe ser mayor que el valor calculado de
             // la velocidad de subida de la línea TD).
             if((Pr_down_Cl_1> Pr_Tr_down_1)==false)
              {
                i=index_down_1+1; TD_down[1]=0.0; TD_down[2]=0.0; time_down_1=0; 
                time_down_2=0; index_down_1=50; index_down_2=50; D=0; continue;
                }
             else
              { // la condición #3 se cumple, la tendencia existe
               Print("  Las condiciones de tendencia alcista se cumplen ");
               TDd1=TD_down[1]; 
               T_d1=time_down_1; 
               TDd2=TD_down[2];  
               T_d2=time_down_2;
               // precio calculado de la línea de tendencia en la barra "0"
               Pr_Tr_down_0=TD_down[1]+(index_down_1*V_down); 
               TrendUpBuffer[index_down_1]=TDd2-2*Point; // poner la flecha hacia arriba
               // precios de 10 barras de la línea de tendencia a la derecha del segundo punto de comprobación
               for(int n=index_down_2;n<index_down_2+10;n++)
                TrendLineBufferUp[n]=Pr_Tr_down_0-n*V_down;
               Print("  Salimos del ciclo de búsqueda porque se han encontrado 2 puntos TD ");
               break;                   
               } 
              } 
             } 
            } 
           } 
          }
// ----------------------------------------------------------------------------+ 

El bloque encargado de dibujar las líneas de tendencia se desarrolla de tal modo que la línea TD más reciente se dibuja con una línea sólida en negrita (STYLE_SOLID), y la línea anterior en dirección opuesta, se pinta con una línea de puntos delgada (STYLE_DOT).

Puede ocurrir que la tendencia vaya en una dirección durante un período largo de tiempo. El segundo punto TD de la tendencia contraria no se encontrará, y los valores intermedios del precio, hora e índice se escribirán en las variables. Para hacer que estos valores intermedios no afecten al dibujo de la línea de tendencia, debemos insertar el filtro de condiciones de dibujo de línea. Por ejemplo, si no se encuentra la segunda línea TD, el valor del precio se establece a "0". Del mismo modo, se fijará el valor del índice del primer punto, y si este valor es menor que el del primer punto TD de la línea en dirección opuesta, entonces se puede dibujar con el otro estilo y color la última línea de tendencia con los parámetros verdaderos. Por este motivo se especifica el filtro de tiempo. Echemos un vistazo al archivo adjuntado.

// ----------------------------------------------------------------------------+
// dibujo de las líneas de tendencia a la derecha del segundo punto de comprobación
// ----------------------------------------------------------------------------+
    if(TDd2==0.0)   index_down_1=50;
    if(TDu2==0.0)   index_up_1=50;
     else
    {    
    Print("  TDd2 = ",TDd2,"   index_up_1 = ",index_up_1,"  >  index_down_1 = ",index_down_1);
     Print("  Dibujamos la descendente y salimos del ciclo de búsqueda de picos para los puntos TD");
       DelObj1(); // borramos la línea anterior
        ObjectCreate("TrDdown",OBJ_TREND,0,T_u2,TDu2,T_u1,TDu1); 
     if(index_up_1>index_down_1) 
      {           // dibujamos la dirección previa de la tendencia con:
       ObjectSet("TrDdown",OBJPROP_COLOR,Yellow);
       ObjectSet("TrDdown",OBJPROP_WIDTH,1);  // línea delgada
       ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_DOT);// línea punteada
       }
      else
       {                // la dirección de la tendencia actual se dibuja con:
        ObjectSet("TrDdown",OBJPROP_COLOR,Yellow);
        ObjectSet("TrDdown",OBJPROP_WIDTH,2);           // línea gruesa
        ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_SOLID); // línea sólida
       }
      }
// -----------------------------
 
     if(TDd2==0.0)   index_down_1=50;
      else
      {
    Print("  TDd1 = ",TDd1,"   index_up_1 = ",index_up_1,"  <  index_down_1 = ",index_down_1);
      Print("  Dibujamos la ascendente y salimos del ciclo de búsqueda de valles para los puntos TD");
        DelObj2(); // borramos la línea anterior
         ObjectCreate("TrDup",OBJ_TREND,0,T_d2,TDd2,T_d1,TDd1); 
       if(index_up_1<index_down_1)
        {   
 
         ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
         ObjectSet("TrDup",OBJPROP_WIDTH,1); 
        ObjectSet("TrDup",OBJPROP_STYLE,STYLE_DOT);
        }
         else
          {
          ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
          ObjectSet("TrDup",OBJPROP_WIDTH,2);  
          ObjectSet("TrDup",OBJPROP_STYLE,STYLE_SOLID);
          }
         }
// ----------------------------------------------------------------------------+
   return(0);
  }

Nota: casi todas las operaciones "Print(...)" sirven para controlar visualmente la ejecución del programa, de modo que pueden comentarse. Los operadores de tipo (TimeToStr()) tienen el mismo propósito.


Conclusión

Esperamos que el indicador presentado en este artículo sea de utilidad tanto para los traders principiantes como para los más experimentados. Puede utilizarse para analizar las órdenes ejecutadas, y también en situaciones reales.

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

Archivos adjuntos |
TL_by_Demark_v6.mq4 (13.44 KB)
Utilizando MetaTrader 4 en el análisis de patrones temporales Utilizando MetaTrader 4 en el análisis de patrones temporales
El análisis de patrones basados en el tiempo sirve para determinar cuál es el mejor momento para entrar en el mercado, o para saber si una operación determinada debe evitarse a toda costa. En este artículo utilizamos MetaTrader 4 para analizar el historial de datos, y generamos unos resultados de optimización que pueden resultar útiles en los sistemas de trading automáticos.
Probando Asesores Expertos en marcos temporales no estándar Probando Asesores Expertos en marcos temporales no estándar
No es fácil, es facilísimo. ¡Los Asesores Expertos se pueden probar en marcos de tiempo no estándar! Tan solo hay que sustituir los datos del marco temporal estándar por los del no estándar. Incluso podemos probar nuestros Asesores Expertos en varios marcos temporales no estándar.
Scalping Agradable Scalping Agradable
Este artículo describe un método para crear una herramienta de scalping. El enfoque de apertura de posiciones que presentaremos puede aplicarse a cualquier tipo de trading.
Dibujando niveles de ruptura horizontales utilizando fractales Dibujando niveles de ruptura horizontales utilizando fractales
Este artículo describe la creación de un indicador que muestra los niveles de soporte y resistencia por medio de fractales alcistas/bajistas.