Как сделать задержку индикатору, что бы не писалась в лог ошибка?

 

Пишу индикатор. Достаточно сложный а завёрнутый. Всё как-бы хорошо, но есть один момент, который мне не нравится.

В OnInit() я создаю хэндлы индикаторов, которые используются при рассчётах этим индикатором, который я пишу.

В OnCalculate() нужно проверить все ли данные используемых индикаторов просчитаны. Для этого пишу примерно так:

  int calculated = -1;
  if ((calculated = BarsCalculated(ZZ_toLimitSearching_handle)) < barsTotal(i_ZZ_toLimitSearching_tf)) {
    Print("Indicator '' calculated only ", calculated, " bars instead of ", barsTotal(i_ZZ_toLimitSearching_tf), ". _LastError = ", _LastError);
  }
  Print("calculated = ", calculated);

Изначально, если бросить индикатор на график или запустить его в тестере ( не важно ) значение переменной calculated = -1. По второму проходу уже всё верно. Возникает вопрос почему так происходит.. Кстати, вот что видно в журнале:

2018.08.28 16:24:43.516 Fakey (EURJPY,H1)       Indicator '' calculated only -1 bars instead of 5000. _LastError = 4806
2018.08.28 16:24:43.516 Fakey (EURJPY,H1)       calculated = -1
2018.08.28 16:24:43.625 Fakey (EURJPY,H1)       calculated = 5000
2018.08.28 16:24:44.360 Fakey (EURJPY,H1)       calculated = 5000
2018.08.28 16:24:44.511 Fakey (EURJPY,H1)       calculated = 5000
2018.08.28 16:24:44.705 Fakey (EURJPY,H1)       calculated = 5000
2018.08.28 16:24:45.307 Fakey (EURJPY,H1)       calculated = 5000

Как я понимаю, в OnInit() создаются хэндлы, но индикаторы не успевают просчитать свои значения. Верно? И соответственно, первый раз calculated  = -1. Ко второму проходу calculated  = 5000 как и нужно. Я думал, что есть вариант сделать Sleep() с большим значение есс-но, но не помогает. Как тогда реализовать задержку?

Правильнее будет реализация так, что бы не было первого ругательства:

2018.08.28 16:44:55.607 Fakey (EURJPY,H1)       Indicator '' calculated only -1 bars instead of 5000. _LastError = 4806
2018.08.28 16:44:55.607 Fakey (EURJPY,H1)       calculated = -1

Что бы в лог не писались лишние ошибки, т.к. это даже не ошибка, по сути. В лог логичнее писать runtime-косяки, а не то, что я описал.

Как этот вопрос решить лучше?

 

Слиип не работает в индикаторах.

а чем вас не устраивает ваш вариант? (пропускать первые проходы)

 
Taras Slobodyanik:

Слиип не работает в индикаторах.

а чем вас не устраивает ваш вариант? (пропускать первые проходы)

Хм. Придётся лишние переменные заводить.. А индикатор будет мониторить все торговые инструменты терминала.. Тут как-бы нужно максимальная производительность.

Ещё момент,.. пропускать нужно лишь раз. А раз, а дальше уже это условие не нужно. Щяс подумаю как лушче написать и отпишу. Может ещё кому-то будет интересно. Да и всегда полезно обсудить реализацию.

 

В общем, я вижу это как-то так:

  static bool firstRun = false;
  int calculated = -1;

  if ((calculated = BarsCalculated(ZZ_toLimitSearching_handle)) < barsTotal(i_ZZ_toLimitSearching_tf)) {
    if (firstRun == true)
      Print("Indicator '' calculated only ", calculated, " bars instead of ", barsTotal(i_ZZ_toLimitSearching_tf), ". _LastError = ", _LastError);
  }
  Print("calculated = ", calculated);
  
  firstRun = true;

Если есть какие-то замечание или варианты, интересно услышать))

Пришлось завести доп. переменную. По идее, хватит 1 тика. На практике нужно смотреть. Чуть-что изменить тип на любое минимальное целое типа char.

 
Viktar Dzemikhau:

В общем, я вижу это как-то так:

Если есть какие-то замечание или варианты, интересно услышать))

Пришлось завести доп. переменную. По идее, хватит 1 тика. На практике нужно смотреть. Чуть-что изменить тип на любое минимальное целое типа char.

А зачем дополнительная переменная? При первом проходе prev_calculated==0.

 
Sergey Savinkin:

А зачем дополнительная переменная? При первом проходе prev_calculated==0.

Ну так я не используюсь prev_calculated. У меня получаеся количество просчитанных баров посредством функции BarsCalculated() из хэндла соответстующего индикатора. Причина проста. Таймфрейм и символ могут быть любыми, а не только открытого графика. Так вот, BarsCalculated() возвращает, либо значение просчитанных баров, либо -1. Поэтому с нулём сравнивать не вариант.

 

Интересно, что такая ошибка возникает на каждом новом баре. Вот такой код есть:

bool isInicatorCalculatedAllBars(int indicatorHandle, ENUM_TIMEFRAMES indicatorTf) {
//---
  static bool firstRun = false;

  int calculated = 0;
  if ((calculated = BarsCalculated(indicatorHandle)) < barsTotal(indicatorTf)) {
    if (firstRun == true)
      Print("Indicator with handle '", iToS(indicatorHandle), "' calculated only ", calculated, " bars instead of ", barsTotal(indicatorTf), ". _LastError = ", _LastError);
  }
  firstRun = true;
//---
  return true;
}

получается, что когда открывается новый бар условие выделенное жёлтым цветом не выполняется т.к. количество просчитанных баров меньше общего количества баров на графике ровно на еденицу. Соответственно, принтуется что мол косяк случился, мол индикатор с таким-то хэндлом рассчитал баров столько-то, вместо такого-то количества. Дальше, пока не появился новый бар всё чётко иуже значение просчитанного количества баров индикатором т.е. calculated, хэндл которого передан в эту функцию верное и соответствует количеству баров того окна того таймфрейма, на котором рассчитывается индикатор. Так вот я думаю, что здесь нужно не булеву переменную и типичную переменную которая будет сохранять время открытия нового бара. И ей уже оперировать. Хотя,.. в отличие от работы с новым баром в OnTick(), где переменной нового бара присваивается значение,  когда совершается какая-то операция, а дальше, пока не изменилось время открытия нового бара мы нечего не делаем. В моём варианте сложнее. Здесь ничего не делаем мы вообще. Поэтому в какой-то ммоент его изменять вопрос. И, соответственно, как узнать, что пришёл 1-ый тик нового бара.. Тоже вопрос. Написать можно алгоритм, конечно, но как-то мне не нравится такой вариант. И возникает вопрос, почему в том же МАКД такого косяка нет? Тут вопрос в том, что МАКД работает с одним таймфрймом. У меня индикатор мультитаймфреймовый. Может с этим головняк?

Но индикатор уже проверен в боевых действиях несколько месяцев и не возникало никаких косяков. Поэтому вопрос не в нём. Тем более, как я уже написал, такая хрень только на первом тике нового бара, а дальше всё отлично.. Как быть?

 

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

А для проверки нового бара, создать отдельную переменную - bars и хранить в ней количество баров на нужном ТФ.

 
Taras Slobodyanik:

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

А для проверки нового бара, создать отдельную переменную - bars и хранить в ней количество баров на нужном ТФ.

Так если пропускать первый раз и потом пропускать, проще вообще забить на неё))

Потом сделаю функцию появляения нового тика или нескольких и отловить можно исключение. Пока не особо важно т.к. нужно алгоритм основной проверить. А это лишь первая стадия..

 
Viktar Dzemikhau:

А почему бы вместо OnCalculated и вместо Sleep не использовать таймер.
В Юните его включаете с периодом, равным времени, которого должно хватить по предварительным расчетам для инициализации буферов. 

А в теле самого таймера, когда все ОК, отключить самого себя командой EventKillTimer(), если не все Ок, то будет следующий заход.

 
Nikolai Semko:

А почему бы вместо OnCalculated и вместо Sleep не использовать таймер.
В Юните его включаете с периодом, равным времени, которого должно хватить по предварительным расчетам для инициализации буферов. 

А в теле самого таймера, когда все ОК, отключить самого себя командой EventKillTimer(), если не все Ок, то будет следующий заход.

Это вариант. Только вот есть тоже косяк. Если бы можно было точечно событие прекратить, а не все сразу т.е. при наличии в функции EventSetTimer() аргумента, это был бы тоже костыль, но вполне нормальный. А так..

Я для себя решил на мкл писал проще. Раз нет возможностей комфортных, то проще писать с минимальными возможностями ООП. Всё-равно другого здесь нет. Поэтому не хочется насиловать себя лишний раз выдумывая что-то..

Причина обращения: