OrderSend() の質問 - ページ 5

 

どうやら、前回の問題をあまり明確に説明していなかったようです。もう一回やらせてください。

この1年間で、ENUM_ORDER_TYPE_FILLING 列挙値リストの記述が少なくとも3回変更された。 以前の記述は次のようなものであった。

enum_order_type_filling

識別子

商品説明

オーダーフィリングフォック

取引は、指定された数量と、注文で指定された価格と同等かそれ以上の価格でのみ実行されます。もし、その注文シンボルに対して十分な供給がその時点で市場にない場合、その注文は成立しません。この充填タイプは SYMBOL_TRADE_EXECUTION_INSTANT 実行モード または SYMBOL_TRADE_EXECUTION_REQUESTで使用さ れます。

オーダーフィリング

注文で指定された数量の範囲内で、市場で入手可能な最大の数量で、注文で指定された価格と同等以上の価格で取引を執行する契約です。この場合、不足分の追加発注は行いません。このフィリングタイプは トレードサーバーの設定により実行モードSYMBOL_TRADE_EXECUTION_MARKET およびSYMBOL_TRADE_EXECUTION_EXCHANGE においてのみ利用 可能です。

オーダーフィリングリターン

注文で指定された数量の範囲内で、市場で入手可能な最大の数量で、注文で指定された価格と同等以上の価格で取引を行うことを約束すること。この場合、不足分の数量について、本注文で指定された価格で追加注文が行われます。このフィリングタイプは、保留中の注文(TRADE_ACTION_PENDING)に対してのみ使用 されます。

簡単にわかるように、ORDER_FILLING_RETURNと保留中の注文は 一対一で対応しています、つまり ORDER_FILLING_RETURNは保留中の注文にのみ適用され、すべての 保留中の注文の type_filling フィールドはORDER_FILLING_RETURNの 値のみで埋められる可能性があります。

成行注文(action==TRADE_ACTION_DEAL)の場合、サーバー側で設定された執行モードに応じて、type_filling フィールドが入力されているはずです。

つまり、保留中の注文があればORDER_FILLING_RETURN、成行注文が あれば ORDER_FILLING_FOKまたはORDER_FILLING_IOC(モードによって 異なる)というパラダイムがあったのです。

今は少しひっくり返った、つまり。

enum_order_type_filling

識別子

商品説明

オーダーフィリングフォック

このオーダーフィリングポリシーは、指定された数量までしかオーダーを満たすことができないことを意味します。その時点で市場に十分な量の金融商品がない場合、注文は執行されません。必要なボリュームは、現在市場にある複数のオファーからまとめることができます。

オーダーフィリング

注文で指定された数量の範囲内で、市場で入手可能な最大の数量まで取引を行うことに同意することを示す。完全な執行が不可能な場合、注文は利用可能な数量まで満たされ、満たされていない数量はキャンセルされます。

オーダーフィリングリターン

このモードは、ORDER_TYPE_BUY_LIMITとORDER_TYPE_SELL_LIMITの注文にのみ使用されます。部分約定した場合、残りの数量の指値注文は削除されず、有効なままとなります。

ORDER_TYPE_BUY_STOP_LIMITとORDER_TYPE_SELL_STOP_LIMIT注文に対応するORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMITリミットオーダーで実行タイプが ORDER_FILLING_RETURN のものは起動時に作成されることになります。

ORDER_FILLING_FOKとORDER_FILLING_IOCは、成行注文でのみ 使用するという制約がなくなりました。 また、ORDER_FILLING_FOKとORDER_FILLING_IOCは、サーバーで設定された実行モードによっては、成行注文で 使用することに制限はない。 ORDER_FILLING_RETURNは、指値注文と逆指値注文でのみ 使用できるという制約があります。

そこで質問なのですが、指値・逆指値注文を含むすべての注文(成行・保留ともに)に対して、 ORDER_FILLING_FOKと ORDER_FILLING_IOCを全く 使用しなくてもよいのでしょうか。どなたか変更点を把握された方はいらっしゃいますか?

 

標準ライブラリには、この方法(模式図)があります。

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   return(true);
  }

ここでは、ポジション量が取引可能な最大量より多い場合、連続して部分決済を試み ます。

OrderSend() 関数の呼び出しが成功すると、 秒単位の 遅延が設定され、その後、Do-whileループの本体内でPositionSelect() 関数が呼び出されます。つまり、サーバーが成行注文を正常に受け入れた場合、ベースターミナルのオープンポジションに関するデータを更新し、次の反復で更新されたポジションデータ(この例ではポジション量)を取得するには、1秒あれば十分だと想定されます。しかし、2年前、同じメソッドでPositionSelect() 関数を呼び出すまでの遅延は3秒でした。そこで質問です。

OrderSend() の呼び出しが成功した後、端末データベースが更新されたポジションデータを受け取ることが保証される(それによって、端末側で残りのポジション量を正しく処理できる)には、すべてのケースで1 秒あれば十分ですか?この場合、端末データベースが更新された位置データを受信することを保証すべき最大時間は?

 

選手権にはこんなルールがある。

取引条件は限りなく現実に 近いものになります。

  • 取引要求の処理時間 2秒から7秒へ
あるブローカーでリアルに(出金後)処理が3秒程度になった(開設-閉鎖-変更)。
 
Karlson:

選手権にはこんなルールがある。

取引条件は限りなく現実に 近いものになります。

  • 処理時間2~7秒

