Libraries: IsNewBar

 

IsNewBar:

СIsNewBar class allows to determine the moment of a bar change. Usually IsNewBar() function is used for such things instead of a class. But such a function contains a static variable, and therefore we cannot use several calls of this function. To be able to reuse such function repeatedly in Expert Advisor's code, it would be much easier to make it a class member. In this case that has been accomplished using IsNewBar.mqh.

Author: Nikolay Kositsin

 
Automated-Trading:

IsNewBar:

Author: Nikolay Kositsin

There is a little bug in your class (as in most of the functions I saw the code). First time you call you method IsNewBar, it always return true, irrespective of the existence of a real new bar.

But such a function contains a static variable, and therefore we cannot use several calls of this function.

One can also use a two dimensional array to keep last bar open time.

 
I made a alternative version of CIsNewBar, without any static variable. I just used the Tick.time_msc to do a idempotent function:


class CIsNewBar{
private:
   long checkedMs;
   datetime lastBarOpenedAt;
   bool lastValue;
   CTickUtils tickUtils;
public:
   CIsNewBar(){}
   ~CIsNewBar(){}

   bool isNewBar(){
      MqlTick tick;
      SymbolInfoTick(_Symbol, tick);
      long tickMs = tick.time_msc;

      
      if(checkedMs >= tickMs){ //already processed this function on this tick?
         return lastValue;     //so, return the buffered value
      }

      datetime time[1];
      CopyTime(_Symbol, _Period, 0, 1, time);


      if(lastBarOpenedAt != time[0]){
         lastBarOpenedAt = time[0];
         lastValue = true;
      } else {
         lastValue = false;
      }

      checkedMs = tickMs;
      return lastValue;
   }
 

I think this is a speedy lightweight class that fixes the above mentioned problems.

This version:

  • won't give a false alert on the first time the .isNewBar() function is called. 
  • eliminates the constant re-instantiation of new variables each time the function is called without using static variables, which speeds up execution. 
  • returns true only one time per bar.
  • has a lightweight memory footprint. 
class CIsNewBar{
        private:
                datetime lastBarOpenedAt;
                datetime time[1];
        public:
                CIsNewBar(){CopyTime(_Symbol, _Period, 0, 1, time);lastBarOpenedAt = time[0];}
                ~CIsNewBar(){}
                bool isNewBar(){
                        CopyTime(_Symbol, _Period, 0, 1, time);
                        if(lastBarOpenedAt < time[0]){
                                lastBarOpenedAt = time[0];
                                return(true);
                                }
                        else { return(false);}
                        }
        };

To implement the class:

CIsNewBar someName;

void OnTick(){
        if(someName.isNewBar()){
                /// Call new bar event handler or
                /// Do work for new bar. 
                }
        }
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
  • www.mql5.com
Predefined Macro Substitutions - Named Constants - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

@DeepFocus' code works great but I've made some minor adjustments so it's compatible with any Symbol or Timeframe.


class CNewCandle {
  private:
    string              m_symbol;
    ENUM_TIMEFRAMES     m_timeframe;
    datetime            m_lastBarOpenedAt;
    datetime            m_time[1];

  public:
                     CNewCandle(const string symbol, const ENUM_TIMEFRAMES timeframe);
                    ~CNewCandle(void) {};

                     bool                       IsNewCandle(void);
};


CNewCandle::CNewCandle(const string symbol, const ENUM_TIMEFRAMES timeframe) {
    m_symbol = symbol;
    m_timeframe = timeframe;
    CopyTime(m_symbol, m_timeframe, 0, 1, m_time);
    m_lastBarOpenedAt = m_time[0];
}


/**
 * @brief Check if a new candle has been formed
 *
 * @return true | false
 */
bool CNewCandle::IsNewCandle(void) {
    CopyTime(m_symbol, m_timeframe, 0, 1, m_time);
    if(m_lastBarOpenedAt < m_time[0]) {
        m_lastBarOpenedAt = m_time[0];
        return(true);
    } else {
        return(false);
    }

}


To Implement:

CIsNewCandle someName(_Symbol, PERIOD_CURRENT);

void OnTick(){
        if(someName.IsNewCandle()){
                /// Call new bar event handler or
                /// Do work for new bar. 
                }
        }

Reason: