Тики в реальном времени - страница 4

 
Vladimir Mikhailov:

Небольшие итоги с экспериментами по анализу тиков.

1. Обработчик OnTick пропускает значительное количество тиков.
Поэтому, если требуется анализировать ленту сделок через пришедший тик, то смысла нет.
При таком подходе результаты работы алгоритма в тестере и реальные результаты торговли будут отличаться.

Как вариант, можно анализировать ленту сделок за выбранный период или определенное количество последних сделок посредством получения исторических тиков через функции CopyTicks() или CopyTicksRange().
В этом случае результаты тестирования алгоритма в тестере и реальные результаты торговли совпадают.
Из минусов понижение производительности алгоритма.

Да, советник тики может пропускать. Поэтому либо индикатор, либо CopyTicks.

А снижение производительности за счет чего? Копируйте только необходимый отрезок (который появился с момента последнего успешного получения данных).

 
Andrey Khatimlianskii:

Зачем их собирать "в реальном времени", если все равно используется CopyTicks?

В любой нужный момент можно скопировать тики на нужную глубину.

Андрей, прочтите название темы

Добавлено

На нужную глубину не получится с CopyTicks(), а только 2000 тиков!

 
prostotrader:

Андрей, прочтите название темы

Что из того, что задача изначально неправильно поставлена?

Анализ тиков в реальном времени возможен, но, чтобы не было пропусков, нужно использовать индикатор или CopyTicks.


prostotrader:

На нужную глубину не получится с CopyTicks(), а только 2000 тиков!

Нет такого ограничения, посмотрите пример из документации:

Пример вывода
Si-12.16: received 11048387 ticks in 4937 ms
Last tick time = 2016.09.26 18:32:59.775 
First tick time = 2015.06.18 09:45:01.000 
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyTicks
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyTicks
  • www.mql5.com
[in]  Количество запрашиваемых тиков. Если параметры from и count не указаны, то в массив ticks_array[] будут записаны все доступные последние тики, но не более 2000. Первый вызов CopyTicks() инициирует синхронизацию базы тиков, хранящихся на жёстком диске по данному символу. Если тиков в локальной базе не хватает, то недостающие тики...
 
Andrey Khatimlianskii:

Что из того, что задача изначально неправильно поставлена?

Анализ тиков в реальном времени возможен, но, чтобы не было пропусков, нужно использовать индикатор или CopyTicks.


Нет такого ограничения, посмотрите пример из документации:

1. Не обязательно индикатор!

Если Вы имеете ввиду справку, где написано

В экспертах и скриптах функция CopyTicks() может дожидаться результата до 45 секунд....

ТО если прочитать до конца, то там написано:

Скорость выдачи: терминал хранит по каждому символу 4096 последних тиков в кеше для быстрого доступа (для символов с запущенным стаканом – 65536 тиков), запросы к этим данным выполняются быстрее всего.

Событие OnBookEvent() срабатывает, когда в терминал поступает новый пакет тиков, поэтому

и из советника можно собирать тики. Возьмите пример и проверьте.

//+------------------------------------------------------------------+
//|                                                   Ticks_test.mq5 |
//|                                      Copyright 2019 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019 prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
bool is_book;
MqlTick ticks[];
ulong last_time, mem_time;
bool is_first;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
    is_first = false;
    is_book = MarketBookAdd(Symbol());
    int result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, 0, 1);
    if(result > 0)
    {
      last_time = ticks[0].time_msc;
      is_first = true;
    }
    else
    {
      Alert("No start time!");
      return(INIT_FAILED);
    }   
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
    if(is_book == true) MarketBookRelease(Symbol());
   
  }
void PrintResult(const int cnt)
{
  if(cnt > 0)
  {
    for(int i= 0; i<cnt; i++)
    {
      if((ticks[i].flags&TICK_FLAG_ASK)==TICK_FLAG_ASK) Print("Tick is ", "TICK_FLAG_ASK"); else
      if((ticks[i].flags&TICK_FLAG_BID)==TICK_FLAG_BID) Print("Tick is ", "TICK_FLAG_BID"); else
      if((ticks[i].flags&TICK_FLAG_BUY)==TICK_FLAG_BUY) Print("Tick is ", "TICK_FLAG_BUY"); else
      if((ticks[i].flags&TICK_FLAG_LAST)==TICK_FLAG_LAST) Print("Tick is ", "TICK_FLAG_LAST"); else
      if((ticks[i].flags&TICK_FLAG_SELL)==TICK_FLAG_SELL) Print("Tick is ", "TICK_FLAG_SELL"); else
      if((ticks[i].flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME) Print("Tick is ", "TICK_FLAG_VOLUME"); else
      Print("Unknown flag is ", ticks[i].flags);
    }
  }
}  
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
    if(Symbol() == symbol)
    {
      int result;
      if(is_first == true)
      {
        Print("First packet of ticks:");
        result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0);
        if(result > 0)
       {
         PrintResult(result);
         is_first = false;
         mem_time = last_time;
         last_time = ticks[0].time_msc + 1;
       } 
      }
      else
      {
        result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, mem_time, 0);
        if(result > 0)
        {
          for(int i= 0; i<result; i++)
          {
            if(ticks[i].time_msc == mem_time)
            {
              Print("Tick with old time:");
              if((ticks[i].flags&TICK_FLAG_ASK)==TICK_FLAG_ASK) Print("Tick is ", "TICK_FLAG_ASK"); else
              if((ticks[i].flags&TICK_FLAG_BID)==TICK_FLAG_BID) Print("Tick is ", "TICK_FLAG_BID"); else
              if((ticks[i].flags&TICK_FLAG_BUY)==TICK_FLAG_BUY) Print("Tick is ", "TICK_FLAG_BUY"); else
              if((ticks[i].flags&TICK_FLAG_LAST)==TICK_FLAG_LAST) Print("Tick is ", "TICK_FLAG_LAST"); else
              if((ticks[i].flags&TICK_FLAG_SELL)==TICK_FLAG_SELL) Print("Tick is ", "TICK_FLAG_SELL"); else
              if((ticks[i].flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME) Print("Tick is ", "TICK_FLAG_VOLUME"); else
              Print("Unknown flag is ", ticks[i].flags);
            }
          }
        }
        result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0);
        if(result > 0)
        {
          Print("Ticks with new time:");
          PrintResult(result);
          mem_time = last_time;
          last_time = ticks[0].time_msc + 1;
        }
      }
    }
 }
//+------------------------------------------------------------------+


2. Есть такое ограничение, проверьте сами (CopyTicksRange() не имеет ограничений)


 
prostotrader:

1. Не обязательно индикатор!

Событие OnBookEvent() срабатывает, когда в терминал поступает новый пакет тиков, поэтому

и из советника можно собирать тики. Возьмите пример и проверьте.

OnBookEvent не дает ни каких гарантий, что тики не будут пропущены. Если там будут тяжелые вычисления, будет такой же пропуск, как и в OnTick.

А откуда копировать нужную глубину тиков через CopyTicks - не важно.


prostotrader:

2. Есть такое ограничение, проверьте сами

Оно есть как раз для параметров 0, 0, о чем в справке прямо указано:

Если параметры from и count не указаны, то в массив ticks_array[] будут записаны все доступные последние тики, но не более 2000.
 
Andrey Khatimlianskii:

OnBookEvent не дает ни каких гарантий, что тики не будут пропущены. 

Повторяю

OnBookEvent() именно дает такую гарантию, что пришел новый пакет тиков!

Из справки:

Скорость выдачи: терминал хранит по каждому символу 4096 последних тиков в кеше для быстрого доступа (для символов с запущенным стаканом – 65536 тиков), запросы к этим данным выполняются быстрее всего.

Конец цитаты----

Если бы OnBookEvent не срабатывал, то всю торговлю (биржевую) в МТ5 можно бы было выбросить в помойку!

Пришел новый пакет тиков - 100% сработал OnBookEvent, а уж сколько тиков пришло, покажет CopyTicks(),

данные-то уже храняться в кеше и доступ к ним самый быстрый!

Поэтому и можно реализовать сборщик тиков в реальном времени и в индикаторе и в советнике (при запущеном стакане).

Добавлено

Возьмите код выше и проверьте, чем спорить...

 

В коде сборщика тиков принцип верный, но есть ошибки реализации, подправлю

и выложу чуть позже.  

Добавлено

Сборщик всез тиков в реальном времени из советника

Пользуйтесь

//+------------------------------------------------------------------+
//|                                                   Ticks_test.mq5 |
//|                                      Copyright 2019 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019 prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
bool is_book;
MqlTick ticks[];
ulong last_time, mem_cnt;
bool is_first;
int t_cnt, result;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  is_book = MarketBookAdd(Symbol());
  result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, 0, 1);
  if(result > 0)
  {
    last_time = ulong(ticks[0].time_msc);
    is_first = true;
  }
  else
  {
    is_first = false;
    Alert("No start time!");
    return(INIT_FAILED);
  }   
  return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+ 
//| возвращает строковое описание тика                               | 
//+------------------------------------------------------------------+ 
string GetTickDescription(MqlTick &tick) 
  { 
   string res = string(tick.time) + "." +  string(tick.time_msc%1000); 
// 
   bool buy_tick = ((tick.flags&TICK_FLAG_BUY)==TICK_FLAG_BUY); 
   bool sell_tick = ((tick.flags&TICK_FLAG_SELL)==TICK_FLAG_SELL); 
   bool ask_tick = ((tick.flags&TICK_FLAG_ASK)==TICK_FLAG_ASK); 
   bool bid_tick = ((tick.flags&TICK_FLAG_BID)==TICK_FLAG_BID); 
   bool last_tick = ((tick.flags&TICK_FLAG_LAST)==TICK_FLAG_LAST); 
   bool volume_tick = ((tick.flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME); 
// 
   if((buy_tick== true) || (sell_tick == true)) 
   { 
     res = res + (buy_tick?StringFormat(" Buy Tick: Last=%G Volume=%d ",tick.last,tick.volume):""); 
     res = res + (sell_tick?StringFormat(" Sell Tick: Last=%G Volume=%d ",tick.last,tick.volume):""); 
     res = res + (ask_tick?StringFormat(" Ask=%G ",tick.ask):""); 
     res = res + (bid_tick?StringFormat(" Bid=%G ",tick.ask):""); 
   } 
   else 
   { 
     res = res + (ask_tick?StringFormat(" Ask=%G ",tick.ask):""); 
     res = res + (bid_tick?StringFormat(" Bid=%G ",tick.ask):""); 
     res = res + (last_tick?StringFormat(" Last=%G ",tick.last):""); 
     res = res + (volume_tick?StringFormat(" Volume=%d ",tick.volume):""); 
   } 
   return res; 
  } 
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(is_book == true) MarketBookRelease(Symbol());
}
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
//void OnTick()
void OnBookEvent(const string &symbol)
{
  if(Symbol() == symbol)
  {
    if(is_first == true)
    {
      result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0);
      if(result > 0)
      {
        Print("First packet of ticks:");
        t_cnt = 0;
        for(int i= 0; i<result; i++)
        {
          if(ticks[i].time_msc == ticks[0].time_msc) t_cnt++;
          Print(GetTickDescription(ticks[i]));
        }
        is_first = false;
        last_time = ulong(ticks[0].time_msc);
      } 
    }
    else
    {
      result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0);
      if(result > 0)
      {
        if(result > t_cnt)
        {
          mem_cnt = t_cnt;
          t_cnt = 0;
          for(int i= 0; i<(result - int(mem_cnt)); i++)
          {
            if(ticks[i].time_msc == ticks[0].time_msc) t_cnt++;
            Print(GetTickDescription(ticks[i]));
          } 
          if(last_time == ulong(ticks[0].time_msc))
          {
            t_cnt += int(mem_cnt);
          }
          else last_time = ulong(ticks[0].time_msc + 1);
        }
        else
        {
          t_cnt = 0;
          last_time++;
        }
      }
      else
      {
        t_cnt = 0;
        last_time++;
      }
    }
  }
}
//+------------------------------------------------------------------+
 

Чтобы сравнить как работает сборщик тиков, то из него в один момент можно сделать Ленту всех сделок

(заменив COPY_TICKS_ALL на COPY_TICKS_TRADE в двух местах) и сравнить с лентой сделок,

встроенной в стакан инструмента.

Если инструмент высоколиквидный, то принты могут идти с большой задержкой

 
prostotrader:
 if((ticks[i].flags&TICK_FLAG_ASK)==TICK_FLAG_ASK) {Print("Tick is ", "TICK_FLAG_ASK", " Tick time: ", ticks[i].time, ".", string(t_msc));} else
          if((ticks[i].flags&TICK_FLAG_BID)==TICK_FLAG_BID) {Print("Tick is ", "TICK_FLAG_BID", " Tick time: ", ticks[i].time,  ".", string(t_msc));} else
          if((ticks[i].flags&TICK_FLAG_BUY)==TICK_FLAG_BUY) {Print("Tick is ", "TICK_FLAG_BUY", " Tick time: ", ticks[i].time,  ".", string(t_msc));} else
          if((ticks[i].flags&TICK_FLAG_LAST)==TICK_FLAG_LAST) {Print("Tick is ", "TICK_FLAG_LAST", " Tick time: ", ticks[i].time,  ".", string(t_msc));} else
          if((ticks[i].flags&TICK_FLAG_SELL)==TICK_FLAG_SELL) {Print("Tick is ", "TICK_FLAG_SELL", " Tick time: ", ticks[i].time,  ".", string(t_msc));} else
          if((ticks[i].flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME) {Print("Tick is ", "TICK_FLAG_VOLUME", " Tick time: ", ticks[i].time,  ".", string(t_msc));} else

Одновременно разве у тиков не может стоять больше одного  флага?

 
prostotrader:

Повторяю

OnBookEvent() именно дает такую гарантию, что пришел новый пакет тиков!


Но это разве означает что есть гарантия, что вы обработаете ВСЕ события OnBookEvent?

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