mql5/Indicators/Arjo Indicators/Fair Value Gaps.mq5

210 lines
7 KiB
MQL5

2026-03-04 16:40:44 +02:00
//+------------------------------------------------------------------+
//| Fair Value Gaps.mq5 |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property copyright "Copyright 2025, ScarraLuba."
#property link "https://concrete-goonies.web.app"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_plots 2
//--- plot BullFVG
#property indicator_label1 "BullFVG"
#property indicator_type1 DRAW_CANDLES
#property indicator_color1 clrBlack , clrMintCream
#property indicator_style1 STYLE_SOLID
#property indicator_width1 5
//--- plot BearFVG
#property indicator_label2 "BearFVG"
#property indicator_type2 DRAW_CANDLES
#property indicator_color2 clrBlack , clrMistyRose
#property indicator_style2 STYLE_SOLID
#property indicator_width2 5
//--- input parameters
input int InpLeftRightBars = 1;
//--- indicator buffers
double BullFVGBuffer1[];
double BullFVGBuffer2[];
double BullFVGBuffer3[];
double BullFVGBuffer4[];
double BearFVGBuffer1[];
double BearFVGBuffer2[];
double BearFVGBuffer3[];
double BearFVGBuffer4[];
double c_highBuffer[]; // raw external highs
double c_lowBuffer[]; // raw external lows
int swingHandle0;datetime last_bar_time = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);
//--- indicator buffers mapping
SetIndexBuffer(0, BullFVGBuffer1, INDICATOR_DATA);
SetIndexBuffer(1, BullFVGBuffer2, INDICATOR_DATA);
SetIndexBuffer(2, BullFVGBuffer3, INDICATOR_DATA);
SetIndexBuffer(3, BullFVGBuffer4, INDICATOR_DATA);
SetIndexBuffer(4, BearFVGBuffer1, INDICATOR_DATA);
SetIndexBuffer(5, BearFVGBuffer2, INDICATOR_DATA);
SetIndexBuffer(6, BearFVGBuffer3, INDICATOR_DATA);
SetIndexBuffer(7, BearFVGBuffer4, INDICATOR_DATA);
ArraySetAsSeries(c_highBuffer, true);
ArraySetAsSeries(c_lowBuffer, true);
ArraySetAsSeries(BullFVGBuffer1, true);
ArraySetAsSeries(BullFVGBuffer2, true);
ArraySetAsSeries(BullFVGBuffer3, true);
ArraySetAsSeries(BullFVGBuffer4, true);
ArraySetAsSeries(BearFVGBuffer1, true);
ArraySetAsSeries(BearFVGBuffer2, true);
ArraySetAsSeries(BearFVGBuffer3, true);
ArraySetAsSeries(BearFVGBuffer4, true);
swingHandle0 = iCustom(_Symbol, _Period, "Arjo Indicators\\Swing", InpLeftRightBars);
if(swingHandle0 == INVALID_HANDLE)
{
Print("Error loading external indicator 'bt': ", GetLastError());
return INIT_FAILED;
}
last_bar_time = 0;
return(INIT_SUCCEEDED);
}
int OnCalculate(const int32_t rates_total,
const int32_t prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int32_t &spread[])
{ if(rates_total > 0 && time[rates_total - 1] == last_bar_time)
return rates_total;
if(rates_total < 10)
return prev_calculated;
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(open, true);
ArraySetAsSeries(close, true);
if(CopyBuffer(swingHandle0, 0, 0, rates_total, c_highBuffer) <= 0 ||
CopyBuffer(swingHandle0, 1, 0, rates_total, c_lowBuffer) <= 0)
{
Print("Failed to copy buffers from external indicator: ", GetLastError());
return prev_calculated;
}
if(prev_calculated == 0)
{
ArrayInitialize(BullFVGBuffer1, 0.0);
ArrayInitialize(BullFVGBuffer2, 0.0);
ArrayInitialize(BullFVGBuffer3, 0.0);
ArrayInitialize(BullFVGBuffer4, 0.0);
ArrayInitialize(BearFVGBuffer1, 0.0);
ArrayInitialize(BearFVGBuffer2, 0.0);
ArrayInitialize(BearFVGBuffer3, 0.0);
ArrayInitialize(BearFVGBuffer4, 0.0);
}
for(int i = 0; i < rates_total; i++)
{
if(c_highBuffer[i] != 0.0)
{
int s1 = i;
int a1 = s1 - 1;
int a3 = s1 - 3;
int b1 = s1;
int b3 = s1 - 2;
int c1 = s1 - 2;
int c3 = s1 - 4;
if(a3 < 0 || b3 < 0 || c3 < 0 || a1 - 1 < 0 || b1 - 1 < 0 || c1 - 1 < 0)
continue;
bool fvgA = (low[a1] > high[a3]);
bool fvgB = (low[b1] > high[b3]);
bool fvgC = (low[c1] > high[c3]);
if(fvgB)
{
BearFVGBuffer1[b1 - 1] = low[b1];
BearFVGBuffer2[b1 - 1] = low[b1];
BearFVGBuffer3[b1 - 1] = high[b3];
BearFVGBuffer4[b1 - 1] = high[b3];
}
else if(fvgA)
{
BearFVGBuffer1[a1 - 1] = low[a1];
BearFVGBuffer2[a1 - 1] = low[a1];
BearFVGBuffer3[a1 - 1] = high[a3];
BearFVGBuffer4[a1 - 1] = high[a3];
}
else if(fvgC)
{
BearFVGBuffer1[c1 - 1] = low[c1];
BearFVGBuffer2[c1 - 1] = low[c1];
BearFVGBuffer3[c1 - 1] = high[c3];
BearFVGBuffer4[c1 - 1] = high[c3];
}
}
}
for(int i = 0; i < rates_total; i++)
{
if(c_lowBuffer[i] != 0.0)
{
int a1 = i;
int a2 = i - 1;
int a3 = i - 2;
int a4 = i + 1;
if(a2 < 0 || a3 < 0 || a1 - 1 < 0 || a2 - 1 < 0 || a3 - 1 < 0 || a3 - 2 < 0 || a2 - 2 < 0 || a1 - 2 < 0 || a4 >= rates_total)
continue;
bool firstFvg = isBoolishFvg(high, low, a1);
bool secondFvg = isBoolishFvg(high, low, a2);
bool thirdFvg = isBoolishFvg(high, low, a3);
if(firstFvg)
{
BullFVGBuffer1[a1 - 1] = high[a1];
BullFVGBuffer2[a1 - 1] = high[a1];
BullFVGBuffer3[a1 - 1] = low[a1 - 2];
BullFVGBuffer4[a1 - 1] = low[a1 - 2];
}
/* else if(secondFvg)
{
BullFVGBuffer1[a2 - 1] = high[a2];
BullFVGBuffer2[a2 - 1] = high[a2];
BullFVGBuffer3[a2 - 1] = low[a2 - 2];
BullFVGBuffer4[a2 - 1] = low[a2 - 2];
}
else if(thirdFvg)
{
BullFVGBuffer1[a3 - 1] = high[a3];
BullFVGBuffer2[a3 - 1] = high[a3];
BullFVGBuffer3[a3 - 1] = low[a3 - 2];
BullFVGBuffer4[a3 - 1] = low[a3 - 2];
}*/
}
}
last_bar_time = time[rates_total - 1];
return(rates_total);
}
bool isBoolishFvg(const double &high[], const double &low[], int fromIndex = 2)
{
int a3 = MathMax(fromIndex - 2, 1);
return (high[fromIndex] < low[a3]);
}