Expert Advisors • Indicators • Scripts • Libraries

MQL.RobotFX.org is the biggest collection of MetaTrader expert advisors (MT5 & MT4), indicators, scripts and libraries that can be used to improve trading results, minimize risks or simply automate trading tasks

Metatrader 5 Indicator | Consecutive Bars (with history) indicator for MT5 | MQL5 Code

New free code from MQL5: indicators, EAs, and scripts for traders.

I have repeatedly seen traders clamoring for an indicator that counts consecutive up and down candles (bars) in the Forum. Clearly, many traders use, or want to use, that indicator. Although I've seen various options for MT4, options for MT5 appear to be limited. The consecutive bar counting indicators that I found merely show the current count of consecutive bars that print in the current price direction. Therefore, I coded this Consecutive_Bars indicator for MT5.

The main benefit of this indicator is that you can set a level at the most frequently appearing "false swing" count─thereby filtering those false swings out of your trading. The blue line study shows up bars, and the red line study show down bars. Upon 1 bar printing in the opposite direction of the count, the line studies respectively return to the 0 level.

The only input setting is MaxBars which sets the maximum lookback/drawing period of the entire indicator.

Reduce lag and improve accuracy with the NonLagMA Expert Advisor for MT4/MT5. Discover it.

The code (framed below) is heavily commented as a detailed explanation, especially for aspiring coders.

Image for Consecutive Bars (with history) indicator for MT5

//+------------------------------------------------------------------+
//|                                             Consecutive_Bars.mq5 |
//|                            Copyright 2026, Ryan Lawrence Johnson |
//|                                https://www.mql5.com/en/users/rjo |
//+------------------------------------------------------------------+

//--- store price, time, and volume data for access as in MQL4
#define SERIES(name,type)                               \                            
class C##name                                           \
{                                                       \
public:                                                 \
type operator[](const int i){return i##name(NULL,0,i);} \                                                
}name;                                                  
SERIES(Open,double)
SERIES(Low,double)
SERIES(High,double)
SERIES(Close,double)
SERIES(Time,datetime)
SERIES(Volume,long)
SERIES(TickVolume,long)

//--- properties
#property copyright "© 2026, Ryan Lawrence Johnson"
#property link      "https://www.mql5.com/en/users/rjo"
#property version   "1.00"
#property indicator_separate_window

#property indicator_buffers 2
#property indicator_plots 2

#property indicator_type1 DRAW_SECTION
#property indicator_style1 STYLE_SOLID
#property indicator_color1 clrDodgerBlue
#property indicator_width1 1

#property indicator_type2 DRAW_SECTION
#property indicator_style2 STYLE_SOLID
#property indicator_color2 clrRed
#property indicator_width2 1

//--- settings
input int MaxBars = 200;

//--- variables on global scope
int countUp;
int countDn;

//--- arrays for indicator data buffers
double consecUpBars[];
double consecDnBars[];

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, consecUpBars, INDICATOR_DATA); // set index buffer 0 to store up bars
        PlotIndexSetString(0, PLOT_LABEL, "Consec Up Bars"); // set on-screen label (for mouse cursor rollover) for up bars
        PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, Bars(NULL, 0) - MaxBars); // PLOT_DRAW_BEGIN defines undrawn bars ==> so skip all bars except MaxBars
                                                                          // (this indicator loops thruogh bars in reverse chronological order)
        
        SetIndexBuffer(1, consecDnBars, INDICATOR_DATA); // set index buffer 1 to store down bars
        PlotIndexSetString(1, PLOT_LABEL, "Consec Dn Bars"); // set on-screen label (for mouse cursor rollover) for down bars
        PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, Bars(NULL, 0) - MaxBars); // PLOT_DRAW_BEGIN defines undrawn bars ==> so skip all bars except MaxBars
                                                                          // (this indicator loops thruogh bars in reverse chronological order)

//--- indicator short name
        IndicatorSetString(INDICATOR_SHORTNAME, "Consec Bars"); // set the indicator short name
                                                                // (required if you use ChartIndicatorDelete() in an EA)
        
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//--- align indicator data direction with price data direction
        ArraySetAsSeries(consecUpBars, true); // set the up bars indicator buffer (array) to align with the time series of price data
        ArraySetAsSeries(consecDnBars, true); // set the down bars indicator buffer (array) to align with the time series of price data

   int limit; // declare a variable of the integer type to store the main loop starting bar index
   int bar; // declare a variable of the integer type to store the current bar index
   
   //--- calculation of the starting bar index                   
   limit = rates_total + (MaxBars - rates_total) - 1;  // starting index for the calculation of all of the bars
                                                       // use rates_total - 1 for reverse chronological loop
                                                       // avoids the need to use prev_calculated
                                                       // skip all bars except MaxBars ==> a negative integer is added to rates_total - 1

   //--- main loop
   for(bar = limit; bar >= 0; bar--) // loop iterates in reverse chronological order starting at current bar 0
                                     // adding 1, 2, 3, an so on for previous/older bars
                                     // every call to a specific bar number inside the loop must reference the variable, bar
     {
      // consecutive up bars
      if(Close[bar] > Open[bar] // current close is higher than current open ==> a curent up bar
         && Close[bar + 1] < Open[bar + 1]) // previous close is lower than previous open ==> a previous down bar
        {
         countUp = 1; // set the up bar count to 1 ==> to prepare for a potential consecutive up bars swing
        }
         
      if(Close[bar] > Open[bar] // current close is higher than current open ==> a current up bar
         && Close[bar + 1] > Open[bar + 1]) // previous close is higher than previous open ==> a previous up bar
        {
         countUp++; // add, and keep adding, to the up bar count ==> while additional up bars continue to form
        }
      
      consecUpBars[bar] = countUp; // set the up bars indicator buffer to the up bars count

      if(Close[bar] < Open[bar]) // current close is lower than current open ==> a current down bar
        {
         consecUpBars[bar] = 0; // set the up bars indicator buffer to 0 ==> the consecutive up bars swing has ended
        }

      // consecutive down bars
      if(Close[bar] < Open[bar] // current close is lower than current open ==> a current down bar
         && Close[bar + 1] > Open[bar + 1]) // previous close is higher than previous open ==> a previous up bar
        {
         countDn = 1; // set down bar count to 1 ==> to prepare for a potential consecutive down bars swing
        }
         
      if(Close[bar] < Open[bar] // current close is lower than current open ==> a current down bar
         && Close[bar + 1] < Open[bar + 1]) // previous close is lower than previous open ==> a previous down bar
        {
         countDn++; // add, and keep adding, to the down bar count ==> while additional down bars continue to form
        }
      
      consecDnBars[bar] = countDn; // set the down bars indicator buffer to the down bars count

      if(Close[bar] > Open[bar]) // current close is higher than previous open ==> a current up bar
        {
         consecDnBars[bar] = 0; // set the down bars indicator buffer to 0 ==> the consecutive down bars swing has ended
        }
     }

//--- return value of prev_calculated for next call
   return(rates_total + (MaxBars - rates_total) - 1); // again, rates_total is edited to reference MaxBars and - 1
                                                      // this aligns with the definition of the variable, limit
  }

//+------------------------------------------------------------------+

Thanks for reading. Discover premium MetaTrader solutions at RobotFX.

74521

Best MetaTrader Indicators + Profitable Expert Advisors