Аналог iBarShift - страница 14

 
fxsaber:

Тогда не понимаю, почему Bars считает, что 18:00:01 принадлежит M1-бару 18:01, а не 18:00.

А здесь такая же логика, как то, что моей дочке сейчас идет второй годик, хотя ей исполнился один год лишь неделю назад. Или сегодня 09.04.2018 года, хотя 01 января 00 года было 2017 лет, 3 месяца и 8 дней назад .

Кстати, TimeCurrent нужно заменить на SYMBOL_TIME.

Спасибо! Я реально не знал про такой идентификатор.

 

Кстати, когда я тестировал на правильность алгоритма iBars, сравнивая с эталоном Bars в MQL4, перебирая случайным образом различные варианты, то обнаружил баг в Bars:

Print(Bars(_Symbol,PERIOD_MN1,D'2005.08.31 00:00:00',D'2005.08.31 23:00:00')); // 1  должен быть 0, т.к. временной диапазон находиться внутри одного бара.
Print(Bars(_Symbol,PERIOD_MN1,D'2006.08.31 00:00:00',D'2006.08.31 23:00:00')); // 0

Причем на MQL5 этого бага нет.

Он конечно малозначительный, т.к. он появляется только на ТФ = MN1, при датах 30 и 31, часах времени stop_time = 23 и только до 2005 года :)))

Вот скрипт для MQL4, который его отлавливает, при этом iBars оказался более эталонным чем родной Bars.

Файлы:
TestiBars.mq4  10 kb
 
fxsaber:


Кстати, TimeCurrent нужно заменить на SYMBOL_TIME.

Нет, не нужно.
Корректности она не добавит, т.к. TimeCurrent() универсальная для всех символов, т.к. возвращает последнее время прихода котировки по всем символам, а не по текущему.

При этом SymbolInfoInteger(symbol_name,SYMBOL_TIME) очень тормознутая в сравнении с TimeCurrent(), а это время необходимо при каждом вызове iBars

 

Для тех, кому интересно.

Подредактированная версия iBars (аналог встроенной Bars, только без глюков и быстрее).

Исправлены некоторые ошибки. 

Если вы наблюдали, что ваш MQL5-код ни с того, ни с сего подвисает на 10-20 секунд и в нем есть функция Bars, которая может возвращать 0, тогда настоятельно рекомендую заменить ее на этот вариант.
Будет работать быстрее и без этого зависания. 

int iBars(string symbol_name,ENUM_TIMEFRAMES  timeframe,datetime start_time,datetime stop_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(LastTimeFrame!=timeframe) if(timeframe==PERIOD_MN1) PerSec=2419200; else PerSec=::PeriodSeconds(timeframe);
   if(timeframe<PERIOD_W1) TimeCur-=TimeCur%PerSec;
   if(start_time>TimeCur) {LastSymb=NULL; return(0);}
   if(LastTimeFrame!=timeframe || LastSymb!=symbol_name || ((TimeCur-LastBAR)>0 && 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 tS,tF=0;
   bool check=true;
   if(timeframe<PERIOD_W1) tS=start_time-(start_time-1)%PerSec-1;
   else if(timeframe==PERIOD_W1) tS=start_time-(start_time-259201)%PerSec-1;
   else
     {
      PerSec=2678400;
      MqlDateTime dt;
      TimeToStruct(start_time-1,dt);
      tS=dt.year*12+dt.mon;
     }
   if(stop_time<=LastBAR)
     {
      if(timeframe<PERIOD_W1) tF=stop_time-(stop_time)%PerSec;
      else if(timeframe==PERIOD_W1) tF=stop_time-(stop_time-259200)%PerSec;
      else
        {
         MqlDateTime dt0;
         TimeToStruct(stop_time,dt0);
         tF=dt0.year*12+dt0.mon;
        }
      if(tS==tF) {PreBars=0; check=false;}
     }
   if((LastTimeFrame!=timeframe || LastSymb!=symbol_name || tS!=LastTime || tF!=LastTime0) && check)
      PreBars=Bars(symbol_name,timeframe,start_time,stop_time);
   LastTime=tS; LastTime0=(datetime)tF;
   LastTimeFrame=timeframe;
   LastSymb=symbol_name;
   return(PreBars);
  }
 
Nikolai Semko:

Подредактированная версия iBars (аналог встроенной Bars, только без глюков и быстрее).

Исправлены некоторые ошибки. 

Встроенная Bars() перегружена:

1. int Bars(const string symbol_name,ENUM_TIMEFRAMES timeframe)
2. int Bars(const string symbol_name,ENUM_TIMEFRAMES timeframe,datetime start_time,datetime stop_time)

У вас лишь одна форма вызова.

 
Artyom Trishkin:

Встроенная Bars() перегружена:

У вас лишь одна форма вызова.

если нужна короткая форма, то вполне нормально пользоваться встроенной. Вряд ли там есть глюки.

 
Nikolai Semko:

Нет, не нужно.
Корректности она не добавит, т.к. TimeCurrent() универсальная для всех символов, т.к. возвращает последнее время прихода котировки по всем символам, а не по текущему.

При этом SymbolInfoInteger(symbol_name,SYMBOL_TIME) очень тормознутая в сравнении с TimeCurrent(), а это время необходимо при каждом вызове iBars

Котиры могут идти по всем символам, кроме интересуемого.

Ладно, посмотрел новый исходник. Увидел, что правки, которые обсуждали, не сделаны. Выхожу.

 
Вот почему разработчики не сделают это сами? 
 
Было бы намного удобнее пользователям чтобы вызвать одну функцию и получить синхронизированный (выровненный) по времени массив рядов по нескольким инструментам
 
Кстати, по поводу функции Bars(). Возможно - это причина клинча.