
Indicador de líneas de tendencia según el enfoque de T. Demark
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





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso