N-ый открытый бар на определённом таймфрейме - страница 3

 
Виктор Демихов #:

Неординарная реализация, которая заставила меня призадуматься..

Особенно, строка:

TimeCurrent() делим и умножаем на тоже самое. Что это нам даёт?

Чтобы было проще проанализровать правильный ли алгоритм, я накинул индюк, отображающий торговые сессии и распринтовал значения цена открытия, закрытия, хай и лоу. Вижу, что всё выдаёт верно, но есть один косяк. Тол и в котировках, то ли в логике кода.

До смены торговой сессии всё чётко, все цены корректные и нужные. И один принт при смене торговой сессии выдаёт не актуальную информацию. А дальше всё снова верно. Интересно, с чем это связано. Я вот так проверил в боте:

делим время от 1970 на кол-во секунд в сутках. НАЦЕЛО ! предполагаем получить кол-во полных дней с того момента. 

потом снова умножаем и ожидаем увидеть время начала дня. Фокус в целочисленном делении.

В принципе логично, если секунду не подкручивали. Условия подкрутки одной секунды не помню :-(

вообще это плохая практика работы с реальным временем. но зато быстрая. 

 
Maxim Kuznetsov #:

делим время от 1970 на кол-во секунд в сутках. НАЦЕЛО ! предполагаем получить кол-во полных дней с того момента. 

потом снова умножаем и ожидаем увидеть время начала дня. Фокус в целочисленном делении.

В принципе логично, если секунду не подкручивали. Условия подкрутки одной секунды не помню :-(

вообще это плохая практика работы с реальным временем. но зато быстрая. 

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

только в правильно получать а не в MQL5 формате, дальше сами преобразуете и уберете лишнее

MQL6 уже давно актуален

там ведб вопрос не в ленивости изучения только, а просто никто не знает какие там процессы, как все работает, если это все не знать, то и вообще надо упразднить большую часть функционала


я работаю с огромными каталогами данных, если-бы я их полностью внедрял, производитель охренел бы от одной только номенклатуры, а если я уйду от них то, и от кол-ва ненужных настроек

 
lynxntech #:

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

вообще можно было не делить на const чтобы после умножить, а просто взять модуль - получить кол-во секунд с начала календарного дня. Как правило именно они важны для дальнейших рассчётов

повторюсь, это неправильно, со временем так не работают. Это чревато ошибками

 
Maxim Kuznetsov #:

вообще можно было не делить на const чтобы после умножить, а просто взять модуль - получить кол-во секунд с начала календарного дня. Как правило именно они важны для дальнейших рассчётов

повторюсь, это неправильно, со временем так не работают. Это чревато ошибками

Максим, в Терминале есть уже точные "час" и минуты, в Обзоре рынка

но досихпор умножаем 60*60*24

 
lynxntech #:

Максим, в Терминале есть уже точные "час" и минуты, в Обзоре рынка

но досихпор умножаем 60*60*24

писать 24*60*60 сильно читабельнее длинной константы или её имени (SECONDS_IN_DAY например.. в MQL и так имён гора) :-)

а потом в любом продукте (индикаторе, советнике) по мере развития появляется методы OnDay() и так далее, и долгие сложные вычисления дат и смещений секунд резко упрощаются.

А во время начальных проб и ошибок, тестирования и развития - вполне катит, там важнее скорость реализации чем исполнения :-) 

 
Maxim Kuznetsov #:
вообще это плохая практика работы с реальным временем.

Почему плохая? Можете привести пример ситуации, когда это сработает неправильно?

Сам очень давно вычисляю таким образом время начала дня, ни разу проблем не было.

#define _secsInDay 86400
#define _calculDayStartDt(a) ((a / _secsInDay) * _secsInDay)
 
Vladislav Boyko #:
Почему плохая? Можете привести пример ситуации, когда это сработает неправильно?

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

По моему вопросу.. начало дня можно получить, если бар на рабочем таймфрейме закрыт. Иначе, пока он не закрыт цена закрытия будет всегда разная и плясать (на часовике целый час). Тут либо, конкретно забить время количествао милисекунд в чате и прибавить к началу дня это количество + несколько секунду для надёжности, толи ещё как-то изращаться. Ведь, чтобы получить цену закрытия нужного бара, нужно чтобы он точно закрылся..))

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

Я говорил про утверждение о плохой практике, а не о константах.


По поводу констант - вообще пофигу, как записывать. Если вы запишите как 24*60*60, то компилятор вычислит это выражение на этапе компиляции и заменит на 86400.

Я вон вообще объявил свою константу с помощью макроса, так как мне лень копаться в справочнике и искать готовую.

По нормальному, в моем _calculDayStartDt нужно 'a' в скобки обернуть, конечно. Но я никогда не передам туда выражение.

 
Vladislav Boyko #:

Почему плохая? Можете привести пример ситуации, когда это сработает неправильно?

Сам очень давно вычисляю таким образом время начала дня, ни разу проблем не было.

например упомянутые выше доп.секунды года (не помню правил коррекций и как они учитываются в UNIXTIME. Но они есть.)

в работе с календарём надо полагаться на системные библиотеки, которые у нас транслируются через API терминала.

Или получать зарплату за реализацию альтернатив :-) За ф-цию "первый торговый день второго квартала прошлого года" например. Или кол-во баров от второго полугодия.


у нас ещё и календарь "рваный" - время первого дня недели не всегда совпадает с временем начала недели, кол-во 5-ти минуток в сутках может отличаться, и так далее..

то есть в надёжной реализации - всё равно будет CopyRates или iTime или iBarShift - так что не надо их объезжать. Знать особенности надо. Выигрыш в миллисек рассчета не скомпенсирует ошибку вычислений.

 

Велосипед на коленке за 10 минут. Никаких iXXX (терпеть их не могу)

#define _secsInDay 86400
#define _calculDayStartDt(a) ((a / _secsInDay) * _secsInDay)

#define _numOfBars 1000
void OnStart()
  {
   //--- Такой массив у вас уже где-то есть готовый, если вы не любитель обмазываться iXXX
   MqlRates arr[];
   ArraySetAsSeries(arr, true);
   if(CopyRates(Symbol(), PERIOD_CURRENT, 0, _numOfBars, arr) != _numOfBars)
     {
      Print("CopyRates() failed");
      return;
     }
   //--- Находим первый бар сегодняшнего дня
   int idxOfFirstBar = findIdxOfFirstBarOfDay(arr, 0);
   PrintFormat("The first bar of the day has index %i, time %s", idxOfFirstBar, TimeToString(arr[idxOfFirstBar].time));
  }
#undef _numOfBars

int findIdxOfFirstBarOfDay(const MqlRates &rates[], int idxFrom)
  {
   int limit = ArraySize(rates);
   datetime dayStartDt = _calculDayStartDt(rates[idxFrom].time);
   for(int i = idxFrom + 1; i < limit; i++)
      if(rates[i].time < dayStartDt)
         return(i - 1);
   Print(__FUNCTION__" Could not find the nearest bar of the previous day for ", TimeToString(rates[idxFrom].time));
   return(limit - 1);
  }

//---
#undef _secsInDay
#undef _calculDayStartDt