Тестируем 'CopyTicks' - страница 19

 

1434 - 1 мс в среднем уходит на получение CopyTicks уже закачанных 1000 тиков. Медленно, вроде.

Запрашиваю TRADE0тик с from_msc последнего тика, полученного ранее. Получаю 3 тика, но за 0.3 - 0.9 мс! - Очень медленно стало.

 
fxsaber:

Сильно залогировал код выше и выяснил причины. Если CopyTicks (from > 0) получает тики до самого свежего, то он может пропускать некоторые.

Очень важный ответ из Сервисдеска

По поводу изначальной проблемы - что CopyTicks на следующем вызове может отдать больше тиков за тот же период:

Это действительно так. Проблема в том, что биржевые потоки данных бид/аски  и ласты/объемы это разные потоки, которое не синхронизированы между собой уже на стороне биржи.

Из-за этого возникают ситуации, что сначала приходит бид/аск со временем биржи 12:12:12.300, а чуть позже приходит ласт/объем с временем 12:12:12.299. 

Соответственно запрашивая данные с момента последнего тика (12:12:12.300) вы не получите новый ласт за 12:12:12.299.

PS. терминал копит и отдает тики отсортированные по времени. То есть временная последовательность тиков отданная в CopyTicks всегда возрастает.

Есть два потока получения тиков - INFO и TRADE. ALL - это синтезированное объединение (похоже, на стороне терминала), поэтому могут возникать такие казусы.

Именно из-за синтезированности и были такие слова 

Slawa:

начальные записи тиков после вызова CopyTicks будут содержать не нули, а текущие на запрашиваемый момент времени значения bid, ask и last

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

 

С лентой такой проблемы возникнуть при правильной работе CopyTicks не должно.

Думаю, Справку очень серьезно дополнят. 

 
fxsaber:
Вы можете сами добавить любые перегрузки.
Я много могу, Вы много можете, другие программисты - тоже многое могут, но, надеюсь, разработчики лучше знают всю "начинку" и могут создать быстрые алгоритмы получения необходимых тиков.
 

Протестировал CopyTicks с флагом COPY_TICKS_TRADE

Разхождений нет.

2016.10.03 15:50:48.507 Check_ticks (RTS-12.16,M1)      History ticks = 9
2016.10.03 15:50:48.507 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 9
2016.10.03 15:50:48.956 Check_ticks (RTS-12.16,M1)      History ticks = 11
2016.10.03 15:50:48.956 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 11
2016.10.03 15:50:49.184 Check_ticks (RTS-12.16,M1)      History ticks = 12
2016.10.03 15:50:49.184 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 12
2016.10.03 15:50:49.510 Check_ticks (RTS-12.16,M1)      History ticks = 14
2016.10.03 15:50:49.511 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 14
2016.10.03 15:50:51.568 Check_ticks (RTS-12.16,M1)      History ticks = 15
2016.10.03 15:50:51.568 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 15
2016.10.03 15:50:51.627 Check_ticks (RTS-12.16,M1)      History ticks = 16
2016.10.03 15:50:51.627 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 16
2016.10.03 15:50:53.143 Check_ticks (RTS-12.16,M1)      History ticks = 19
2016.10.03 15:50:53.143 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 19
2016.10.03 15:50:54.514 Check_ticks (RTS-12.16,M1)      History ticks = 27
2016.10.03 15:50:54.514 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 26
2016.10.03 15:50:54.542 Check_ticks (RTS-12.16,M1)      History ticks = 27
2016.10.03 15:50:54.542 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 27
2016.10.03 15:50:54.847 Check_ticks (RTS-12.16,M1)      History ticks = 30
2016.10.03 15:50:54.847 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 30
2016.10.03 15:50:57.052 Check_ticks (RTS-12.16,M1)      History ticks = 31
2016.10.03 15:50:57.052 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 31
2016.10.03 15:50:57.301 Check_ticks (RTS-12.16,M1)      History ticks = 32
2016.10.03 15:50:57.301 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 32
2016.10.03 15:51:00.498 Check_ticks (RTS-12.16,M1)      History ticks = 44
2016.10.03 15:51:00.498 Check_ticks (RTS-12.16,M1)      Dynamic ticks = 44
Файлы:
Check_ticks.mq5  41 kb
 
prostotrader:

Протестировал CopyTicks с флагом COPY_TICKS_TRADE

Разхождений нет.

 
fxsaber:

Сильно залогировал код выше и выяснил причины. Если CopyTicks (from > 0) получает тики до самого свежего, то он может пропускать некоторые.

Пример.

Запросил тики с from = 2016.09.29 11:05:55.564. Получил в ответ три тика

Спустя какое-то время запрашиваю тиковую историю издалека и вижу тик, который CopyTicks пропустил ранее

Вот такой баг!

Похоже, какой-то конфликт параллельной записи в базу тиков и считывания из нее.

1434 - тот же баг для TRADE-тиков. Воспроизводящий советник
#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

long LastTime = 0; // time_msc-время последнего тика (самого свежего), полученного из истории
int Count = 0;     // Количество тиков в последенем запросе, у которых time_msc == LastTime

// Возвращает свежие тики, пришедшие после предыдущего вызова
int GetFreshTicks( MqlTick &Ticks[], const uint flags = COPY_TICKS_TRADE, const uint count = 100000 )
{
  int Res = 0;

  MqlTick NewTicks[];
  const int NewAmount = CopyTicks(Symbol(), NewTicks, flags, LastTime, count);

  if ((NewAmount > 0) && (Count < NewAmount))
  {
    Res = ArrayCopy(Ticks, NewTicks, 0, Count);

    // Взяли крайнее время из текущей истории
    LastTime = Ticks[Res - 1].time_msc;
    Count = 1;

    // Находим (Count) в текущей истории количество тиков со временем LastTime
    for (int i = Res - 2; i >= 0; i--)
    {
      if (Ticks[i].time_msc < LastTime)
        break;

      Count++;
    }
  }
  
  return(Res);
}

string GetTickFlag( uint tickflag )
{
  string flag = "";

#define TICKFLAG_MACRO(A) flag += ((bool)(tickflag & TICK_FLAG_##A)) ? " TICK_FLAG_" + #A : "";
  TICKFLAG_MACRO(BID)
  TICKFLAG_MACRO(ASK)
  TICKFLAG_MACRO(LAST)
  TICKFLAG_MACRO(VOLUME)
  TICKFLAG_MACRO(BUY)
  TICKFLAG_MACRO(SELL)
#undef TICKFLAG_MACRO

  if (flag == "")
    flag = " FLAG_UNKNOWN (" + (string)tickflag + ")";
     
  return(flag);
}

#define TOSTRING(A) " " + #A + " = " + (string)Tick.A

string TickToString( const MqlTick &Tick )
{
  return(TOSTRING(time) + "." + (string)IntegerToString(Tick.time_msc %1000, 3, '0') +
         TOSTRING(bid) + TOSTRING(ask) + TOSTRING(last)+ TOSTRING(volume) + GetTickFlag(Tick.flags));
}

#define TOSTRING2(A) #A + " = " + (string)(A) + " "

template <typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
  const int Amount = MathMin(ArraySize(Array1), ArraySize(Array2));
  bool Res = (Amount > 0);

  if (Res)
    for (int i = 0; i < Amount; i++)
      if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/ru/code/16280
      {
        Print(TOSTRING2(i) + TOSTRING2(ArraySize(Array1)) + TOSTRING2(ArraySize(Array2)));
        Print(TOSTRING2(TickToString(Array1[i])) + "\n" + TOSTRING2(TickToString(Array2[i])) + "\n");
        Print(TOSTRING2(TickToString(Array1[i - 1])) + "\n" + TOSTRING2(TickToString(Array2[i - 1])) + "\n");
        
        Res = false;
        
        ExpertRemove();

        break;
      }

  return(Res);
}

void OnTick( void )
{
  static bool FirstRun = true;
  static MqlTick PrevTicks[];
  
  if (FirstRun)
  {
    LastTime = TimeCurrent() * 1000;
    Count = 0;
    
    FirstRun = false;
  }
  
  MqlTick Ticks[];

  // Взяли свеженькие тики
  const int Amount = GetFreshTicks(Ticks);

  ArrayCopy(PrevTicks, Ticks, ArraySize(PrevTicks));
  
  if (ArraySize(PrevTicks) > 0)    
  {
    MqlTick NewTicks[];
    
    // Взяли историю тиков
    Print(CopyTicks(_Symbol, NewTicks, COPY_TICKS_TRADE, PrevTicks[0].time_msc, 1000000));
    
    // Проверка на совпадение собираемой истории с самой историей
    Print(ArrayEqual(NewTicks, PrevTicks) ? "Equal" : "Not Equal");
  }  
}
Результат
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   Not Equal
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   ExpertRemove() function called
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   TickToString(Array2[i-1]) =  time = 2016.10.04 10:37:07.791 bid = 99680.0 ask = 99690.0 last = 99690.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   TickToString(Array1[i-1]) =  time = 2016.10.04 10:37:07.791 bid = 99680.0 ask = 99690.0 last = 99690.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   TickToString(Array2[i]) =  time = 2016.10.04 10:37:07.791 bid = 99680.0 ask = 99690.0 last = 99690.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   TickToString(Array1[i]) =  time = 2016.10.04 10:37:08.773 bid = 99690.0 ask = 99700.0 last = 99690.0 volume = 1 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_SELL 
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   i = 144 ArraySize(Array1) = 145 ArraySize(Array2) = 146 
2016.10.04 10:36:17.743 Test13 (RTS-12.16,M1)   145
2016.10.04 10:36:16.768 Test13 (RTS-12.16,M1)   Equal

Собираемая реал-тайм тиковая история TRADE-потока не содержала тика со временем 2016.10.04 10:37:08.773, который оказался позже впихнут в историю.

Это несколько не согласуется со словами выше. Проблемы не только с синтезированным ALL-потоком, но и с прямым - TRADE.

 
fxsaber:
1434 - тот же баг для TRADE-тиков. Воспроизводящий советник
Прошу прощения, это мой грубейший косяк.
 
fxsaber:

1434 - 1 мс в среднем уходит на получение CopyTicks уже закачанных 1000 тиков. Медленно, вроде.

Запрашиваю TRADE0тик с from_msc последнего тика, полученного ранее. Получаю 3 тика, но за 0.3 - 0.9 мс! - Очень медленно стало.

Актуально! Ускорить никак?

 

Пользуясь случаем, хочу поблагодарить разработчиков за проделанную работу с CopyTicks!

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

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

 
Каков оптимальный (быстродействие) алгоритм получения тиков с from_time до to_time?
Причина обращения: