TendenciaPrecioFecha
- Utilities
- Version: 1.31
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;
}
