【MQL5】OrderSendAsync関数の使い方と自動売買実装コード

1. OrderSendAsync関数の概要と実務での活用法

MQL5での注文送信には、大きく分けて「同期(OrderSend)」と「非同期(OrderSendAsync)」の2種類があります。

OrderSendAsyncは、売買注文の「リクエスト」をサーバーに送信した直後、その結果(約定したかどうか)を待たずに即座にプログラムの処理を次の行へ進める関数です。

実務レベルの開発において、この関数は「高頻度取引(HFT)」や「複数の通貨ペアを同時に監視するロジック」で極めて重要になります。通常のOrderSendを使うと、サーバーからの応答が返ってくるまでの数十〜数百ミリ秒間、EA全体の動きが止まってしまいます(ブロッキング)。しかし、OrderSendAsyncを活用すれば、注文処理の裏側で別のテクニカル指標の計算を続けたり、他のポジションの管理を行ったりすることが可能になります。

初心者が特につまずきやすいのは、「関数がtrueを返したからといって、約定に成功したわけではない」という点です。この関数はあくまで「注文リクエストをサーバーへ送ることに成功したか」のみを返します。実際の約定結果は、別途OnTradeTransactionイベントなどでハンドルする必要があるため、中級者へのステップアップには避けて通れない関数と言えます。

2. 構文と戻り値

OrderSendAsyncの構文は、同期版のOrderSendとほぼ同じです。

bool  OrderSendAsync(
   MqlTradeRequest&  request,      // 注文リクエスト構造体
   MqlTradeCheckResult&  result    // チェック結果構造体
   );

パラメーター

  1. request: MqlTradeRequest型の構造体。注文の種類(成行・指値)、通貨ペア、ロット数、マジックナンバーなどを格納します。
  2. result: MqlTradeCheckResult型の構造体。送信前のチェック結果(証拠金が足りているか、引数が正しいか等)が格納されます。

戻り値

  • true: 注文リクエストが取引サーバーのキュー(待ち行列)に正常に渡されたことを意味します。
  • false: リクエストの送信自体に失敗しました。この場合はGetLastError()で原因を確認する必要があります。

注意: 戻り値がtrueであっても、その後にサーバー側でリジェクト(拒絶)されたり、リクオート(価格再提示)が発生したりする可能性があります。

3. 具体的な使い方・実践サンプルコード

以下は、成行買い注文を非同期で送信する実用的なサンプルコードです。

//+------------------------------------------------------------------+
//| 非同期注文のサンプルEA                                              |
//+------------------------------------------------------------------+
#property strict

// 注文送信関数
void QuickBuy(double volume)
{
   MqlTradeRequest request;
   MqlTradeCheckResult check_result;

   // 構造体の初期化(ゼロクリア)
   ZeroMemory(request);
   ZeroMemory(check_result);

   // 注文パラメータの設定
   request.action       = TRADE_ACTION_DEAL;         // 成行注文
   request.symbol       = _Symbol;                   // 現在の通貨ペア
   request.volume       = volume;                    // ロット数
   request.type         = ORDER_TYPE_BUY;            // 買い
   request.price        = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // 現在の買値
   request.deviation    = 10;                        // 許容スリッページ
   request.magic        = 123456;                    // マジックナンバー
   request.comment      = "Async Order Sample";      // コメント
   request.type_filling = ORDER_FILLING_IOC;         // フィルポリシー(業者により異なる)

   // 非同期注文の送信
   if(!OrderSendAsync(request, check_result))
   {
      // 送信自体に失敗した場合
      PrintFormat("OrderSendAsync 失敗: Error %d", GetLastError());
   }
   else
   {
      // 送信成功(約定したかどうかは別問題)
      Print("注文リクエストをサーバーへ送信しました。結果はOnTradeTransactionで確認してください。");
   }
}

// 実際の約定結果を受け取るイベントハンドラ
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
   // 取引が完了(リクエストに対するレスポンス)したか確認
   if(trans.type == TRADE_TRANSACTION_REQUEST)
   {
      if(result.retcode == TRADE_RETCODE_DONE)
      {
         Print("注文が正常に約定しました! チケット番号: ", result.order);
      }
      else
      {
         PrintFormat("約定失敗。エラーコード: %d", result.retcode);
      }
   }
}

4. 使用上の注意点とよくあるエラー

  1. 結果の確認を忘れないこと
    OrderSendAsyncを呼んだ直後にMqlTradeResultを参照しても、約定後のチケット番号や価格は取得できません。必ずOnTradeTransaction関数を実装し、非同期で返ってくる結果を待つロジックを組む必要があります。

  2. 多重送信のリスク
    ループ内でOrderSendAsyncを使うと、最初の注文が約定する前に次の注文が送られてしまい、意図しない大量のポジションを持つリスクがあります。注文中(In-Flight)の状態をフラグ変数などで管理することが必須です。

  3. リクオートとスリッページ
    非同期送信の場合、リクエストを送ってからサーバーに届くまでのわずかな時間に価格が動くと、TRADE_RETCODE_REQUOTE(価格再提示)となる確率が上がります。特にボラティリティが高い場面では注意が必要です。

  4. フィルポリシー(Order Filling)の不一致
    request.type_fillingの設定が利用しているFX業者の仕様と異なると、注文が即座に却下されます。デモ口座で必ず事前に確認しましょう。

5. 【重要】自動売買における約定スピードと環境の罠

プロのクオンツやアルゴリズムトレーダーの世界では、ロジックの優劣以上に「実行環境」が勝敗を分けます。いくらOrderSendAsyncでプログラムの内部処理を高速化しても、あなたのPCから取引サーバー(多くはロンドンやニューヨークに設置)までの物理的な距離が遠ければ、そのネットワーク遅延(レイテンシ)だけで致命的な損失を生みます。自宅のWi-Fi環境からの注文は、プロが使う専用サーバーと比較して数百ミリ秒以上も遅れて届くため、成行注文では常に不利な価格を掴まされる「負け確」の状況になりかねません。

このミリ秒単位の競争を勝ち抜くには、FX業者のデータセンターに限りなく近い場所に位置する「専用VPS」の導入が不可欠です。低レイテンシなVPS環境でEAを稼働させることは、システムトレーダーにとってコストではなく、安定した期待値を積み上げるための「必須設備」と言えます。ネットワーク遅延によるスリッページを最小限に抑え、プログラムの性能を100%引き出す環境を整えることこそが、自動売買で利益を残し続けるための第一歩です。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました