Analogue to iBarShift - page 12

 
Nikolai Semko :

You said that everything should work in MQL4.

But this script can be run in MQL5 too

With exact=True and future time you should return -1

My script also found a strange error:

This error is confirmed by this check:

So I was right about the existence of abnormal situations in your algorithm after all.

It's nice that you finally found the error

I will check it out, thank you.

 

Good evening all. Perhaps I'm misunderstanding something, but still - it's not quite clear what's wrong with the standard function, which has already been suggested at the beginning of Bars(). I've been using it all the time and it hasn't caused any problems. The only thing is that you may encounter "array out of range" or negative value when using TimeCurrent(), but then you need to make a check for it. Examples:

//найти бар на котором продали
Bar_sell_H4=Bars(Symbol(),PERIOD_H4,P_opentime,32000000000)-1;
if(Bar_sell_H4<=0)
   {
      Bar_time_sell_H4=Time_H4[0];
   }
else
   {
      Bar_time_sell_H4=Time_H4[Bar_sell_H4];
   }
Bars_forsearch_highfr_H1=Bars(Symbol(),PERIOD_H1,TimeCurrent(),Time_M15[B_DownTrend_M15_int]);
if(Bars_forsearch_highfr_H1<=0)
   {
      high_H1_int=0;
   }
else
   {
      high_H1_int=ArrayMaximum(High_H1,0,Bars_forsearch_highfr_H1);
   }
 
Almat Kaldybay:

Good evening all. Perhaps I'm misunderstanding something, but still - it's not quite clear what's wrong with the standard function, which has already been suggested at the beginning of Bars(). I've been using it all the time and it hasn't caused any problems. The only thing is that you may encounter "array out of range" or negative value when using TimeCurrent(), but then you need to make a check for it. Examples:

Judging by the number 32000000000 this is also my creation. UINT_MAX is simply shorter and more solid looking. ))

The point is that this variant is more correct, as it turns out:

Bars(Symb,TimeFrame,time+1,UINT_MAX);

rather than

Bars(Symb,TimeFrame,time,UINT_MAX)-1;

there is almost no external difference. But the upper variant repeats very precisely the standard iBarShift function of MQL4

 
Nikolai Semko:

Judging by the number 32000000000, this is also my creation. UINT_MAX simply looks shorter and more solid. ))

The point is that this variant is more correct, as it turns out:

rather than

there is almost no external difference. But the upper variant repeats very precisely the standard iBarShift function of MQL4.

So what's the easiest and the right one?

 
Vitaly Muzichenko:

So what's the easiest and the right thing to do?

So far this variant, but now I want to supplement it to bypass the bug of Bars function freeze, about which I have already reported to Service Desk.

The essence of this bug is that if in Bars function bothstart_time andstop_time are inside one bar or are in the future (to the right of zero bar), then this function hangs for more than 10 seconds.

Maybe I'll make a proper faster but more cumbersome version later.

 

I have decided to go a different way.
I won't redo iBarShift, but will redo the glitchy Bars feature.

And the new iBars feature will not only bypass the hiccups bug, it will also be faster than the original Bars.

Others will be able to use this feature and the algorithms already in place will work faster.

I just need time. I won't be able to do it until a day later.

 
Nikolai Semko:

I've decided to go a different route.
I won't redo iBarShift, but will redo the glitchy Bars feature.

And the new iBars feature will not only bypass the hiccups bug, it will also be faster than the original Bars.

Others will be able to use this feature and the algorithms already in place will work faster.

I just need time. Won't be able to do it before one day.

Very good! Looking forward to it!

 
Nikolai Semko:

From all the analysis I've done, we can conclude that this full analogue of the iBarShift:

int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=Bars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==Bars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }

is by far the most correct, and at the same time the fastest and with the simplest and shortest algorithm.

It's nice, but something confuses me...

will have to test it )

 

The iBars function is quite cumbersome, but I still recommend using it instead of the regular Bars, until MQ fixes the hang-up bug in it.

The iBar hangs when logically it should return 0. As a rule, it returns it for more than 10 seconds. There is no such bug in MQL4.

In the majority of tasks, iBars will work faster than the regular Bars since it will not only avoid the bug, but tries not to use the Bars and SeriesInfoInteger functions whenever possible due to the algorithm of saving previous values.

int iBars(string symbol_name,ENUM_TIMEFRAMES  timeframe,datetime start_time,datetime stop_time) // stop_time > start_time
  {
   static string LastSymb=NULL;
   static ENUM_TIMEFRAMES LastTimeFrame=0;
   static datetime LastTime=0;
   static datetime LastTime0=0;
   static int PerSec=0;
   static int PreBars=0;
   static datetime LastBAR=0;
   static datetime LastTimeCur=0;
   datetime TimeCur;
   if(stop_time<start_time) {TimeCur=stop_time; stop_time=start_time; start_time=TimeCur; }
   TimeCur=TimeCurrent();
   if(start_time>TimeCur) {LastSymb=NULL; return(0);}
   if(LastTimeFrame!=timeframe) if(timeframe==PERIOD_MN1) PerSec =2419200; else PerSec=::PeriodSeconds(timeframe);
   if(LastTimeFrame!=timeframe || LastSymb!=symbol_name || ((TimeCur-LastBAR)>=PerSec && TimeCur!=LastTimeCur))
      LastBAR=(datetime)SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE);

   LastTimeCur=TimeCur;
   if(PerSec==0) return(0);
   if(start_time>LastBAR)
     {LastTimeFrame=timeframe; LastSymb=symbol_name; return(0);}

   datetime t,t0=0;
   bool check=true;
   if(timeframe<PERIOD_W1) t=start_time-(start_time-1)%PerSec;
   else if(timeframe==PERIOD_W1) t=start_time-(start_time-259201)%PerSec;
   else
     {
      PerSec=2678400;
      MqlDateTime dt;
      TimeToStruct(start_time-1,dt);
      t=dt.year*12+dt.mon;
     }
   if(stop_time<=LastBAR)
     {
      if(timeframe<PERIOD_W1) t0=stop_time-(stop_time)%PerSec;
      else if(timeframe==PERIOD_W1) t0=stop_time-(stop_time-259200)%PerSec;
      else
        {
         MqlDateTime dt0;
         TimeToStruct(stop_time,dt0);
         t0=dt0.year*12+dt0.mon;
        }
      if(t0==t) {PreBars=0; check=false;}
     }
   if((LastTimeFrame!=timeframe || LastSymb!=symbol_name || t!=LastTime || t0!=LastTime0) && check)
      PreBars=Bars(symbol_name,timeframe,start_time,stop_time);
   LastTime=t; LastTime0=t0;
   LastTimeFrame=timeframe;
   LastSymb=symbol_name;
   return(PreBars);
  }

I have tested this function far and wide. It seems to be a full copy of Bars.

Perhaps it can be done in a more elegant way. If you have a desire, you are welcome. If you find errors, we will fix them.

So...

Then the full analogue of iBarsShift function will have the following form:

int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=iBars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==iBars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }

And variant without last parameter, which is used in the vast majority of cases will have this form:

int iBarShift1(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   return(iBars(Symb,TimeFrame,time+1,UINT_MAX));
  }
// ИЛИ БОЛЕЕ СОКРАЩЕННЫЙ БЕЗ ФУНКЦИИ:

iBars(Symb,TimeFrame,time+1,UINT_MAX);
 

Indicator showing the performance of the iBars function compared to the built-in Bars and the iBarShift function from @Alain Verleyen
Function execution time in microseconds.


Files: