Services , новый функциона в архитеркуте MT5, похороны MT4 не за горой. - страница 8

 

от англ.

data -- данные

feed -- подача

datafeed -- источник данных (хотя слово "источник" не совсем правильно передаёт смысл)


feeder -- питатель, подающий механизм, загрузочное устройство

 

О датафидах. Сколько встречал этот термин, сложилось ощущение, что этим словом обозначают источник данных (котировок). Буквально "заполнитель данных". Когда речь идет о собственных инструментах, понимаю так, что мы сможем вычислять котировки, например, никем не котируемого MXNRUB по известным курсам MXNUSD и USDRUB, выгруженным из терминала в .csv формат, и легализовать для терминала новые котировки, указав файл .csv как новый датафид. Возможно, будет реализовано и более изящное решение, без выгрузки в файлы, путем онлайновых операций */ над тиками (MXNRUB =  MXNUSD * USDRUB). И это будет новый датафид.

А чт, уже сделали для МТ5 иммпорт .csv котровок в тиках???
 
Andrey Khatimlianskii:

Не осталось ссылки на обсуждение, баг-репорт или что-то подобное? Или только ощущение, что такое было, но сейчас не проверяли?

Насколько помню я, собранные в OnCalculate тики совпадали с запрошенными через КопиТикс.

Сейчас специально проверил... как и предполагал, получил какую-то фигню, но не ту, которую ожидал:)

2017.05.22 12:47:10.591 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.591 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.599 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.605 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.617 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.637 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.649 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.683 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.765 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.771 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.193 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.781 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.193 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.843 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.244 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 0
2017.05.22 12:47:10.843 (RTS-6.17,M1)   OnBookEvent: Время последнего OnCalculate = 2017.05.22 10:47:11.193 ms (88), время последнего OnBookEvent = 2017.05.22 10:47:11.244 ms (0)
2017.05.22 12:47:10.859 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.282 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.863 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.282 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88

Через OnBookEvent() ловятся тики с флагом 0...

 

А вот это уже то, что ожидал увидеть:

2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.704 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.697 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME )
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.704 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.697 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME )
2017.05.22 13:24:38.254 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.262 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.262 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.270 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.280 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.280 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.730 ms (TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.719 ms (TICK_FLAG_BID )
2017.05.22 13:24:38.282 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.283 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
Как видно, при запросе последнего тика на каждом вызове функции OnCalculate() с помощью функции SymbolInfoTick() - идет пропуск некоторых тиков, которые возвращает CopyTicks().
 

Код для проверки:

#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
MqlTick _tick;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Подписываемся на стакан
   MarketBookAdd(_Symbol);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   ResetLastError();
//--- Проверяем получение параметров тика
   if(!SymbolInfoTick(_Symbol,_tick))
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": параметры тика не получены!");
   else
      Print(__FUNCTION__,": "+GetMsToStringTime(_tick.time_msc)+" v = ",_tick.volume,", bid = "+DoubleToString(_tick.bid,_Digits)+
            ", ask = "+DoubleToString(_tick.ask,_Digits)+", last = "+DoubleToString(_tick.last,_Digits)+", flags = '"+GetStrFlags(_tick.flags)+"'");
//---
   ResetLastError();
//---
   MqlTick t[1];
   if(CopyTicks(_Symbol,t,COPY_TICKS_ALL,0,1)!=1)
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Последний тик не получен!");
   else
     {
      if(t[0].time_msc!=_tick.time_msc)
        {
         Print(__FUNCTION__,": Время последнего STick = "+GetMsToStringTime(_tick.time_msc)+" ("+GetStrFlags(_tick.flags)+")"+
               ", время последнего CopyTicks = "+GetMsToStringTime(t[0].time_msc)+" ("+GetStrFlags(t[0].flags)+")");
        }
     }
//---
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
//---
   if(symbol!=_Symbol)
      return;
//--- Структура - приемник последнего тика
   MqlTick tick;
//---
   ResetLastError();
//--- Проверяем получение параметров тика
   if(!SymbolInfoTick(_Symbol,tick))
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": параметры тика не получены!");
   else
      Print(__FUNCTION__,": "+GetMsToStringTime(tick.time_msc)+" v = ",tick.volume,", bid = "+DoubleToString(tick.bid,_Digits)+
            ", ask = "+DoubleToString(tick.ask,_Digits)+", last = "+DoubleToString(tick.last,_Digits)+", flags = '"+GetStrFlags(tick.flags)+"'");
//--- Сравниваем последний тик OnCalculate с последним тиком OnBookEvent
   if(tick.time_msc!=_tick.time_msc)
     {
      Print( __FUNCTION__,": Время последнего OnCalculate = "+GetMsToStringTime( _tick.time_msc )+" ("+GetStrFlags( _tick.flags )+")"+
            ", время последнего OnBookEvent = "+GetMsToStringTime( tick.time_msc )+" ("+GetStrFlags( tick.flags )+")" );
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Отписываемся от стакана
   MarketBookRelease(_Symbol);
  }
//+------------------------------------------------------------------+
//| Получаем строку времени из миллисекунд                                                                      |
//+------------------------------------------------------------------+
string GetMsToStringTime(const ulong ms)
  {
   const int MS_KOEF=1000;               // Коэффициент перевода секунд в миллисекунды
   return( TimeToString( ms/MS_KOEF, TIME_DATE|TIME_SECONDS )+"."+string( ms%MS_KOEF )+" ms" );
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string GetStrFlags(const uint flags)
  {
   string s="";
//---
   if(( flags&TICK_FLAG_ASK)==TICK_FLAG_ASK)
      s+="TICK_FLAG_ASK ";
   if(( flags&TICK_FLAG_BID)==TICK_FLAG_BID)
      s+="TICK_FLAG_BID ";
   if(( flags&TICK_FLAG_BUY)==TICK_FLAG_BUY)
      s+="TICK_FLAG_BUY ";
   if(( flags&TICK_FLAG_SELL)==TICK_FLAG_SELL)
      s+="TICK_FLAG_SELL ";
   if(( flags&TICK_FLAG_LAST)==TICK_FLAG_LAST)
      s+="TICK_FLAG_LAST ";
   if(( flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME)
      s+="TICK_FLAG_VOLUME ";
//---
   return( s );
  }
//+------------------------------------------------------------------+
 
Alexey Kozitsyn:

Код для проверки:

Я бы для верности (чтоб не OnBookEvent и CopyTicks тестировать, а OnCalculate, как задумывалось), оставил бы только запись тиков в файл при вызове OnCalculate.

А потом скриптом сгенрировал бы такой же файл, получив тики через CopyTicks. Разница была бы нагляднее, и свидетельствовала бы либо о пропуске тиков в OnCalculate либо о некорректной работе CopyTicks.

 
Andrey Khatimlianskii:

Я бы для верности (чтоб не OnBookEvent и CopyTicks тестировать, а OnCalculate, как задумывалось), оставил бы только запись тиков в файл при вызове OnCalculate.

А потом скриптом сгенрировал бы такой же файл, получив тики через CopyTicks. Разница была бы нагляднее, и свидетельствовала бы либо о пропуске тиков в OnCalculate либо о некорректной работе CopyTicks.

С таким простым расчетом не вижу смысла дальше заморачиваться. Есть конкретное сравнение двух вызовов: SymbolInfoTick() и CopyTicks(). И наглядно показаны все вызовы SymbolInfoTick(). И видно, что CopyTicks() вернул тик, который не был получен при запросе из SymbolInfoTick() из OnCalculate(). И тут может быть две причины ошибки: 1. Либо OnCalculate() пропускает тики, либо 2. SymbolInfoTick() где-то возвращает не то, что должна.

Да, это часть лога, который собирался секунд так 30... так что представьте себе количество пропущенных тиков.

 
Alexey Kozitsyn:

Наш диалог с сервис-деском:

Пропуск тиков в OnCalculate
Открыта, Начата: 2017.05.22 14:52, #1751442

Посмотрите, чтобы не потерялось: https://www.mql5.com/ru/forum/190129/page8#comment_5081300 и 2 следующих сообщения.

CopyTicks из индикатора дает тик, который индикатор не получает в OnCalculate (ни до ни после).

Support Team 2017.05.23 09:44
Статус: Необработана  Открыта
Ваша заявка принята к рассмотрению.
Support Team 2017.05.23 09:46

OnCalculate вызывается на каждый тик.

Тики складываются в базу в отдельном потоке. То есть, асинхронно. Не факт, что при помощи CopyTicks Вы получите тот самый тик, который вызвал OnCalculate

Andrey Khatimlianskii 2017.05.23 14:08

Речь не об этом.

С помощью CopyTicks удается получить тик, которого в OnCalculate не было (узнаем мы об этом в OnCalculate на тике, время которого больше пропущенного).

Посмотрите логи.

Support Team 2017.05.23 14:13

Речь как раз об этом

Пришла пачка тиков. Обрабатывать эту пачку начали 2 потока - один поток в цикле запускает OnCalculate на каждый тик в пачке; другой поток всю пачку укладывает в тиковую базу. Эти 2 потока никак не синхронизированы между собой, и неизвестно, какой из потоков обработает пачку тиков быстрее

Andrey Khatimlianskii 2017.05.23 14:26

Но каждый тик из пачки должен быть обработан OnCalculate. А этого не происходит.

Тика с таким временем нет. Есть тик с меньшим временем, и тик с большим временем. А между ними вызова OnCalculate не было.

Support Team 2017.05.23 14:33

komposter

Но каждый тик из пачки должен быть обработан OnCalculate. А этого не происходит.

Тика с таким временем нет. Есть тик с меньшим временем, и тик с большим временем. А между ними вызова OnCalculate не было.

Каждый тик из пачки обрабатывается в OnCalculate. Там нет никаких пропусков. Цикл так написан.

Чтобы узнать, какой тик обрабатывается в OnCalculate, используйте SymbolInfoTick - здесь всё чётко. Тик применяется к информации о символе, затем вызываются все индикаторы этого символа, всё в одном потоке

Andrey Khatimlianskii 2017.05.23 14:36

Посмотрите, пожалуйста, лог по ссылке.

SymbolInfoTick из OnCalculate не видит тика, который можно получить из CopyTicks.

Я поэтому и написал

Support Team 2017.05.23 14:40

Надо сделать именно так, как Вы предложили в https://www.mql5.com/ru/forum/190129/page8#comment_5082755

Я бы для верности (чтоб не OnBookEvent и CopyTicks тестировать, а OnCalculate, как задумывалось), оставил бы только запись тиков в файл при вызове OnCalculate.

А потом скриптом сгенрировал бы такой же файл, получив тики через CopyTicks. Разница была бы нагляднее, и свидетельствовала бы либо о пропуске тиков в OnCalculate либо о некорректной работе CopyTicks.

Мы как раз так и проверяли в своё время правильность работы CopyTicks. Тестовые скрипты и индикаторы остались, будем ещё проверять

 

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

Ошибки, баги, вопросы

fxsaber, 2017.02.07 13:41

SymbolInfoTick в индикаторах работает совсем не так, как в советниках.

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

В советнике же SymbolInfoTick в OnTick вовсе не возвращает тик, который инициировал запуск OnTick, а делает полноценный запрос на текущее состояние.

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

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2017.03.29 22:32

Calculate-событие генерируется на КАЖДОМ тике. Поэтому есть очередь тиков для индикаторов. Если она доходит до определенного количества, в журнал идет предупреждение, что индикатор слишком медленный.

Сами бары по природе своей являются индикаторами и формируются по Calculate-событиям. Поэтому, если ТФ M1 и сейчас 10:15:00.020 и приходит пачка на 50 мс, то первый тик в ней еще имеет время 10:14:59.970. И все индикаторы вызываются сначала на этом Calculate-событии - сначала индикатор таймсерий, затем кастомные индикаторы с этими таймсериями. Т.е. при таком раскладе 10:15-бар еще не сформирован, как нулевой. А нулевой - 10:14.


Далее, когда пачка начнет раскручиваться через Calculate-события, появится и 10:15-бар. Вроде, подробно расписал.

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

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2017.03.29 22:41

Как следствие, вполне нормальная ситуация, когда советник получил тик еще не сформированного бара. Но это такой тонкий момент, что даже специально воспроизвести - надо постараться. В общем, больше теоретический, чем практический.


ЗЫ Если параноидально нужна скорость, использование индикаторов (и баров, конечно) - не вариант. Все в советнике.

 
Andrey Khatimlianskii:

Наш диалог с сервис-деском:

Сервис деск, к сожалению, в своем репертуаре. Им не нужно ссылку кидать, если дело дошло до обсуждения. А приводить конкретный пример, на пальцах. Они ведь совсем не о том говорят. Как раз говорят, что SymbolInfoTick() возвращает текущий проверяемый тик, а т.к. OnCalculate() В ТЕОРИИ обрабатывает каждый тик - получается, что и вывод должен быть каждого тика. А CopyTicks() говорит нам обратное. Ну... а они говорят, дак не надо смотреть CopyTicks() :). Про два потока они мне тоже объясняли, как раз тогда, когда чинили CopyTicks() в конце того года. Только тут дело не в нем (хотя, может и в нем тоже, хз).

Про тики с флагом 0 при получении из OnBookEvent() не спрашивали у них?