FX
MQL4のOrderSendでFX自動売買の新規注文を組む手順

MQL4のOrderSendは、MT4で成行注文や待機注文を新しく出す関数です。FX自動売買で使うときは、引数を埋めて呼ぶだけで終わらせず、銘柄と数量を確かめ、返された注文番号で実際の注文を照合するところまで設計します。
買いなのにBidを渡す、ロットの刻み幅を無視する、送信結果が分からないまま再送する。このような実装では、売買条件が正しくても別の問題が起こります。この記事では、発注条件の組み立て方と、デモ口座で確かめる順序を整理します。
掲載コードの確認用スクリプトは注文を送りません。実際に利益が出る売買ルールや、本番へそのまま置ける完成EAを示すものではありません。まず送信する数値を説明できる状態を目指しましょう。
- 新規注文と変更・決済に使う関数の違い
- 銘柄・数量・価格・損切りを別々に点検する方法
- 発注せずに対象銘柄の仕様を読み取る確認用コード
- 注文番号と注文一覧で送信結果を照合する順序
MQL4のOrderSendでFX自動売買の注文を組む

新規・変更・決済を分けて考える
OrderSendが扱うのは、新しい成行注文と待機注文です。すでにある注文の損切りや利確を変える処理はOrderModify、保有中の注文を閉じる処理はOrderClose、待機注文を取り消す処理はOrderDeleteへ分けます。処理したい対象を先に決めると、関数を選ぶ段階で迷いにくくなります。
成行注文は現在の価格を使って売買する要求、待機注文は指定した条件での売買を待つ要求です。待機注文を受け付けても、まだ建玉になったとは限りません。EAが「注文を出した」と判断する条件と「建玉がある」と判断する条件を同じ変数で済ませないことが大切です。
たとえば、買いの指値を送った直後に同じ条件が成立し続ける場合、保有中の買いだけを数えていると待機注文を見落とします。新規要求をもう一度送る前に、対象銘柄と識別番号が一致する待機注文も確認する設計が必要です。
| 目的 | MQL4の処理 | 確認する状態 |
|---|---|---|
| 新しい売買を要求 | OrderSend | 注文番号と注文の種類 |
| 保護価格などを変更 | OrderModify | 対象番号と変更後の値 |
| 保有注文を決済 | OrderClose | 決済と残存注文 |
| 待機注文を取消 | OrderDelete | 未約定注文の残存 |
正式な引数と戻り値はMetaQuotesのOrderSendリファレンスで確認できます。本記事はMT4のMQL4を対象にしています。MT5の同名関数は要求と結果を構造体で渡す別の形式なので、サンプルを混在させないでください。
十一個の引数を役割で整理する
int ticket = OrderSend(symbol, cmd, volume, price, slippage,
stoploss, takeprofit, comment, magic,
expiration, arrow_color);
これは呼び出し形式を説明する断片です。各変数の宣言や値の検証は省略しているため、この一行だけで発注用プログラムにはなりません。引数の順番を暗記するより、「何を、どちら向きに、どれだけ、いくらで」という条件に分解して読みましょう。
symbolは業者の実在する銘柄名、cmdは注文の種類、volumeはロット数、priceは要求価格です。銘柄名には末尾の記号や接尾辞が付くことがあります。一般的な通貨ペア名をコードへ固定し、実際の口座に同じ名前がないまま要求を作らないようにします。
slippageは成行の許容価格差をポイントで指定する引数です。stoplossとtakeprofitには、幅ではなく価格水準を渡します。「20」と入力したら20pipsの損切りになる、という引数ではありません。価格へ換算する処理と、その価格が許容されるかの検証を分けます。
残りはcomment、magic、expiration、arrow_colorです。コメントはサーバーが末尾を変える場合があるので、完全一致する唯一の識別子と考えない方がよいですね。magicを使う場合も、銘柄や注文種類を併せて照合します。有効期限は待機注文向け、矢印の色は表示用の設定です。
買いと売りで提示価格をそろえる

成行の買いでは最新のAsk、売りでは最新のBidを使います。通常のチャートに見えている一本の価格だけを注文価格と決めると、買いの基準と売りの基準を取り違えることがあります。要求価格は、方向と同時に読み直す項目にしましょう。
現在のチャートと違う銘柄を発注する場合、そのチャートのAskやBidを流用してはいけません。対象銘柄を指定したMarketInfoなどで価格を取得し、小数桁やポイントもその銘柄の仕様へそろえます。EURUSDのチャートからUSDJPYを扱う処理なら、この区別が特に重要です。
処理に時間がかかった場合は、手元の価格が古くなることもあります。RefreshRatesは現在の銘柄の定義済み変数や時系列を更新するための関数です。戻り値がfalseでも、更新すべき新しいデータがない場合があります。falseをそのまま通信障害と決め付けないようにします。
また、価格を読み直しただけで、さきほど成立した売買条件まで有効なままとは限りません。大きく値が動いた場合に追いかけて発注するか、条件を再判定して見送るかはEA側の仕様です。許容差を広げるだけで、その判断を置き換えないでください。
更新の対象と戻り値の説明はRefreshRatesの公式仕様を参照してください。提示価格をそろえる確認と、利益が出るかどうかの検証は別の工程です。
ロットと保護価格を検算する

volumeは小数なので、0.03などの値を代入すること自体はできます。ただし、受け付け可能な最小ロット・最大ロット・刻み幅は銘柄の取引仕様で決まります。小数点以下を二桁に丸めるだけでは、すべての銘柄の数量条件を満たせません。
仮に最小0.10、刻み0.10の銘柄なら、0.15をそのまま送る前に仕様との整合を確かめる必要があります。これは説明用の仮定で、実際の口座の条件ではありません。自動計算した数量が最小値より小さい場合も、勝手に最小値へ引き上げず、許容損失の条件を満たせるかを先に確認します。
仕様の取得にはMODE_MINLOT、MODE_MAXLOT、MODE_LOTSTEPなどを使えます。数量を補正する処理を作るなら、元の数量、補正後の数量、補正理由を分けて点検しましょう。数値が正しく受け付けられることと、資金面で無理がないことは同じではありません。
損切りと利確には、注文方向に合う価格を指定します。さらに、業者の最小距離を示すMODE_STOPLEVELをポイントから価格差へ換算して確認します。0と取得できても、動的な制限によって注文が拒否される場合があることが公式に説明されています。

小数桁の調整だけで最小距離違反が直るとは限りません。価格の向き、ポイントの大きさ、許容される距離を順番に確認します。注文を通すために損切りを0へ置き換える方法は、予定していた保護条件を変えてしまうので、一般的な修正策として採用しないようにしましょう。
ロットや距離の仕様は銘柄プロパティの公式一覧で照合できます。価格方向と距離の詳しい切り分けが必要なら、MT4のエラー130と注文条件の確認手順も参照してください。
待機注文は種類と期限も確認する
MQL4の基本的な注文種類には、成行のOP_BUY・OP_SELLに加え、OP_BUYLIMIT・OP_SELLLIMIT・OP_BUYSTOP・OP_SELLSTOPがあります。指値と逆指値は、現在価格に対して注文価格を置く方向が異なります。買いか売りかだけでなく、どの条件を待つのかを先に決めます。
待機注文で期限を設定するときは、expirationへ渡す日時の基準と、対象サーバーでの期限受付条件を確認します。期限指定が拒否されるサーバーもあります。「拒否されたから期限をなくして続ける」という変更は、注文が残る期間を変えるため、自動で行うべき補正とはいえません。
待機注文の受付は、価格条件を満たしたときの約定を保証しません。注文が期限切れになった、取り消された、建玉へ変わった、という状態ごとに次の処理が変わります。新規発注関数だけで全状態を管理しようとせず、確認する注文種類と終了条件を整理しておきましょう。
六種類の定数はMQL4の注文種類の一覧で確認できます。最初のデモ検証では成行と待機を一度に実装せず、一種類ずつ条件を固定して比較すると、不一致の原因を見つけやすくなります。
MQL4のOrderSendを送信前後に検証する

