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

 
Vasiliy Pushkaryov:

Вот скрипт

Он просто виснет. Принудительно удалив его с графика, получаю результат.

Так что попробовал, поэтому посоветовал и Вам. Но раз Вы пользовались и Вам подходит, я переубеждать не буду.

Прошу прощения, Василий. Я вас не правильно понял. Просто быстро читал ваше сообщение, т.к. был за рулем. Я думал, что речь идет о последнем параметре, где у меня стоит 32000000000, оказывается Вы имели ввиду параметр t. Да, действительно,  - это единственый случай когда результат отличается от оригинального MQL4 iBarShift(). Но очень странно пытаться использовать эту функцию, чтобы получить количество бар ( или индекс бара) от текущего момента времени, т.е. TimeCurrent(), когда и так понятно что бар нулевой. Странно вообще что функция Bars() при времени TimeCurrent()  выдает 0, а не 1. Формально это косяк разработчиков, хотя как посмотреть.  А вот что-то виснуть из-за использования штатной  функции Bars() не может ну ни как, тем более скрипт отработал Print() , значит все ОК.
Поймите, Василий, я не хочу принижать другие реализации аналога iBarShift, просто лично я использую именно такую конструкцию (Bars(NULL,0,t,32000000000)-1;), так как она самая быстрая. И эта конструкция используется не как замена iBarShift, а просто как функция нахождения индекса бара по указанному времени, и мне не понятно что Вы имеете в виду под универсальностью. А использовать все вышеприведенные функции не считаю разумным из-за большей временной стоимости. (Вспомните рекламу порошка Дося). Дело в том, что использование данной функции очень часто происходит в больших циклах, что значительно увеличивает время выполнения программ,  а я жутко жаден до времени выполнения. Я проводил эксперементы по подсчету времени выполнения различных функций( и не только я, см. предыдущее сообщение) , и однозначно этот вариант самый быстрый. Даже этот вариант ,  который позиционируется как самый быстрый - тоже самое, просто в конструкции (Bars(NULL,0,t,32000000000)-1;) все еще более упрощено. Конечно, дело каждого, что юзать.

В любом случае спасибо Вам за ваше замечание по существу.

 
Nikolai Semko:

Но очень странно пытаться использовать эту функцию, чтобы получить количество бар ( или индекс бара) от текущего момента времени, т.е. TimeCurrent(), когда и так понятно что бар нулевой. Странно вообще что функция Bars() при времени TimeCurrent()  выдает 0, а не 1. Формально это косяк разработчиков, хотя как посмотреть.

TimeCurrent() просто как частный случай под руку попался.

Сейчас более внимательно прочитал вот это примечание к функции Bars():

"При запросе количества баров в заданном диапазоне дат учитываются только те бары, чье время открытия попадает в этот диапазон. Например, если текущий день недели — суббота, то при запросе количества недельных баров с указанием start_time=последний_вторник и stop_time=последняя_пятница функция вернет 0, так как время открытия на недельном таймфрейме всегда приходится на воскресенье, и ни один недельный бар не попадает в указанный диапазон."

Так как время TimeCurrent() почти все время позже времени открытия текущего бара, поэтому функция Bars() возвращает 0. Получается, если мы передадим в качестве параметра start_time время, соответствующее 02:05 на часовом ТФ, и хотим, чтобы нам засчитали бар, начавшийся в 2 часа, тогда нужно получить время открытия бара (02:00:00) через CopyTime(). Иначе функция Bars() этот бар проигнорирует.

Т.е. если сейчас время 3:30, я понимаю, что на часовом ТФ, время 2:05 относится к бару с индексом 1. Этот индекс не вернет ни одна из функций со 2-й страницы. Вот с такой поправкой функция Renat Akhtyamov вернула, то что я ожидал.

int iBarShift2(string symbol, ENUM_TIMEFRAMES timeframe, datetime time)
{
  datetime tm0[1], tm1[1];      
  CopyTime(symbol, timeframe, 0, 1, tm0);             // время открытия 0-го бара
  CopyTime(symbol, timeframe, time, 1, tm1);          // время открытия бара, в который попадает указанный time

  return Bars(symbol, timeframe, tm0[0], tm1[0])-1;
}

Прикладываю скрипт, с 4-мя вариантами функций по поиску индекса, который использовал в качестве теста.

Файлы:
TestIBS.mq5  5 kb
 
Vasiliy Pushkaryov:

TimeCurrent() просто как частный случай под руку попался.

Сейчас более внимательно прочитал вот это примечание к функции Bars():

"При запросе количества баров в заданном диапазоне дат учитываются только те бары, чье время открытия попадает в этот диапазон. Например, если текущий день недели — суббота, то при запросе количества недельных баров с указанием start_time=последний_вторник и stop_time=последняя_пятница функция вернет 0, так как время открытия на недельном таймфрейме всегда приходится на воскресенье, и ни один недельный бар не попадает в указанный диапазон."

Так как время TimeCurrent() почти все время позже времени открытия текущего бара, поэтому функция Bars() возвращает 0. Получается, если мы передадим в качестве параметра start_time время, соответствующее 02:05 на часовом ТФ, и хотим, чтобы нам засчитали бар, начавшийся в 2 часа, тогда нужно получить время открытия бара (02:00:00) через CopyTime(). Иначе функция Bars() этот бар проигнорирует.

Т.е. если сейчас время 3:30, я понимаю, что на часовом ТФ, время 2:05 относится к бару с индексом 1. Этот индекс не вернет ни одна из функций со 2-й страницы. Вот с такой поправкой функция Renat Akhtyamov вернула, то что я ожидал.

Прикладываю скрипт, с 4-мя вариантами функций по поиску индекса, который использовал в качестве теста.

Естественно нужно передать время бара. Забыл уточнить.
 
не понмиаю почему этой функции до сих пор нет в СБ
 
transcendreamer:
не понмиаю почему этой функции до сих пор нет в СБ

Перепробовал все варианты, самая правильная от Alain Verleyen. 
(тестировал на сложном индикаторе, с кучей объектов)
 
Taras Slobodyanik:

Перепробовал все варианты, самая правильная от Alain Verleyen. 
(тестировал на сложном индикаторе, с кучей объектов)
https://www.mql5.com/ru/code/18305
Высокопроизводительная библиотека iTimeSeries
Высокопроизводительная библиотека iTimeSeries
  • голосов: 17
  • 2017.05.25
  • nicholishen
  • www.mql5.com
Эта библиотека предоставляет молниеносный доступ к таймсериям для реализации привычных методов MQL4 (например, iBarShift) в чувствительных к задержкам приложениях на MQL5.
 

На мой взгляд использование функции SeriesInfoInteger  является излишнем, ведь она весьма не бесплатная.

Было:

int iBarShift3( const string Symb, const ENUM_TIMEFRAMES TimeFrame, datetime time, const bool Exact = false )
{
  static int Res = -1;
  static string LastSymb = NULL;
  static ENUM_TIMEFRAMES LastTimeFrame = 0;
  static datetime LastTime = 0;
  static bool LastExact = false;

  time -= time % ::PeriodSeconds(TimeFrame);

  if ((time != LastTime) || (Symb != LastSymb) || (TimeFrame != LastTimeFrame) || (Exact != LastExact))
  {
    datetime LastBar;

     if (::SeriesInfoInteger(Symb, TimeFrame, ::SERIES_LASTBAR_DATE, LastBar))
     {
        if (time > LastBar)
          Res = 0;
        else
        {
          const int Shift = ::Bars(Symb, TimeFrame, time, LastBar);

          if (Shift > 0)
            Res = Shift - 1;
        }
      }

    LastTime = time;
    LastSymb = Symb;
    LastTimeFrame = TimeFrame;
    LastExact = Exact;
  }

  return(Res);
}

Стало:

int iBarShift3(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,const bool Exact=false)
  {
   static int Res=-1;
   static string LastSymb=NULL;
   static ENUM_TIMEFRAMES LastTimeFrame=0;
   static datetime LastTime=0;
   static bool LastExact=false;
   static int PerSec=::PeriodSeconds(LastTimeFrame);
   
   if (LastTimeFrame!=TimeFrame) PerSec=::PeriodSeconds(TimeFrame);
   time-=time%PerSec;

   if((time!=LastTime) || (Symb!=LastSymb) || (TimeFrame!=LastTimeFrame) || (Exact!=LastExact))
     {
      Res=::Bars(Symb,TimeFrame,time,UINT_MAX)-1;
      if(Res<0) Res=0;

      LastTime = time;
      LastSymb = Symb;
      LastTimeFrame=TimeFrame;
      LastExact=Exact;
     }

   return(Res);
  }

Выигрыш в скорости где-то в полтора раза.

И, похоже, что это самый быстрый вариант. Правда последний параметр Exact  фейковый и его можно убрать. Но как по мне - так он и не нужен. Лично я ни разу не было задач, в которых бы надо было испльзовать Exact  = true.

Но если кому-то все же это нужно , тогда без CopyTime не обойтись и лучше использовать этот вариант от @Alain Verleyen.

ЗЫ: еще обошел лишние обращения к функции PeriodSeconds , если ТФ не менялся с последнего обращения. Выйгрыш правда слабый- несколько процентов, но все же. 

И еще одно уточнение: Конструкция

time-=time%PerSec;
будет отрабатываться некорректно при PERIOD_W1 и PERIOD_MN1, т.к. отсчет ведется с 1 января 1970 года, а это не понедельник, а четверг. И в каждом месяце разное количество секунд.
 
Nikolai Semko:

На мой взгляд использование функции SeriesInfoInteger  является излишнем, ведь она весьма не бесплатная.

Было:

Стало:

Выигрыш в скорости где-то в полтора раза.

И, похоже, что это самый быстрый вариант. Правда последний параметр Exact  фейковый. Но как по мне - так он и не нужен.

Или я не прав?

ЗЫ: еще обошел лишние обращения к функции PeriodSeconds , если ТФ не менялся с последнего обращения. Выйгрыш правда слабый- несколько процентов, но все же. 

Как заумно написан код, мне вот не понятно, поэтому спрошу. Будет ли код работать, если в чарте не полные сутки?

 
Aleksey Vyazmikin:

Как заумно написан код, мне вот не понятно, поэтому спрошу. Будет ли код работать, если в чарте не полные сутки?

Я не понял сути вопроса. Сформулируйте его как-то по другому. 

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

О каком ТФ идет речь? День? 

И что Вам мешает проверить?

Код не мой, я лишь его упростил и убыстрил

Я в своем предыдущем сообщении сделал дополнение на счет PERIOD_W1 и PERIOD_MN1.

Нештатные ситуации есть во всех алгоритмах, которые были до этого, в том числе и у @Alain Verleyen

Можно создать полный аналог iBarShift MQL4, но код будет весьма объёмный и смысла в этом я никакого не вижу. 

 
Nikolai Semko:

Я не понял сути вопроса. Сформулируйте его как-то по другому. 

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

О каком ТФ идет речь? День? 

И что Вам мешает проверить?

Код не мой, я лишь его упростил и убыстрил

Я в своем предыдущем сообщении сделал дополнение на счет PERIOD_W1 и PERIOD_MN1.

Нештатные ситуации есть во всех алгоритмах, которые были до этого, в том числе и у @Alain Verleyen

Можно создать полный аналог iBarShift MQL4, но код будет весьма объёмный и смысла в этом я никакого не вижу. 

Не проверял - потому что надо знать точно, будет работать код или нет под конкретную ситуацию, а то пенять на другого не корректно, если сам ошибся.

Я говорю о таких вот ситуациях, допустим у нас в сутках 14 часов(или меньше, если не было котировок каждый час), у меня чарт M1 и мне надо узнать сдвиг бара по M15 в прошлом дне. Т.е. будет ли корректно все работать, если в часе получилось 45 минут или в сутках 14 часов или ещё какие выпады временные/свечные?