TendenciaPrecioFecha

AutoFindBestTrendLine — Detector Automático de Líneas de Tendencia

Descripción general: AutoFindBestTrendLine es una utilidad para MetaTrader 5 que analiza el historial del gráfico y detecta automáticamente la mejor línea de tendencia posible, ya sea de máximos (resistencias), mínimos (soportes) o ambos. El script identifica los dos puntos más relevantes y dibuja una línea óptima basada en el número de toques reales sobre el precio.

Ventajas principales:

  • Detección automática de líneas de tendencia sin intervención manual.

  • Funciona en cualquier símbolo y período.

  • Permite elegir entre análisis de máximos, mínimos o ambos.

  • Traza líneas con color, estilo y grosor configurables.

  • No elimina líneas anteriores: cada ejecución crea una nueva.

  • Ligero, rápido y sin consumo continuo de recursos (es un script).

  • Ideal para traders técnicos que buscan soportes y resistencias reales.

Cómo funciona: El script analiza todas las velas desde la fecha indicada y evalúa combinaciones de puntos para encontrar la línea con mayor número de toques. Una vez detectada, la dibuja automáticamente en el gráfico y muestra información detallada en el registro.

Parámetros de entrada:

  • InpStartDate — Fecha de inicio del análisis.

  • InpSearchMode — Tipo de búsqueda: Máximos, Mínimos o Ambos.

  • InpLineColor — Color de la línea de tendencia.

  • InpLineStyle — Estilo de línea (sólida, rayas, puntos).

  • InpLineWidth — Grosor de la línea (1 a 5).

Uso recomendado: Ejecute el script en cualquier gráfico para obtener una línea de tendencia óptima basada en el comportamiento real del precio. Útil para validar zonas de soporte/resistencia, detectar estructuras técnicas y complementar análisis manual.       //+------------------------------------------------------------------+

//|                                    AutoFindBestTrendLine.mq5     |

//|                                  Copyright 2026                  |

//|                                                                  |

//+------------------------------------------------------------------+

#property copyright "Copyright 2026"

#property link      ""

#property version   "1.31"

#property script_show_inputs


// Enumeración para elegir qué tipo de puntos analizar

enum ENUM_SEARCH_MODE

{

   SEARCH_BOTH = 0,       // Analizar Máximos y Mínimos

   SEARCH_HIGHS_ONLY = 1, // Solo Máximos (Resistencias)

   SEARCH_LOWS_ONLY = 2   // Solo Soportes (Mínimos)

};


// Parámetros de entrada configurables

input datetime        InpStartDate   = D'2026.01.01 00:00'; // Fecha de inicio del análisis

input ENUM_SEARCH_MODE InpSearchMode = SEARCH_BOTH;         // Modo de búsqueda

input color           InpLineColor   = clrDodgerBlue;       // Color de la línea de tendencia

input ENUM_LINE_STYLE InpLineStyle   = STYLE_SOLID;         // Estilo de línea (Sólida, Rayas, Puntos...)

input int             InpLineWidth   = 3;                   // Grosor de la línea (1 a 5)


//+------------------------------------------------------------------+

//| Script program start function                                    |

//+------------------------------------------------------------------+

void OnStart()

{

   // 1. Copiar datos de las barras del gráfico actual

   MqlRates rates[];

   ArraySetAsSeries(rates, true);

   int totalBars = CopyRates(_Symbol, _Period, 0, Bars(_Symbol, _Period), rates);

   

   if(totalBars < 5)

   {

      Print("Error: No hay suficientes barras en el gráfico para analizar.");

      return;

   }

   

   // Encontrar el índice de la barra que corresponde a la fecha de inicio seleccionada

   int startIndex = -1;

   for(int i = 0; i < totalBars; i++)

   {

      if(rates[i].time <= InpStartDate)

      {

         startIndex = i;

         break;

      }

   }

   

   if(startIndex < 0)

   {

      startIndex = totalBars - 1; // Si la fecha es más antigua que el historial, usa la más antigua disponible

   }

   

   Print("==================================================");

   Print(" INICIANDO BARRIDO AUTOMÁTICO");

   Print(" Desde: ", TimeToString(rates[startIndex].time, TIME_DATE|TIME_MINUTES), " | Velas analizadas: ", startIndex + 1);

   Print("==================================================");

   

   int bestTouches = -1;

   datetime bestT1 = 0, bestT2 = 0;

   double   bestP1 = 0.0, bestP2 = 0.0;

   string   lineTypeFound = "";

   

   // 2. Evaluar combinaciones según el modo seleccionado (ajustado para admitir gráficos cortos)

   int minLimit = MathMin(2, startIndex);

   for(int i = startIndex; i >= minLimit; i--)

   {

      for(int j = i - 1; j >= 0; j--)

      {

         datetime t1 = rates[i].time;

         datetime t2 = rates[j].time;

         if(t1 == t2) continue;

         

         // Evaluar Máximos

         if(InpSearchMode == SEARCH_BOTH || InpSearchMode == SEARCH_HIGHS_ONLY)

         {

            double p1 = rates[i].high;

            double p2 = rates[j].high;

            int touches = CountLineTouches(p1, t1, p2, t2, rates, startIndex);

            

            if(touches > bestTouches)

            {

               bestTouches = touches;

               bestT1 = t1; bestP1 = p1;

               bestT2 = t2; bestP2 = p2;

               lineTypeFound = "Resistencia (High-High)";

            }

         }

         

         // Evaluar Mínimos

         if(InpSearchMode == SEARCH_BOTH || InpSearchMode == SEARCH_LOWS_ONLY)

         {

            double p1 = rates[i].low;

            double p2 = rates[j].low;

            int touches = CountLineTouches(p1, t1, p2, t2, rates, startIndex);

            

            if(touches > bestTouches)

            {

               bestTouches = touches;

               bestT1 = t1; bestP1 = p1;

               bestT2 = t2; bestP2 = p2;

               lineTypeFound = "Soporte (Low-Low)";

            }

         }

      }

   }

   

   if(bestTouches <= 0)

   {

      Print("Aviso: No se pudo trazar ninguna línea. Prueba a poner una fecha de inicio más reciente (ej. hace pocos días) en los ajustes del script.");

      return;

   }

   

   // 3. Crear un nombre ÚNICO para que no borre las líneas anteriores

   string lineName = StringFormat("AutoTrend_%d", GetTickCount());

   

   if(ObjectCreate(0, lineName, OBJ_TREND, 0, bestT1, bestP1, bestT2, bestP2))

   {

      // Configurar diseño, rayos y permitir modificarla con el ratón

      ObjectSetInteger(0, lineName, OBJPROP_RAY_LEFT, true);

      ObjectSetInteger(0, lineName, OBJPROP_RAY_RIGHT, true);

      ObjectSetInteger(0, lineName, OBJPROP_COLOR, InpLineColor);

      ObjectSetInteger(0, lineName, OBJPROP_STYLE, InpLineStyle);

      ObjectSetInteger(0, lineName, OBJPROP_WIDTH, InpLineWidth);

      ObjectSetInteger(0, lineName, OBJPROP_SELECTABLE, true);

      ObjectSetInteger(0, lineName, OBJPROP_HIDDEN, false);

      

      ChartRedraw(0);

   }

   

   // 4. Mostrar información detallada en el registro (log)

   Print("==================================================");

   Print(" TENDENCIA ÓPTIMA ENCONTRADA Y GRAFICADA:");

   Print(" Nombre del objeto : ", lineName);

   Print(" Tipo detectado    : ", lineTypeFound);

   Print(" [COPIAR] Punto 1  -> Tiempo: ", TimeToString(bestT1, TIME_DATE|TIME_MINUTES), " | Precio: ", DoubleToString(bestP1, _Digits));

   Print(" [COPIAR] Punto 2  -> Tiempo: ", TimeToString(bestT2, TIME_DATE|TIME_MINUTES), " | Precio: ", DoubleToString(bestP2, _Digits));

   Print(" Velas tocadas     : ", bestTouches);

   Print("==================================================");

}


// Función auxiliar para contar los toques

int CountLineTouches(double p1, datetime t1, double p2, datetime t2, const MqlRates &rates[], int limitIndex)

{

   int touches = 0;

   double slope = (double)(p2 - p1) / (double)(t2 - t1);

   

   for(int k = limitIndex; k >= 0; k--)

   {

      datetime barTime = rates[k].time;

      double linePrice = p1 + (double)(barTime - t1) * slope;

      

      if(linePrice >= rates[k].low && linePrice <= rates[k].high)

      {

         touches++;

      }

   }

   return touches;

}


Filtro:
No hay comentarios
Respuesta al comentario