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

 
Andrey Khatimlianskii:

ログの時間を見てください。これはすべて1つのmsで起こったことで、その隣には(同じmsで)たくさんのOnBookがありました。

すべてのイベントをカウンターで数えることができますが、視覚的にもOnBooksが増えていることがわかります。

Andrew: この数字は、OnFunctionsがトリガーされたときの固定マイクロ秒数で、配列からすべてまとめてプリントされます。もしかしたら、OnBookは全部でもっとあるかもしれません。数えてみますが、キューの中でOnTicksより先にスキップされる理由は不明です。それとも、すべてのOnTickがOnBookに対応するわけではないのですか?
 
prostotrader:


Async orderを使うって書いてなかったっけ?
気になったのですが、取引の執行を制御するためにどのようなアルゴリズムを使っているのでしょうか?

 
Aleksey Mavrin:
Andrew: この数字は、OnFunctionsがトリガーされたときの固定マイクロ秒数で、そのときに配列からすべてをまとめてプリントしています。OnBooksの合計はもっと多いかもしれない。数えてみるが、なぜOnTicksより先にキューに飛ばすのか、その理由は不明である。それとも、すべてのOnTickがOnBookに対応するわけではないのですか?

ようこそ、ネットワークの世界へ ))))

一番簡単なのは、管理者権限でNetstat - a -b を実行することです。

ポートやソフトを見ればわかると思いますが、MT5サーバは非同期でパケットを渡し、端末が必要な "棚 "に様々な情報を入れているのだと思います。

SZZY:Print()と、一度にたくさんプリントした場合のプリントのスキップについてですが、ご存知ですか?- ファイルに情報を書き込むだけ - そうすれば、すべてと順番に保存されますが、閉じる前にファイルを閉じることを忘れないでください。理論的には、ファイル内のログでPrint()が完了する必要がありますが、チェックしていないと一般的に私は信頼しない場合、多くのデータを出力します。ここで議論されているhttps://www.mql5.com/ru/forum/329730, 非常によく「ミッシングプリント」が議論されている ))) 。- 探索

 
Aleksey Mavrin:
アンドリュー、OnFunctionsがトリガーされたときのマイクロ秒を固定し、配列からまとめて出力しています。もしかしたら、OnBookは全部でもっとあるかもしれません。数えてみますが、キューの中でOnTicksより先にスキップされる理由は不明です。それとも、すべてのOnTickがOnBookに対応するわけではないのですか?

了解です。

まあ、とにかくOnBookがいっぱいあるんですよ。そんなログでは結論は出せない。

 
Roman:

Async orderを使ってるって書いてなかったっけ?
取引執行を制御するために、どのようなアルゴリズムを使用しているのでしょうか?

OnTradeTransaction() において、長時間サーバーからの応答がない場合のチェック機能を追加。

一般的にはマジックで。

EA設定時に各シンボルに対して65535個のマジックシンボルを予約しています。

そして、オーダーを送る際には、他のシンボルと一切交差しないユニークなマジックナンバーを割り当てます。

他の楽器と一切重複しないものであること。

これは、シンボルの初期マジックナンバーを設定する方法です。

//+------------------------------------------------------------------+
//|                                                    AutoMagic.mqh |
//|                                 Copyright 2017-2018 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
//version   "1.01
ulong symb_magic;
//-------------------------------------------------------------------+
// Split string function                                             |
//+------------------------------------------------------------------+
string SplitString(const string a_str,ulong &a_month,ulong &a_year)
  {
   int str_size=StringLen(a_str);
   int str_tire=StringFind(a_str, "-");
   int str_tochka=StringFind(a_str, ".", str_tire);
   if((str_tire>0) && (str_tochka>0) &&(str_size > 0))
     {
      a_month= ulong(StringToInteger(StringSubstr(a_str,str_tire+1,str_tochka-str_tire-1)));
      a_year = ulong(StringToInteger(StringSubstr(a_str,str_tochka+1,str_size-str_tochka-1)));
      if((a_month > 0) && (a_year > 0)) return(StringSubstr(a_str, 0, str_tire));
     }
   return("");
  }
//-------------------------------------------------------------------+
// Get Magic function                                                |
//+------------------------------------------------------------------+
ulong GetMagic(const string a_symbol)
{
  symb_magic = 0;
  if(SymbolSelect(Symbol(), true) == false)
  {
    Print(__FUNCTION__, ": Нет такого символа!");
    return(0);
  }
  ulong month = 0;
  ulong year = 0;
  string new_str = SplitString(a_symbol,month,year);
  if(StringLen(new_str)>0)
  {
    uchar char_array[];
    int result=StringToCharArray(new_str,char_array,0,WHOLE_ARRAY,CP_ACP);
    if(result>0)
   {
     ulong value;
     for(int i = 0; i < result - 1; i++)
     {
       value=ulong(char_array[i]);
       value<<=(56 -(i*8));
       symb_magic += value;
     }
     month<<=24;
     symb_magic += month;
     year<<=16;
     symb_magic += year;
     return(symb_magic);
   }
 }
  return(0); 
}
//-------------------------------------------------------------------+
// Is my magic function                                              |
//+------------------------------------------------------------------+
bool IsMyMagic(const ulong m_magic)
{
  if(m_magic > 0)
  {
    ulong stored_magic=symb_magic;
    stored_magic>>=16;
    ulong in_magic = m_magic;
    in_magic>>=16;
    if(in_magic == stored_magic) return(true);
  }  
  return(false);
}
//-------------------------------------------------------------------+
// Get stored magic function                                         |
//+------------------------------------------------------------------+
ulong GetStoredMagic()
{
  if(symb_magic > 0) return(symb_magic);
  return(0);  
}
//+------------------------------------------------------------------+

マジック - ulong (8 バイト) 例.

GAZR-3.12

Byte[7](上位バイト)は "G"

Byte[6]は "A"

バイト[5] "Z "用

Byte[4]は "R "です。

Byte[3]は "3 "です。

Byte[2]は "12"

Byte[1]とByte[0]はマジコン予備軍(65535)

注文を出すときは、こうしてマジックを進めています。

  mem_magic = magic_storage + 1;
  if(magic_storage >= (magic_number + 65530)) mem_magic = magic_number;

しかし、これはシンボル名が標準化されて いるFORTSにのみ有効です!

追加

オーダーの送信に成功した場合

ときをきざむ

  if(OrderSendAsync(request, result) == true)
  {
    if((result.retcode == TRADE_RETCODE_PLACED) || (result.retcode == TRADE_RETCODE_DONE)) 
    {
      req_id = result.request_id;
      magic_storage = mem_magic;
      state = ORD_DO_SET;
      mem_time = GetMicrosecondCount();
      mem_start_time = TimeCurrent();
      SetTransCount();
    }
    else
    {
      mem_magic = 0;
      mem_time = 0;
      mem_start_time = 0;
      CheckError(result.retcode, "Place: Ордер не установлен! Причина: ", order_status, ticket);
    }
  }
mem_time = GetMicrosecondCount(); - для проверки времени задержки OnTradeTransaction
mem_start_time = TimeCurrent();   - для сужения рамок поиска в истории

そして、(OnTradeTransactionで応答がない場合)。

ticket = FindOrderBuyMagic(mem_magic, start_time);

そして、FindOrderBuyMagic 関数自体も

#define  TIME_DELAY    180
//+------------------------------------------------------------------+
// Expert Find order Buy Magic function                              |
//+------------------------------------------------------------------+
ulong FindOrderBuyMagic(const ulong a_magic, const datetime set_time)
{
  if(a_magic > 0)
  {
    if(IsMyMagic(a_magic) == true)
    {
      ulong cur_ticket = 0;
      for(int i = OrdersTotal() - 1; i >= 0; i--)
      {
        cur_ticket = OrderGetTicket(i);
        if(OrderSelect(cur_ticket))
        {
          if( ulong(OrderGetInteger(ORDER_MAGIC)) == a_magic) return(cur_ticket);
        }  
     }
      cur_ticket = 0;
      datetime start_time = datetime(ulong(set_time) - TIME_DELAY);
      datetime end_time = datetime(ulong(TimeCurrent()) + TIME_DELAY);    
      if(HistorySelect(start_time, end_time))
      {
        for(int i = HistoryOrdersTotal() - 1; i >= 0; i--)
        {
          cur_ticket = HistoryOrderGetTicket(i);
          if(ulong(HistoryOrderGetInteger(cur_ticket, ORDER_MAGIC)) == a_magic) return(cur_ticket);
        }
      }
    }
  }
  return(0);
}

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

オートマジックの1バイト目にEA識別子(0〜255)を追加するのが "グッドアイディア "です。

が、まだ必要ないので、やってません :)

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
В языке MQL5 предусмотрена обработка некоторых предопределенных событий. Функции для обработки этих событий должны быть определены в программе MQL5: имя функции, тип возвращаемого значения, состав параметров (если они есть) и их типы должны строго соответствовать описанию функции-обработчика события. Именно по типу возвращаемого значения и по...
 
prostotrader:

OnTradeTransaction() において、長時間サーバーからの応答がない場合のチェック機能を追加。

ご指摘ありがとうございます。

 
prostotrader:

1.証券会社の2台目以降の端末は有料で、株だけを取引する戦略(ストックポートフォリオ)は持っていない。

2.蓄積されたGetMicrosecondCount() を出力するのであれば

OnDeinit()でタイマーを使わずに実行すると、EAが終了するときにすべてが表示されます。

ブローカーへのリンクを送ってください、LCで可能です。

これは面白い枝だ...。:-)

 
Igor Makanu:

ようこそ、ネットワークの世界へ ))))

一番簡単なのは、管理者権限でNetstat - a -b を実行することです。

ポートやソフトを見ればわかると思いますが、MT5サーバは非同期でパケットを渡し、端末が必要な "棚 "に様々な情報を入れているのだと思います。

HH:Print()と、一度にたくさん出力した場合のプリントのスキップについてご存知ですか?- ファイルに情報を書き込むだけです。そうすれば、すべてを順番に保存することができますが、その前にファイルを閉じるのを忘れないでください。理論的には、ファイル内のログでPrint()が完了する必要がありますが、チェックしていないと一般的に私は信頼しない場合、多くのデータを出力します。ここで議論されているhttps://www.mql5.com/ru/forum/329730, 非常によく「ミッシングプリント」が議論されている ))) 。- 探索

イゴール プリントの消失については、ログファイルを開いていない人たちが100回くらい議論していますし、リナット・ファットクリン自身もログファイルでは何も消失していないと書いていますね。しかし、あなたの投稿は無駄ではありませんでした :) 私は別のファイルに出力を追加しました、さらに、私は2つの配列を注文する私の設計の可能なバグを回避するために少し異なる出力(CArrayObjにすべてのイベントを収集)、すなわち、私は二つの配列からCArrayObjにすべてを入れて、マイクロ秒によってソートして何のイベントTickまたはBookをマークして出力した2番目のファイルを作りました。

そうそう、それとポートがどうのこうの、どうのこうのって。EAのイベントキューをテストしているところです。OnBookは常にキューに入れられ、OnTickが既にキューにある場合、OnTickは消えることがあります(マニュアルの通り)。1.OnTicksが「キューに入れずに」2.OnBookのシステム遅延がある場合のみ、OnTickなしで別のOnTickの後の状況は、私がチェックしたいものです、これは、以前に同僚によって識別秒のラグを説明することができます。Total OnBooksは1日で2倍以上になっていますが、なぜ遅れているのでしょうか? この遅れが非同期パケットやパースによるものならそうかもしれませんが、今のところExpert Advisorで到着の事実を確認する程度です。残りのニュアンスを考えてどうテストするか、まだ考えていない。

