フォルツァ執行上の問題点 - ページ 74

 
leonerd:
なるほど、性能の保証はないわけですね。
銀行といえども100%の保証はない。オールナッシングの実行ポリシー で遊んでみてください。砦の上だけこのモードが使えないようです。また、直接市場に参入する前に、スタックの流動性を分析することができます - 多くの場合、これは役立つかもしれません。しかし、100%の保証はできません。市場は、約定を保証 するか、価格を保証 するかのどちらか ですが、これら2つの要素を同時に保証することはできません。どちらが重要かは、あなた次第です。
 

さて、ミハイル・ フィリモノフ氏の要請により、追放を解いたようです。

それだけなんです。

 

じっくりと読む。

トピックの発案者が禁止された理由は明らかです。

ノーマン、ノープロブレム。

遅延は解消されたのか?

 
prostotrader:

じっくりと読む。

トピックの発案者が禁止された理由は明らかです。

ノーマン、ノープロブレム。

遅れは解消されたのでしょうか?

今、彼以外の誰が測定するのでしょうか? 誰もが禁止されることを恐れているのです。)

 
coderex :

そして、彼以外に誰がそれらを測定するのでしょうか?誰もが禁止を恐れています:)

まず、テストEAを作成する必要があります。

 //+------------------------------------------------------------------+
//|                                                   Test_delay.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link        "https://www.mql5.com"
#property version    "1.00"
input int Transactions= 1500 ;
ulong order_ticket;
int tr_cnt;
ulong Magic= 1234567890 ;
ulong order_id;
ulong start,stop;
#define ERR_ZERO_TICKET - 1 ;
bool exp_busy;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_ORD_SELECT
  {
   SELECT_ERROR = 0 ,
   SELECT_FALSE = 1 ,
   SELECT_TRUE  = 2 ,
   SELECT_BUSY  = 3
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_ORD_REAL_STATE
  {
   ORD_NOT_SPECIFIED         = 0 , //Состояние ордера не определено
   ORD_NONE_CANCELED         = 1 , //Ордера нет, отменён пользователем
   ORD_NONE_PARTIAL_CANCELED = 2 , //Ордера нет, исполнился частично (не был залит вторым объёмом)
   ORD_NONE_PARTIAL          = 3 , //Ордера нет, исполнился частично
   ORD_NONE_EXPIRED          = 4 , //Ордера нет, удалён по сроку
   ORD_NONE_FILLED           = 5 , //Ордера нет, исполнился полностью
   ORD_NONE_REJECTED         = 6 , //Ордера нет, отклонён брокером(биржей)
   ORD_BUSY                  = 7 , //Ордер находится в переходном состоянии
   ORD_EXIST                 = 8 , //Ордер выставлен на биржу, возможны действия над ним
   ORD_EXIST_PARTIAL         = 9    //Ордер выставлен на биржу, частично исполнился, возможны действия над ним
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct ORDER_DATA
  {
   int                error_code;
   datetime           time_setup;
   ENUM_ORDER_TYPE    type;
   ENUM_ORDER_STATE   state;
   ENUM_ORD_REAL_STATE real_state;
   datetime           expiration;
   datetime           time_done;
   long               t_set_msc;
   long               t_done_msc;
   ENUM_ORDER_TYPE_FILLING type_filling;
   ENUM_ORDER_TYPE_TIME type_time;
   long               magic;
   long               pos_id;
   double             vol_init;
   double             vol_cur;
   double             price_open;
   double             sl;
   double             tp;
   double             price_cur;
   double             price_stlim;
   string             symbol;
   string             comment;
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit ()
  {
//---
   order_ticket= 0 ;
   tr_cnt= 0 ;
   start= 0 ;
   stop= 0 ;
   exp_busy= false ;
   Print ( "Тест начат: " , TimeTradeServer ());
//---
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick ()
  {
//---
   ORDER_DATA order_data;
   if (!exp_busy)
     {
       if (tr_cnt>=Transactions)
        {
         if ((order_ticket> 0 ) && (OrderRealSelect(order_ticket,order_data, false )==SELECT_TRUE)) RemoveOrder(order_ticket);
         Print ( "Тест закончен: " , TimeTradeServer ());
        }
       else
        {
         if (order_ticket> 0 )
           {
             if (OrderRealSelect(order_ticket,order_data, false )==SELECT_TRUE) RemoveOrder(order_ticket);
           }
         else
           {
            SetOrder();
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction ( const MqlTradeTransaction &trans,
                         const MqlTradeRequest &request,
                         const MqlTradeResult &result)
  {
   switch (trans.type)
     {
       case TRADE_TRANSACTION_REQUEST : if ((order_id!= 0 ) && (result.request_id==order_id))
        {
         order_ticket=result.order;
         order_id= 0 ;
        }
       break ;
       case TRADE_TRANSACTION_ORDER_UPDATE :   if ((order_ticket!= 0 ) && (trans.order==order_ticket))
        {
         ORDER_DATA order_data;
         if (OrderRealSelect(order_ticket,order_data, false )==SELECT_TRUE)
           {
            stop= GetMicrosecondCount ();
            tr_cnt++;
             Print ( "Время установки ордера: " , NormalizeDouble ( double (stop-start)/ 1000 , 2 ), " ms" );
             Sleep ( 1000 );
            exp_busy= false ;
           }
        }
       break ;
       case TRADE_TRANSACTION_HISTORY_ADD : if ((order_ticket!= 0 ) && (trans.order==order_ticket))
        {
         ORDER_DATA order_data;
         if (OrderRealSelect(order_ticket,order_data, false )==SELECT_FALSE)
           {
            stop= GetMicrosecondCount ();
            tr_cnt++;
            order_ticket= 0 ;
             Print ( "Время удаления ордера: " , NormalizeDouble ( double (stop-start)/ 1000 , 2 ), " ms" );
             Sleep ( 1000 );
            exp_busy= false ;
           }
        }
       break ;
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetOrder()
  {
   MqlTradeRequest request={ 0 };
   MqlTradeResult   result={ 0 };
   order_id= 0 ;
   order_ticket= 0 ;
   request.magic=Magic;
   request.symbol= Symbol ();
   request.volume= 1 ;
   request.type_filling= ORDER_FILLING_RETURN ;
   request.type_time= ORDER_TIME_DAY ;
   request.action= TRADE_ACTION_PENDING ;
   request.type= ORDER_TYPE_SELL_LIMIT ;
   request.comment= "" ;
   request.price= SymbolInfoDouble ( Symbol (), SYMBOL_SESSION_PRICE_LIMIT_MAX );
   if ( OrderSendAsync (request,result))
     {
       if (result.retcode== TRADE_RETCODE_PLACED )
        {
         order_id=result.request_id;start= GetMicrosecondCount ();exp_busy= true ;
         Print ( "Запрос на установку ордера." );
        }
     }
   else
     { Print ( "Ордер не отослан!" );}
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void RemoveOrder( const ulong o_ticket)
  {
   MqlTradeRequest request={ 0 };
   MqlTradeResult   result={ 0 };
   order_id= 0 ;
   request.action= TRADE_ACTION_REMOVE ;
   request.order=o_ticket;
   if ( OrderSendAsync (request,result))
     {
       if (result.retcode== TRADE_RETCODE_PLACED )
        {
         order_id=result.request_id;start= GetMicrosecondCount ();exp_busy= true ;
         Print ( "Запрос на удаление ордера." );
        }
     }
   else
     { Print ( "Ордер не отослан!" );}
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_ORD_SELECT OrderRealSelect( const ulong ticket,ORDER_DATA &ord_data, const bool get_data) //Отличная функция, спасибо Михаилу
  {
   double init_vol= 0 ;
   double cur_vol = 0 ;
   ZeroMemory (ord_data);
   ord_data.real_state = ORD_NOT_SPECIFIED;
   ord_data.error_code = ERR_SUCCESS ;
   ResetLastError ();
//---  
   if (ticket> 0 )
     {
       if ( HistoryOrderSelect (ticket))
        {
         if (get_data)
           {
            ord_data.comment= HistoryOrderGetString (ticket, ORDER_COMMENT );
            ord_data.expiration= datetime ( HistoryOrderGetInteger (ticket, ORDER_TIME_EXPIRATION ));
            ord_data.magic= HistoryOrderGetInteger (ticket, ORDER_MAGIC );
            ord_data.pos_id= HistoryOrderGetInteger (ticket, ORDER_POSITION_ID );
            ord_data.price_cur= HistoryOrderGetDouble (ticket, ORDER_PRICE_CURRENT );
            ord_data.price_open= HistoryOrderGetDouble (ticket, ORDER_PRICE_OPEN );
            ord_data.price_stlim= HistoryOrderGetDouble (ticket, ORDER_PRICE_STOPLIMIT );
            ord_data.sl= HistoryOrderGetDouble (ticket, ORDER_SL );
            ord_data.state= ENUM_ORDER_STATE ( HistoryOrderGetInteger (ticket, ORDER_STATE ));
            ord_data.symbol= HistoryOrderGetString (ticket, ORDER_SYMBOL );
            ord_data.t_done_msc= datetime ( HistoryOrderGetInteger (ticket, ORDER_TIME_DONE_MSC ));
            ord_data.t_set_msc = datetime ( HistoryOrderGetInteger (ticket, ORDER_TIME_SETUP_MSC ));
            ord_data.time_done = datetime ( HistoryOrderGetInteger ( ticket, ORDER_TIME_DONE ));
            ord_data.time_setup= datetime ( HistoryOrderGetInteger (ticket, ORDER_TIME_SETUP ));
            ord_data.tp= HistoryOrderGetDouble (ticket, ORDER_TP );
            ord_data.type= ENUM_ORDER_TYPE ( HistoryOrderGetInteger (ticket, ORDER_TYPE ));
            ord_data.type_filling= ENUM_ORDER_TYPE_FILLING ( HistoryOrderGetInteger (ticket, ORDER_TYPE_FILLING ));
            ord_data.type_time= ENUM_ORDER_TYPE_TIME ( HistoryOrderGetInteger (ticket, ORDER_TYPE_TIME ));
            ord_data.vol_cur= HistoryOrderGetDouble (ticket, ORDER_VOLUME_CURRENT );
            ord_data.vol_init= HistoryOrderGetDouble (ticket, ORDER_VOLUME_INITIAL );
           }
         else
           {
            ord_data.state= ENUM_ORDER_STATE ( HistoryOrderGetInteger (ticket, ORDER_STATE ));
            cur_vol= HistoryOrderGetDouble (ticket, ORDER_VOLUME_CURRENT );
            init_vol= HistoryOrderGetDouble (ticket, ORDER_VOLUME_INITIAL );
           }
         //---
         switch (ord_data.state)
           {
             case ORDER_STATE_CANCELED : if (get_data)
              {
               if (ord_data.vol_init==ord_data.vol_cur)
                 {
                  ord_data.real_state=ORD_NONE_CANCELED;
                 }
               else
                 {
                  ord_data.real_state=ORD_NONE_PARTIAL_CANCELED;
                 }
              }
             else
              {
               if (init_vol==cur_vol)
                 {
                  ord_data.real_state=ORD_NONE_CANCELED;
                 }
               else
                 {
                  ord_data.real_state=ORD_NONE_PARTIAL_CANCELED;
                 }
              }
             break ;

             case ORDER_STATE_PARTIAL :  ord_data.real_state=ORD_NONE_PARTIAL;
             break ;

             case ORDER_STATE_EXPIRED :  ord_data.real_state=ORD_NONE_EXPIRED;
             break ;

             case ORDER_STATE_FILLED :   ord_data.real_state=ORD_NONE_FILLED;
             break ;

             case ORDER_STATE_REJECTED : ord_data.real_state=ORD_NONE_REJECTED;
             break ;
           }
        }
       else
       if ( OrderSelect (ticket))
        {
         if (get_data)
           {
            ord_data.comment= OrderGetString ( ORDER_COMMENT );
            ord_data.expiration= datetime ( OrderGetInteger ( ORDER_TIME_EXPIRATION ));
            ord_data.magic= OrderGetInteger ( ORDER_MAGIC );
            ord_data.pos_id= OrderGetInteger ( ORDER_POSITION_ID );
            ord_data.price_cur= OrderGetDouble ( ORDER_PRICE_CURRENT );
            ord_data.price_open= OrderGetDouble ( ORDER_PRICE_OPEN );
            ord_data.price_stlim= OrderGetDouble ( ORDER_PRICE_STOPLIMIT );
            ord_data.sl= OrderGetDouble ( ORDER_SL );
            ord_data.state= ENUM_ORDER_STATE ( OrderGetInteger ( ORDER_STATE ));
            ord_data.symbol= OrderGetString ( ORDER_SYMBOL );
            ord_data.t_done_msc= datetime ( OrderGetInteger ( ORDER_TIME_DONE_MSC ));
            ord_data.t_set_msc = datetime ( OrderGetInteger ( ORDER_TIME_SETUP_MSC ));
            ord_data.time_done = datetime ( OrderGetInteger ( ORDER_TIME_DONE ));
            ord_data.time_setup= datetime ( OrderGetInteger ( ORDER_TIME_SETUP ));
            ord_data.tp= OrderGetDouble ( ORDER_TP );
            ord_data.type= ENUM_ORDER_TYPE ( OrderGetInteger ( ORDER_TYPE ));
            ord_data.type_filling= ENUM_ORDER_TYPE_FILLING ( OrderGetInteger ( ORDER_TYPE_FILLING ));
            ord_data.type_time= ENUM_ORDER_TYPE_TIME ( OrderGetInteger ( ORDER_TYPE_TIME ));
            ord_data.vol_cur= OrderGetDouble ( ORDER_VOLUME_CURRENT );
            ord_data.vol_init= OrderGetDouble ( ORDER_VOLUME_INITIAL );
           }
         else
           {
            ord_data.state= ENUM_ORDER_STATE ( OrderGetInteger ( ORDER_STATE ));
           }
         //--- 
         switch (ord_data.state)
           {
             case ORDER_STATE_STARTED :
             case ORDER_STATE_REQUEST_ADD :
             case ORDER_STATE_REQUEST_MODIFY :
             case ORDER_STATE_REQUEST_CANCEL : ord_data.real_state=ORD_BUSY;
             break ;

             case ORDER_STATE_PARTIAL :        ord_data.real_state=ORD_EXIST_PARTIAL;
             break ;

             case ORDER_STATE_PLACED :         ord_data.real_state=ORD_EXIST;
             break ;
           }
        }
       else
        {
         ord_data.error_code= GetLastError ();
        }
       //---   
       if (( ord_data.error_code!= ERR_SUCCESS ) || 
         (ord_data.real_state==ORD_NOT_SPECIFIED))
        {
         return (SELECT_ERROR);
        }
       else
        {
         switch (ord_data.real_state)
           {
             case ORD_BUSY:           return (SELECT_BUSY);
             break ;

             case ORD_EXIST:
             case ORD_EXIST_PARTIAL: return (SELECT_TRUE);
             break ;

             default :                 return (SELECT_FALSE);
             break ;
           }
        }
     }
   else
     {
      ord_data.error_code=ERR_ZERO_TICKET;
       return (SELECT_ERROR);
     }
  }
//+------------------------------------------------------------------+
 

テストはブローカー「0t」のリアル口座で、ターミナルビルド1375、ミドルマーケット商品SILV-9.16で行われました。

1500回(~3時間)の取引で、次のようなことが判明しました。

平均速度(ごく稀に発生する遅延を除く)は〜22msでした

ごくまれに300ms強の遅延が発生するのは、ネットワーク接続が原因である可能性があります。

おそらく開発者が修正したのでしょう。

地下にあるExpert Advisorとターミナルログをフル活用。

ファイル:
MT-5.zip  76 kb
 

ところで、ログをよく見てみると、時々次のようなことがあります。

PN      0       16:44:22.973    Test_delay (SILV-9.16,M1)       Время удаления ордера: 91.84999999999999 ms

なぜかというと、コードに小数点以下2桁に丸めるように書いてあるからです。

Print("Время удаления ордера: ",NormalizeDouble(double(stop-start)/1000,2)," ms");
 
prostotrader:

ところで、ログをよく見てみると、時々次のようなことがあります。

なぜかというと、コードでは小数点以下2桁に丸めることが指定されているからです。

印刷 するには、double を string に変換する機能を使用する必要があります。

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   ulong  stop=123457;
   ulong  start=123400;
   for(int i=0;i<10;i++)
     {
      stop+=i;
      Print("Время удаления ордера, old: ",NormalizeDouble(double(stop-start)/1000,2)," ms",
            ", new: ",DoubleToString((double)(stop-start)/1000.0,2)," ms");
     }
  }

で、そのテキストを「Experts」に出力します。

2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.06 ms, new: 0.06 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.06 ms, new: 0.06 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.06 ms, new: 0.06 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.06 ms, new: 0.06 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.07000000000000001 ms, new: 0.07 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.07000000000000001 ms, new: 0.07 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.08 ms, new: 0.08 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.09 ms, new: 0.09 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.09 ms, new: 0.09 ms
2016.08.20 11:53:50.227 Test (EURUSD,D1)        Время удаления ордера, old: 0.1 ms, new: 0.10 ms
 
教えてください、FORTSの買い逆指値注文はオープン時に滑るのでしょうか?
 
Евгений:
FORTSのオープン時の買いストップ注文は滑るのか、教えてください。

バイ・ストップは取引所に出力されるのではなく、MT5サーバー上で「勤務中」であるため。

相場の動きが激しいと、スリッページが発生することがあります。

理由: