Рассинхронизация времени?

 

Эксперт тестируется в реальном времени. Работает на M30, обращается к D1. Переодический возникает странная ситуация.

Информация из лога:

e-HS-VB-M30 EURUSD,M30: * TimeCurrent= 2015.09.14 00:00:00, Time(D1, 0)= 2015.09.13 00:00:00

Т.е. пришел 1-й тик нового дня, а дневная свеча не обновилась.

Лог выводится из функции OnTick(), в начале OnTick() вызывается функция RefreshCandles для D1, которая не ругается  на HISTORY_WILL_UPDATED.

bool RefreshCandles(int _TF)
{
  datetime DTArr[];

  ArrayCopySeries(DTArr, MODE_TIME, Symbol(), _TF);
  int error = GetLastError();
  if (error == ERR_HISTORY_WILL_UPDATED)
  {
    PrintFormat("ERR_HISTORY_WILL_UPDATED (%s)", TF2Str(_TF));
    
    for (int i=0; i < 10; i++)
    {
      if (IsStopped()) break;

      Sleep(1000);
    }
    
    return (false);
  }
  
  return (true);
}

В чем может быть причина?

 

В общем - раз никто не сталкивался. Я добавил такой код в самое начало OnTick:

if (TimeDay(TimeCurrent()) != TimeDay(iTime(NULL, PERIOD_D1, 0))) return;

По идее теперь эксперт будет ждать подкачки бара на D1.

Посмотрим.

 

Вы в курсе про функцию RefreshRates?

Вы в курсе, что ошибку ERR_HISTORY_WILL_UPDATED Вы получите только один раз? Только в том случае, когда данных по запрашиваемому символу-периоду нет в клиентском терминале - только тогда уходит запрос на обновление истории.

Тема давным-давно обсуждена. Многократно. Даже странно, что Вы задаёте такие вопросы

 
stringo:

Вы в курсе, что ошибку ERR_HISTORY_WILL_UPDATED Вы получите только один раз? Только в том случае, когда данных по запрашиваемому символу-периоду нет в клиентском терминале - только тогда уходит запрос на обновление истории.

Нет, не в курсе. В документации об этом нет ни слова. Как раз считаю, что любое обращение к i-функциям (iTime и пр.) приведет к ошибке ERR_HISTORY_WILL_UPDATED до тех пор, пока идет загрузка данных. Ведь в противном случае об окончании загрузки невозможно будет узнать.

Вполне возможно, что где-то в документации было обновление на сей счет. Тогда, пожалуйста, укажите, в каком месте, чтобы в будущем этот вопрос не возникал. 

 Тема давным-давно обсуждена. Многократно. Даже странно, что Вы задаёте такие вопросы

При разработке программ обычно руководствуются документацией к языку, а не обсуждениями на форуме. Тем более, в последнее время появилось много нового, что делает былые обсуждения несостоятельными. 
 
stringo:

Вы в курсе про функцию RefreshRates?

Вы в курсе, что ошибку ERR_HISTORY_WILL_UPDATED Вы получите только один раз? Только в том случае, когда данных по запрашиваемому символу-периоду нет в клиентском терминале - только тогда уходит запрос на обновление истории.

Тема давным-давно обсуждена. Многократно. Даже странно, что Вы задаёте такие вопросы


1) Т.е. вызов RefreshRates подгружает историю по всем таймфреймам? Про все таймфреймы в документации явно не сказано. Сказано только о массивах-таймсериях и  собственной копии исторических данных.

2) Означает ли, что вызов RefreshRates() в начале OnTick() является обязательным для всех экспертов, которые обращаются к другим таймфреймам?

3) Заменяет ли вызов RefreshRates() вызов ArrrayCopySeries с отловом ERR_HISTORY_WILL_UPDATED?

 
RickD:


1) Т.е. вызов RefreshRates подгружает историю по всем таймфреймам? Про все таймфреймы в документации явно не сказано. Сказано только о массивах-таймсериях и  собственной копии исторических данных. 

В том то и дело, что RefreshRates никак не влияет на наличие/отсутствие исторических данных в терминале. Функция только копирует в переменные Bid и Ask обновленные данные, которые поступили в терминал. Также обновляется состояние массивов High, Low, Close, Open, Volume и Time. Иначе в этих переменных и массивах хранятся те данные, которые были там на момент начала исполнения функции start или OnTick.

2) Означает ли, что вызов RefreshRates() в начале OnTick() является обязательным для всех экспертов, которые обращаются к другим таймфреймам?

Вообще нет. Без нее можно отлично обойтись, не используя предопределенные переменные. Вся информация и без того доступна, если использовать i-функции (iOpen и т. п.) вместо массивов-таймсерий и SymbolInfoDouble вместо обращений к Bid и Ask.

3) Заменяет ли вызов RefreshRates() вызов ArrrayCopySeries с отловом ERR_HISTORY_WILL_UPDATED?

Нет. Насколько я понял со слов Станислава, ArrayCopySeries также не инициирует обновление данных по ТФ. Всю жизнь делал это только через i-функции. Но, как оказывается, тоже неверно. Ждем разъяснений, как правильно.

 

Вот такая идея пришла в голову.

void OnTick()
{
  if (TimeCurrent() - iTime(NULL, PERIOD_D1, 0) >= PERIOD_D1*60) return;
  if (TimeCurrent() - iTime(NULL, PERIOD_H4, 0) >= PERIOD_H4*60) return;
  if (TimeCurrent() - iTime(NULL, PERIOD_H1, 0) >= PERIOD_H1*60) return;
  ...


В начале OnTick поверяем каждый нужный таймфрейм на временной разрыв больше одной свечи. Если он больше, то выходим. И надеемся - что через пару десятков тиков нужный таймфрейм будет асинхронно подгружен терминалом.

 

Кстати о птичках...

TimeCurrent() может давать время несуществующего бара для какого-нибудь символа, потому-что TimeCurrent() это время последнего тика по любому из символов находящихся в обзоре рынка.

 

RefreshRates обновляет не только переменные Bid, Ask, Bars, Time, Open etc, но и закешированные экспертом исторические данные других символов-периодов.

Например, если вы работая на часовке, обратились к днёвкам, то у эксперта будет создана локальная копия существующих на момент запроса днёвок. На следующем тике все данные, включая днёвки, автоматически обновятся. Но если вы в большом цикле будете обращаться к днёвкам, то вы получите возможно неактуальные данные, если не было вызова RefreshRates

 
Scriptong:

Нет. Насколько я понял со слов Станислава, ArrayCopySeries также не инициирует обновление данных по ТФ. Всю жизнь делал это только через i-функции. Но, как оказывается, тоже неверно. Ждем разъяснений, как правильно.

Не инициирует. Мы пока думаем, как это сделать, не нарушив архитектуру четвёрки.
 
Integer:

Кстати о птичках...

TimeCurrent() может давать время несуществующего бара для какого-нибудь символа, потому-что TimeCurrent() это время последнего тика по любому из символов находящихся в обзоре рынка.

 

Да. С этим приходилось сталкиваться, когда в эксперте ведется торговля из OnTimer(). По TimeCurrent() наступил новый день, но не по данному инструменту. Тут лучше использовать SymbolInfoInteger(Symbol(), SYMBOL_TIME) вместо TimeCurrent().
Причина обращения: