Аналоги Sleep для таймера в индикаторе - или как синхронизировать время

 

Всем привет. Поделитесь опытом, как в индикаторе можно запустить таймер с заданной секунды?

Проблема: индикатор должен выполнять действие через заданный промежуток времени, например, через каждые 5 минут, НО в начале этой минуты (т.е. в 0, 5, 10, 15 и т.д. минут каждого часа). Обычно в советнике я в таких случаях использую Sleep в OnInit, пока время не станет кратно заданному.
Но то же мне необходимо реализовать в индикаторе, а Sleep в индикаторе использовать запрещено. Тогда получается, что OnTimer становится бесполезен для индикаторов, так как будет запускаться в случайное время - в зависимости от того, когда пользователь запустил индикатор на графике и активировалась EventSetTimer. Есть ли иные способы синхронизировать таймер ЗАДАННОГО ПЕРИОДА в индикаторе? (вариант использовать миллисекундный таймер и счетчик остатка при каждом запуске использовать не хочется).

 
в OnInit:  ФлагЗапуска=True   в OnCalculate:  if(ФлагЗапуска && ! ВремяПришло) return; else ФлагЗапуска=false;
 

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

Market closed

fxsaber, 2018.01.23 14:23

Это не отставание. Вы выводите время из OnTimer на экран, затем ожидаете 500 мс. За эти 500 мс время меняется, но OnTimer еще не вызвался.

Вам нужно синхронизироваться - выставить EventSetTimer(1) ровно в момент, когда "TimerCurrent изменился".


Попробовал так синхронизироваться

bool SetTimerSync( const uint TimerMs = 1000, const uint SyncError = 50 )
{
  // https://www.mql5.com/ru/forum/166646/page5#comment_5796939  
  return((GetCurrenTime() % 1000 > 1000 - SyncError) && EventSetMillisecondTimer(TimerMs));
}

void OnTimer()
{
  static bool Sync = GetCurrenTime() * 0;
   // --- при максимизированном окне выводим время на график
  if (Sync)
    showHideTime(); // https://www.mql5.com/ru/forum/166646/page7#comment_6384173
  else
    Sync = SetTimerSync();
}


int OnInit()
{
  EventSetMillisecondTimer(1);
  
  return INIT_SUCCEEDED;
} 
Не получается. И у меня нехорошие мысли в сторону лага MT5. Посмотрите сами, как Ваш скрипт будет вести себя с этими изменениями.
 
STARIJ:
в OnInit:  ФлагЗапуска=True   в OnCalculate:  if(ФлагЗапуска && ! ВремяПришло) return; else ФлагЗапуска=false;

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


fxsaber:
Правильно ли  я понял Вашу идею - сначала запустить милисекундный таймер, потом при получении правильного времени убить его и запустить новый таймер с нужным интервалом?
 
Artyom Kuraev:

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

Да. Но учитывайте, что даже после синхронизации расхождения будут все равно расти.

 

Зачем так усложнять с таймерами, сравнивайте локальное время компьютера, и в таймере его просто постоянно проверяете. Не наступило ли оно, наступило увеличиваете счётчик времени на сколько нужно и опять ждёте.

Вот справка по структуре даты и времени, там всё есть для ваших целей. https://www.mql5.com/ru/docs/constants/structures/mqldatetime

Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура даты
Документация по MQL5: Стандартные константы, перечисления и структуры / Структуры данных / Структура даты
  • www.mql5.com
Порядковый номер в году day_of_year в високосном году, начиная с марта, будет отличаться от порядкового номера соответствующего дня в невисокосном году.
 
Alexey Valeev:

Зачем так усложнять с таймерами, сравнивайте локальное время компьютера, и в таймере его просто постоянно проверяете. Не наступило ли оно, наступило увеличиваете счётчик времени на сколько нужно и опять ждёте.

Вот справка по структуре даты и времени, там всё есть для ваших целей. https://www.mql5.com/ru/docs/constants/structures/mqldatetime

Благодарю. Правильно ли понял, что без таймера младшего порядка не обойтись? И принцип обнаружения нового нужного времени такой же, как при обнаружении нового бара?

 

Верно.

 
Artyom Kuraev:

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

Тики эмулируйте: по таймеру вызывайте OnCalculate

 
Artyom Kuraev:

Благодарю. Правильно ли понял, что без таймера младшего порядка не обойтись? И принцип обнаружения нового нужного времени такой же, как при обнаружении нового бара?

Вот я пример быстренько накидал, каждые 5 минут ровно срабатывает.

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
   MqlDateTime dt;
   static int minute_prev;
//---
   TimeToStruct(TimeLocal(),dt);
   
   if(minute_prev!=dt.min && MathMod(dt.min,5)==0)
   {
      Print("Прошло 5 минут, минута: "+IntegerToString(dt.min));
      minute_prev=dt.min;
   }
//---
}
 
Alexey Valeev:

Вот я пример быстренько накидал, каждые 5 минут ровно срабатывает.

Это решение совсем другой задачи. И оно может обойтись без TimeLocal.

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