0
votes

I'm using the code from this article https://www.mql5.com/en/articles/159 to calculate when a new bar opens but it's not displaying the historical data for the indicator.

I have modified the TimeCurrent() to iTime( _Symbol, _Period, shift ) so as to try to handle this, but it's not working.

Could you tell me what I'm doing wrong please?


    #property indicator_separate_window 
    #property indicator_buffers 1
    #property indicator_color1 RoyalBlue

    #include <Lib_CisNewBar.mqh>
    CisNewBar current_chart;

    //---- input parameters
    extern int    Length=18;      // Bollinger Bands Period
    extern int    Deviation=2;    // Deviation was 2
    extern double MoneyRisk=1.00; // Offset Factor
    extern int    Signal=1;       // Display signals mode: 1-Signals & Stops; 0-only Stops; 2-only Signals;
    extern int    Line=1;         // Display line mode: 0-no,1-yes  
    extern int    Nbars=1000;

    //---- indicator buffers
    double TrendBuffer[];
    extern bool SoundON=true;
    bool TurnedUp = false;
    bool TurnedDown = false;
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
      int init()
      {
       string short_name;
    //---- indicator line

       SetIndexBuffer(0,TrendBuffer);
       SetIndexStyle(0,DRAW_LINE,0,1);
       IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
       short_name="Example ("+Length+","+Deviation+")";
       IndicatorShortName(short_name);
       SetIndexLabel(0,"Trend Value");
       //----
       SetIndexDrawBegin(0,Length);
       //----
       return(INIT_SUCCEEDED);
      }

    void deinit()
    {
    }

    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[])
    {
       int    shift;

       for (shift=Nbars;shift>=0;shift--)
       {
          TrendBuffer[shift]=0;
       }

       for (shift=Nbars-Length-1;shift>=0;shift--)
       {    

          int period_seconds=PeriodSeconds(_Period);                    
          datetime     new_time=iTime(_Symbol,_Period,shift)/period_seconds*period_seconds; 

          if(current_chart.isNewBar(new_time)) 
          {
             Print("time[shift] = "+TimeToString(time[shift]));

             if( Close[shift] > Close[shift+1] )
                TrendBuffer[shift]=1;
                  else if(Close[shift] < Close[shift+1] ) 
                TrendBuffer[shift]=-1;
             else
                TrendBuffer[shift]=0;
             }
       }
            return(0);      
    }

Thanks.

1
Andrew, could you - please - complete your MCVE code? It #include-s <Lib_CisNewBar.mqh> with some struct{} definitions used in the code. Thanksuser3666197
@user3666197 The library can be downloade from here mql5.com/en/articles/159 I've not changed the library at all.Andrew

1 Answers

1
votes

a) The "new"-MQL4.56789 has another syntax

For Custom Indicator, the "new"-MQL4.56789 source shall rather read
void OnInit(){ ... }
and
void OnDeinit( const int anMT4_Reason2callDeinit ){ ... }


b) The datetime

Your code defines a variable new_time, typed as a datetime

The datetime type is intended for storing the date and time as the number of seconds elapsed since January 01, 1970.

and

Values range from 1 January, 1970 to 31 December, 3000

So, in case of your new_time assignment, the proper iTime() value is divided by an amount of PeriodSeconds() and right next it is re-multiplied by the exact same value, which should not change the value of the iTime() result.

Such operation, while having no theoretical impact on result, might in practice of a code-execution introduce a risk of a numerical inaccuracy, range overflow/underflow and a theoretical notice about a resolution of an 8-byte class storage is not helping to go past the upper bound limit, stated in the documentation as Dec-31, 3000.

In similar cases unpredicatable results and even MT4 unhandled exceptions and MQL4-code terminations are to be expected.

What worse one may expect for a production grade software? So, avoid, avoid and avoid any such risk.

There is no direct positive value for such a Custom Indicator calculation step.


c) TimeCurrent() / PeriodSeconds() side-effect of rounding

While iTime() is always divisible by it's "own" time-frame PeriodSeconds(), TimeCurrent() is not.

Thus one may read the original ( assumed ) construct of

TimeCurrent() / PeriodSeconds()   // .DIV is subject to rounding to int
              * PeriodSeconds();  //      before the forthcoming .MUL

"hacks" the need to align a [last known server time, time of the last quote receipt for one of the symbols selected in the "Market Watch" window] to one's "own" time-frame value of a start-of-current bar time.


d) The article is from 11 October 2010 (!) - be very carefull in MQL4

Current MQL4 code-execution engine is Build 890 ( 25 Sep 2015 ), so your cited source was using an MQL5 language syntax some 5 years old (!!), which namely in MQL4-domain means _be_very_carefull_

In the meantime string-s ceased to be string-s,
many GUI functions have several calling protocols in parallel,
and
countless man*years of DLL/API-code-base dev/maint were lost due to similar moving sands.

So -5- years gap is a warning per-se.


One never enters the same river twice


The recent state of "new"-MQL4.56789 allows a clean approach:

in case your motivation is just to be able to detect on-demand a situation a new bar has started, the Build-890/1174 compiler allows for a cleaner approach:

bool aNewBarEVENT(   const string anFxSYMBOL,               // _Symbol,
                     const int    aTimeFRAME                // PERIOD_M6
                     )
{    static int   pBars  = EMPTY;                           // previous
            int   oBars  = iBars( anFxSYMBOL, aTimeFRAME ); // observed

     if (         pBars == oBars ) return( False );         // .NACK
                  pBars  = oBars,  return( True  );         // .UPD + .ACK
}