Tiki in real time - page 19

 
Yuriy Zaytsev:

Alternatively, to avoid concerns that Symbol() will eat up time, then let both handlers "feed" equally.

We can replace the Symbol() function with a predefined variable _Symbol

 

Symbol() has nothing to do with it. The time in the log is correct.

The delay is in the event queue or SymbolInfo functions.

That's what I'm talking about.


So, if you need the glass, work with OnBook. If not needed, work in OnTick (without queues and unnecessary calls).

What's left to figure out is the fastest way to get the actual tick history for both methods.

I think, if only last tick is needed, SymbolInfo is better. If we need history without gaps, then only CopyTicks.

 
Andrey Khatimlianskii:

Symbol() has nothing to do with it. The time in the log is correct.

The delay is in the event queue or SymbolInfo functions.

That's what I'm talking about.

I agree that Symbol can not chew a lot, but can make some contribution, and certainly for the purity of the test take timebefore any calls.

As for the queue - I'm curious about this point - how far OnBook can lag behind the same OnTick under ideal conditions. I.e. when only this Symbol is subscribed, the terminal is not busy with anything else, etc., and what causes it.

So far I can't agree that it's just about the queue, because if the handlers aren't doing anything, then the queue of 5-6 OnBooks shouldn't consume more than the operation of checking the Symbol.

We should remove all checks and see what fallsbetween OnTick and OnBook for the same tick.

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

ap: It became clear that the voracious Print does not allow to check cleanly, because the queue will be long because of the Print)

I have to put the time without the print in the array ulong, and then already once every 5 minutes to output everything to Prints, I'll later code it.

 

Wanted to put the code to test first

//---
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;
  }
//---

But I can't open the demo opener account for something. Time is probably not working, or there are some other problems?



Then code to dopilize to compare exactly from one event tick.

 
Aleksey Mavrin:

Wanted to put the code to test first

But I can't open the demo opener account for something. Time is probably out of order, or is there something else wrong with it?



Then code to dopilize to compare exactly from one event tick.

You have to open it on their website. They then send a code to the post office.

 
Andrey Khatimlianskii:


I think if only last tick is needed, SymbolInfo is better. If you need history without skips, then only CopyTicks.

The matter is that the Urgent Market (FORTS) even on "highly liquid" instruments is very weak,

It means that at the right price you can buya verylimited number of contracts, so we need not only the price,

The volume of contracts at this price is very important.


And SymbolInfo doesn't give the volume of this price.

Due to this, we need to useMarketBookGet() that provides both price and volume of the whole book.

You can useMarketBookGet() only in pair with MarketBookAdd, getting the changes of the market cup.

in OnBookEvent. You can add the market (MarketBookAdd) and useMarketBookGet() from OnTck(),

but in this case we miss some other changes of the market(pending orders not at the best price).

It's true, the market may play with this and build the market slip from incoming ticks, but is it really necessary?

Added by

And I don't agree that we can get ticks from history when OnTck() is triggered.

By remembering the last tick time, when OnTck() is triggered we can get ticks

in real time a new tick(s) came in - triggered OnTck() we read it immediately, i.e. it's not history.

 
Andrey Khatimlianskii:

It remains to find out the fastest way to get actual tick history for both methods.


My OnTick() is the same or slightly faster than OnBook (but OnBook has huge delays).

I was testing speed of functions(microseconds)

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

The fastest isSymbolInfoTick, but this function does not put volume in the tick!

See for help.

tick

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

I.e. only time and price, but no volume :(

 

For Exchange traded instruments (especially FORTS) it is not just the price that matters,

but also the volume of contracts at that price!

 

Tried taking the glass by OnTick() - huge delays clearly visible "by eye"!

//+------------------------------------------------------------------+
//|                                                   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);
    }  
  }
}
//+------------------------------------------------------------------+
 

You've got it all messed up.

I wrote earlier that trades and level2 are different data subscriptions, so they are different event handlers.
That's why trades should be called from OnTick, and volume gangs from OnBook.
You're trying to call trades from OnBook events and gangs from OnTick. Thinking that OnBook will be faster for trades.
It won't be faster, I think it's a delusion to compare two event handlers, each dedicated to its own data stream.
I understand that it's all experiments, but without understanding the logic that there are two data streams (trades and Level2), you will endlessly confuse these OnTick and OnBook handlers.

Reason: