サービス , MT5アーキテックの新機能, MT4の葬式はすぐそこです。 - ページ 8

 

Eng.より

データ

フィード

datafeed -- データソース (ソースという言葉はちょっと違うが)


フィーダー -- フィーダー、フィーダー、フィーダー

 

О датафидах. Сколько встречал этот термин, сложилось ощущение, что этим словом обозначают источник данных (котировок). Буквально "заполнитель данных". Когда речь идет о собственных инструментах, понимаю так, что мы сможем вычислять котировки, например, никем не котируемого MXNRUB по известным курсам MXNUSD и USDRUB, выгруженным из терминала в .csv формат, и легализовать для терминала новые котировки, указав файл .csv как новый датафид. Возможно, будет реализовано и более изящное решение, без выгрузки в файлы, путем онлайновых операций */ над тиками (MXNRUB =  MXNUSD * USDRUB). И это будет новый датафид.

MT5用のティックでの.csvクォートのインポートは既にされているのでしょうか?
 
Andrey Khatimlianskii:

ディスカッションやバグレポートなどのリンクは残っていないのですか?それとも、あったような気がするけど、今は確認していないだけ?

私の記憶では、OnCalculateで収集されたティックは、CopyTix経由で要求されたものと一致していました。

今、わざとチェックしました...思った通り、いくつかのガラクタを得ましたが、私が期待していたものではありませんでした :)

2017.05.22 12:47:10.591 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.591 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.599 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.605 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.617 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.637 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.649 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.683 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.765 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.27 ms v = 1, bid = 108320, ask = 108330, last = 108330, flags = 4
2017.05.22 12:47:10.771 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.193 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.781 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.193 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.843 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.244 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 0
2017.05.22 12:47:10.843 (RTS-6.17,M1)   OnBookEvent: Время последнего OnCalculate = 2017.05.22 10:47:11.193 ms (88), время последнего OnBookEvent = 2017.05.22 10:47:11.244 ms (0)
2017.05.22 12:47:10.859 (RTS-6.17,M1)   OnCalculate: 2017.05.22 10:47:11.282 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88
2017.05.22 12:47:10.863 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 10:47:11.282 ms v = 1, bid = 108320, ask = 108330, last = 108320, flags = 88

OnBookEvent()はフラグ0を持つティックをキャッチする...

 

そして、これが私の期待するところです。

2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.242 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.689 ms v = 2, bid = 108540, ask = 108560, last = 108550, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.704 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.697 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME )
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.253 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.704 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.697 ms (TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME )
2017.05.22 13:24:38.254 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.255 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.704 ms v = 2, bid = 108550, ask = 108560, last = 108550, flags = 'TICK_FLAG_SELL TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.261 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.262 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.262 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.270 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.710 ms v = 1, bid = 108540, ask = 108560, last = 108560, flags = 'TICK_FLAG_BID '
2017.05.22 13:24:38.280 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.280 (RTS-6.17,M1)   OnCalculate: Время последнего STick = 2017.05.22 11:24:38.730 ms (TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME ), время последнего CopyTicks = 2017.05.22 11:24:38.719 ms (TICK_FLAG_BID )
2017.05.22 13:24:38.282 (RTS-6.17,M1)   OnBookEvent: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
2017.05.22 13:24:38.283 (RTS-6.17,M1)   OnCalculate: 2017.05.22 11:24:38.730 ms v = 2, bid = 108550, ask = 108560, last = 108560, flags = 'TICK_FLAG_BUY TICK_FLAG_LAST TICK_FLAG_VOLUME '
ご覧のように、OnCalculate()の各コールでSymbolInfoTick() を使って最後のティックを要求すると、CopyTicks()が返すティックのいくつかにスキップが発生します。
 

確認するコード

#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
MqlTick _tick;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Подписываемся на стакан
   MarketBookAdd(_Symbol);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   ResetLastError();
//--- Проверяем получение параметров тика
   if(!SymbolInfoTick(_Symbol,_tick))
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": параметры тика не получены!");
   else
      Print(__FUNCTION__,": "+GetMsToStringTime(_tick.time_msc)+" v = ",_tick.volume,", bid = "+DoubleToString(_tick.bid,_Digits)+
            ", ask = "+DoubleToString(_tick.ask,_Digits)+", last = "+DoubleToString(_tick.last,_Digits)+", flags = '"+GetStrFlags(_tick.flags)+"'");
//---
   ResetLastError();
//---
   MqlTick t[1];
   if(CopyTicks(_Symbol,t,COPY_TICKS_ALL,0,1)!=1)
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Последний тик не получен!");
   else
     {
      if(t[0].time_msc!=_tick.time_msc)
        {
         Print(__FUNCTION__,": Время последнего STick = "+GetMsToStringTime(_tick.time_msc)+" ("+GetStrFlags(_tick.flags)+")"+
               ", время последнего CopyTicks = "+GetMsToStringTime(t[0].time_msc)+" ("+GetStrFlags(t[0].flags)+")");
        }
     }
//---
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
//---
   if(symbol!=_Symbol)
      return;
