1. OrderSendAsync関数の概要と実務での活用法
MQL5での注文送信には、大きく分けて「同期(OrderSend)」と「非同期(OrderSendAsync)」の2種類があります。
OrderSendAsyncは、売買注文の「リクエスト」をサーバーに送信した直後、その結果(約定したかどうか)を待たずに即座にプログラムの処理を次の行へ進める関数です。
実務レベルの開発において、この関数は「高頻度取引(HFT)」や「複数の通貨ペアを同時に監視するロジック」で極めて重要になります。通常のOrderSendを使うと、サーバーからの応答が返ってくるまでの数十〜数百ミリ秒間、EA全体の動きが止まってしまいます(ブロッキング)。しかし、OrderSendAsyncを活用すれば、注文処理の裏側で別のテクニカル指標の計算を続けたり、他のポジションの管理を行ったりすることが可能になります。
初心者が特につまずきやすいのは、「関数がtrueを返したからといって、約定に成功したわけではない」という点です。この関数はあくまで「注文リクエストをサーバーへ送ることに成功したか」のみを返します。実際の約定結果は、別途OnTradeTransactionイベントなどでハンドルする必要があるため、中級者へのステップアップには避けて通れない関数と言えます。
2. 構文と戻り値
OrderSendAsyncの構文は、同期版のOrderSendとほぼ同じです。
bool OrderSendAsync(
MqlTradeRequest& request, // 注文リクエスト構造体
MqlTradeCheckResult& result // チェック結果構造体
);
パラメーター
- request:
MqlTradeRequest型の構造体。注文の種類(成行・指値)、通貨ペア、ロット数、マジックナンバーなどを格納します。 - 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. 使用上の注意点とよくあるエラー
-
結果の確認を忘れないこと
OrderSendAsyncを呼んだ直後にMqlTradeResultを参照しても、約定後のチケット番号や価格は取得できません。必ずOnTradeTransaction関数を実装し、非同期で返ってくる結果を待つロジックを組む必要があります。 -
多重送信のリスク
ループ内でOrderSendAsyncを使うと、最初の注文が約定する前に次の注文が送られてしまい、意図しない大量のポジションを持つリスクがあります。注文中(In-Flight)の状態をフラグ変数などで管理することが必須です。 -
リクオートとスリッページ
非同期送信の場合、リクエストを送ってからサーバーに届くまでのわずかな時間に価格が動くと、TRADE_RETCODE_REQUOTE(価格再提示)となる確率が上がります。特にボラティリティが高い場面では注意が必要です。 -
フィルポリシー(Order Filling)の不一致
request.type_fillingの設定が利用しているFX業者の仕様と異なると、注文が即座に却下されます。デモ口座で必ず事前に確認しましょう。
5. 【重要】自動売買における約定スピードと環境の罠
プロのクオンツやアルゴリズムトレーダーの世界では、ロジックの優劣以上に「実行環境」が勝敗を分けます。いくらOrderSendAsyncでプログラムの内部処理を高速化しても、あなたのPCから取引サーバー(多くはロンドンやニューヨークに設置)までの物理的な距離が遠ければ、そのネットワーク遅延(レイテンシ)だけで致命的な損失を生みます。自宅のWi-Fi環境からの注文は、プロが使う専用サーバーと比較して数百ミリ秒以上も遅れて届くため、成行注文では常に不利な価格を掴まされる「負け確」の状況になりかねません。
このミリ秒単位の競争を勝ち抜くには、FX業者のデータセンターに限りなく近い場所に位置する「専用VPS」の導入が不可欠です。低レイテンシなVPS環境でEAを稼働させることは、システムトレーダーにとってコストではなく、安定した期待値を積み上げるための「必須設備」と言えます。ネットワーク遅延によるスリッページを最小限に抑え、プログラムの性能を100%引き出す環境を整えることこそが、自動売買で利益を残し続けるための第一歩です。
💡 この記事の内容を実運用で活かすには?
この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント