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

 
Yuriy Zaytsev:

как вариант,  что бы отсечь опасения что  Symbol() жрет время ,  пусть тогда оба обработчика "питаются" одинаково.

Можно функцию Symbol(), заменить на предопределённую переменную _Symbol

 

Symbol() не при чем здесь. В лог время выводится правильное.

Задержка в очереди событий или в SymbolInfo-функциях.

О чем я и говорил.


Поэтому, если нужен стакан, работаем в ОнБук. Если не нужен, работаем в ОнТик (без очередей и лишних вызовов).

Осталось выяснить самый быстрый способ получения актуальной истории тиков для обоих методов.

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

 
Andrey Khatimlianskii:

Symbol() не при чем здесь. В лог время выводится правильное.

Задержка в очереди событий или в SymbolInfo-функциях.

О чем я и говорил.

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

Насчёт очереди - мне интересно такой момент - насколько ОнБук может отстать от того же ОнТик при идеальных условиях. Т.е. когда подписка только на этот Символ, терминал больше ничем не загружен и т.д., и чем это вызвано.

Пока не могу согласиться что дело лишь в очереди, т.к. если обработчики ничего не делают, то и жрать очередь из 5-6 ОнБуков должна не больше, чем операция проверки Символа.

Надо убрать все проверки и посмотреть заодно что попадает между  ОнТик и ОнБук для того же тика.

void OnBookEvent(const string &symbol)
{
ul=GetMicrosecondCount();  
  Print(__FUNCTION__, "; Time: ", ul, " mcs");
}
void OnTick()
{
ul=GetMicrosecondCount();  
  Print(__FUNCTION__, "; Time: ", ul, " mcs");
}
//+--

ап: Стало ясно, что прожорливый Принт не даёт проверить чисто, т.к. очередь будет долгая из-за принта)

Надо без принта время загонять в массив улонг, а потом уже раз в 5 минут всё выводить в Принты, позже закодю.

 

Хотел поставить проверить код для начала

//---
bool is_book;
enum ENUM_BOOK_OR_TICK
{
        USE_BOOK,       // Use OnBookEvent
        USE_TICK        // Use OnTick
};
input ENUM_BOOK_OR_TICK Mode = USE_BOOK;
input int   SecForPrint =  120;
ulong TimeArrayBook[65536];
ulong TimeArrayTick[65536];
ushort curBook,curTick;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   curBook=0;
   curTick=0; 
   ArrayInitialize(TimeArrayBook,INT_MAX);
   ArrayInitialize(TimeArrayTick,INT_MAX);
  if(Mode == USE_BOOK) is_book = MarketBookAdd(Symbol());
  if (EventSetTimer(SecForPrint)) 
  return(INIT_SUCCEEDED);
  else return (INIT_FAILED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(Mode == USE_BOOK)
  {
    if(is_book == true) MarketBookRelease(Symbol());
  }  
}
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
{
  TimeArrayBook[curBook++]=GetMicrosecondCount();
}
void OnTick()
{
  TimeArrayTick[curTick++]=GetMicrosecondCount();
}
//+------------------------------------------------------------------+
void OnTimer()
  {  
   int total=MathMax(curBook,curTick);
   int i=0,k=0;
   while(i<total)
     {
      while(i<total && TimeArrayBook[i]<TimeArrayTick[k])
        {
          Print("Book ",TimeArrayBook[i++]);
        }    
      if(k<curTick-1)
        {
         Print("Tick ",TimeArrayTick[k++]);
        }       
        i++;
     }
     if (curTick>0)Print("Tick ",TimeArrayTick[curTick-1], " last");
     curBook=0;
     curTick=0;
  }
//---

Но что-то не могу открыть демо-счёт открывашки. Время нерабочее наверное, или ещё есть заморочки?



Потом код допилить чтобы сравнить именно от одного тика события.

 
Aleksey Mavrin:

Хотел поставить проверить код для начала

Но что-то не могу открыть демо-счёт открывашки. Время нерабочее наверное, или ещё есть заморочки?



Потом код допилить чтобы сравнить именно от одного тика события.

Открывать нужно на их сайте. Они потом код на почту присылают.

 
Andrey Khatimlianskii:


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

Дело в том, что Срочный ранок (ФОРТС) даже на "высоколиквидных" инструментах очень слабый,

т.е по нужной цене можно купить очень ограниченное кол-во контрактов, поэтому нужна не только цена,

но очень важен объем контрактов по этой цене.


А SymbolInfo не дает объема этой цены.

В связи с этом нужно использовать MarketBookGet(), который дает и цены и объем всего стакана.

А MarketBookGet() можно использовать только в паре с MarketBookAdd, получая изменения стакана

в OnBookEvent. Можно, конечно, добавлять стакан (MarketBookAdd), а испольковать MarketBookGet() из OnTck(),

но тогда будут пропущены другие изменения стакана (отложенные ордера не по лучшей цене)

Правда можно "поизголяться" и построить свой стакан из приходящих тиков, но нужно ли это

Добавлено

И я не согласен, что при срабатывании OnTck() мы можем получать тики из истории.

Запоминая последнее время тика, при срабатывании OnTck() мы можем получать тики

в реальном времени пришел новый тик(и) - сработал OnTck() мы его сразу считали, т.е это не история

 
Andrey Khatimlianskii:

Осталось выяснить самый быстрый способ получения актуальной истории тиков для обоих методов.


У меня с OnTick() получается так же или чуть быстрее чем ОнБук (правда с Онбук случаются огромные задержки)

Вот я тестировал скорость исполнения функций (микросекунды)

2020.02.04 13:09:13.101 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: time = 2 mcs 2020.02.04 13:09:10.720 Bid=1573.1 
2020.02.04 13:09:13.101 Ticks_test (GOLD-3.20,M1)       SymbolInfoDouble: time = 28 mcs ask = 1573.3
2020.02.04 13:09:13.101 Ticks_test (GOLD-3.20,M1)       SymbolInfoDouble: time = 33 mcs bid = 1573.1
2020.02.04 13:09:13.101 Ticks_test (GOLD-3.20,M1)       SymbolInfoDouble: time = 36 mcs last = 1573.4
2020.02.04 13:09:13.101 Ticks_test (GOLD-3.20,M1)       OnTick: time = 41 mcs 2020.02.04 13:09:10.720 Bid=1573.1 
2020.02.04 13:09:13.101 Ticks_test (GOLD-3.20,M1)       OnTick: time = 41 mcs 2020.02.04 13:09:00.328 Ask=1573.3 
OnTick - имеется ввиду CopyTicks из OnTick

Самый быстрый SymbolInfoTick, но в этой функции в тик не вкладывается объем!

Справка

tick

[out]  Ссылка на структуру типа MqlTick, в которую будут помещены текущие цены и время последнего обновления цен.

Т.е только время и цена, а объема нет :(

 

Для Биржевых инструментов (особенно для ФОРТС) важна не только цена,

но еще объем контрактов по этой цене!

 

Попробовал брать стакан по OnTick() - огромные задержки хорошо видные "на глаз"!

//+------------------------------------------------------------------+
//|                                                   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;
MqlBookInfo BookInfo[];
int book_cnt;
struct MARKET_DATA
{
  double ask;
  long   ask_vol;
  double bid;
  long   bid_vol;
  double prev_ask;
  long   prev_ask_vol;
  double next_bid;
  long   next_bid_vol; 
};
MARKET_DATA m_data;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  is_book = MarketBookAdd(Symbol());
  if(is_book == false)
  {
    Alert("No add book!");
    return(INIT_FAILED);
  }
  return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(is_book == true) MarketBookRelease(Symbol());
}
//+------------------------------------------------------------------+
//| Expert OnTick function                                           |
//+------------------------------------------------------------------+
bool GetBook(const string a_symb, int &cnt)
{
  cnt = 0;
  if(MarketBookGet(a_symb, BookInfo) == true)//getBook )
  {
    m_data.ask = 0;
    m_data.ask_vol = 0;
    m_data.prev_ask = 0;
    m_data.prev_ask_vol = 0;
    m_data.bid = 0;
    m_data.bid_vol = 0;
    m_data.next_bid = 0;
    m_data.next_bid_vol = 0;
    cnt = ArraySize(BookInfo);
    if(cnt > 0)
    {
      for(int i = 0; i < cnt; i++)
      {
        if(BookInfo[i].type == BOOK_TYPE_BUY) //Стакан агрегирован, т.е от наибольшего Sell к наименьшему Buy
        {
          if((i + 1) <= (cnt- 1))
          {
            m_data.ask = BookInfo[i-1].price;
            m_data.ask_vol = BookInfo[i-1].volume;
            m_data.prev_ask = BookInfo[i-2].price;
            m_data.prev_ask_vol = BookInfo[i-2].volume;
            m_data.bid = BookInfo[i].price;
            m_data.bid_vol = BookInfo[i].volume;
            m_data.next_bid = BookInfo[i+1].price;
            m_data.next_bid_vol = BookInfo[i+1].volume;
            break;
          } else break;
        }
      }
      return(true);
    }
  }
  return(false);
}  
//+------------------------------------------------------------------+
//| Expert OnTick function                                           |
//+------------------------------------------------------------------+
void OnTick()
{
  if(GetBook(Symbol(), book_cnt) == true)
  {
    if(book_cnt >= 4)
    {
      Print("Prev Sell: ask = ", m_data.prev_ask, " volume = ",m_data.prev_ask_vol); 
      Print("Sell: ask = ", m_data.ask, " volume = ",m_data.ask_vol);
      Print("Buy: bid = ", m_data.bid, " volume = ",m_data.bid_vol);
      Print("Next Buy: bid = ", m_data.next_bid, " volume = ",m_data.next_bid_vol);
    }  
  }
}
//+------------------------------------------------------------------+
 

Что то вы всё намудрили.

Я же писал ранее, что трейды и левел2, это разные подписки на данные, соответственно это разные событийные обработчики.
По этому трейды нужно вызывать из ОнТик, а банды с объемом из ОнБук
А вы трейды пытаетесь вызывать из событий  ОнБук, а банды из ОнТик. При этом думая, что для трейдов ОнБук будет быстрее.
Не будет он быстрее, мне кажется это заблуждение, сравнивать два обработчика событий, предназначенные каждый под свой поток данных.
Я понимаю что это всё эксперименты, но не понимая логики что приходит два потока данных (трейды и левел2), вы бесконечно будете путаться в этих обработчиках ОнТик и ОнБук.

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