リアルタイムで見るTiki - ページ 19

 
Yuriy Zaytsev:

また、Symbol()が時間を食うことを避けるために、両方のハンドラを同じように「フィード」させることもできます。

Symbol()関数を定義済み変数_Symbolに置き換えることができます。

 

Symbol() は関係ありません。ログの時刻は正しいです。

イベントキューやSymbolInfo関数に遅延がある。

そういうことなんです。


だから、ガラスが必要ならOnBookと組めばいいんです。不要な場合は、OnTickで作業する(キューや不要な呼び出しがない)。

あとは、両方の方式で実際のティック履歴を最速で取得する方法です。

最後のティックだけが必要な場合は、SymbolInfoの方が良いと思います。隙間のない歴史が必要なら、CopyTicksだけでいいのです。

 
Andrey Khatimlianskii:

Symbol()は関係ありません。ログの時刻は正しいです。

イベントキューや SymbolInfo関数に遅延が ある。

そういうことなんです。

私はシンボルが多くを噛むことはできませんが、いくつかの貢献をすることができますし、確かにテストの純度のためにすべての呼び出しの前に 時間がかかることに同意するものとします。

キューについては、理想的な条件下でOnBookが同じOnTickにどこまで遅れを取れるか、この点が気になりますね。I.e.このSymbolだけが購読されているとき、端末が他のものでビジー状態でないときなど、何が原因か。

ハンドラが何もしていないのであれば、5~6個のOnBooksのキューは、Symbolをチェックする操作以上に消費することはないはずだからです。

すべてのチェックを外し、同じtickについてOnTickとOnBookの間に 何が入るかを確認する必要があります。

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

ap:貪欲なPrintは、Printのためにキューが長くなるので、きれいにチェックすることができないことが明らかになった)

printのない時間を配列ulongに入れて、もう5分に一度、すべてをPrintsに出力する必要があるので、後でコーディングします。

 

まず、コードをテストすることを希望

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

でも、なんかデモのオープナー口座が開けないんです。時間が合わないのか、それとも他の問題があるのか?



次に、1つのイベントティックから正確に比較するためにドピル化するコードを記述します。

 
Aleksey Mavrin:

まず、コードをテストすることを希望

でも、なんかデモのオープナー口座が開けないんです。時間が合わないのか、それとも他の問題があるのか?



次に、1つのイベントティックから正確に比較するためにドピル化するコードを記述します。

ホームページで開く必要があります。そして、郵便局にコードを送るのです。

 
Andrey Khatimlianskii:


最後のティックだけが必要な場合は、SymbolInfoの方が良いと思います。隙間のない歴史が 必要なら、CopyTicksだけです。

問題は、「流動性の高い」商品であっても緊急市場(FORTS)が非常に弱いということだ。

適正な価格で あれば、ごく限られた 契約数しか買えないということですから、価格だけではありません。

が、この価格での契約数量は 非常に重要 です。


そして、SymbolInfoはこの価格の出来高を出しません。

このため、ブック全体の価格と数量の両方を提供するMarketBookGet()を使用する必要があります。

MarketBookGet() は、MarketBookAdd と組み合わせて使用し、マーケットカップの変更を取得することのみが可能です。

をOnBookEventに含める。マーケットを追加し(MarketBookAdd)、OnTck()からMarketBookGet() を使用することができます。

しかし、この場合、市場の他の変化 ベストプライスでない保留中の注文)を見逃してしまいます。

確かに、相場はこれで遊んで、入ってくるティックから相場の滑りを構築することがありますが、本当に必要な のでしょうか?

によって追加されました。

また、OnTck()がトリガーされたときに履歴からtickを取得できるのは納得がいきません。

最後のティックタイムを記憶しておくことで、OnTck()がトリガーされたときにティックを取得することができます。

リアルタイムで新しいティック(複数可)が入ってきました - OnTck()をトリガーに、すぐに それを読みます、つまり、それは履歴ではありません

 
Andrey Khatimlianskii:

あとは、両方の方式で実際のティック履歴を最速で取得する方法を見つけることです。


私のOnTick()はOnBookと同じか少し速いです(しかしOnBookは大きな遅延があります)。

関数の速度(マイクロ秒)をテストしていました。

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, в которую будут помещены текущие цены и время последнего обновления цен.

つまり、時間と価格だけ で、出来高はない :(

 

取引所取引商品(特にFORTS)の場合、重要なのは価格だけではありません。

が、その価格での成約量も!?

 

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

めちゃくちゃになってるやんけ。

先ほど、trade と level2 は異なるデータサブスクリプションなので、異なるイベントハンドラであると書きました。
そのため、トレードはOnTickから、ボリュームギャングはOnBookから呼び出す必要が あります。
OnBookイベントからトレードを、OnTickからギャングを呼び出そうとしていますね。OnBookの方がトレードが早いと思っていること。
速くなるわけではありません。それぞれのデータストリームに特化した2つのイベントハンドラを比較するのは、妄想に過ぎないと思います。
実験ばかりなのはわかりますが、データの流れが2つある(tradeとLevel2)というロジックを理解しないと、このOnTickとOnBookのハンドラを延々と混同することになります。