最初は発注しないコードで確認する
下のスクリプトは、現在のチャート銘柄について価格・ロット条件・最小距離を表示します。OrderSendを呼ばないので、実行しても新しい注文は出しません。まずMetaEditorでスクリプトとして作成し、ご自身のMT4でコンパイル結果を確認してください。ここで実機検証済みの完成品として配布するものではありません。
#property strict
void OnStart()
{
string s = Symbol();
RefreshRates();
int digits = (int)MarketInfo(s, MODE_DIGITS);
double point = MarketInfo(s, MODE_POINT);
double bid = MarketInfo(s, MODE_BID);
double ask = MarketInfo(s, MODE_ASK);
double minLot = MarketInfo(s, MODE_MINLOT);
double maxLot = MarketInfo(s, MODE_MAXLOT);
double lotStep = MarketInfo(s, MODE_LOTSTEP);
double stopPoints = MarketInfo(s, MODE_STOPLEVEL);
if(point <= 0 || bid <= 0 || ask <= 0 || lotStep <= 0)
{
Print("Specification or quote unavailable. No order sent.");
return;
}
Print("Symbol=", s, " Bid=", DoubleToString(bid, digits),
" Ask=", DoubleToString(ask, digits));
Print("MinLot=", minLot, " MaxLot=", maxLot,
" LotStep=", lotStep);
Print("StopLevel(points)=", stopPoints,
" StopDistance(price)=", DoubleToString(stopPoints*point, digits));
Print("Inspection only. No OrderSend call.");
}
表示結果は同じ銘柄の「仕様」と照合します。銘柄名、買いと売りの提示価格、数量の範囲、ポイント換算が一致するかを見る工程です。文字が出たことだけで合格とせず、数字の意味まで一致しているかを確認してください。
このスクリプトは注文可能性を完全に判定するものではありません。取引許可、口座の余剰証拠金、発注しようとする数量、保護価格、同時注文などは別に検査する必要があります。接続直後などで仕様や価格を取得できない場合も、適当な既定値で続きを動かさず、取得状況を確かめます。
送信許可と証拠金は直前に点検する
実際の送信を組み込むときは、EAの取引許可と、取引処理を行える状態を点検します。IsTradeAllowedはEAの売買許可と取引コンテキストの状態を確認する関数です。ただし、trueならどんな銘柄・数量でも注文が通る、という最終保証ではありません。
余剰証拠金を確認するAccountFreeMarginCheckは、対象銘柄・売買方向・数量を渡して、現在の条件で注文後に残る余剰を調べます。口座残高だけを見て数量を決めるより、実際に送る条件との対応を確認できます。確認後に別EAが発注する可能性もあるので、事前確認を予約や資金の確保と取り違えないでください。
確認する数量が0.10でも、OrderSendへ別の変数から1.00を渡していれば意味がありません。事前確認と本送信で同じ確定値を使うことが大切です。変数の上書き、単位変換、複数EAの同時実行がある場合は、値を作った時刻と使用する箇所を追えるようにします。
関数の範囲はIsTradeAllowedとAccountFreeMarginCheckの公式仕様で確認できます。資金不足の切り分けを詳しく行う場合は、MT4のエラー134と送信ロットの確認を参照してください。
注文番号から実際の状態を照合する

