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

 
Nikolai Semko #:

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

не проверял

Можно также вместо CopyRates использовать iOpen(), iClose(), iLow() ... по индексу бара, если не нужна полная заполненная структура MqlRates, т.к. она избыточна

Нет Николай. Для CopyRates без разницы сколько баров считывать, один или сто. Выигрыш в том, что после получения массива не будет никаких затрат на получение данных другого бара. А что касается iOpen(), iClose(), iLow()…… так это самый плохой вариант. И по скорости однозначно будет медленнее чем считывание массива структур для ста баров.

Потом, в вашем коде для чего вычислять номер бара по времени, если в CopyRates можно поставить время и количество баров для получения данных… 

 
Nikolai Semko #:

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

не проверял

Можно также вместо CopyRates использовать iOpen(), iClose(), iLow() ... по индексу бара, если не нужна полная заполненная структура MqlRates, т.к. она избыточна

iBarShift() внутри сводит в ноль все потуги ускорить и упростить. 

не проверял

на границе дней будет чудить

 
Alexey Viktorov #:

Нет Николай. Для CopyRates без разницы сколько баров считывать, один или сто. Выигрыш в том, что после получения массива не будет никаких затрат на получение данных другого бара. А что касается iOpen(), iClose(), iLow()…… так это самый плохой вариант. И по скорости однозначно будет медленнее чем считывание массива структур для ста баров.

Потом, в вашем коде для чего вычислять номер бара по времени, если в CopyRates можно поставить время и количество баров для получения данных… 

- Не верю. Все бары текущего дня уже есть в памяти с вероятностью очень близкой к 100%
- iBarShift  нужен для получения номера искомого бара, поэтому CopyRates по времени не годится
 
Maxim Kuznetsov #:

iBarShift() внутри сводит в ноль все потуги ускорить и упростить. 

на границе дней будет чудить

Ну я дал схему. Я все это знаю , так как работал с iBarShift дольше других. Проблемы могут возникнуть только в момент инициализации индикатора, но, как я понял, работать эта функция должна и в процессе работы индикатора. Как правило уместно ставить проверку на получение -1 от iBarShift и в этом случае использовать мой вариант fBarShift. Недавно писал об этом.
Все равно наноснкунды выигрывают у микросекунд
 
Nikolai Semko #:
Лучше уж как-то так:

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

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

datetime dayOpen = (TimeCurrent() / (24 * 60 * 60)) * 24 * 60 * 60;

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

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

2024.10.20 13:34:46.392 2018.04.13 20:00:00   ________________________
2024.10.20 13:34:47.285 2018.04.13 21:00:00   high = 1.55243
2024.10.20 13:34:47.285 2018.04.13 21:00:00   low = 1.55122
2024.10.20 13:34:47.285 2018.04.13 21:00:00   open = 1.55139
2024.10.20 13:34:47.285 2018.04.13 21:00:00   close = 1.55133
2024.10.20 13:34:47.285 2018.04.13 21:00:00   ________________________
2024.10.20 13:34:48.144 2018.04.13 22:00:00   high = 1.55243
2024.10.20 13:34:48.144 2018.04.13 22:00:00   low = 1.55122
2024.10.20 13:34:48.144 2018.04.13 22:00:00   open = 1.55139
2024.10.20 13:34:48.144 2018.04.13 22:00:00   close = 1.55133
2024.10.20 13:34:48.144 2018.04.13 22:00:00   ________________________
2024.10.20 13:34:49.018 2018.04.13 23:00:00   high = 1.55243
2024.10.20 13:34:49.018 2018.04.13 23:00:00   low = 1.55122
2024.10.20 13:34:49.018 2018.04.13 23:00:00   open = 1.55139
2024.10.20 13:34:49.018 2018.04.13 23:00:00   close = 1.55133
2024.10.20 13:34:49.018 2018.04.13 23:00:00   ________________________
2024.10.20 13:34:49.881 2018.04.14 00:00:00   high = 1.5551
2024.10.20 13:34:49.881 2018.04.14 00:00:00   low = 1.5551
2024.10.20 13:34:49.881 2018.04.14 00:00:00   open = 1.5551
2024.10.20 13:34:49.881 2018.04.14 00:00:00   close = 1.5551
2024.10.20 13:34:49.881 2018.04.14 00:00:00   ________________________
2024.10.20 13:34:50.740 2018.04.16 01:00:00   high = 1.55577
2024.10.20 13:34:50.740 2018.04.16 01:00:00   low = 1.55417
2024.10.20 13:34:50.740 2018.04.16 01:00:00   open = 1.5551
2024.10.20 13:34:50.740 2018.04.16 01:00:00   close = 1.55445
2024.10.20 13:34:50.740 2018.04.16 01:00:00   ________________________
2024.10.20 13:34:51.612 2018.04.16 02:00:00   high = 1.55577
2024.10.20 13:34:51.612 2018.04.16 02:00:00   low = 1.55417
2024.10.20 13:34:51.612 2018.04.16 02:00:00   open = 1.5551
2024.10.20 13:34:51.612 2018.04.16 02:00:00   close = 1.55445
2024.10.20 13:34:51.612 2018.04.16 02:00:00   ________________________
2024.10.20 13:34:52.281 2018.04.16 03:00:00   high = 1.55577
2024.10.20 13:34:52.281 2018.04.16 03:00:00   low = 1.55417
2024.10.20 13:34:52.281 2018.04.16 03:00:00   open = 1.5551
2024.10.20 13:34:52.281 2018.04.16 03:00:00   close = 1.55445

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

void OnTick() {
  MqlRates firstBarData = neededBarIndex(0, PERIOD_CURRENT);
  Print("high = ", firstBarData.high);
  Print("low = ", firstBarData.low);
  Print("open = ", firstBarData.open);
  Print("close = ", firstBarData.close);
  Print("________________________");
}

MqlRates neededBarIndex(int index, ENUM_TIMEFRAMES tf = PERIOD_CURRENT) {
  datetime dayOpen = (TimeCurrent() / (24 * 60 * 60)) * 24 * 60 * 60;
  int shift = iBarShift(_Symbol, tf, dayOpen) - index;
  if (shift < 0) shift = 0;
  MqlRates res[1];
  CopyRates(_Symbol, tf, shift, 1, res);
  return res[0];
}
 
Виктор Демихов #:
TimeCurrent() делим и умножаем на тоже самое. Что это нам даёт?

Это даёт экономное вычисление начала текущих суток. Деление целочисленное, остаток отбрасывается.

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

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

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

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

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

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

Если тест проводится по H1 по ценам открытия, то понятно. В этом случае берётся только первый тик нового дня, когда все все 4 цены H1 равны
 
Nikolai Semko #:
Если тест проводится по H1 по ценам открытия, то понятно. В этом случае берётся только первый тик нового дня, когда все все 4 цены H1 равны

Т.е. для точного теста обязательно прогонять на каждом тике?

Это долго...((
 
Виктор Демихов #:

Т.е. для точного теста обязательно прогонять на каждом тике?

Это долго...((
А зачем принтовать каждый тик?
Как минимум, существует функция rand()
Например:
If (rand()%5678 == 5) Print(...  - в этом случае принтуется статистически каждый 5678 тик
И почему индекс всегда 0? Ведь главное проверить именно работу индекса.

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

 
Nikolai Semko #:
А зачем принтовать каждый тик?

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

Nikolai Semko #:
И почему индекс всегда 0?

Так проще проверить функцию. Взял 0-ой индекс (1-ый бар) и смотришь на 1-ый открытый бар в торговой сессии..

Nikolai Semko #:
И вообще для теста нужно сравнивать с работой другой  функции через контрольную сумму, а не принтовку.

Знать бы, как здесь можно иначе..