OK、教えてくれてありがとう!OrderSend( )関数の呼び出しが成功した後、端末データベースが更新されたポジションデータを受け取る には、1秒では 不十分であることが判明しました

この結論から、私が引用したStandard Libraryの方法は、ポジションがクローズされるのではなく、リバースされることを全く保証していないことになります。つまり、PositionClose()メソッドが次の反復を1秒遅らせ、取引要求の処理に2~7倍の時間がかかる場合、新しい反復中にPositionSelect() 関数がベースターミナルからポジションの状態に関する以前の 情報を受け取り、同一の注文でサーバーを攻撃する可能性を排除できません。この場合、合計数量は閉鎖されるポジションの初期金額より 多くなります。

PositionClose()メソッドでは、ポジションを閉じる代わりに反転させることができますが、なぜ1秒の遅れがあるのでしょうか?そして、「限りなく本物に近い取引条件」との整合性がとれていないのでは?

一般的に、 OrderSend() 関数の呼び出しが成功した後、ターミナルデータベースが更新されたポジションデータを受け取ることが保証される時間、および標準のPositionClose()メソッドの1秒の 遅延の理由は何であるかについての詳細情報が必要です。

 
というところから始めましょう。
if(PositionSelect(symbol))

は何も保証しません。使用することはできません。

次に、ターミナルデータの更新は保証されていません。 自分で人工的なTradeContextBusyを設定し、すべての注文が処理されるのを待つ必要があります。
すぐに、MQL5に頭から突っ込むことはできません。時間保証はありません。

 

sergeev:

начнем с того, что

if(PositionSelect(symbol))

は何も保証しません。適用できない。

第二に、端末のデータ更新が保証されていないことです。自分で人工的なTradeContextBusyを組織して、すべての注文が処理されるのを待つ必要があります。
MQL5を直接、使用することはできません。時間保証はありません。

うん、考え続けなければならないね。リサイクルの例として、ライブラリの標準的なメソッドを取り上げるべきであったことがわかりました。

で履歴に案件が表示されたら教えてもらえますか?

DEAL_ENTRY_OUT

市場の出口

というのは、端末のデータベースにあるすべての 情報が自動的に変更された(現在の状態に更新された)ことを意味するのでしょうか?あるいは、すでに取引履歴に表示されているのに、ポジションの情報がまだ更新されないのでしょうか。つまり、履歴の中の取引に関する情報と、それに対応するポジションに関する情報は同時に変化するのか、という興味深い問題である。それとも、この場合、取引やポジションも非同期で端末に更新されるのでしょうか?Roshさんの記事で何とか聞き取れませんでした。私が理解した限りでは、端末のベース更新と取引要求 結果の返送の非同期性はそこに記述されています。

 

端末でのデータ交換モデルは、お気づきのように非同期です。

そのため、取引(注文・取引・ポジションのプロパティを取得する)時には、データ取得の成功を分析する必要があります。そして、何らかのエラー(false/0)が発生した場合は、売買ロジックの解析を終了する。

約定済みで未確認のOrdSend注文はすべて記憶し、まだ前の送信からの回答がない場合は新しい注文の送信自体をブロックして出現を待つ必要があります。

また、例えば、PositionSelectをコンストラクトに置き換えたほうが

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

一般に、取引 ロジックは非同期でなければならない。端末が非同期なので、MT-serverと流動性プロバイダーのサーバーは非同期である。

同期を確認する作業は、すべてMQLプログラマーに任されています。

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций - Документация по MQL5
 

前回の選手権では、この回答で問題なかったのですが

https://www.mql5.com/ru/forum/4342#comment_88688

Дублирование запросов на открытие позиций.
Дублирование запросов на открытие позиций.
  • www.mql5.com
Дублирование запросов на открытие позиций.
 
sergeev:

また、例えば、PositionSelectを構成する

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

PositionSelect()を使うより、PositionTotal()+PositionGetSymbol()を使う方が有利なのか、難しくなければ教えてください。3つの関数とも同じ端子台にアクセスしており、PositionGetSymbol() 関数とPositionSelect()関数が失敗する可能性があります。すなわち、端末ベースに位置が存在する場合、PositionSelect()関数と提案する構築の両方が失敗する可能性がある。やはり、エラーコードを確認する必要があります。

そのコンストラクションの特徴や信頼性は?それでもわからなかったんです。

Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Торговые функции / PositionSelect - Документация по MQL5
 

頭を悩ます...ストップがどうしても決まらない...エラーも多い。これが実験の残骸で、もううまくいかない

void OnTick(){ if(PositionsTotal()<1){OPEN();}}

bool OPEN(){
             MqlTradeRequest request;
             MqlTradeResult result;
             

             request.symbol       = _Symbol;
             request.action       = TRADE_ACTION_DEAL;
             request.type_filling = ORDER_FILLING_FOK;
             request.deviation    = 100;
             request.volume       = NormalizeDouble(2,2);
             request.type         = ORDER_TYPE_BUY;
             request.price        = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             request.tp           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) + 500*_Point,_Digits);
             request.sl           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) - 500*_Point,_Digits);

             OrderSend(request,result);     
                        
             if(result.retcode==10009 || result.retcode==10008)  Print("Succsesful open");
             else                                               Print("Error open: ",DoubleToString(GetLastError(),0),"  response code: ",result.retcode);
    
   return(true);}

このようにすると、エラーは出ませんが、ストップロスが設定されないままです

MqlTradeRequest request={0};MqlTradeResult result={0};