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

 
Roman:

ディーリングFXは使っていない。
CopyTickの 例では、構造の最後の1つの要素、実際には最良の価格のみを得る ことができます。

なぜ、1品目だけ だと思うのですか?

それこそ、絶対に全部のダニが出る(ダニだけでなく、カップの中の変化も)ので

チェック

//+------------------------------------------------------------------+
//|                                                   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[], s_tick;
ulong last_time, mem_cnt, tot_cnt;
bool is_first;
int t_cnt, result;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  tot_cnt = 0;
  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);
  } 
  ArraySetAsSeries(ticks, true);  
  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.bid):""); 
   } 
   else 
   { 
     res = res + (ask_tick?StringFormat(" Ask=%G ",tick.ask):""); 
     res = res + (bid_tick?StringFormat(" Bid=%G ",tick.bid):""); 
     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 OnBookEvent(const string &symbol)
{
  if(symbol != Symbol()) return;
  tot_cnt++;
  if(SymbolInfoTick(Symbol(), s_tick) == true)
  {
    Print("SymbolInfoTick: ",GetTickDescription(s_tick));
  }
  if(is_first == true)
  {
    result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0); //копируем все вновь пришедшие тики от последнего известного времени
    if(result > 0)
    {
      t_cnt = 0;
      for(int i= 0; i<result; i++)
      {
        if(ticks[i].time_msc == ticks[0].time_msc) t_cnt++;             //Считаем кол-во тиков с одинаковым временем
        Print(__FUNCTION__, ": ",GetTickDescription(ticks[i]));
      }
    //  l_tick = ticks[0];
      is_first = false;
      last_time = ulong(ticks[0].time_msc);                             //Запоминаем время последнего тика
    } 
  }
  else
  {
    if(SymbolInfoTick(Symbol(), s_tick) == true)
    {
      Print("SymbolInfoTick: ",GetTickDescription(s_tick));
    }
    result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0); //забираем тики из последнего (посчитанного пакета тикив и считываем тики из нового пакета)
    if(result > 0)
    {
     // l_tick = ticks[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(__FUNCTION__, ": ",GetTickDescription(ticks[i]));
        } 
        if(last_time == ulong(ticks[0].time_msc))
        {
          t_cnt += int(mem_cnt);
        }
        else last_time = ulong(ticks[0].time_msc);
      }
      else
      {
        Print(__FUNCTION__, ": Pending order!");                          //Изменения стакана (добавлен/удален отложенный ордер)
      }
    }
    else
    {
      Print(__FUNCTION__, ": Pending order!");                          //Изменения стакана (добавлен/удален отложенный ордер)
    }
  }
}
//+------------------------------------------------------------------+
 

そこそこ、いいんじゃないでしょうか。

OnBookと比較して、OnTickのもう一つの利点についてお話することをお約束しました。OnBookは配信が保証されているため、少しでも重い計算(あるいは神頼みでトレード)をすると、意味の ない(イベント関連情報を含まない)イベントのキューがかなり蓄積されるからだ。ここで、よくあることですが、メリットがデメリットに変わってしまうのです。

この場合、OnTickは計算時に入ってきたイベントを単純にスキップし、最初の新しい関連するイベントでトリガーされます。OnBookのバリアントでは、キューを解放する(無駄なイベントを飛ばす)には、自分で松葉杖を作らなければならない。

 
Andrey Khatimlianskii:

そこそこ、いいんじゃないでしょうか。

OnBookと比較して、OnTickのもう一つの利点についてお話することをお約束しました。OnBookは配信が保証されているため、少しでも重い計算(あるいは神頼みでトレード)をすると、意味の ない(イベント関連情報を含まない)イベントのキューがかなり蓄積されるからだ。ここで、よくあることですが、メリットがデメリットに変わってしまうのです。

この場合、OnTickは計算時に入ってきたイベントを単純にスキップし、最初の新しい関連するイベントでトリガーされます。OnBookの変形版では、キューを解放する(無駄なイベントを飛ばす)ためには、自分で松葉杖を作らなければならない。

個人的には、取引業務で非同期 注文を使うことが多いですね。

本気で取引所で取引するなら)市場のすべての 変化が必要だということです。

そして、このイベントが早く来れば来るほど良いのです。

さらに、アスク量とビッド量も必要...。