//--- Структура - приемник последнего тика
   MqlTick tick;
//---
   ResetLastError();
//--- Проверяем получение параметров тика
   if(!SymbolInfoTick(_Symbol,tick))
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": параметры тика не получены!");
   else
      Print(__FUNCTION__,": "+GetMsToStringTime(tick.time_msc)+" v = ",tick.volume,", bid = "+DoubleToString(tick.bid,_Digits)+
            ", ask = "+DoubleToString(tick.ask,_Digits)+", last = "+DoubleToString(tick.last,_Digits)+", flags = '"+GetStrFlags(tick.flags)+"'");
//--- Сравниваем последний тик OnCalculate с последним тиком OnBookEvent
   if(tick.time_msc!=_tick.time_msc)
     {
      Print( __FUNCTION__,": Время последнего OnCalculate = "+GetMsToStringTime( _tick.time_msc )+" ("+GetStrFlags( _tick.flags )+")"+
            ", время последнего OnBookEvent = "+GetMsToStringTime( tick.time_msc )+" ("+GetStrFlags( tick.flags )+")" );
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Отписываемся от стакана
   MarketBookRelease(_Symbol);
  }
//+------------------------------------------------------------------+
//| Получаем строку времени из миллисекунд                                                                      |
//+------------------------------------------------------------------+
string GetMsToStringTime(const ulong ms)
  {
   const int MS_KOEF=1000;               // Коэффициент перевода секунд в миллисекунды
   return( TimeToString( ms/MS_KOEF, TIME_DATE|TIME_SECONDS )+"."+string( ms%MS_KOEF )+" ms" );
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string GetStrFlags(const uint flags)
  {
   string s="";
//---
   if(( flags&TICK_FLAG_ASK)==TICK_FLAG_ASK)
      s+="TICK_FLAG_ASK ";
   if(( flags&TICK_FLAG_BID)==TICK_FLAG_BID)
      s+="TICK_FLAG_BID ";
   if(( flags&TICK_FLAG_BUY)==TICK_FLAG_BUY)
      s+="TICK_FLAG_BUY ";
   if(( flags&TICK_FLAG_SELL)==TICK_FLAG_SELL)
      s+="TICK_FLAG_SELL ";
   if(( flags&TICK_FLAG_LAST)==TICK_FLAG_LAST)
      s+="TICK_FLAG_LAST ";
   if(( flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME)
      s+="TICK_FLAG_VOLUME ";
//---
   return( s );
  }
//+------------------------------------------------------------------+
 
Alexey Kozitsyn:

テストするコード

OnCalculateが呼ばれたときにファイルにtickを書き込むだけにしておきます(OnBookEventとCopyTicksをテストするため、ただしOnCalculateは 意図したとおりに)。

そして、スクリプトによって同じファイルが生成され、CopyTicksによってティックが取得されることになります。この違いは、OnCalculateでの目盛りのずれか、CopyTicksの不正な操作のどちらかを示しており、より明白なものとなるでしょう。

 
Andrey Khatimlianskii:

念のため(OnBookEventやCopyTicksのテストではなく、意図したとおりのOnCalculate)、OnCalculateが呼ばれたときにticksだけをファイルに書き込むようにしておきます。

そして、スクリプトによって同じファイルが生成され、CopyTicksによってティックが取得されることになります。この違いは、OnCalculateでの目盛りのスキップか、CopyTicksの不正な動作のどちらかを示しており、より明確なものとなるはずです。

こんな単純な計算で、わざわざやる意味があるのか。SymbolInfoTick() とCopyTicks()の2つの呼び出しを 具体的に比較したものがあります。そして、SymbolInfoTick()のすべての呼び出しが明確に表示されます。そして、OnCalculate()からSymbolInfoTick()呼び出しで受け取らなかったティックをCopyTicks()が返していることが明確にわかります。そして、ここでのエラーの理由は2つ考えられます。1.OnCalculate()で目盛りが外れるか、2.SymbolInfoTick()は、どこかで間違ったものを返しています。

はい、これはログの一部で、約30秒間収集されたものです...。ということで、欠けたティックの数を想像してください。

 
Alexey Kozitsyn:

サービスデスクとの対話

OnCalculateでのティックスキップ
公開、開始:2017.05.22 14:52, #1751442

迷子にならないように見てください。https://www.mql5.com/ru/forum/190129/page8#comment_5081300、 次の2つの投稿があります。

インジケータからのCopyTicksは、インジケータがOnCalculateで取得しないティックを与えます(前でも後でもない)。

サポートチーム2017.05.23 09:44
ステータス:未処理開封済み
あなたのアプリケーションは審査に合格しました。
サポートチーム2017.05.23 09:46

OnCalculateはtick毎に呼び出されます。

ダニは別スレッドでデータベースに追加されます。つまり、非同期で。CopyTicksではOnCalculateを呼び出した同じtickを取得するということではありません。

そういうことではないんです。

CopyTicksを使えば、OnCalculateになかったtickを取得することが可能です(OnCalculateでは、ミスした時間より長いtickでそれを知ることができます)。

過去ログを見てみましょう。

サポートチーム2017.05.23 14:13

まさにその通りです。

ダニのバッチが届いた。ループ内の1つのスレッドがパック内の各目盛りにOnCalculateを実行し、もう1つのスレッドがパック全体を目盛りのデータベースに格納します。これら2つのスレッド間は一切同期しておらず、どちらのスレッドがティックのパックを速く処理するかは不明です

しかし、パックからのすべてのティックはOnCalculateで処理される必要があります。そして、これは実現できていない。

その時間には刻みがない。時間が少ないティックと、時間が多いティックがあります。そして、その間にOnCalculateの呼び出しはない。

サポートチーム2017.05.23 14:33

コンポーザー

しかし、パック内のすべてのティックはOnCalculateで処理されなければなりません。そして、これは実現できていない。

その時間には刻みがない。時間が少ないティックと、時間が多いティックがあります。また、その間にOnCalculateの呼び出しはない。

パック内の各ティックはOnCalculateで処理されます。そこにはスキップがない。ループはこのように書かれています。

OnCalculateで処理されるティックを知るには、SymbolInfoTickを 使用します - ここですべてが明らかになります。ティックがシンボル情報に適用され、その後、このシンボルのすべてのインジケータが呼び出され、すべて1つのスレッドになります

リンク先でログをご覧ください。

OnCalculateからのSymbolInfoTickは、CopyTicksから取得できるティックを見ません。

と書いたのはそのためです。

サポートチーム2017.05.23 14:40

https://www.mql5.com/ru/forum/190129/page8#comment_5082755 で提案されたとおりのことをする必要があります。

念のため(OnBookEventやCopyTicksの代わりにOnCalculateをテストするため、意図したとおり)、OnCalculateが呼ばれたときにファイルにティックの書き込みだけを残すようにします。

そして、スクリプトによって同じファイルが生成され、CopyTicksによってティックが取得されることになります。この違いは、OnCalculateでの目盛りのスキップか、CopyTicksの不正な動作のどちらかを示しており、より明確なものとなるはずです。

そして、まさにこの方法でCopyTicksの正しさを確認した時期があったのです。テストスクリプトとインジケータが残っているので、再度確認します。

 

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

バグ、バグ、質問

fxsaber さん 2017.02.07 13:41

インジケーターのSymbolInfoTickは、EAとは全く異なる動作をします。

インジケータでは、OnCalculateコールの開始点であるティックを常に返します。そして、インジケーターのこのイニシエーター・ティックを省略してはならない、これが開発者の思想です。問題は、このダニの行列の形成にある。

Expert Advisor では、OnTick の SymbolInfoTick は、OnTick の呼び出しを開始したティックを返さず、現在の状態を完全に要求します。

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

mql5言語の特徴、微妙なニュアンスとコツ

fxsaber, 2017.03.29 22:32

Calculateイベントは、EVERY TICKで 発生します。つまり、インジケーターのティックキューが存在するのです。ある数値に達すると、ログにインジケーターが遅すぎるという警告が表示されます。

バーそのものはもともと指標であり、Calculate-eventsによって生成される。したがって、TF M1で10:15:00.020のときに50msのパックが来た場合、その中の最初のティックはまだ10:14:59.970の時間を持っていることになります。そして、すべてのインジケータは、このCalculateイベントで最初に呼び出されます。最初に時系列インジケータ、次にこれらの時系列を持つカスタムインジケータです。つまり、このレイアウトでは10時15分のバーがまだゼロバーとして形成されていないのです。そして、ゼロバーは10時14分です。


そして、Calculateイベントでパックの巻き戻しが始まると、10:15-バーも表示されるようになります。詳しく説明したつもりです。

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

mql5言語の特徴、微妙なニュアンスとコツ

fxsaber, 2017.03.29 22:41

その結果、EAがまだ形成されていないバーのティックを取得することは、ごく普通のことなのです。しかし、これはわざと再現するのにも努力が必要なほど微妙なポイントなのです。一般的には、実用性よりも理論性が重視されます。


スピードに偏執的で あれば、インジケータ(もちろんバーも)を使うという選択肢はない。全てはEAの中にある。

 
Andrey Khatimlianskii:

サービスデスクとの対話

サービスデスクは、残念ながら、彼らのレパートリーです。議論になるときにリンクを貼る必要はないのです。しかし、具体的な例を挙げると、彼らの指の上。そういう話ではないんです。実際には、SymbolInfoTick()はチェックする現在のティックを返し、OnCalculate()は各ティックを 処理するので、その出力は各ティックのものであるべきだと言うことがわかります。そして、CopyTicks()はそうでないことを教えてくれる。まあ、CopyTicks()を見てはいけないと言われていますしね :)年末にCopyTicks()を修正する際に、2スレッドほど私も説明されました。ただ、ここではそれが問題ではない(とはいえ、その中もかもしれないが)。

OnBookEvent()で受信したときのフラグが0のティックについては聞いていないのでしょうか?