Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2017.09.22 09:45
// Время последнего тика символа long GetSymbolTime( const string Symb ) { MqlTick Tick; return(SymbolInfoTick(Symb, Tick) ? Tick.time_msc : 0); } // Время последнего тика Обзора рынка long GetMarketWatchTime( void ) { long Res = 0; for (int i = SymbolsTotal(true) - 1; i >= 0; i--) { const long TmpTime = GetSymbolTime(SymbolName(i, true)); if (TmpTime > Res) Res = TmpTime; } return(Res); } // Текущее время на торговом сервере без учета пинга long GetCurrenTime( void ) { static ulong StartTime = GetMicrosecondCount(); static long PrevTime = 0; const long TmpTime = GetMarketWatchTime(); if (TmpTime > PrevTime) { PrevTime = TmpTime; StartTime = GetMicrosecondCount(); } return(PrevTime + (long)((GetMicrosecondCount() - StartTime) / 1000)); }
Сначала читал код, думал, зачем устраивать цикл по всем инструментам и использовать структуру MqlTick, если аналогичное значение в TimeCurrent(). Протестировал код - понял, что разница лишь в том, что идет расчет интервала с того момента как мы НАШЛИ самое свежее время (но это не означает, что оно пришло прямо сейчас - мы его лишь нашли сейчас) до момента выхода из функции. Такой вариант мне не совсем понравился (так как это не гарантирует, что то, что мы нашли, пришло прямо сейчас - оно могло прийти пол-секунды назад. Но навело меня на мысль. Каждые 100 мс запрашиваем TimeCurrent и запоминаем время прихода свежего времени (с учетом периодичности таймера устаревание значения не более, чем на 100 сек.). Таким образом будет обеспечена погрешность не более 100 мс. Если сократить таймер - то можно еще большей точности добиться.
Спасибо!
Может отказаться от OnTick в пользу OnTimer? Или использовать обе.
Решил сделать финт ушами - в обычное время работать в режиме онтик, а за 15 минут до времени наступления события - активировать миллитаймер. При наступлении нужного времени - выполнять событие и вызывать киллера (EventKillTimer). Плюс добавить флаг существования таймера на глобальном уровне программы. Получилась вот такая конструкция для теста, работает сносно)
#property copyright "Artem Kuraev" #property link "https://vk.com/artyom52" #property version "1.00" #property strict bool activate_timer=false; //+------------------------------------------------------------------+ int OnInit() { activate_timer=false; if(Minute()%2==1) { EventSetTimer(5); activate_timer=true; Print("таймер активирован"); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(activate_timer) EventKillTimer(); } //+------------------------------------------------------------------+ void OnTick() { if(activate_timer) { if(Minute()%2==0) { EventKillTimer(); activate_timer=false; Print("таймер деактивирован"); } } else { if(Minute()%2==1) { EventSetTimer(5); activate_timer=true; Print("таймер активирован"); } } } //+------------------------------------------------------------------+ void OnTimer() { if(Minute()%2==0) { EventKillTimer(); activate_timer=false; Print("таймер деактивирован"); return; } Print(activate_timer," ",Minute()," ",TimeCurrent()); } //+------------------------------------------------------------------+Если кто-то захочет использовать, нужно учесть, что для тестера необходимо прописывать свой вариант работы, без таймера.
Решил сделать финт ушами - в обычное время работать в режиме онтик, а за 15 минут до времени наступления события - активировать миллитаймер. При наступлении нужного времени - выполнять событие и вызывать киллера (EventKillTimer). Плюс добавить флаг существования таймера на глобальном уровне программы. Получилась вот такая конструкция для теста, работает сносно)
Если кто-то захочет использовать, нужно учесть, что для тестера необходимо прописывать свой вариант работы, без таймера.мелкий фикс - EventSetTimer может завершаться неудачно. В "боевой" обстановке, бывает редко но метко блин....зависит то-ли от нагрузки, то ли от наличия DLL или просто луны сатурна не в той конфигурации
Поэтому признак activate_timer надо ставить в зависимости от получилось/не получилось.
а если не получилось - то "закат солнца вручную", то есть проверять время при каждой возможности (в OnTick , OnChartEvent) и периодически вызывать OnTimer самому и пытаться всё-же запустить EventSetTimer
мелкий фикс - EventSetTimer может завершаться неудачно. В "боевой" обстановке, бывает редко но метко блин....зависит то-ли от нагрузки, то ли от наличия DLL или просто луны сатурна не в той конфигурации
Поэтому признак activate_timer надо ставить в зависимости от получилось/не получилось.
а если не получилось - то "закат солнца вручную", то есть проверять время при каждой возможности (в OnTick , OnChartEvent) и периодически вызывать OnTimer самому и пытаться всё-же запустить EventSetTimer
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Всем привет.
Мне периодически приходится писать программы, в которых какое-то событие должно происходить в строго заданное время с точностью до секунды.
Раньше я писал такую функцию и долгое время с ней работал (есть в CodeBase)
Но она тоже не дает 100% точности. Кроме того, она предназначена для OnTick, а в таймере, кроме как дождаться обновления TimeCurrent в цикле while, нет иных способов узнать точное серверное время.
Можно было бы конечно еще один раз в OnInit найти разницу между серверным и локальным временем и работать по локальным часам. Есть ли у такого подхода минусы?
Есть ли еще способы запустить выполнение кода в строго заданную секунду по времени сервера, с учетом того, что котировок вообще может не прийти в это время и за несколько минут до?