Узнать время первого часового бара дня - страница 2

 
Aleksandr Slavskii #:

Блин, наврал.

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

Визуально похоже на то, что написал  Ihor Herasko, но работает по другому и результат выдаёт правильный.

Доброе утро, Александр! Интересный момент обнаружил при использовании Вашего кода. Оформил его в виде скрипта и запустил на символе EURUSD с таймфреймом М1. Получил результат вывода на печать:

2023.02.13 10:25:38.751 Proba_Open_Day (EURUSDrfd,M1)   2023.02.13 02:01:00

Дальше запускаю на том же самом символе, но уже с таймфреймом D1, а результат уже другой:

2023.02.13 10:28:00.563 Proba_Open_Day (EURUSDrfd,D1)   2023.02.13 00:00:00

Честно говоря, не понял, почему так произошло.

С уважением, Владимир.

 
Alexey Viktorov #:

PeriodSeconds(PERIOD_H1) я взял для уменьшения объёма полученных тиков. Да и тема размещена там, где нет гарантий, что это касается мосбиржи. Так-что можно заменить (timeDay+PeriodSeconds(PERIOD_H1))*1000 даже на TimeCurrent()*1000

О какой универсальности вы говорите? 

Хочется, чтоб один раз написал, а работало оно везде, хоть на форексе, хоть на Мосбирже, хоть на CME и не зависимо от перехода на зимнее/летнее время  :)

 

Если в Вашем коде вместо PERIOD_CURRENCY использовать PERIOD_D1, то вот тогда время совпадает на всех таймфреймах и равно 00:00:00. Хотя, время, когда появился первый тик по текущему символу, было 02:00:00. Вот такая ситуация.

С уважением, Владимир.

 
MrBrooklin #:

Доброе утро, Александр! Интересный момент обнаружил при использовании Вашего кода. Оформил его в виде скрипта и запустил на символе EURUSD с таймфреймом М1. Получил результат вывода на печать:

Дальше запускаю на том же самом символе, но уже с таймфреймом D1, а результат уже другой:

Честно говоря, не понял, почему так произошло.

С уважением, Владимир.

Потому, что : справка - "время открытия баров должны соответствовать таймфрейму M1". А код берёт значение времени открытия бара. На дневке не может быть бара с часами и минутами, только 00:00

Вот поэтому код от  Alexey Viktorov будет корректно работать на всех таймфреймах, но не на всех торговых площадках.

А мой код корректен на всех торговых площадках, но не на всех таймфреймах )))

Но если исправить на 

   datetime time[];
   datetime TimeOpenDay = iTime(_Symbol, PERIOD_D1, 0);
   CopyTime(_Symbol, PERIOD_M1, TimeOpenDay, TimeCurrent(), time);
   TimeOpenDay = time[0];
   Print(TimeOpenDay);

То вполне корректно будет на разных таймах.

 
Aleksandr Slavskii #:

Потому, что графики строятся кратно минуте. А код берёт значение времени открытия свечи.

Вот поэтому код от  Alexey Viktorov будет корректно работать на всех таймфреймах, но не на всех торговых площадках.

А мой код корректен на всех торговых площадках, но не на всех таймфреймах )))

Но если исправить на 

То вполне корректно будет на разных таймах.

Спасибо. Только что, хотел предложить решение с PERIOD_M1, но Вы меня уже опередили. :)

С уважением, Владимир.

 
Aleksandr Slavskii #:

Хочется, чтоб один раз написал, а работало оно везде, хоть на форексе, хоть на Мосбирже, хоть на CME и не зависимо от перехода на зимнее/летнее время  :)

От перехода на зимнее\летнее время и так ничего не зависит. А вот на форексе или мосбирже зависит от типа тиков. Так-что если есть огромное желание скрестить топор и метлу, то можете поставить соответствующую проверку и от этого запрашивать какие тики считать.

 

Бурная дискусия образовалась :) Всем привет и спасибо за комментарии! Все верно: основная проблема в том, что время открытия бара кратно таймфрейму. Если на графике время открытия дневного бара 00:00:00, то по факту это совершенно не означает, что рынок открылся в это же время. При попытке получения котировок первого часа по времени открытия дневного бара система возвращает данные последнего бара предыдущего дня, потому что бара с запрашиваемым временем открытия по факту не существует. Это описано в документации:

При запросе данных по начальной дате и количеству требуемых элементов возвращаются только данные, дата которых меньше (раньше) или равна указанной. При этом интервал задается и учитывается с точностью до секунды. То есть дата открытия любого бара, для которого возвращается значение (объем, спред, значение в индикаторном буфере, цена Open, High, Low, Close или время открытия Time), всегда равна или меньше указанной.

https://docs.mql4.com/ru/series/copytime

Поэтому было решено написать функцию. Для определения фактического времени открытия рынка (в данном случае используется первый минутный бар в сутках) мы перебираем минутные бары с 23 часов предыдущего дня до 4 часов следующего дня (для надежности :)) и ищем первый бар в новом дне. Может кому пригодится:

datetime getFirstBarTimeByDay(datetime anyDayTime = 0) {
   if (0 == anyDayTime)
      anyDayTime = TimeCurrent();

   MqlDateTime day;
   TimeToStruct(anyDayTime, day);

   string strDayStartTime = day.year+"."+day.mon+"."+day.day+" 00:00:00";
   datetime dtStartTime = StrToTime(strDayStartTime);

   MqlRates MOCRates[300];
   CopyRates(_Symbol, PERIOD_M1, dtStartTime + PeriodSeconds(PERIOD_H4), 300, MOCRates);

   for(int i = 0; i < 299; i++)
   {
      datetime dtBarOpen = MOCRates[i].time;
      MqlDateTime barOpen;
      TimeToStruct(dtBarOpen, barOpen);

      if(dtBarOpen >= dtStartTime)
      {
         Comment(
            "Day Open Time: " + TimeToStr(dtBarOpen,TIME_DATE|TIME_MINUTES|TIME_SECONDS) + "\n"
         );
         return dtBarOpen;
      }
   }

   return 0;
}
 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Узнать время первого часового бара дня

multiwins, 2023.02.14 22:13

Бурная дискусия образовалась :) Всем привет и спасибо за комментарии! Все верно: основная проблема в том, что время открытия бара кратно таймфрейму. Если на графике время открытия дневного бара 00:00:00, то по факту это совершенно не означает, что рынок открылся в это же время. При попытке получения котировок первого часа по времени открытия дневного бара система возвращает данные последнего бара предыдущего дня, потому что бара с запрашиваемым временем открытия по факту не существует. Это описано в документации:

Поэтому было решено написать функцию. Для определения фактического времени открытия рынка (в данном случае используется первый минутный бар в сутках) мы перебираем минутные бары с 23 часов предыдущего дня до 4 часов следующего дня (для надежности :)) и ищем первый бар в новом дне. Может кому пригодится:

datetime getFirstBarTimeByDay(datetime anyDayTime = 0) {
   if ("0" == anyDayTime)
      anyDayTime = TimeCurrent();

   MqlDateTime day;
   TimeToStruct(anyDayTime, day);

   string strDayStartTime = day.year+"."+day.mon+"."+day.day+" 00:00:00";
   datetime dtStartTime = StrToTime(strDayStartTime);

   MqlRates MOCRates[300];
   CopyRates(_Symbol, PERIOD_M1, dtStartTime + PeriodSeconds(PERIOD_H4), 300, MOCRates);

   for(int i = 0; i < 299; i++)
   {
      datetime dtBarOpen = MOCRates[i].time;
      MqlDateTime barOpen;
      TimeToStruct(dtBarOpen, barOpen);

      if(dtBarOpen >= dtStartTime)
      {
         Comment(
            "Day Open Time: " + TimeToStr(dtBarOpen,TIME_DATE|TIME_MINUTES|TIME_SECONDS) + "\n"
         );
         return dtBarOpen;
      }
   }

   return 0;
}

Что за глупость? У вас входящая переменная типа datetime, а потом вы её проверяете со строкой "0"

Дальше даже смотреть нет желания. Тоже чушь несусветная… Если вам надо получить время с точностью до минуты, то проще так

  datetime timeDay = iTime(_Symbol, PERIOD_D1, 0);
  MqlRates rates[];
  int ticks = CopyRates(_Symbol, PERIOD_M1, timeDay, TimeCurrent(), rates);
   Print(rates[0].time);
 
   datetime time_D1x[];// стандартное направление слева направо - нулевой элемент - слева
   ArraySetAsSeries(time_D1x,true);    // перенаправление индексов массива справа налево - как бары на графике - справа - нулевой элемент
   int copied=CopyTime(NULL,PERIOD_D1,0,10,time_D1x); //--- скопировали 10 значений времени ( но будем использовать только одно - нулевое  )
   datetime time_H1x[];              // стандартное направление слева направо
   ArraySetAsSeries(time_H1x,true);  // перенаправление индексов массива справа налево - как бары на графике
   int i = CopyTime(_Symbol, PERIOD_H1,  TimeCurrent(), time_D1x[0], time_H1x); //---    получить количество скопированных баров
   Print(time_H1x[i-1]); //--- минус 1 -  обращение к последнему элементу,  : т.к. нулевой элемент идет в счет "количества элементов в массиве"
// в данном случае, начало на 5, 25, 55 минутах покажет открытие часового бара - 00:00:00 - как и было необходимо по задаче. 
// для определения минутного начала работы рынка, необходимо обращаться к минутному периоду, т.е. PERIOD_H1 заменить на PERIOD_M1
// для последовательного получения времени открытия : сегодня, вчера, позавчера, ... необходимо соответственно обратиться к 
// последующим значениям элементов в дневном массиве : 0, 1, 2, ... 
 
DDFedor #:

Стесняюсь спросить, а зачем копировать 10 значений, если использоваться будет только ОДНО??? И зачем кувыркать массивы с ног на голову?