私自身は、OnBookに代わるものはないと考えて います。

 
Roman:

ディーリングFXは使っていない。
CopyTickからの 例では構造の最後の1つの要素しか得られず、実際には最良の価格しか 得られません。

上記のコードを実行すると、以下のことが判明します。

 if(SymbolInfoTick(Symbol(), s_tick) == true)
  {
    Print("SymbolInfoTick: ",GetTickDescription(s_tick));
  }
s_tick.flags = 0

:)

2020.02.03 19:28:14.656 Ticks_test (GOLD-3.20,M1)       OnTick: 2020.02.03 19:28:13.160 Bid=1581.9 
2020.02.03 19:28:14.656 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 19:28:13.160
2020.02.03 19:28:14.656 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 19:28:13.160
2020.02.03 19:28:14.656 Ticks_test (GOLD-3.20,M1)       OnBookEvent: 2020.02.03 19:28:13.160 Bid=1581.9 

同じティックで、SymbolInfoTickを 呼び出すとフラグが立たない :)

追加

if(tick.flags == 0)
   {
     res = res + " ask = " + string(tick.ask) + "; bid = " + string(tick.bid);
   }

ダニを捕まえても、誰が「作った」のかわからない。

2020.02.03 19:36:56.576 Ticks_test (GOLD-3.20,M1)       OnTick: 2020.02.03 19:36:54.735 Bid=1583 
2020.02.03 19:36:56.576 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 19:36:55.61 ask = 1583.3; bid = 1583.0
2020.02.03 19:36:56.576 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 19:36:55.61 ask = 1583.3; bid = 1583.0
2020.02.03 19:36:56.576 Ticks_test (GOLD-3.20,M1)       OnBookEvent: 2020.02.03 19:36:54.735 Bid=1583 

ティックタイムはどうなっているのでしょうか?

不条理に見える。新 しいパケットから時刻19:36:54.735の ティックを受信しましたが、SymbolInfoTickはティックを900ミリ秒 "先取り " していました。

SymbolInfoTick ヘルプより

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

美しいトピック、たくさんの興味深い内容、みんなありがとう。

冗談も冗談抜きで...。

ただ、コードを破らないように、配慮はしますけど...。

 
prostotrader:

ところでカチカチってどうなってるんですか?

無茶な話だ。新しいパケットから時刻19:36:54.735の ティックを取得しますが、SymbolInfoTickを呼び出すと、900ms先のティックを取得します?

参考文献より

Bidの値は全て同じなのに、SymbolInfoTickの 時間が異なるのは本当に不思議です。

 
Roman:

本当に不思議なことに、Bidの値は全て同じなのに、SymbolInfoTickの時間が違うのです。

端末が「好きなように」時間をアレンジしてくれるようです :)

2020.02.03 21:56:44.409 Ticks_test (GOLD-3.20,M1)       OnTick: 2020.02.03 21:56:42.776 Sell Tick: Last=1582.9 Volume=2 
2020.02.03 21:56:48.122 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 21:56:42.780 ask = 1583.1; bid = 1582.9
2020.02.03 21:56:48.122 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 21:56:42.780 ask = 1583.1; bid = 1582.9
2020.02.03 21:56:48.122 Ticks_test (GOLD-3.20,M1)       OnBookEvent: 2020.02.03 21:56:42.776 Sell Tick: Last=1582.9 Volume=2 

現地時間では 4秒 近く経過しています

そんなはずはない!

そして、ここではすべてが普通なのです。

2020.02.03 21:57:02.294 Ticks_test (GOLD-3.20,M1)       OnTick: 2020.02.03 21:57:00.671 Sell Tick: Last=1582.9 Volume=5 
2020.02.03 21:57:02.294 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 21:57:00.671 Sell Tick: Last=1582.9 Volume=5 
2020.02.03 21:57:02.294 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick: 2020.02.03 21:57:00.671 Sell Tick: Last=1582.9 Volume=5 
2020.02.03 21:57:02.294 Ticks_test (GOLD-3.20,M1)       OnBookEvent: 2020.02.03 21:57:00.671 Sell Tick: Last=1582.9 Volume=5 
 
prostotrader:

端末が「好きなように」タイミングをとっているように見えますね :)

現地時間では4秒 近く経過しています

そんなはずはない!


