STATUS: IN DEVELOPMENTPINE + MQL5 SOURCE: PROVIDED, NOT YET TESTED ON A PLATFORMRELEASED: NONE

Home / MT5

MetaTrader 5, MQL5

FVG indicator for MT5, MQL5 source in full

An MQL5 indicator that draws rectangles for the same three-candle gaps as the Pine version and the browser detector.

Source provided, not yet tested on a platform. Nobody has compiled or run this code on TradingView or in MetaTrader 5. It was written to follow the rule on this site line by line, and a test in this repository checks its inputs and its comparisons as text. That is not the same as running it. Do not trade on it before you have tested it yourself on a demo or on history.

Planned A listing on the MQL5 marketplace. Nothing has been submitted, and no price is set.

To try it yourself

These are the usual MetaEditor steps. Since the file has never been compiled, expect that you may have to fix a compile error, and tell us if you do.

  1. In MetaTrader 5, open MetaEditor and create a new custom indicator file, or save the code below as fvg.mq5 in the MQL5/Indicators folder.
  2. Compile it. Read the log for errors.
  3. Drag the indicator from the Navigator onto a chart and set the inputs.

The inputs are explained on the settings page. If you use MT4, read the MT4 page first.

Source: indicator/fvg.mq5

indicator/fvg.mq5, MQL5 (120 lines). Source provided, not yet tested on a platform.
//+------------------------------------------------------------------+
//| FVG Indicator, three-candle rule. MQL5.                           |
//| Source provided, not yet tested on a platform: it has not been    |
//| compiled or run in MetaTrader 5.                                  |
//|                                                                   |
//| The rule (the same one the browser detector on this site uses):   |
//|   bullish gap: the low of candle 3 is above the high of candle 1  |
//|   bearish gap: the high of candle 3 is below the low of candle 1  |
//| Wicks only. The comparison is strict, so touching is not a gap.   |
//| A gap is kept only if its height is at least minSize.             |
//| Only closed bars are read: the forming bar is never used.         |
//| A gap is filled when a later closed bar trades through its far    |
//| edge: bullish, low <= bottom; bearish, high >= top.               |
//| This marks a pattern that has already formed. It predicts nothing.|
//+------------------------------------------------------------------+
#property copyright "FairValueGapIndicator.com editors"
#property version   "0.10"
#property description "Marks fair value gaps (three-candle rule) on closed bars. Source provided, not yet tested on a platform."
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0

input double minSize    = 0.0;          // minSize: minimum gap size (price units)
input int    lookback   = 300;          // lookback: bars
input bool   showFilled = true;         // showFilled: keep filled gaps on the chart
input bool   extendOpen = true;         // extendOpen: extend open gaps to the right
input color  bullColor  = clrRoyalBlue; // bullColor: bullish gap color
input color  bearColor  = clrTomato;    // bearColor: bearish gap color
input bool   alertOnNew = false;        // alertOnNew: alert when a gap completes on the last closed bar

#define PREFIX "FVGI_"

int      g_doneFor   = 0;   // rates_total at the last full pass
datetime g_lastAlert = 0;   // closing bar that last raised an alert

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, PREFIX, 0, OBJ_RECTANGLE);
   ChartRedraw();
  }
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int 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 int &spread[])
  {
   if(rates_total < 4)
      return(rates_total);
   // The bar at rates_total-1 is still forming. Nothing runs until a new bar opens.
   if(prev_calculated > 0 && g_doneFor == rates_total)
      return(rates_total);
   g_doneFor = rates_total;

   ArraySetAsSeries(time, false);
   ArraySetAsSeries(high, false);
   ArraySetAsSeries(low, false);

   int last    = rates_total - 2;      // last closed bar
   int formIdx = rates_total - 1;      // the forming bar, never read below
   int firstC3 = MathMax(2, formIdx - lookback);

   ObjectsDeleteAll(0, PREFIX, 0, OBJ_RECTANGLE);

   for(int c3 = firstC3; c3 <= last; c3++)
     {
      int c1 = c3 - 2;
      bool bull = (low[c3] > high[c1]);
      bool bear = (high[c3] < low[c1]);
      if(!bull && !bear)
         continue;
      double top    = bull ? low[c3]  : low[c1];
      double bottom = bull ? high[c1] : high[c3];
      if(top - bottom < minSize)
         continue;

      // later closed bars: find the first one that trades through the far edge
      int fillIdx = -1;
      for(int j = c3 + 1; j <= last; j++)
        {
         if(bull ? (low[j] <= bottom) : (high[j] >= top))
           {
            fillIdx = j;
            break;
           }
        }
      if(fillIdx >= 0 && !showFilled)
         continue;

      datetime right = time[c3];
      if(fillIdx >= 0)
         right = time[fillIdx];
      else if(extendOpen)
         right = time[last];

      string name = PREFIX + IntegerToString((long)time[c1]) + (bull ? "U" : "D");
      if(ObjectCreate(0, name, OBJ_RECTANGLE, 0, time[c1], top, right, bottom))
        {
         ObjectSetInteger(0, name, OBJPROP_COLOR, bull ? bullColor : bearColor);
         ObjectSetInteger(0, name, OBJPROP_FILL, true);
         ObjectSetInteger(0, name, OBJPROP_BACK, true);
         ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
        }

      if(alertOnNew && c3 == last && time[last] != g_lastAlert)
        {
         g_lastAlert = time[last];
         Alert(_Symbol, " ", bull ? "bullish" : "bearish", " fair value gap completed on the last closed bar");
        }
     }
   ChartRedraw();
   return(rates_total);
  }
//+------------------------------------------------------------------+

Repainting: what the code does on the current bar

This section describes the code. It has not been observed in a running terminal.

A repaint test report for each release is planned. None exists yet.

What it does not do

It marks a pattern that has already formed. It does not predict price or size a trade.