ここに新しいコードがあります。オープニングで私は仕事の正しさをテストし、一日のために実行されます。

s.w. 理由は、Tickがカップを変えずに同じ価格で通過した場合 - OnBookが形成されていない、とも考えられます。 私は株式取引の専門家ではないので、誰が教えてくれるでしょうか。OnTickは常にOnBookを引き起こすと思って いました。

//+------------------------------------------------------------------+
//|                                                   TestOnBook.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Allex\Logger.mqh>
#include <Arrays\ArrayObj.mqh>
//---
bool is_book;
enum ENUM_BOOK_OR_TICK
{
        USE_BOOK,       // Use OnBookEvent
        USE_TICK        // Use OnTick
};
class CMcsOn: public CObject
{
public:
ulong mcs;
ENUM_BOOK_OR_TICK Ontype;
CMcsOn(ulong m, ENUM_BOOK_OR_TICK t):mcs(m),Ontype(t){};
int       Compare(const CObject*Object,const int mode=0) const
     {
      const CMcsOn* obj1=dynamic_cast<const CMcsOn*>(Object);
      CMcsOn* obj=(CMcsOn*)(obj1);
      if(!obj)return 0;
      return (mcs-obj.mcs);
      }
};
input ENUM_BOOK_OR_TICK Mode = USE_BOOK;
input int   SecForPrint =  3600;
//---
ulong TimeArrayBook[65536];
ulong TimeArrayTick[65536];
ushort curBook,curTick;
ulong  DelaySum=0,DelayCount=0,CountOnBook=0,CountOnTick=0;
int delay,delayMax=0;
CLogger* Logger,*Logger2;
CArrayObj ArrayObj;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   curBook=0;
   curTick=0; 
   DelaySum=0;DelayCount=0;CountOnBook=0;CountOnTick=0;delayMax=0;
   ArrayInitialize(TimeArrayBook,INT_MAX);
   ArrayInitialize(TimeArrayTick,INT_MAX);
   Logger=CLogger::GetLogger();
   Logger2= new CLogger();
   Logger.SetSetting(__FILE__+"\\",Symbol()+"_"+EnumToString(Period())+"_"+TimeToString(TimeCurrent(),TIME_DATE));  
   Logger2.SetSetting(__FILE__+"\\","Alt_"+Symbol()+"_"+EnumToString(Period())+"_"+TimeToString(TimeCurrent(),TIME_DATE));  
  if(Mode == USE_BOOK) is_book = MarketBookAdd(Symbol());
  ArrayObj.Shutdown();
  if (EventSetTimer(SecForPrint) &&  Logger.Init() && Logger2.Init()) 
  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());
  }  
   delete Logger;
   delete Logger2;
}
//+------------------------------------------------------------------+
//| BookEvent function                                               |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
{  
  TimeArrayBook[curBook++]=GetMicrosecondCount();
  CountOnBook++;
  //Print(__FUNCTION__, " ",curBook);
}
void OnTick()
{
  TimeArrayTick[curTick++]=GetMicrosecondCount();
  CountOnTick++;
  //Print(__FUNCTION__, " ",curTick);

}
//+------------------------------------------------------------------+
void OnTimer()
  {
   string out=NULL;
   int total=MathMax(curBook,curTick);
   int i=0,k=0;
   while(i<total)
     {
      while(i<total && TimeArrayBook[i]<TimeArrayTick[k] )
        {
          MyPrint("Book "+TimeArrayBook[i++]);
        }    
      if(k<curTick-1)
        {
        if(i<total)
          {
           delay=TimeArrayBook[i]-TimeArrayTick[k];
           if (delay>delayMax) 
            delayMax=delay;
           if (delay>0)
              {
                 DelaySum+=delay;
                 DelayCount++;
              }
          }
         MyPrint("Tick "+TimeArrayTick[k++]+ " delay mcs "+delay);
        }       
        i++;
     }
     if (curTick>0)
     {
     MyPrint("Tick "+TimeArrayTick[curTick-1]+ " last");
     string out="Count Event Book after Tick "+DelayCount+". Delay Average "+DoubleToString(DelaySum/DelayCount,2)+". Max "+delayMax+" OnBooks "+CountOnBook+" OnTicks "+CountOnTick;
     MyPrint (out);
     Comment(out);
     }
     Logger.Logger();
     Alt();
     curBook=0;
     curTick=0;
  }