ログによると、OnTickは OnBookEventよりも 4秒早く同じティックをキャッチしています。

1  2020.02.03 21:56:44.409 Ticks_test (GOLD-3.20,M1)       OnTick:            2020.02.03 21:56:42.776 Sell Tick: Last=1582.9 Volume=2 
   2020.02.03 21:56:48.122 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick:    2020.02.03 21:56:42.780 ask = 1583.1; bid = 1582.9
   2020.02.03 21:56:48.122 Ticks_test (GOLD-3.20,M1)       SymbolInfoTick:    2020.02.03 21:56:42.780 ask = 1583.1; bid = 1582.9
2  2020.02.03 21:56:48.122 Ticks_test (GOLD-3.20,M1)       OnBookEvent:       2020.02.03 21:56:42.776 Sell Tick: Last=1582.9 Volume=2 
 
Yuriy Zaytsev:

ログによると、OnTickは OnBookEventよりも 4秒早く同じtickをキャッチしていることが判明しました。

これは、現実には絶対にありえないことです。

ティックがすでに端末にあるため(つまり、新しいティックのパケットがすでに到着している)。

 
prostotrader:

これは、現実には絶対にありえないことです。

ティックがすでに端末にあるため(つまり、新しいティックのパケットがすでに到着している)。

でも、ログを見ると、ログ1と4秒差の同じ刻みが来ているんです。

追伸

私は「ありえない」という言葉が本当に嫌いで、「何が起こるかわからない」ということに慣れました。

ところで、話はそれますが、かつて、地球が丸いという主張に対して、「そんなはずはない」と、こんなことも言っていました。

一般的に、私は確認し、そしてダブルチェックし、できれば誰かが何度かダブルチェックするまで、いつも疑っています。


ログを作成したり、データを処理したりするコードがおかしくなっていないでしょうか?


このコードが、4秒の差で奇跡を起こした?


//+------------------------------------------------------------------+
//|                                                   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[], s_tick;
ulong last_time, mem_cnt, tot_cnt;
bool is_first;
int t_cnt, result;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  tot_cnt = 0;
  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);
  } 
  ArraySetAsSeries(ticks, true);  
  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.bid):""); 
   } 
   else 
   { 
     res = res + (ask_tick?StringFormat(" Ask=%G ",tick.ask):""); 
     res = res + (bid_tick?StringFormat(" Bid=%G ",tick.bid):""); 
     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 OnBookEvent(const string &symbol)
{
  if(symbol != Symbol()) return;
  tot_cnt++;
  if(SymbolInfoTick(Symbol(), s_tick) == true)
  {
    Print("SymbolInfoTick: ",GetTickDescription(s_tick));
  }
  if(is_first == true)
  {
    result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0); //копируем все вновь пришедшие тики от последнего известного времени
    if(result > 0)
    {
      t_cnt = 0;
      for(int i= 0; i<result; i++)
      {
        if(ticks[i].time_msc == ticks[0].time_msc) t_cnt++;             //Считаем кол-во тиков с одинаковым временем
        Print(__FUNCTION__, ": ",GetTickDescription(ticks[i]));
      }
    //  l_tick = ticks[0];
      is_first = false;
      last_time = ulong(ticks[0].time_msc);                             //Запоминаем время последнего тика
    } 
  }
  else
  {
    if(SymbolInfoTick(Symbol(), s_tick) == true)
    {
      Print("SymbolInfoTick: ",GetTickDescription(s_tick));
    }
    result = CopyTicks(Symbol(), ticks, COPY_TICKS_ALL, last_time, 0); //забираем тики из последнего (посчитанного пакета тикив и считываем тики из нового пакета)
    if(result > 0)
    {
     // l_tick = ticks[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(__FUNCTION__, ": ",GetTickDescription(ticks[i]));
        } 
        if(last_time == ulong(ticks[0].time_msc))
        {
          t_cnt += int(mem_cnt);
        }
        else last_time = ulong(ticks[0].time_msc);
      }
      else
      {
        Print(__FUNCTION__, ": Pending order!");                          //Изменения стакана (добавлен/удален отложенный ордер)
      }
    }
    else
    {
      Print(__FUNCTION__, ": Pending order!");                          //Изменения стакана (добавлен/удален отложенный ордер)
    }
  }
}
//+------------------------------------------------------------------+