ICTLibraryExamples/Benchmark/OtherCode/Code6.mq5
745 lines
56 KiB
MQL5
Nique_372
2026-01-14 07:05:58 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| FVG_Detector_EA.mq5 |
//| Fair Value Gap Detection Tool |
//| Professional Smart Money Concepts Expert |
//+------------------------------------------------------------------+
#property copyright "FVG Detector - SMC Analysis Tool"
#property link "https://www.smartmoneyconcepts.com"
#property version "2.01"
#property description "Expert Advisor para detecci<00>n y visualizaci<00>n de Fair Value Gaps (FVG)"
#property description "<00>&<0F> SOLO AN<00>LISIS VISUAL - NO EJECUTA OPERACIONES"
#property strict
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "..\\Utils\\MetricSaver.mqh"
/* Codigo hecho por ia Claude Opus 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.
*/
//+------------------------------------------------------------------+
//| ENUMERACIONES PERSONALIZADAS |
//+------------------------------------------------------------------+
// Estilos de borde para los rect<EFBFBD>ngulos FVG
enum ENUM_FVG_BORDER_STYLE
{
FVG_BORDER_SOLID = STYLE_SOLID, // L<EFBFBD>nea S<EFBFBD>lida
FVG_BORDER_DASH = STYLE_DASH, // L<EFBFBD>nea Discontinua
FVG_BORDER_DOT = STYLE_DOT, // L<EFBFBD>nea Punteada
FVG_BORDER_DASHDOT = STYLE_DASHDOT, // Gui<EFBFBD>n-Punto
FVG_BORDER_DASHDOTDOT = STYLE_DASHDOTDOT // Gui<EFBFBD>n-Punto-Punto
};
// Tipo de extensi<EFBFBD>n del FVG
enum ENUM_FVG_EXTENSION
{
FVG_EXTEND_FIXED = 0, // Extensi<EFBFBD>n Fija (N velas)
FVG_EXTEND_UNTIL_FILL = 1 // Hasta ser llenado
};
//+------------------------------------------------------------------+
//| PAR<EFBFBD>METROS DE ENTRADA - CONFIGURACI<EFBFBD>N DEL USUARIO |
//+------------------------------------------------------------------+
// === CONFIGURACI<EFBFBD>N GENERAL ===
input group "P%P%P%P%P%P%P%P%P%P% CONFIGURACI<00>N GENERAL P%P%P%P%P%P%P%P%P%P%"
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // Timeframe de an<EFBFBD>lisis
input int InpLookbackBars = 500; // Velas a analizar (historial)
input int InpMinFVGSize = 5; // Tama<EFBFBD>o m<EFBFBD>nimo FVG (puntos)
input bool InpShowFilledFVG = false; // Mostrar FVG ya llenados
input ENUM_FVG_EXTENSION InpExtensionType = FVG_EXTEND_UNTIL_FILL; // Tipo de extensi<EFBFBD>n
// === FVG ALCISTAS (BULLISH) ===
input group "P%P%P%P%P%P%P%P%P%P% FVG ALCISTAS (BULLISH) P%P%P%P%P%P%P%P%P%P%"
input bool InpShowBullishFVG = true; // Activar FVG Alcistas
input color InpBullishColor = clrDodgerBlue; // Color FVG Alcista
input uchar InpBullishOpacity = 50; // Opacidad (0-255)
input int InpBullishWidth = 1; // Grosor del borde
input ENUM_FVG_BORDER_STYLE InpBullishStyle = FVG_BORDER_SOLID; // Estilo del borde
input bool InpBullishFill = true; // Rellenar rect<EFBFBD>ngulo
// === FVG BAJISTAS (BEARISH) ===
input group "P%P%P%P%P%P%P%P%P%P% FVG BAJISTAS (BEARISH) P%P%P%P%P%P%P%P%P%P%"
input bool InpShowBearishFVG = true; // Activar FVG Bajistas
input color InpBearishColor = clrCrimson; // Color FVG Bajista
input uchar InpBearishOpacity = 50; // Opacidad (0-255)
input int InpBearishWidth = 1; // Grosor del borde
input ENUM_FVG_BORDER_STYLE InpBearishStyle = FVG_BORDER_SOLID; // Estilo del borde
input bool InpBearishFill = true; // Rellenar rect<EFBFBD>ngulo
// === CONFIGURACI<EFBFBD>N AVANZADA ===
input group "P%P%P%P%P%P%P%P%P%P% CONFIGURACI<00>N AVANZADA P%P%P%P%P%P%P%P%P%P%"
input int InpFixedExtension = 50; // Extensi<EFBFBD>n fija (velas)
input bool InpDeleteOnFill = true; // Eliminar FVG al llenarse
input int InpUpdateFrequency = 1; // Frecuencia actualizaci<EFBFBD>n (ticks)
input string InpObjectPrefix = "FVG_"; // Prefijo objetos gr<EFBFBD>ficos
//+------------------------------------------------------------------+
//| ESTRUCTURA PARA ALMACENAR INFORMACI<EFBFBD>N DE FVG |
//+------------------------------------------------------------------+
struct FVG_Data
{
datetime timeStart; // Tiempo de inicio (vela del gap)
datetime timeEnd; // Tiempo de fin (extensi<EFBFBD>n)
double priceHigh; // Precio superior del gap
double priceLow; // Precio inferior del gap
bool isBullish; // true = alcista, false = bajista
bool isFilled; // true si el gap ha sido llenado
int barIndex; // <EFBFBD>ndice de la vela donde se form<EFBFBD>
string objectName; // Nombre del objeto gr<EFBFBD>fico
};
//+------------------------------------------------------------------+
//| VARIABLES GLOBALES |
//+------------------------------------------------------------------+
FVG_Data g_fvgArray[]; // Array din<EFBFBD>mico de FVGs detectados
int g_totalFVG = 0; // Contador total de FVGs
int g_tickCounter = 0; // Contador de ticks para optimizaci<EFBFBD>n
datetime g_lastBarTime = 0; // Tiempo de la <EFBFBD>ltima vela procesada
int g_lastBarsCount = 0; // <EFBFBD>ltimo conteo de barras
string g_chartSymbol; // S<EFBFBD>mbolo del gr<EFBFBD>fico
ENUM_TIMEFRAMES g_chartTimeframe; // Timeframe activo
double g_pointValue; // Valor del punto
int g_digits; // D<EFBFBD>gitos del s<EFBFBD>mbolo
//+------------------------------------------------------------------+
//| FUNCI<EFBFBD>N DE INICIALIZACI<EFBFBD>N DEL EXPERT ADVISOR |
//+------------------------------------------------------------------+
int OnInit()
{
CMetricsSave::Start(FILE_CODE6);
// Validar par<EFBFBD>metros de entrada
if(!ValidateInputParameters())
{
Print("L' Error: Par<00>metros de entrada inv<00>lidos");
return(INIT_PARAMETERS_INCORRECT);
}
// Inicializar variables globales
g_chartSymbol = _Symbol;
g_chartTimeframe = (InpTimeframe == PERIOD_CURRENT) ? Period() : InpTimeframe;
g_pointValue = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
g_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
g_lastBarTime = 0;
g_lastBarsCount = 0;
g_tickCounter = 0;
// Limpiar objetos gr<EFBFBD>ficos anteriores
CleanupGraphicObjects();
// Inicializar array de FVGs
ArrayResize(g_fvgArray, 0);
g_totalFVG = 0;
// Detectar FVGs en el historial
DetectHistoricalFVGs();
// Dibujar FVGs detectados
DrawAllFVGs();
// Forzar actualizaci<EFBFBD>n del gr<EFBFBD>fico
ChartRedraw(0);
// Mensaje de inicializaci<EFBFBD>n exitosa
Print("P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%");
Print("' FVG Detector EA iniciado correctamente");
Print("=<3D><><EFBFBD> S<00>mbolo: ", g_chartSymbol, " | Timeframe: ", EnumToString(g_chartTimeframe));
Print("=<3D><><EFBFBD> FVGs Alcistas: ", InpShowBullishFVG ? "Activados" : "Desactivados");
Print("=<3D><><EFBFBD> FVGs Bajistas: ", InpShowBearishFVG ? "Activados" : "Desactivados");
Print("=<3D><><EFBFBD> FVGs detectados: ", g_totalFVG);
Print("P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| FUNCI<EFBFBD>N DE DESINICIALIZACI<EFBFBD>N |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Limpiar todos los objetos gr<EFBFBD>ficos creados
CleanupGraphicObjects();
// Liberar memoria del array
ArrayFree(g_fvgArray);
g_totalFVG = 0;
// Mensaje de cierre
string reasonText = "";
switch(reason)
{
case REASON_PROGRAM: reasonText = "Programa terminado"; break;
case REASON_REMOVE: reasonText = "EA eliminado del gr<00>fico"; break;
case REASON_RECOMPILE: reasonText = "EA recompilado"; break;
case REASON_CHARTCHANGE: reasonText = "S<00>mbolo o timeframe cambiado"; break;
case REASON_CHARTCLOSE: reasonText = "Gr<00>fico cerrado"; break;
case REASON_PARAMETERS: reasonText = "Par<00>metros modificados"; break;
case REASON_ACCOUNT: reasonText = "Cuenta cambiada"; break;
case REASON_TEMPLATE: reasonText = "Nueva plantilla aplicada"; break;
default: reasonText = "Raz<00>n desconocida"; break;
}
Print("P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%");
Print("<00>#<0F> FVG Detector EA detenido - ", reasonText);
Print("P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%");
CMetricsSave::Destroy();
}
//+------------------------------------------------------------------+
//| FUNCI<EFBFBD>N PRINCIPAL OnTick - PROCESAMIENTO EN TIEMPO REAL |
//+------------------------------------------------------------------+
void OnTick()
{
// Control de frecuencia de actualizaci<EFBFBD>n para optimizaci<EFBFBD>n
g_tickCounter++;
if(g_tickCounter < InpUpdateFrequency)
return;
g_tickCounter = 0;
// Obtener tiempo de la vela actual
datetime currentBarTime = iTime(g_chartSymbol, g_chartTimeframe, 0);
int currentBarsCount = iBars(g_chartSymbol, g_chartTimeframe);
// Verificar si hay una nueva vela
bool isNewBar = (currentBarTime != g_lastBarTime);
bool barsChanged = (currentBarsCount != g_lastBarsCount);
if(isNewBar || barsChanged)
{
g_lastBarTime = currentBarTime;
g_lastBarsCount = currentBarsCount;
// Detectar nuevo FVG potencial (solo en la vela m<EFBFBD>s reciente completa)
CheckForNewFVG(1);
// Actualizar estado de FVGs existentes (verificar si fueron llenados)
UpdateFVGStatus();
// Redibujar FVGs si es necesario
RedrawModifiedFVGs();
}
else
{
// Solo actualizar extensiones si no hay nueva vela
UpdateFVGExtensions();
}
}
//+------------------------------------------------------------------+
//| VALIDACI<EFBFBD>N DE PAR<EFBFBD>METROS DE ENTRADA |
//+------------------------------------------------------------------+
bool ValidateInputParameters()
{
bool isValid = true;
// Validar lookback
if(InpLookbackBars < 10 || InpLookbackBars > 10000)
{
Print("<00>&<0F> Advertencia: LookbackBars debe estar entre 10 y 10000. Usando 500.");
// Continuar con valor por defecto
}
// Validar tama<EFBFBD>o m<EFBFBD>nimo
if(InpMinFVGSize < 0)
{
Print("<00>&<0F> Advertencia: MinFVGSize no puede ser negativo.");
}
// Validar que al menos un tipo de FVG est<EFBFBD> activo
if(!InpShowBullishFVG && !InpShowBearishFVG)
{
Print("<00>&<0F> Advertencia: Ambos tipos de FVG est<00>n desactivados. El EA no mostrar<00> nada.");
}
return isValid;
}
//+------------------------------------------------------------------+
//| LIMPIEZA DE OBJETOS GR<EFBFBD>FICOS |
//+------------------------------------------------------------------+
void CleanupGraphicObjects()
{
int totalObjects = ObjectsTotal(0, 0, OBJ_RECTANGLE);
// Iterar en orden inverso para eliminar objetos con nuestro prefijo
for(int i = totalObjects - 1; i >= 0; i--)
{
string objName = ObjectName(0, i, 0, OBJ_RECTANGLE);
if(StringFind(objName, InpObjectPrefix) == 0)
{
ObjectDelete(0, objName);
}
}
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| DETECCI<EFBFBD>N DE FVGs EN DATOS HIST<EFBFBD>RICOS |
//+------------------------------------------------------------------+
void DetectHistoricalFVGs()
{
// Determinar el rango de barras a analizar
int totalBars = iBars(g_chartSymbol, g_chartTimeframe);
int barsToAnalyze = MathMin(InpLookbackBars, totalBars - 3);
if(barsToAnalyze < 3)
{
Print("<00>&<0F> No hay suficientes datos hist<00>ricos para an<00>lisis");
return;
}
// Reservar memoria para el array (estimaci<EFBFBD>n inicial)
ArrayResize(g_fvgArray, 0, barsToAnalyze / 10);
// Iterar desde la vela m<EFBFBD>s antigua hacia la m<EFBFBD>s reciente
for(int i = barsToAnalyze; i >= 2; i--)
{
CheckForFVGAtBar(i);
}
// Ajustar tama<EFBFBD>o final del array
ArrayResize(g_fvgArray, g_totalFVG);
}
//+------------------------------------------------------------------+
//| VERIFICAR FVG EN UNA VELA ESPEC<EFBFBD>FICA |
//+------------------------------------------------------------------+
void CheckForFVGAtBar(int barIndex)
{
// Obtener datos OHLC de las 3 velas necesarias
// Vela 0 (barIndex+1): Primera vela
// Vela 1 (barIndex): Vela del impulso (donde se forma el gap)
// Vela 2 (barIndex-1): Tercera vela
double high0 = iHigh(g_chartSymbol, g_chartTimeframe, barIndex + 1);
double low0 = iLow(g_chartSymbol, g_chartTimeframe, barIndex + 1);
double high2 = iHigh(g_chartSymbol, g_chartTimeframe, barIndex - 1);
double low2 = iLow(g_chartSymbol, g_chartTimeframe, barIndex - 1);
// Verificar datos v<EFBFBD>lidos
if(high0 <= 0 || low0 <= 0 || high2 <= 0 || low2 <= 0)
return;
// Tiempos de las velas
datetime time1 = iTime(g_chartSymbol, g_chartTimeframe, barIndex);
datetime time2 = iTime(g_chartSymbol, g_chartTimeframe, barIndex - 1);
// Tama<EFBFBD>o m<EFBFBD>nimo en precio
double minSize = InpMinFVGSize * g_pointValue;
// === DETECCI<EFBFBD>N FVG ALCISTA (BULLISH) ===
// Se forma cuando: Low de vela 3 > High de vela 1
if(InpShowBullishFVG && low2 > high0)
{
double gapHigh = low2;
double gapLow = high0;
double gapSize = gapHigh - gapLow;
if(gapSize >= minSize)
{
// Crear nuevo FVG
FVG_Data newFVG;
newFVG.timeStart = time1;
newFVG.timeEnd = time2;
newFVG.priceHigh = gapHigh;
newFVG.priceLow = gapLow;
newFVG.isBullish = true;
newFVG.isFilled = false;
newFVG.barIndex = barIndex;
newFVG.objectName = GenerateFVGObjectName(true, barIndex);
// Verificar si ya fue llenado en el historial
CheckIfFVGFilledHistorical(newFVG);
// Solo agregar si no est<EFBFBD> llenado o si queremos mostrar llenados
if(!newFVG.isFilled || InpShowFilledFVG)
{