ICTLibraryEasy/Examples/Benchmark/OtherCode/Code4.mq5

497 líneas
36 KiB
MQL5

2026-01-14 07:41:55 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| FVG_Detector.mq5 |
//| Expert Advisor para MT5 |
//| Detecci<EFBFBD>n y Visualizaci<EFBFBD>n de Fair Value Gaps|
//+------------------------------------------------------------------+
#property copyright "FVG Visual Detector"
#property link ""
#property version "1.00"
#property description "Expert Advisor exclusivo para detectar y dibujar Fair Value Gaps"
#property description "NO ejecuta trades - Solo an<00>lisis visual"
#property strict
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "..\\Utils\\MetricSaver.mqh"
/* Codigo hecho por ia Claude Sonnet 4.5
Promt:
Desarrolla un BOT (Expert Advisor) para MetaTrader 5 (MT5) que EXCLUSIVAMENTE detecte y dibuje Fair Value Gaps (FVG) en el gr<EFBFBD>fico.
<EFBFBD>&<EFBFBD> Este BOT NO debe ejecutar operaciones, NO debe abrir/cerrar trades y NO debe funcionar como indicador. Su <EFBFBD>nica funci<EFBFBD>n es an<EFBFBD>lisis visual mediante dibujo en el gr<EFBFBD>fico
. Requisitos t<EFBFBD>cnicos obligatorios: Implementado como Expert Advisor (EA) en MQL5. Detecci<EFBFBD>n y dibujo de FVG alcistas y bajistas.
Funcionamiento r<EFBFBD>pido, eficiente y altamente optimizado. Capaz de trabajar con datos hist<EFBFBD>ricos y en tiempo real.
Configuraci<EFBFBD>n personalizable desde el panel del BOT: Colores de los FVG. Opacidad / transparencia.
Grosor y estilo de los rect<EFBFBD>ngulos. Activar o desactivar FVG alcistas o bajistas. Timeframe de an<EFBFBD>lisis. Aspectos visuales:
Los FVG deben dibujarse como zonas (rect<EFBFBD>ngulos) claras y limpias. Evitar redibujados innecesarios. El BOT debe actualizar los FVG solo cuando sea necesario.
Buenas pr<EFBFBD>cticas de desarrollo: C<EFBFBD>digo limpio, modular y bien comentado. Uso eficiente de OnInit, OnTick y manejo de objetos gr<EFBFBD>ficos.
Optimizaci<EFBFBD>n de loops y c<EFBFBD>lculos para m<EFBFBD>nimo consumo de CPU.
Usa todo tu conocimiento avanzado en MQL5, optimizaci<EFBFBD>n y Smart Money Concepts para crear un BOT profesional, estable y r<EFBFBD>pido,
enfocado <EFBFBD>nicamente en dibujar Fair Value Gaps.
*/
//+------------------------------------------------------------------+
//| INPUTS - Configuraci<EFBFBD>n Personalizable |
//+------------------------------------------------------------------+
input group "===== CONFIGURACI<00>N GENERAL ====="
input bool InpEnableBullishFVG = true; // Activar FVG Alcistas
input bool InpEnableBearishFVG = true; // Activar FVG Bajistas
input int InpMaxBarsToAnalyze = 500; // M<EFBFBD>ximo de barras a analizar
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // Timeframe de an<EFBFBD>lisis
input group "===== CONFIGURACI<00>N VISUAL FVG ALCISTAS ====="
input color InpBullishColor = clrLimeGreen; // Color FVG Alcistas
input int InpBullishTransparency = 85; // Transparencia (0-100)
input ENUM_LINE_STYLE InpBullishBorderStyle = STYLE_SOLID; // Estilo de borde
input int InpBullishBorderWidth = 1; // Grosor de borde
input group "===== CONFIGURACI<00>N VISUAL FVG BAJISTAS ====="
input color InpBearishColor = clrTomato; // Color FVG Bajistas
input int InpBearishTransparency = 85; // Transparencia (0-100)
input ENUM_LINE_STYLE InpBearishBorderStyle = STYLE_SOLID; // Estilo de borde
input int InpBearishBorderWidth = 1; // Grosor de borde
input group "===== CONFIGURACI<00>N AVANZADA ====="
input bool InpDeleteFilledFVG = false; // Eliminar FVG cuando precio los llena
input double InpMinFVGSize = 5.0; // Tama<EFBFBD>o m<EFBFBD>nimo FVG en puntos
input bool InpExtendToRight = true; // Extender rect<EFBFBD>ngulos a la derecha
input int InpMaxFVGsToDisplay = 50; // M<EFBFBD>ximo de FVGs a mostrar
//+------------------------------------------------------------------+
//| Estructura para almacenar datos de FVG |
//+------------------------------------------------------------------+
struct FVGData
{
datetime time; // Tiempo de creaci<EFBFBD>n del FVG
double topPrice; // Precio superior del gap
double bottomPrice; // Precio inferior del gap
bool isBullish; // true = Alcista, false = Bajista
string objectName; // Nombre del objeto gr<EFBFBD>fico
bool isFilled; // Si el precio ha llenado el FVG
};
//+------------------------------------------------------------------+
//| Variables Globales |
//+------------------------------------------------------------------+
FVGData g_FVGList[]; // Array din<EFBFBD>mico para almacenar FVGs
int g_FVGCount = 0; // Contador de FVGs activos
string g_prefix = "FVG_"; // Prefijo para objetos gr<EFBFBD>ficos
int g_lastAnalyzedBar = -1; // <EFBFBD>ltima barra analizada
double g_point; // Valor del punto del s<EFBFBD>mbolo
int g_digits; // D<EFBFBD>gitos del s<EFBFBD>mbolo
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
CMetricsSave::Start(FILE_CODE4);
// Inicializar variables del s<EFBFBD>mbolo
g_point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
g_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
// Validar inputs
if(!ValidateInputs())
{
Print("L' Error: Configuraci<00>n inv<00>lida");
return(INIT_PARAMETERS_INCORRECT);
}
// Limpiar objetos gr<EFBFBD>ficos anteriores
CleanupOldObjects();
// Redimensionar array de FVGs
ArrayResize(g_FVGList, InpMaxFVGsToDisplay);
// An<EFBFBD>lisis inicial de barras hist<EFBFBD>ricas
AnalyzeHistoricalBars();
Print("' FVG Detector iniciado correctamente");
Print("=<3D><><EFBFBD> S<00>mbolo: ", _Symbol);
Print("<00>#<0F> Timeframe: ", EnumToString(InpTimeframe));
Print("=<3D> <EFBFBD> Analizando hasta ", InpMaxBarsToAnalyze, " barras");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Limpiar todos los objetos gr<EFBFBD>ficos creados
CleanupAllFVGObjects();
Print("=<3D><1A> FVG Detector detenido. Raz<00>n: ", GetDeinitReasonText(reason));
CMetricsSave::Destroy();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Obtener informaci<EFBFBD>n de la <EFBFBD>ltima barra
int bars = iBars(_Symbol, InpTimeframe);
if(bars < 3)
return; // Necesitamos al menos 3 barras
// Verificar si hay una nueva barra
if(g_lastAnalyzedBar != bars)
{
// Analizar nuevos FVGs
DetectNewFVGs();
// Actualizar estado de FVGs existentes (si est<EFBFBD>n llenos)
if(InpDeleteFilledFVG)
UpdateFVGStatus();
g_lastAnalyzedBar = bars;
}
}
//+------------------------------------------------------------------+
//| Validar par<EFBFBD>metros de entrada |
//+------------------------------------------------------------------+
bool ValidateInputs()
{
if(InpMaxBarsToAnalyze < 10 || InpMaxBarsToAnalyze > 5000)
{
Print("<00>&<0F> Advertencia: InpMaxBarsToAnalyze fuera de rango (10-5000)");
return false;
}
if(InpBullishTransparency < 0 || InpBullishTransparency > 100)
{
Print("<00>&<0F> Advertencia: Transparencia alcista fuera de rango (0-100)");
return false;
}
if(InpBearishTransparency < 0 || InpBearishTransparency > 100)
{
Print("<00>&<0F> Advertencia: Transparencia bajista fuera de rango (0-100)");
return false;
}
if(!InpEnableBullishFVG && !InpEnableBearishFVG)
{
Print("<00>&<0F> Advertencia: Debe activar al menos un tipo de FVG");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Analizar barras hist<EFBFBD>ricas |
//+------------------------------------------------------------------+
void AnalyzeHistoricalBars()
{
int barsToAnalyze = MathMin(InpMaxBarsToAnalyze, iBars(_Symbol, InpTimeframe) - 3);
Print("=<3D><04> Analizando ", barsToAnalyze, " barras hist<00>ricas...");
for(int i = barsToAnalyze; i >= 2; i--)
{
CheckForFVG(i);
}
Print("' An<00>lisis hist<00>rico completado. FVGs detectados: ", g_FVGCount);
}
//+------------------------------------------------------------------+
//| Detectar nuevos FVGs en tiempo real |
//+------------------------------------------------------------------+
void DetectNewFVGs()
{
// Analizar las <EFBFBD>ltimas 3 barras para nuevos FVGs
CheckForFVG(2);
CheckForFVG(1);
}
//+------------------------------------------------------------------+
//| Verificar si existe un FVG en la barra especificada |
//+------------------------------------------------------------------+
void CheckForFVG(int barIndex)
{
// Obtener datos de 3 barras consecutivas
double high1 = iHigh(_Symbol, InpTimeframe, barIndex + 1);
double low1 = iLow(_Symbol, InpTimeframe, barIndex + 1);
double high2 = iHigh(_Symbol, InpTimeframe, barIndex);
double low2 = iLow(_Symbol, InpTimeframe, barIndex);
double high3 = iHigh(_Symbol, InpTimeframe, barIndex - 1);
double low3 = iLow(_Symbol, InpTimeframe, barIndex - 1);
datetime time2 = iTime(_Symbol, InpTimeframe, barIndex);
// Detectar FVG ALCISTA (Bullish FVG)
// Condici<EFBFBD>n: El low de la barra 3 est<EFBFBD> por encima del high de la barra 1
if(InpEnableBullishFVG && low3 > high1)
{
double gapSize = (low3 - high1) / g_point;
if(gapSize >= InpMinFVGSize)
{
// Verificar si ya existe este FVG
if(!FVGExists(time2, high1, low3))
{
CreateFVG(time2, high1, low3, true);
}
}
}
// Detectar FVG BAJISTA (Bearish FVG)
// Condici<EFBFBD>n: El high de la barra 3 est<EFBFBD> por debajo del low de la barra 1
if(InpEnableBearishFVG && high3 < low1)
{
double gapSize = (low1 - high3) / g_point;
if(gapSize >= InpMinFVGSize)
{
// Verificar si ya existe este FVG
if(!FVGExists(time2, high3, low1))
{
CreateFVG(time2, high3, low1, false);
}
}
}
}
//+------------------------------------------------------------------+
//| Verificar si un FVG ya existe |
//+------------------------------------------------------------------+
bool FVGExists(datetime time, double bottomPrice, double topPrice)
{
for(int i = 0; i < g_FVGCount; i++)
{
if(g_FVGList[i].time == time &&
MathAbs(g_FVGList[i].bottomPrice - bottomPrice) < g_point &&
MathAbs(g_FVGList[i].topPrice - topPrice) < g_point)
{
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| Crear y dibujar un nuevo FVG |
//+------------------------------------------------------------------+
void CreateFVG(datetime time, double bottomPrice, double topPrice, bool isBullish)
{
// Verificar l<EFBFBD>mite de FVGs
if(g_FVGCount >= InpMaxFVGsToDisplay)
{
// Eliminar el FVG m<EFBFBD>s antiguo
RemoveOldestFVG();
}
// Crear nombre <EFBFBD>nico para el objeto
string objName = g_prefix + (isBullish ? "Bull_" : "Bear_") + TimeToString(time, TIME_DATE | TIME_SECONDS);
// Crear rect<EFBFBD>ngulo
if(!ObjectCreate(0, objName, OBJ_RECTANGLE, 0, time, bottomPrice, 0, topPrice))
{
Print("L' Error al crear objeto: ", objName, " - Error: ", GetLastError());
return;
}
// Configurar propiedades del rect<EFBFBD>ngulo
datetime endTime = InpExtendToRight ? 0 : TimeCurrent() + PeriodSeconds(InpTimeframe) * 100;
ObjectSetInteger(0, objName, OBJPROP_TIME, 1, endTime);
// Colores y estilos
color fillColor = isBullish ? InpBullishColor : InpBearishColor;
int transparency = isBullish ? InpBullishTransparency : InpBearishTransparency;
ENUM_LINE_STYLE borderStyle = isBullish ? InpBullishBorderStyle : InpBearishBorderStyle;
int borderWidth = isBullish ? InpBullishBorderWidth : InpBearishBorderWidth;
// Aplicar transparencia al color
color finalColor = ColorWithTransparency(fillColor, transparency);
ObjectSetInteger(0, objName, OBJPROP_COLOR, finalColor);
ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, borderWidth);
ObjectSetInteger(0, objName, OBJPROP_FILL, true);
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objName, OBJPROP_SELECTED, false);
ObjectSetInteger(0, objName, OBJPROP_HIDDEN, true);
// Tooltip
string tooltip = (isBullish ? "=<3D><><EFBFBD> FVG Alcista" : "=<3D>4<EFBFBD> FVG Bajista") +
"\nTiempo: " + TimeToString(time) +
"\nRango: " + DoubleToString(bottomPrice, g_digits) + " - " + DoubleToString(topPrice, g_digits);
ObjectSetString(0, objName, OBJPROP_TOOLTIP, tooltip);
// Guardar en el array
g_FVGList[g_FVGCount].time = time;
g_FVGList[g_FVGCount].topPrice = topPrice;
g_FVGList[g_FVGCount].bottomPrice = bottomPrice;
g_FVGList[g_FVGCount].isBullish = isBullish;
g_FVGList[g_FVGCount].objectName = objName;
g_FVGList[g_FVGCount].isFilled = false;
g_FVGCount++;
}
//+------------------------------------------------------------------+
//| Aplicar transparencia a un color |
//+------------------------------------------------------------------+
color ColorWithTransparency(color baseColor, int transparency)
{
// Convertir transparencia de 0-100 a alpha 0-255
int alpha = (int)((100 - transparency) * 255 / 100);
// Extraer componentes RGB
int r = (int)((baseColor) & 0xFF);
int g = (int)((baseColor >> 8) & 0xFF);
int b = (int)((baseColor >> 16) & 0xFF);
// Aplicar alpha al color
// En MT5, la transparencia se maneja con la saturaci<EFBFBD>n del color
double factor = alpha / 255.0;
r = (int)(r * factor + 255 * (1 - factor));
g = (int)(g * factor + 255 * (1 - factor));
b = (int)(b * factor + 255 * (1 - factor));
return (color)(r | (g << 8) | (b << 16));
}
//+------------------------------------------------------------------+
//| Actualizar estado de los FVGs (verificar si est<EFBFBD>n llenos) |
//+------------------------------------------------------------------+
void UpdateFVGStatus()
{
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
for(int i = g_FVGCount - 1; i >= 0; i--)
{
if(g_FVGList[i].isFilled)
continue;
bool isFilled = false;
// FVG Alcista se llena cuando el precio baja y toca el nivel inferior
if(g_FVGList[i].isBullish && currentPrice <= g_FVGList[i].bottomPrice)
{
isFilled = true;
}
// FVG Bajista se llena cuando el precio sube y toca el nivel superior
if(!g_FVGList[i].isBullish && currentPrice >= g_FVGList[i].topPrice)
{
isFilled = true;
}
if(isFilled)
{
g_FVGList[i].isFilled = true;
// Eliminar el objeto gr<EFBFBD>fico
ObjectDelete(0, g_FVGList[i].objectName);
// Remover del array
RemoveFVGFromArray(i);
}
}
}
//+------------------------------------------------------------------+
//| Remover FVG del array |
//+------------------------------------------------------------------+
void RemoveFVGFromArray(int index)
{
if(index < 0 || index >= g_FVGCount)
return;
// Mover elementos
for(int i = index; i < g_FVGCount - 1; i++)
{
g_FVGList[i] = g_FVGList[i + 1];
}
g_FVGCount--;
}
//+------------------------------------------------------------------+
//| Eliminar el FVG m<EFBFBD>s antiguo |
//+------------------------------------------------------------------+
void RemoveOldestFVG()
{
if(g_FVGCount == 0)
return;
// El FVG m<EFBFBD>s antiguo est<EFBFBD> en el <EFBFBD>ndice 0
ObjectDelete(0, g_FVGList[0].objectName);
RemoveFVGFromArray(0);
}
//+------------------------------------------------------------------+
//| Limpiar objetos antiguos al inicio |
//+------------------------------------------------------------------+
void CleanupOldObjects()
{
int totalObjects = ObjectsTotal(0, 0, OBJ_RECTANGLE);
for(int i = totalObjects - 1; i >= 0; i--)
{
string objName = ObjectName(0, i, 0, OBJ_RECTANGLE);
if(StringFind(objName, g_prefix) == 0)
{
ObjectDelete(0, objName);
}
}
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Limpiar todos los objetos FVG |
//+------------------------------------------------------------------+
void CleanupAllFVGObjects()
{
for(int i = 0; i < g_FVGCount; i++)
{
ObjectDelete(0, g_FVGList[i].objectName);
}
g_FVGCount = 0;
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Obtener texto de la raz<EFBFBD>n de desinicializaci<EFBFBD>n |
//+------------------------------------------------------------------+
string GetDeinitReasonText(int reason)
{
switch(reason)
{
case REASON_PROGRAM:
return "Programa cerrado";
case REASON_REMOVE:
return "EA removido del gr<00>fico";
case REASON_RECOMPILE:
return "EA recompilado";
case REASON_CHARTCHANGE:
return "Cambio de s<00>mbolo o timeframe";
case REASON_CHARTCLOSE:
return "Gr<00>fico cerrado";
case REASON_PARAMETERS:
return "Par<00>metros modificados";
case REASON_ACCOUNT:
return "Cambio de cuenta";
default:
return "Raz<00>n desconocida";
}
}
//+------------------------------------------------------------------+