Inicio Indicador técnico Publicación

Visualiza la Tendencia Actual en Todos los Marcos de Tiempo con un Panel Simple - Indicador para MetaTrader 4

Archivos adjuntos
15620.zip (2.17 KB, Descargar 0 veces)

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.

SlopeDirection 

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

Comentarios (0)