//+------------------------------------------------------------------+ //| 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]); }