Корректное сравнение дат

 

Сегодня я решил проверить и дописать код, над которыми сейчас думаю некоторое время. Вижу, что либо даты не сравниваются корректно, либо оператор return из функции не позволяет выйти целиком, либо ещё что-то.

Если есть такая структура:

int firstBarOfDayCheck(const MqlRates &rates[], int indexFrom) {
// код..
  
  for (int i = indexFrom + 1; i < limit; i++) {
    Print("___rates[", i, "].time = ", rates[i].time);
    Print("___dayStartDt = ", dayStartDt);
    if (rates[0].time < dayStartDt) {
      isFirstBarUnclosed = true;
      return -5;
    }

// код..

  Print("__________________________________________");

  return (limit - 1);
}

Я опустил весь остальной код т.к. он здесь не принципиален.

Особенно, интересен участок кода:

if (rates[0].time < dayStartDt) {

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

Вот что я вижу в журнале:

2024.10.23 00:49:52.232 2018.04.14 00:00:00   The first bar of the day has index 0, time 2018.04.14 00:00
2024.10.23 00:49:53.128 2018.04.16 01:00:00   Before for
2024.10.23 00:49:53.128 2018.04.16 01:00:00   ___rates[1].time = 2018.04.14 00:00:00
2024.10.23 00:49:53.128 2018.04.16 01:00:00   ___dayStartDt = 2018.04.16 00:00:00
2024.10.23 00:49:53.128 2018.04.16 01:00:00   After for
2024.10.23 00:49:53.128 2018.04.16 01:00:00   __________________________________________
2024.10.23 00:49:53.128 2018.04.16 01:00:00   The first bar of the day has index 0, time 2018.04.16 01:00

И так понятно, что ___rates[1].time < ___dayStartDt, а это означает, что из циукла должны мы выйти. И из функции firstBarOfDayCheck() тоже..

Но, далее я вижу:

Print("__________________________________________");

А значит, из функции не выходит. С чего это вдруг? Я уже придумал переменную булевскую (извращаюсь как могу), которая становится истиной, если условие времени, сравнение которого я привёл выше соблюдается. Не помогло.

Сколько писал в других языках, если указываешь return, выполнение функции завершается. С чего в друг не так?

Прирепляю файл целиком.

Файлы:
 
Виктор Демихов:
  datetime dayStartDt = calculateDayOpenDt(rates[indexFrom].time);
  for (int i = indexFrom + 1; i < limit; i++) {
    if (rates[0].time < dayStartDt) {
      isFirstBarUnclosed = true;
    }

  • Вопервых зачем оно внутри цикла?
  • Во вторых, в чем его смысл?
    • Вы ведь dayStartDt вычислили от rates[0].time, поэтому rates[0].time не может быть меньше dayStartDt.
      Результат выражения ((rates[0].time / 86400) * 86400) никогда не будет больше rates[0].time.
    • Только текущий бар является "unclosed".
      Текущий бар это rates[0] (при условии, что вы для CopyRates передаете start_pos = 0 и для массива rates[] установлен AS_SERIES = true).
      Другими словами, только самый правый бар на графике является "unclosed", все остальные - "closed".
 

Сама идея искать N-ый бар дня выглядит некорректной. Потому что вы не можете предвидеть время открытия того бара, так как несколько первых баров дня могут быть пропущены.

Если вам нужен индекс бара с конкретным временем открытия, то ищите именно его, а не N-ый бар дня. И обрабатывайте ситуацию, когда на графике отсутствует (пропущен) бар с нужным вам временем открытия.

Даже на H1 не всегда день начинается с бара со временем 00:00. Первый бар дня может иметь время открытия 01:00, 03:00, ...

 
Vladislav Boyko #:
Вопервых зачем оно внутри цикла?

Потому что это работает корректно только в скрипте, если уже 2-ой бар, т.е. индекс у него будет 1. Если бар не закрыт, результат прыгает и не всегда корректен. Может отобразить не то, что нужно.

Я это всё перенёс в бота и прогнал на истории. Открывает очередной день и вижу.. что цены открытия и закрытия дня не те, которые на самом деле у 1-го бара на заданном ТФ.

А внутри цикла условие почему.. я же писал, что return не отрабатывает почему-то..

Vladislav Boyko #:
Во вторых, в чем его смысл?

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

Vladislav Boyko #:
Результат выражения ((rates[0].time / 86400) * 86400) никогда не будет больше rates[0].time.

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


 
Vladislav Boyko #:
Даже на H1 не всегда день начинается с бара со временем 00:00. Первый бар дня может иметь время открытия 01:00, 03:00, ...

Так это уже от инструмента зависит. Я вот думаю, может проще не извращаться т.к. не особо много вариантов и удобств нет для комфортной реализации этой задачи. Может проще просто брать диапазон времени и всё?

Например,

0-бар, если часовик, то время открытия от 12.55 до 00.05

1-ый индекс (2-ой бар), цена открытия ищется с 00.55 до 01.05.

и т.д..

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

Цены незакрытого бара пляшут потому, что он не закрыт.

Виктор Демихов #:
Такой косяк может быть, если мы будет искать бар с 0-индексом, как я понимаю, находясь на 0-ом индексе.

Если искомый вами бар находится на нулевом индексе, то у вас 2 варианта:

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

Я не понимаю, что у вас на скриншоте и при чем здесь rates[0].time.

Виктор Демихов:
  Print("Before for");
  for (int i = indexFrom + 1; i < limit; i++) {
    Print("___rates[", i, "].time = ", rates[i].time);
    Print("___dayStartDt = ", dayStartDt);

А вы точно учли, что вы печатаете rates[i].time, но функция вернет (i - 1), а не i?

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

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

Сделайте принты корректными.

У вас в цикле сравнение идёт с  нулевым индексом 

rates[0].time

а распечатываете совсем с другим индексом

Print("___rates[", i, "].time = ", rates[i].time);

Вот когда в распечатке будет, то что в сравнении

if (rates[0].time < dayStartDt)

вот тогда посмотрим как работает return )))


Зы. а какая задача у этого кода? Что вы хотите получить на выходе?

 
Aleksandr Slavskii #:
Вот когда в распечатке будет, то что в сравнении

В том то и прикол, что никогда. Переменная i (счетчик цикла) никогда не будет равна нулю. Собственно этим и был вызван тот мой вопрос:

Vladislav Boyko #:
зачем оно внутри цикла?

[edit]

Цикл ищет ближайший бар предыдущего дня. А первый бар искомого дня находится на один бар правее, поэтому возвращается (i - 1).

 
Я так искал предыдущий бар. Но пишут, что код работает не стабильно.
Вопросы от начинающих MQL5 MT5 MetaTrader 5 - Проверьте на совпадение времени.
Вопросы от начинающих MQL5 MT5 MetaTrader 5 - Проверьте на совпадение времени.
  • 2024.10.14
  • Maxim Kuznetsov
  • www.mql5.com
Так как новая свеча открывается на некоторых символах позже. чем на основном - актуальные данные по тому символу не получим. и если на всех символах время открытия совпадает - продолжаем. -- Собственно вопрос Как сделать выполнение кода для тех символов
 

выдержка из более большого кода, как иллюстрация, лишние проверки покоцаны

тут ищется первый за предыдущий день, бар текущего ТФ (который меньше D1).

   // предыдущий день (любой)
   int prevDayShift=iBarShift(_Symbol,PERIOD_D1,time)+1;	// индекс пред.дня
   datetime prevDayTime=iTime(_Symbol,PERIOD_D1,prevDayShift);	// время D1
   int prevBarShift=iBarShift(_Symbol,PERIOD_CURRENT,prevDayTime);	// индекс на текущем ТФ (но может попасть в "позавчера")
   datetime prevBarTime=iTime(_Symbol,PERIOD_CURRENT,prevBarShift);	// и его время
								// так как может попасть в "позавчера" - придётся сдвигать, пока не попадём
   while(prevBarShift>0 && prevBarTime<prevDayTime) {
      prevBarShift--;
      prevBarTime=iTime(_Symbol,PERIOD_CURRENT,prevBarShift);
   }

просто iBarShift возвращает первый подходящий бар с временем меньше указанного. То есть если время попадает в выходной, или есть пропуски баров то может вернуть последний бар предыдущего дня (недели) вместо ожидаемого первого.
Поэтому его результат приходится фиксить небольшим циклом