OrderSendの戻り値は、受け付けられた注文のチケット番号、失敗時は-1です。true・falseの二択として保存するより、int型の番号を保持して照合する方が、どの注文を確認しているかが明確になります。番号を受け取った後は、OrderSelectでその番号を選び直します。
選択後に見るのは、銘柄、注文種類、ロット、注文価格、損切り、利確、magic、期限です。要求した数字が入っているか、待機注文なら未約定の状態か、すでに決済・取消になっていないかを確かめます。表示されている行の位置だけで対象を決めず、番号を基準に確認しましょう。
OrderSelectは注文のデータをプログラム側へコピーする関数です。以前に選択した値を読み続けると、現在の注文状態とずれる可能性があります。確認する直前に選び直すこと、選択に失敗したら前回の注文データを使わないことが重要です。
また、SELECT_BY_TICKETではpool引数が無視されます。選べたから保有中とは決めず、OrderCloseTimeが0か、OrderTypeが成行か待機かを確認します。状態の判定と選択方法はOrderSelectの公式仕様を参照してください。より詳しい絞り込み方はMQL4のOrderSelectで対象注文を選ぶ手順にまとめています。
失敗と結果不明で対応を変える
失敗したときは、別の処理を挟む前にGetLastErrorを一度だけ呼び、その値を変数へ保存します。この関数を呼ぶと内部のエラー値がリセットされます。画面表示用と分岐用に二回呼び、二回目の0を見て原因なしと判断しないようにしましょう。
129は価格、130はストップ、131は数量、134は資金不足など、番号によって点検する項目が変わります。番号だけで理由を断定しすぎず、失敗した要求の銘柄・方向・数量・価格・時刻と対応させます。入力条件を直せる問題と、市場休止・取引権限の問題を分けると、不要な再送を減らせます。
| 確認結果 | 次に行うこと | 避けたい処理 |
|---|---|---|
| 価格・数量などの不備が判明 | 該当値と仕様を照合する | 同じ値で連続再送 |
| 市場休止や取引不可 | セッションと許可を確認する | 数量を変えて通そうとする |
| タイムアウトなどで結果が不明 | 注文一覧と履歴を照合する | 失敗と決めて新規送信 |
| チケットを取得 | 番号を選び直して注文内容を見る | 送信成功だけで検証終了 |
公式のエラー一覧には、128の取引タイムアウトや、1の結果不明などがあります。ここからの運用設計として、本記事では結果を照合できない状態での無条件再送を勧めません。同一銘柄・識別番号・方向・数量・要求時刻付近の注文を、保有中と履歴の両方で確認してから判断します。
候補が複数あってどれが該当するか分からない場合は、都合のよい一件を選んで再開しないことです。新規発注を止め、注文一覧と接続状況を確認し、必要なら業者へ問い合わせます。これはエラーの公式仕様そのものではなく、重複発注を避けるための実装上の方針です。
番号の意味は取引サーバーの戻りコード一覧、エラー値がリセットされる動作はGetLastErrorの説明で確認できます。エラーを消すことより、実際の注文状態を説明できることを優先しましょう。
MQL4のOrderSendは照合までで完了する
デモでの確認は、仕様を読むだけの状態から始め、送信する一種類の注文を決め、戻り値と注文一覧を照合する順に進めます。成行の買いが確認できたら売り、次に必要な待機注文というように、比較する条件を一つずつ増やすと原因を追いやすくなります。
正常系だけでなく、値を変更しない見送り、数量条件を満たさない場合の停止、通信が不安定な場合の結果照合も確認項目です。実際の注文を使う試験は専用のデモ口座と最小限の対象に分け、試験後に建玉と待機注文の残存まで確認します。
同じ売買条件が何ティックも続く場合は、一回の条件成立に対して何回まで注文を許すかを決めます。保有注文の確認だけでは、要求を送ってから一覧へ反映されるまでの間を扱いきれないことがあります。送信中・照合待ち・確認済み・見送りなどの状態を明示する設計が役立ちます。
売買ロジックそのものをブラウザで組み立てたい場合は、NoCode EA Studioの作成方法と受け取り条件を確認する選択肢もあります。独自のMQL4コードやエラー処理を学びたい方は、この記事の確認を省略して置き換える必要はありません。
同サービスではMT4・MT5向けEAの作成を案内しています。公式ページでは、EAファイルの受け取りに提携先リンクからの口座開設と認証が必要とされています。必要な条件と取引先のリスクを確認し、ご自身の目的に合う場合だけ検討してください。作成ツールを使っても、利益や注文の安全性が保証されるわけではありません。
MQL4のOrderSendで大切なのは、呼べる一行を作ることだけではありません。銘柄・方向・数量・価格を確定し、要求した注文がどの状態で存在するかを確認できて、初めて新規発注の検証が一区切りになります。次の注文へ進む前に、送信前の条件と送信後の事実をそろえてください。
EA作成ツールの検証範囲を確認する
生成コードの動作テスト・コンパイル結果と、その限界 →記事内の戦略や個別のEAの収益性を検証した結果ではありません。学んだルールを、形にしてみよう。
EA作成ツールを開く ↗