//---
void MyPrint(string out)  
{
   Print(out);
   Logger.Log(__FUNCTION__,out,2,false);
}
//---
void Alt()
{
int last=ArrayObj.Total();
for(int i=0;i<curBook;i++)
  {
   if (!ArrayObj.Add(new CMcsOn(TimeArrayBook[i],USE_BOOK)))
      Logger2.Log(__FUNCTION__,"Error Book Add",0);   
  }
for(int i=0;i<curTick;i++)
  {
   if (!ArrayObj.Add(new CMcsOn(TimeArrayTick[i],USE_TICK)))
      Logger2.Log(__FUNCTION__,"Error Tick Add",0);   
  }
  ArrayObj.Sort();
  int total=ArrayObj.Total();
  total-=last;
  CMcsOn*Obj;
  for(int i=0;i<total;i++)
    {    
     Obj=ArrayObj.At(i);
     if(CheckPointer(Obj)==POINTER_INVALID )
      { Logger2.Log(__FUNCTION__,"Error At Array",0); continue;}
      string out = Obj.USE_BOOK ? "Book ": "Tick ";
      out+= Obj.mcs  ;
      Logger2.Log(__FUNCTION__,out,2);
    }
   Logger2.Log("ArrayObj_","Last "+last+" total "+ArrayObj.Total(),1);  
   Logger2.Logger();
   //ArrayObj.Shutdown(); 
}
 
prostotrader:
しかし、担当者はその答えに納得しているのだろうか。

すでにすべての答えを受け取り、自分なりの結論を出しています。
一定期間の取引の価格、実現量などを分析する必要があります。
あと、ストラテジーテスターで アルゴリズムの動作をシミュレートする必要がありますね。
OnTickイベントはこれに完璧に対処しており、実際の取引結果とテスターでのモデリング結果はわずかな誤差で一致しており、私は満足しています。
ストリップの解析をより速く行う必要がある場合は、OnTimerを使用することができます。

また、端末に来た全てのティックをOnBookに入れる必要はありません。これは成行注文の実行の仕様です。

 
Vladimir Mikhailov:


また、端末に入ってくるティックは必ずしもOnBookに入る必要はなく、成行注文の執行に特化したものである。

逆に、OnTickハンドラに来るティック(イベント)はすべて OnBookと同期させる必要があります。
OnTickハンドラには、最良買値の価格変化、最良売値の価格変化、取引(last)の3つのイベントが存在します。
取引なしで買値または売値が変化した場合、これはイベントとなり、OnTickはこれらのイベントを受信します。
そして、OnBookもこれらのイベントをキャッチしなければなりませんが、自分自身のイベント、つまりハンドラです。そうでなければ、ハンドラ間で買値と売値のミスマッチが発生します。

また、OnTickがlastイベントを受信した場合、取引が成立したことを意味します。
取引によってOnTickのイベントが発生するのは、取引後に価格やビッドとアスクの量が市場で変化するためです。
悪循環に陥っているのです。

OnTickでもOnBookと同様に、Best BidとBest Askというイベントがあります。
これらのイベントは、常に両方のハンドラで同期している必要があります。
そして、このイベントはそれ自体で最後に、取引後にOnBookにイベントを発生させます。
したがって、OnTickハンドラに来たイベントは、必ず同期的にOnBookに反映させる必要があります。