ICTLibraryExamples/Benchmark/OtherCode/Code4.mq5
441 lines
29 KiB
MQL5
Nique_372
2026-01-14 07:05:58 -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"
Nique_372
2026-03-23 12:25:01 -05:00
#property description "Expert Advisor exclusivo para detectar y dibujar Fair Value Gaps"
Nique_372
2026-01-14 07:05:58 -05:00
#property description "NO ejecuta trades - Solo an<00>lisis visual"
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
#property strict
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "..\\Utils\\MetricSaver.mqh"
#include <TSN\\MQLArticles\\Utils\\TFManager.mqh>
Nique_372
2026-03-23 12:25:01 -05:00
/* Codigo hecho por ia Claude Sonnet 4.6
Promt:
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
Desarrolla un BOT (Expert Advisor) para MetaTrader 5 (MT5) que EXCLUSIVAMENTE detecte y dibuje Fair Value Gaps (FVG) en el gr<EFBFBD>fico.
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
<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 |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| CFvgFast.mqh  Fair Value Gap <EFBFBD> Zero-alloc <EFBFBD> Flat arrays |
//| Mismo estilo que CFvgBar: Create / Set / SetGraphic / OnNewBar |
//| Sin clases internas <EFBFBD> Sin new/delete <EFBFBD> Arrays est<EFBFBD>ticos |
//+------------------------------------------------------------------+
#property strict
#ifndef FVG_MAX
#define FVG_MAX 200
#endif
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Zona FVG  40 bytes, sin strings din<EFBFBD>micos
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
struct FVGZone
Nique_372
2026-01-14 07:05:58 -05:00
{
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
double hi;
Nique_372
2026-03-23 12:25:01 -05:00
double lo;
datetime t;
bool active;
bool bullish;
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// CFvgFast
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class CFvgFast
{
private:
//--- arrays planos en el heap del objeto (no BSS, pero un solo alloc en Create)
Nique_372
2026-01-14 07:05:58 -05:00
FVGZone m_bull[FVG_MAX];
Nique_372
2026-03-23 12:25:01 -05:00
FVGZone m_bear[FVG_MAX];
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
int m_bull_n;
Nique_372
2026-03-23 12:25:01 -05:00
int m_bear_n;
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
int m_bull_head; // circular overwrite
int m_bear_head;
long m_bull_total; // total insertados (para saber si circular)
long m_bear_total;
//--- nearest (actualizado 1x barra, le<EFBFBD>do N veces por EA)
int m_near_bull;
int m_near_bear;
//--- config
Nique_372
2026-01-14 07:05:58 -05:00
string m_symbol;
Nique_372
2026-03-23 12:25:01 -05:00
ENUM_TIMEFRAMES m_tf;
Nique_372
2026-01-14 07:05:58 -05:00
string m_prefix;
Nique_372
2026-03-23 12:25:01 -05:00
int m_lookback;
double m_min_gap; // en precio, ya convertido
bool m_draw;
//--- visual
color m_col_bull;
color m_col_bear;
ENUM_LINE_STYLE m_style;
bool m_fill;
int m_border_w;
bool m_extend;
Nique_372
2026-01-14 07:05:58 -05:00
int m_extend_bars;
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
//%%%%%%%% helpers privados %%%%%%%%
string _Name(bool bull, int idx)
{
return m_prefix + (bull ? "B" : "S") + IntegerToString(idx);
}
void _DrawZone(int idx, bool bull)
{
if(!m_draw) return;
Nique_372
2026-01-14 07:05:58 -05:00
FVGZone z = bull ? m_bull[idx] : m_bear[idx];
Nique_372
2026-03-23 12:25:01 -05:00
if(!z.active) return;
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
string nm = _Name(bull, idx);
color c = bull ? m_col_bull : m_col_bear;
datetime t1 = z.t;
datetime t2 = m_extend
? z.t + (datetime)PeriodSeconds(m_tf) * m_extend_bars
: 0;
if(ObjectFind(0, nm) < 0)
ObjectCreate(0, nm, OBJ_RECTANGLE, 0, t1, z.hi, t2, z.lo);
Nique_372
2026-01-14 07:05:58 -05:00
else
Nique_372
2026-03-23 12:25:01 -05:00
{
ObjectSetInteger(0, nm, OBJPROP_TIME, 0, t1);
ObjectSetInteger(0, nm, OBJPROP_TIME, 1, t2);
ObjectSetDouble (0, nm, OBJPROP_PRICE, 0, z.hi);
ObjectSetDouble (0, nm, OBJPROP_PRICE, 1, z.lo);
}
ObjectSetInteger(0, nm, OBJPROP_COLOR, c);
ObjectSetInteger(0, nm, OBJPROP_STYLE, m_style);
ObjectSetInteger(0, nm, OBJPROP_WIDTH, m_border_w);
ObjectSetInteger(0, nm, OBJPROP_FILL, m_fill);
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
ObjectSetInteger(0, nm, OBJPROP_BACK, true);
Nique_372
2026-01-14 07:05:58 -05:00
ObjectSetInteger(0, nm, OBJPROP_SELECTABLE, false);
Nique_372
2026-03-23 12:25:01 -05:00
ObjectSetInteger(0, nm, OBJPROP_HIDDEN, true);
}
void _DeleteZone(int idx, bool bull)
{
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
if(!m_draw) return;
ObjectDelete(0, _Name(bull, idx));
}
Nique_372
2026-01-14 07:05:58 -05:00
void _Insert(const FVGZone &z)
Nique_372
2026-03-23 12:25:01 -05:00
{
if(z.bullish)
{
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
int i = m_bull_head;
if(m_bull_total >= FVG_MAX) _DeleteZone(i, true);
m_bull[i] = z;
_DrawZone(i, true);
m_bull_head = (m_bull_head + 1) % FVG_MAX;
if(m_bull_n < FVG_MAX) m_bull_n++;
m_bull_total++;
}
else
{
int i = m_bear_head;
if(m_bear_total >= FVG_MAX) _DeleteZone(i, false);
m_bear[i] = z;
Nique_372
2026-01-14 07:05:58 -05:00
_DrawZone(i, false);
Nique_372
2026-03-23 12:25:01 -05:00
m_bear_head = (m_bear_head + 1) % FVG_MAX;
Nique_372
2026-01-14 07:05:58 -05:00
if(m_bear_n < FVG_MAX) m_bear_n++;
Nique_372
2026-03-23 12:25:01 -05:00
m_bear_total++;
}
Nique_372
2026-01-14 07:05:58 -05:00
}
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
//--- Detecci<EFBFBD>n O(1): lee 3 velas, eval<EFBFBD>a gap
Nique_372
2026-01-14 07:05:58 -05:00
void _Detect(int shift)
Nique_372
2026-03-23 12:25:01 -05:00
{
Nique_372
2026-01-14 07:05:58 -05:00
double hi[3], lo[3];
Nique_372
2026-03-23 12:25:01 -05:00
datetime t[1];
if(CopyHigh(m_symbol, m_tf, shift, 3, hi) < 3) return;
if(CopyLow (m_symbol, m_tf, shift, 3, lo) < 3) return;
Nique_372
2026-01-14 07:05:58 -05:00
if(CopyTime(m_symbol, m_tf, shift+1, 1, t) < 1) return;
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
//--- Bull FVG: low[0] > high[2]
if(lo[0] > hi[2] && (lo[0] - hi[2]) >= m_min_gap)
Nique_372
2026-01-14 07:05:58 -05:00
{
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
FVGZone z;
Nique_372
2026-03-23 12:25:01 -05:00
z.hi = lo[0]; z.lo = hi[2]; z.t = t[0];
Nique_372
2026-01-14 07:05:58 -05:00
z.active = true; z.bullish = true;
Nique_372
2026-03-23 12:25:01 -05:00
_Insert(z);
}
//--- Bear FVG: high[0] < low[2]
if(hi[0] < lo[2] && (lo[2] - hi[0]) >= m_min_gap)
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
{
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
FVGZone z;
z.hi = lo[2]; z.lo = hi[0]; z.t = t[0];
Nique_372
2026-01-14 07:05:58 -05:00
z.active = true; z.bullish = false;
Nique_372
2026-03-23 12:25:01 -05:00
_Insert(z);
}
Nique_372
2026-01-14 07:05:58 -05:00
}
Nique_372
2026-03-23 12:25:01 -05:00
//--- Mitigaci<EFBFBD>n O(n), solo comparaciones de double
void _Mitigate(double price)
Nique_372
2026-10-25 12:04:40 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
{
int n = (int)MathMin(m_bull_n, FVG_MAX);
for(int i = 0; i < n; i++)
{
if(!m_bull[i].active) continue;
if(price <= m_bull[i].hi && price >= m_bull[i].lo)
{
m_bull[i].active = false;
_DeleteZone(i, true);
}
}
n = (int)MathMin(m_bear_n, FVG_MAX);
for(int i = 0; i < n; i++)
{
if(!m_bear[i].active) continue;
Nique_372
2026-01-14 07:05:58 -05:00
if(price >= m_bear[i].lo && price <= m_bear[i].hi)
Nique_372
2026-03-23 12:25:01 -05:00
{
m_bear[i].active = false;
_DeleteZone(i, false);
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
}
}
}
Nique_372
2026-01-14 07:05:58 -05:00
Nique_372
2026-03-23 12:25:01 -05:00
//--- Nearest O(n), 1x barra
Nique_372
2026-01-14 07:05:58 -05:00
void _UpdateNearest(double price)
Nique_372
2026-03-23 12:25:01 -05:00
Nique_372
2026-01-14 07:05:58 -05:00
{