Hoy te traigo un indicador gráfico basado en la dirección de la tendencia que ha tenido varias versiones publicadas, pero ninguna que muestre todos los marcos de tiempo en un solo panel gráfico en tu pantalla.
Si quieres ver diferentes resultados, puedes buscar aquí.
He tomado este indicador y lo he transformado en un panel gráfico que muestra todos los marcos de tiempo, además de realizar algunas modificaciones al código original. Una de las mejoras es que permite al usuario seleccionar el método de la segunda media móvil utilizada para suavizar. El código original usaba una media ponderada lineal en su segundo pase, mientras que ahora le doy la opción al usuario de elegir el método de suavizado. Si usamos la media ponderada para ambos cálculos, el indicador puede ser demasiado sensible y dar lecturas erróneas sobre la tendencia actual. En cambio, si utilizamos la media simple como segundo método de promedio, obtenemos una tendencia que es más indicativa de hacia dónde se dirige el precio.
Otra modificación que he realizado es que ahora no solo podemos obtener la dirección de la tendencia (ascendente, descendente o plana), sino también su valor. En otro artículo que planeo publicar pronto, hablaré sobre cómo utilizar un indicador de Doble SlopeDirection y crear un Sistema de Trading con él.
Ahora, echemos un vistazo rápido al código. Primero, defino todos los nombres de los objetos que voy a utilizar. Esto es una buena práctica, ya que cada vez que pones un nombre de objeto entre comillas, se asigna espacio en el programa. Si los defines una sola vez (usando una declaración de definición), solo utilizas espacio en tu código una vez.
// Definir direcciones de tendencia #define UPTREND 1 #define DOWNTREND -1 #define FLATTREND 0 // Definir Objetos #define TrendPanel "TrendPanel" #define InfoLine1 "InfoLine1" #define InfoLine2 "InfoLine2" #define TrendLabel "Tendencia: M1 M5 M15 M30 H1 H4 D1 W1 MN" #define TrendUp "\233" #define TrendDown "\234" #define TrendFlat "\232" #define TrendUnknown "\251" #define StatObjectError "%s(%d) No se pudo crear '%s'. Error = %d"
Luego, defino dos arreglos. Uno con la posición en píxeles para cada uno de los 9 marcos de tiempo y el segundo con los marcos de tiempo. Estos se definen como variables globales.
// Definir variables globales int TrendPosition[] = { 44, 64, 88, 114, 136, 156, 174, 194, 216 }; int TrendPeriods[] = { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1 };
Nuestra función OnInit() del indicador llama a una función para crear el panel y los objetos dentro de él. También hace una rápida verificación sobre las barras utilizadas para calcular la tendencia. Menos de 3 es un poco inútil.
//+------------------------------------------------------------------+ //| Función de inicialización del indicador personalizado | //+------------------------------------------------------------------+ int OnInit() { // Crear objetos para el panel del indicador if(Create_Panel() && BarCount >= 3) return(INIT_SUCCEEDED); else return(INIT_FAILED); }
No voy a entrar en detalles sobre cómo funciona realmente la función GetTrend(), ya que ya hay buena documentación en este sitio para eso. Solo echaremos un vistazo a la función gráfica DisplayTrend().
//+------------------------------------------------------------------+ //| Mostrar la tendencia actual para todos los marcos de tiempo //+------------------------------------------------------------------+ void DisplayTrend(void) { int i, cntr, Trend, LastTrend; string str; for(i=1; i<10; i++) { str = "Tendencia" + DoubleToStr(i, 0); Trend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method); if(Trend == FLATTREND) { // Estoy plano, encontrar la última dirección de tendencia cntr = 1; do { LastTrend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method, false, cntr++); } while(LastTrend == Trend); ObjectSetText(str, TrendFlat, 8, "WingDings", (LastTrend == UPTREND ? Green : Red)); ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 6); } else { ObjectSetText(str, (Trend == UPTREND ? TrendUp : TrendDown), 8, "WingDings", (Trend == UPTREND ? Green : Red)); ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 5 + (Trend == UPTREND ? 1 : -1)); } } }
Básicamente, simplemente recorremos el arreglo TrendPeriods[] (para obtener todos los marcos de tiempo) y establecemos la flecha de tendencia de acuerdo con la dirección de la tendencia de ese marco de tiempo. Si la tendencia es plana, encontramos la primera dirección que no es plana para saber de dónde venía la tendencia y así poder mostrar la flecha lateral en el color de esa dirección.
La función Create_Panel() en nuestro OnInit() crea los objetos anclados a la parte inferior izquierda de la pantalla y utiliza TrendPosition[] para colocar las flechas en el lugar correcto.
//+------------------------------------------------------------------+ //| Crear el panel de tendencia en la esquina inferior izquierda de la pantalla //+------------------------------------------------------------------+ bool Create_Panel(void) { int i; string str; // Crear la ventana del indicador de tendencia if(ObjectCreate(TrendPanel, OBJ_RECTANGLE_LABEL, 0, 0, 0)) { ObjectSetInteger(0, TrendPanel, OBJPROP_XDISTANCE, 1); ObjectSetInteger(0, TrendPanel, OBJPROP_YDISTANCE, 29); ObjectSetInteger(0, TrendPanel, OBJPROP_XSIZE, 240); ObjectSetInteger(0, TrendPanel, OBJPROP_YSIZE, 26); ObjectSetInteger(0, TrendPanel, OBJPROP_BGCOLOR, White); ObjectSetInteger(0, TrendPanel, OBJPROP_BORDER_TYPE, 0); ObjectSetInteger(0, TrendPanel, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSetInteger(0, TrendPanel, OBJPROP_COLOR, Red); ObjectSetInteger(0, TrendPanel, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, TrendPanel, OBJPROP_WIDTH, 2); ObjectSetInteger(0, TrendPanel, OBJPROP_BACK, false); ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTED, false); ObjectSetInteger(0, TrendPanel, OBJPROP_HIDDEN, true); ObjectSetString(0, TrendPanel, OBJPROP_TOOLTIP, "\n"); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, TrendPanel, GetLastError()); return(false); } if(ObjectCreate(InfoLine1, OBJ_LABEL, 0, 0, 0)) { ObjectSet(InfoLine1, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(InfoLine1, OBJPROP_XDISTANCE, 6); ObjectSet(InfoLine1, OBJPROP_YDISTANCE, 15); ObjectSetInteger(0, InfoLine1, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, InfoLine1, OBJPROP_HIDDEN, true); ObjectSetString(0, InfoLine1, OBJPROP_TOOLTIP, "\n"); ObjectSetText(InfoLine1, TrendLabel, 8, "Arial", Black); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine1, GetLastError()); return(false); } if(ObjectCreate(InfoLine2, OBJ_LABEL, 0, 0, 0)) { ObjectSet(InfoLine2, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(InfoLine2, OBJPROP_XDISTANCE, 6); ObjectSet(InfoLine2, OBJPROP_YDISTANCE, 5); ObjectSetInteger(0, InfoLine2, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, InfoLine2, OBJPROP_HIDDEN, true); ObjectSetString(0, InfoLine2, OBJPROP_TOOLTIP, "\n"); ObjectSetText(InfoLine2, " " + DoubleToStr(BarCount, 0) + " / " + DoubleToStr(Method, 0), 8, "Arial", Black); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine2, GetLastError()); return(false); } // Crear objeto de tendencia y mostrar la tendencia actual for(i=1; i<10; i++) { str = "Tendencia" + DoubleToStr(i, 0); if(ObjectCreate(str, OBJ_LABEL, 0, 0, 0)) { ObjectSet(str, OBJPROP_CORNER, CORNER_LEFT_LOWER); ObjectSet(str, OBJPROP_XDISTANCE, TrendPosition[i-1]); ObjectSet(str, OBJPROP_YDISTANCE, 5); ObjectSetInteger(0, str, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, str, OBJPROP_HIDDEN, true); ObjectSetString(0, str, OBJPROP_TOOLTIP, "\n"); } else { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, str, GetLastError()); return(false); } } // Ir a mostrar la tendencia actual DisplayTrend(); // Todo bien return(true); }
Esta función devolverá TRUE si se logra crear todos los objetos, o devolverá FALSE si ocurrió un error al crear un objeto. Lo bueno es que el indicador mostrará en la pestaña EXPERT de tu consola el código de error y el número de línea donde ocurrió el error.
También necesitamos actualizar el indicador de tendencia para cada nuevo tick que recibimos. Esto se hace llamando a DisplayTrend() en nuestra función start().
//+------------------------------------------------------------------+ //| Función de iteración del indicador personalizado | //+------------------------------------------------------------------+ int start() { // Mostrar tendencia actual para todos los marcos de tiempo DisplayTrend(); return(0); }
Por último, destruimos todos los objetos creados por el indicador cuando cerramos el indicador.
//+------------------------------------------------------------------+ //| Función de desinicialización | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Eliminar objetos del indicador if(ObjectFind(TrendPanel) >= 0) ObjectDelete(TrendPanel); if(ObjectFind(InfoLine1) >= 0) ObjectDelete(InfoLine1); if(ObjectFind(InfoLine2) >= 0) ObjectDelete(InfoLine2); for(int i=1; i<10; i++) if(ObjectFind("Tendencia"+DoubleToStr(i, 0)) >= 0) ObjectDelete("Tendencia"+DoubleToStr(i, 0)); }
Eso es todo. Ahora tienes un panel de indicador que muestra la tendencia actual para todos los marcos de tiempo en la parte inferior izquierda de tu pantalla.
¡Disfrútalo!
Publicaciones relacionadas
- MetaCOT 2 CFTC ToolBox: Herramientas Esenciales para Análisis en MT4
- Oscilador Estocástico con Reducción de Ruido para MetaTrader 4
- iMFISignAlert: Un Indicador Esencial para MetaTrader 5
- iStochKomposterAlert: El Indicador de Señales para MetaTrader 5 con Alertas
- iDeMarkerSignAlert: Tu nuevo indicador para MetaTrader 5