MQL5 OrderSend()完全ガイド|使い方・注文方法・よくあるエラーを徹底解説

目次

1. MQL5 OrderSend()とは何か

OrderSend()は、MQL5(MetaQuotes Language 5)で実際にトレード注文をブローカーへ送信するための関数です。
EA(Expert Advisor:自動売買プログラム)を作る場合、この関数は注文処理の中心となる最重要機能になります。

MetaTrader 5では、売買シグナルを検出するだけではトレードは実行されません。
EAが次の処理を行う必要があります。

  • 注文内容を作成する
  • ブローカーに送信する
  • 約定結果を確認する

この一連の処理のうち、注文送信を担当するのが OrderSend() です。

MQL5では、注文は次のような構造で処理されます。

EA
 ↓
OrderSend()
 ↓
取引サーバー
 ↓
約定結果

つまり、EAが生成した注文リクエストを取引サーバーに送信するインターフェースOrderSend() です。

1.1 OrderSend()の役割

OrderSend()は、トレード注文を実行するために次の情報をまとめて送信します。

主な注文情報

  • 取引する通貨ペア(例:EURUSD)
  • 売買方向(Buy / Sell)
  • ロットサイズ
  • 注文価格
  • ストップロス(SL)
  • テイクプロフィット(TP)

MQL5では、これらの情報を構造体(データのまとまり)に格納して送信します。

具体的には次の2つの構造体を使います。

構造体 役割
MqlTradeRequest 注文内容を格納
MqlTradeResult 注文結果を受け取る

処理の流れは次のようになります。

1 注文内容を作成
2 OrderSend()を実行
3 結果を確認

簡単なイメージコードは次の通りです。

MqlTradeRequest request;
MqlTradeResult  result;

OrderSend(request, result);

この関数を実行すると、注文が取引サーバーへ送信され、
結果が result に格納されます。

1.2 MT4 OrderSend()との違い

MQL5の OrderSend() は、MetaTrader4(MQL4)と大きく設計が異なります。

MT4では、注文関数は次のような単一関数形式でした。

OrderSend(Symbol(),OP_BUY,0.1,Ask,10,0,0);

一方、MQL5では構造体ベースの設計になっています。

理由は次の通りです。

  • 注文情報が増えて複雑化した
  • サーバー処理が高度化した
  • 拡張性を高めるため

そのためMQL5では

MqlTradeRequest

という構造体に注文情報をまとめてから OrderSend() を実行します。

この違いにより、MT4経験者でも最初に戸惑うポイントになりやすいです。

初心者がよく混乱するポイント

  • MT4と同じ書き方はできない
  • 構造体の初期化が必要
  • 価格取得方法が異なる

この点は、EA開発で最も多い初期トラブルの一つです。

1.3 OrderSend()が必要になる典型的なケース

OrderSend()は次のような場面で使用されます。

① EAによる自動売買

最も一般的な用途です。

RSIが30以下 → Buy
RSIが70以上 → Sell

このとき、売買を実行する処理は OrderSend() が担当します。

② 指値注文・逆指値注文

EAは次のような注文も作れます。

  • Buy Limit(押し目買い)
  • Sell Limit(戻り売り)
  • Buy Stop(ブレイクアウト)
  • Sell Stop(ブレイクアウト)

これらのPending注文(予約注文)OrderSend() で送信します。

③ 複数通貨EA

MT5では

  • 複数通貨
  • 複数時間足

を同時に扱うEAが多く作られます。

この場合も、各通貨ペアに対して OrderSend() を実行します。

つまずきやすいポイント(初心者注意)

EA開発では、OrderSend()周辺で次のミスが非常に多く発生します。

よくある失敗

① 価格(price)を設定していない

→ 注文拒否になる

② ロットサイズがブローカー制限外

Invalid volume エラー

③ SL/TPが近すぎる

Invalid stops エラー

④ シンボル未設定

request.symbol=""

→ 注文不可

⑤ Ask / Bidの使い分けミス

注文 価格
Buy Ask
Sell Bid

これらの問題は、次章で解説する注文構造を理解すると解決できます。

2. OrderSend()の基本構文と関数仕様

OrderSend()は、MQL5でトレード注文を実行するための中核関数です。
この関数は、EAが作成した注文情報を取引サーバーへ送信し、注文結果を受け取る役割を持ちます。

MQL5では、注文情報を複数の引数で直接渡すのではなく、構造体(データのまとまり)に格納してから送信する設計になっています。

2.1 OrderSend()の関数構文

MQL5における OrderSend() の基本構文は次の通りです。

bool OrderSend(
   MqlTradeRequest& request,
   MqlTradeResult&  result
);

引数の意味は次の通りです。

引数 説明
request 注文内容を格納する構造体
result 注文結果を受け取る構造体

戻り値は bool 型です。

戻り値 意味
true サーバーへ注文送信成功
false 注文送信失敗

ただし注意点として、trueでも必ず約定したとは限りません。

OrderSend()が成功するのは

サーバーに注文が届いた

という意味であり、注文結果は result を確認する必要があります。

2.2 MqlTradeRequest(注文情報)

MqlTradeRequest は、注文内容を格納する構造体です。
ここに必要な情報を設定してから OrderSend() を実行します。

代表的なメンバーは次の通りです。

項目 意味
action 注文タイプ
symbol 通貨ペア
volume ロットサイズ
type 注文方向
price 注文価格
sl ストップロス
tp テイクプロフィット
deviation 許容スリッページ
magic EA識別番号

最小構成でも、通常は以下を設定します。

action
symbol
volume
type
price

EAではこれらを正しく設定しないと、注文が拒否されます。

2.3 MqlTradeResult(注文結果)

MqlTradeResult は、注文結果を受け取る構造体です。

主なメンバーは次の通りです。

項目 意味
retcode サーバー応答コード
deal 約定チケット
order 注文チケット
price 約定価格

特に重要なのが

retcode

です。

これは注文結果を示すコードであり、EA開発では必ず確認します。

TRADE_RETCODE_DONE

意味

注文成功

逆に、次のようなコードもあります。

retcode 意味
TRADE_RETCODE_REJECT 注文拒否
TRADE_RETCODE_INVALID_VOLUME ロット不正
TRADE_RETCODE_INVALID_PRICE 価格不正

EAでは次のように確認します。

if(result.retcode == TRADE_RETCODE_DONE)
{
   Print("注文成功");
}

2.4 最小構成の注文コード

成行Buy注文の最小例は次のようになります。

MqlTradeRequest request;
MqlTradeResult  result;

ZeroMemory(request);

request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = 0.1;
request.type   = ORDER_TYPE_BUY;
request.price  = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

OrderSend(request, result);

このコードの処理は次の通りです。

1 注文構造体を作成
2 注文内容を設定
3 OrderSend()で送信

EAでは、この処理を売買シグナル発生時に実行します。

つまずきやすいポイント(重要)

OrderSend()の実装では、次のミスが非常に多く発生します。

ZeroMemory()を忘れる

構造体は初期化しないとゴミデータが入ります。

必ず実行します。

ZeroMemory(request);

② Ask / Bidの間違い

注文 価格
Buy Ask
Sell Bid

ORDER_TYPE_BUY → Ask
ORDER_TYPE_SELL → Bid

③ volumeがブローカー制限外

0.01未満

など。

ブローカーの最小ロットは環境により異なります。

④ deviation未設定

急変相場では注文拒否の原因になります。

request.deviation = 10;

⑤ SL/TPが近すぎる

ブローカーは最小ストップ距離を設定しています。

Invalid stops

エラーの原因になります。

実務的なポイント

実際のEAでは次の処理を追加します。

  • エラー処理
  • retcode確認
  • ログ出力
  • リトライ処理

この部分を省略すると、EAがトレードしない原因の特定が困難になります。

3. MqlTradeRequestの主要パラメータと設定方法

OrderSend()を正しく使用するためには、MqlTradeRequest構造体の各パラメータを理解することが不可欠です。
この構造体には、トレード注文に必要な情報をすべて設定します。

EA開発で注文が失敗する原因の多くは、このパラメータ設定ミスによるものです。
ここでは、実務で特に重要な項目を中心に解説します。

3.1 action(注文アクション)

actionは、注文の種類(取引タイプ)を指定するパラメータです。

主に使用される値は次の通りです。

意味
TRADE_ACTION_DEAL 成行注文
TRADE_ACTION_PENDING 指値・逆指値注文
TRADE_ACTION_SLTP SL/TP変更
TRADE_ACTION_REMOVE 注文削除

EAで最も多く使用されるのは成行注文です。

request.action = TRADE_ACTION_DEAL;

指値注文の場合は次のようになります。

request.action = TRADE_ACTION_PENDING;

3.2 symbol(通貨ペア)

symbol`は、取引する銘柄(通貨ペア)を指定します。

通常は次の値を使用します。

request.symbol = _Symbol;

_Symbolは、現在のチャートの通貨ペアを意味します。

EURUSD
USDJPY
XAUUSD

マルチ通貨EAの場合は、明示的に指定する必要があります。

request.symbol = "EURUSD";

3.3 volume(ロットサイズ)

volumeは、取引数量(ロットサイズ)を指定します。

request.volume = 0.10;

注意点として、ロットサイズにはブローカー制限があります。

主な制限

  • 最小ロット
  • 最大ロット
  • ロットステップ

項目
最小ロット 0.01
ロットステップ 0.01

不正な値を設定すると、次のエラーになります。

TRADE_RETCODE_INVALID_VOLUME

EAでは次の関数で確認できます。

SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);

3.4 type(注文方向)

typeは、売買方向または注文タイプを指定します。

代表的な値は次の通りです。

意味
ORDER_TYPE_BUY 成行買い
ORDER_TYPE_SELL 成行売り
ORDER_TYPE_BUY_LIMIT 買い指値
ORDER_TYPE_SELL_LIMIT 売り指値
ORDER_TYPE_BUY_STOP 買い逆指値
ORDER_TYPE_SELL_STOP 売り逆指値

request.type = ORDER_TYPE_BUY;

3.5 price(注文価格)

priceは、注文価格を指定します。

成行注文の場合

注文 価格
Buy Ask
Sell Bid

request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

Sell注文

request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);

価格設定を誤ると、注文は拒否されます。

3.6 sl / tp(ストップロス・テイクプロフィット)

sl損切り価格
tp利益確定価格です。

request.sl = Ask - 100 * _Point;
request.tp = Ask + 200 * _Point;

ここで _Point

最小価格単位

を意味します。

通貨ペア _Point
EURUSD 0.00001
USDJPY 0.001

3.7 deviation(スリッページ許容)

deviationは、価格変動をどこまで許容するかを指定します。

request.deviation = 10;

単位は

ポイント

です。

設定しないと、ボラティリティが高い相場で注文拒否される可能性があります。

3.8 magic(EA識別番号)

magicは、EA専用の識別番号です。

これを設定すると

  • EAのポジション
  • 手動ポジション

を区別できます。

request.magic = 123456;

EA開発では必須に近いパラメータです。

つまずきやすいポイント

MqlTradeRequestの設定で特に多いミスをまとめます。

price未設定

Invalid price

エラーになります。

symbol未設定

request.symbol = ""

注文失敗になります。

volumeが小さすぎる

Invalid volume

④ SL / TPが近すぎる

Invalid stops

ブローカーごとに最小ストップ距離があります。

actiontypeの組み合わせミス

TRADE_ACTION_DEAL
+
ORDER_TYPE_BUY_LIMIT

これは矛盾した設定です。

実務的なコツ

EAでは次の初期化をよく使います。

MqlTradeRequest request;
MqlTradeResult result;

ZeroMemory(request);
ZeroMemory(result);

これを行うことで、不定データによるバグを防止できます。

4. OrderSend()の実用コード例(成行注文)

ここでは、MQL5で OrderSend() を使って成行注文(いますぐ買う・売る注文)を出す基本実装を解説します。
初心者が最初に動かすべきなのは、まず Buy注文Sell注文 の最小構成です。

成行注文では、現在の市場価格を使って発注します。
ただし実装時には、単に OrderSend() を呼ぶだけでは不十分です。少なくとも次の3点を押さえる必要があります。

  • MqlTradeRequest を正しく初期化する
  • BuyはAsk、SellはBidを使う
  • result.retcode で結果確認する

4.1 Buy注文のサンプルコード

まずは、最も基本的な成行Buy注文です。

void BuyOrder()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_BUY;
   request.price     = ask;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "MQL5 Buy Order";

   if(OrderSend(request, result))
   {
      Print("Buy注文送信成功, retcode=", result.retcode);
   }
   else
   {
      Print("Buy注文送信失敗");
   }
}

このコードの流れは次の通りです。

  • requestresult を用意する
  • ZeroMemory() で初期化する
  • Ask価格を取得する
  • Buy注文に必要な情報をセットする
  • OrderSend() を実行する
  • 結果をログで確認する

Buy注文では、価格に Ask を使います。

double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.price = ask;

ここをBidにすると、環境や条件によって注文拒否や想定外動作の原因になります。

4.2 Sell注文のサンプルコード

次に、成行Sell注文です。

void SellOrder()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_SELL;
   request.price     = bid;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "MQL5 Sell Order";

   if(OrderSend(request, result))
   {
      Print("Sell注文送信成功, retcode=", result.retcode);
   }
   else
   {
      Print("Sell注文送信失敗");
   }
}

Sell注文では、価格に Bid を使います。

double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
request.price = bid;

成行注文の価格指定は、初心者が非常に間違えやすい部分です。
まずは次の対応を固定で覚えると安全です。

注文種別 使う価格
Buy Ask
Sell Bid

4.3 SLとTPを含めた実用例

実運用では、損切りと利確を同時に設定することが多いです。
以下はBuy注文に sltp を加えた例です。

void BuyOrderWithSLTP()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_BUY;
   request.price     = ask;
   request.sl        = ask - 100 * _Point;
   request.tp        = ask + 200 * _Point;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "Buy with SLTP";

   if(OrderSend(request, result))
   {
      Print("Buy注文送信, retcode=", result.retcode);
   }
   else
   {
      Print("Buy注文送信失敗");
   }
}

ここでは

  • 損切り:100ポイント下
  • 利確:200ポイント上

に設定しています。

ただし、_Point は銘柄によって値が異なります。
また、ブローカーによっては最小ストップ距離の制限があるため、この値で必ず通るとは限りません。

4.4 MagicNumberの設定

EA開発では、magic の設定が非常に重要です。
これはその注文がどのEAによるものかを識別する番号です。

request.magic = 123456;

MagicNumberを設定しておくと、後でポジション管理を行うときに

  • 手動注文
  • 他のEAの注文
  • 現在のEAの注文

を区別できます。

特に次のような処理で必須に近いです。

  • 自分のEAのポジションだけ決済する
  • 同じ通貨ペアで複数EAを動かす
  • 運用ログを整理する

逆に magic を設定しないと、後から管理が非常に難しくなります。

4.5 最低限の結果確認

OrderSend()true を返しても、実際の注文結果までは保証しません。
そのため、最低でも result.retcode を確認します。

if(OrderSend(request, result))
{
   if(result.retcode == TRADE_RETCODE_DONE)
   {
      Print("注文成功");
   }
   else
   {
      Print("注文は送信されたが約定失敗, retcode=", result.retcode);
   }
}
else
{
   Print("OrderSend自体が失敗");
}

初心者がやりがちな失敗は、true だけ見て「注文成功」と判断してしまうことです。
実務では、retcode確認までが1セットです。

つまずきやすい点・注意点・よくある失敗

① BuyなのにBidを使う

価格の対応を逆にすると、注文拒否や挙動不良の原因になります。

  • Buy → Ask
  • Sell → Bid

ZeroMemory()を省略する

構造体に不要データが残り、原因不明の失敗につながることがあります。

ZeroMemory(request);
ZeroMemory(result);

は基本として毎回入れる方が安全です。

retcodeを見ていない

OrderSend() の戻り値だけでは不十分です。
result.retcode を見ないと、なぜ失敗したか分かりません。

④ ロットサイズが環境に合っていない

0.10 が常に有効とは限りません。
口座や銘柄によって、最小ロット・ロット刻みが異なります。

⑤ SL/TPの距離が近すぎる

ブローカーの制限に引っかかると Invalid stops になります。
固定値で入れる場合は、環境差を考慮する必要があります。

NormalizeDouble()が常に必要だと思い込む

価格計算で使う場面はありますが、何でも機械的に NormalizeDouble() すればよいわけではありません。
まずは価格取得と計算ロジックを正しくし、そのうえで必要な箇所だけ使う方が安全です。

5. 指値注文・逆指値注文の実装

OrderSend()は成行注文だけでなく、指値注文(Limit)や逆指値注文(Stop)にも対応しています。
EA開発では、ブレイクアウト戦略や押し目買い・戻り売りで予約注文を使う場面が多く、ここを理解すると実装できる戦略の幅が大きく広がります。

成行注文との最大の違いは、注文を今すぐ約定させるのではなく、指定価格に到達したときに発動させる点です。
そのため、actiontype の設定に加えて、価格の置き方を正しく理解する必要があります。

5.1 指値注文・逆指値注文の基本

予約注文では、action に次を指定します。

request.action = TRADE_ACTION_PENDING;

そして type で注文種別を選びます。

注文タイプ 意味
ORDER_TYPE_BUY_LIMIT 現在価格より下で買う
ORDER_TYPE_SELL_LIMIT 現在価格より上で売る
ORDER_TYPE_BUY_STOP 現在価格より上で買う
ORDER_TYPE_SELL_STOP 現在価格より下で売る

まずはこの関係を整理して覚えるのが重要です。

価格位置のイメージ

  • Buy Limit
    押し目を待って、現在価格より下で買う
  • Sell Limit
    戻りを待って、現在価格より上で売る
  • Buy Stop
    上抜けを確認して、現在価格より上で買う
  • Sell Stop
    下抜けを確認して、現在価格より下で売る

ここを逆に理解すると、EAが意図と反対の場所に注文を置くため、実運用では致命的です。

5.2 Buy Limit の実装例

Buy Limit は、現在価格より下に買い注文を置く場合に使います。

void PlaceBuyLimit()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double ask   = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double price = ask - 100 * _Point;

   request.action    = TRADE_ACTION_PENDING;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_BUY_LIMIT;
   request.price     = price;
   request.sl        = price - 100 * _Point;
   request.tp        = price + 200 * _Point;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "Buy Limit";

   if(OrderSend(request, result))
      Print("Buy Limit送信, retcode=", result.retcode);
   else
      Print("Buy Limit送信失敗");
}

この例では、現在のAskより100ポイント下にBuy Limitを置いています。

重要なのは、Buy Limitの価格は現在価格より下であることです。
逆に上へ置くと、注文不正になります。

5.3 Sell Limit の実装例

Sell Limit は、現在価格より上に売り注文を置く場合に使います。

void PlaceSellLimit()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double bid   = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double price = bid + 100 * _Point;

   request.action    = TRADE_ACTION_PENDING;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_SELL_LIMIT;
   request.price     = price;
   request.sl        = price + 100 * _Point;
   request.tp        = price - 200 * _Point;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "Sell Limit";

   if(OrderSend(request, result))
      Print("Sell Limit送信, retcode=", result.retcode);
   else
      Print("Sell Limit送信失敗");
}

Sell Limit は、戻り売り型のEAでよく使います。
ここでも位置関係が重要で、Sell Limitは現在価格より上です。

5.4 Buy Stop の実装例

Buy Stop は、現在価格より上に買い注文を置く予約注文です。
高値更新・上抜け確認型の戦略でよく使います。

void PlaceBuyStop()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double ask   = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double price = ask + 100 * _Point;

   request.action    = TRADE_ACTION_PENDING;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_BUY_STOP;
   request.price     = price;
   request.sl        = price - 100 * _Point;
   request.tp        = price + 200 * _Point;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "Buy Stop";

   if(OrderSend(request, result))
      Print("Buy Stop送信, retcode=", result.retcode);
   else
      Print("Buy Stop送信失敗");
}

Buy Stop は 現在価格より上 に置きます。
押し目買いのつもりでこれを使うと、ロジックが完全に逆になります。

5.5 Sell Stop の実装例

Sell Stop は、現在価格より下に売り注文を置く予約注文です。
安値割れ・下抜け確認型で使われます。

void PlaceSellStop()
{
   MqlTradeRequest request;
   MqlTradeResult  result;

   ZeroMemory(request);
   ZeroMemory(result);

   double bid   = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double price = bid - 100 * _Point;

   request.action    = TRADE_ACTION_PENDING;
   request.symbol    = _Symbol;
   request.volume    = 0.10;
   request.type      = ORDER_TYPE_SELL_STOP;
   request.price     = price;
   request.sl        = price + 100 * _Point;
   request.tp        = price - 200 * _Point;
   request.deviation = 10;
   request.magic     = 123456;
   request.comment   = "Sell Stop";

   if(OrderSend(request, result))
      Print("Sell Stop送信, retcode=", result.retcode);
   else
      Print("Sell Stop送信失敗");
}

Sell Stop は 現在価格より下 に置くのが正しい設定です。

5.6 予約注文で追加で意識すべき項目

予約注文では、成行注文以上に価格設定の整合性が重要です。
最低限、次を確認してください。

  • action = TRADE_ACTION_PENDING になっているか
  • type が予約注文向けになっているか
  • price の位置が現在価格との関係で正しいか
  • sl / tp が近すぎないか
  • result.retcode を確認しているか

また、環境によっては注文有効期限の設定が必要になることもあります。
使うブローカーや銘柄仕様で差が出るため、必要に応じて type_timeexpiration の確認も行います。

つまずきやすい点・注意点・よくある失敗

① Limit と Stop を逆に使う

最も多いミスです。

  • 押し目買い → BUY_LIMIT
  • 上抜け買い → BUY_STOP

ここを逆にすると、EAのロジック自体が破綻します。

② 価格位置が不正

例として、Buy Limit を現在価格より上に置くと不正です。
Sell Stop を現在価格より上に置くのも不正です。

注文タイプごとに価格位置のルールがあると理解してください。

actionTRADE_ACTION_DEAL のままにしている

成行注文コードを流用したときに起こりやすい失敗です。
予約注文では必ず

request.action = TRADE_ACTION_PENDING;

が必要です。

④ SL/TPの向きが逆

Buy系注文なのにSLを上、TPを下へ置くなどのミスです。
売買方向ごとに整理すると次の通りです。

方向 SL TP
Buy系
Sell系

retcode を見ずに放置する

予約注文は成行注文以上に、仕様不一致で弾かれやすいです。
送信したら必ず result.retcode を確認してください。

6. MqlTradeResultの見方と注文結果の確認方法

OrderSend()を実行したあと、EAは必ず注文結果を確認する処理を行う必要があります。
多くの初心者は、OrderSend() の戻り値(true / false)だけを見て処理を終えてしまいますが、これは不十分です。

なぜなら、OrderSend() の戻り値は

サーバーに注文送信できたか

しか保証していないためです。

実際の注文結果(成功・拒否など)は、MqlTradeResult構造体の内容を確認することで初めて分かります。

6.1 OrderSend()の戻り値の意味

OrderSend() の戻り値は bool 型です。

bool OrderSend(request, result);

意味は次の通りです。

戻り値 意味
true 注文リクエスト送信成功
false 注文送信自体が失敗

ただし、true でも注文が成立したとは限りません。

注文送信成功
↓
サーバーで拒否

というケースが普通にあります。

そのため、必ず次を確認します。

result.retcode

6.2 retcode(最重要項目)

retcode は、サーバーの注文結果コードです。
EAではこの値を確認して処理を分岐します。

if(result.retcode == TRADE_RETCODE_DONE)
{
   Print("注文成功");
}

代表的な retcode は次の通りです。

retcode 意味
TRADE_RETCODE_DONE 注文成功
TRADE_RETCODE_PLACED 予約注文成功
TRADE_RETCODE_REJECT 注文拒否
TRADE_RETCODE_INVALID_VOLUME ロット不正
TRADE_RETCODE_INVALID_PRICE 価格不正
TRADE_RETCODE_INVALID_STOPS SL/TP不正

EA開発では、この retcode をログ出力することでトラブル原因を特定できます。

6.3 deal(約定チケット)

deal は、約定取引のチケット番号です。

result.deal

注文が成立した場合、この値に取引IDが入ります。

deal = 123456789

このチケットを使って

  • 約定履歴取得
  • トレードログ
  • 取引分析

などを行えます。

ただし、予約注文の場合はまだ約定していないため deal は0になります。

6.4 order(注文チケット)

order は、注文IDです。

result.order

これは

  • 予約注文
  • 成行注文

どちらでも発行されます。

order = 987654321

このIDは次の用途で使います。

  • 注文キャンセル
  • SL/TP変更
  • 注文管理

EAのポジション管理では、この番号を保存するケースもあります。

6.5 price(約定価格)

price は、実際の約定価格です。

result.price

成行注文では、リクエストした価格と完全一致しないことがあります。
これはスリッページ(価格滑り)によるものです。

項目 価格
注文価格 1.10000
約定価格 1.10002

この差は市場の流動性やサーバー処理によって変わります。

6.6 実務で使う結果確認コード

実務では、次のように結果確認とログ出力をセットで実装することが多いです。

if(OrderSend(request, result))
{
   if(result.retcode == TRADE_RETCODE_DONE)
   {
      Print("注文成功");
   }
   else
   {
      Print("注文送信成功だが約定失敗 retcode=", result.retcode);
   }
}
else
{
   Print("OrderSend送信失敗");
}

この形にしておくと

  • 送信エラー
  • サーバー拒否
  • 約定成功

を区別できます。

EA開発では、このログがデバッグの生命線になります。

6.7 EA開発でよく使うログ出力

EAの開発中は、retcodeを必ず表示するようにすると原因特定が容易になります。

Print("retcode=", result.retcode);
Print("order=", result.order);
Print("deal=", result.deal);
Print("price=", result.price);

これにより

注文送信
↓
サーバー応答
↓
EAログ

の流れが確認できます。

つまずきやすい点・注意点・よくある失敗

retcodeを確認していない

OrderSend()の戻り値だけでは、注文結果は判断できません。

TRADE_RETCODE_DONE以外を無視している

予約注文では

TRADE_RETCODE_PLACED

が正常になります。

③ エラーコードをログに出していない

EA開発ではログがないと原因調査が困難です。

dealorderを混同している

初心者が混乱しやすい部分です。

項目 意味
order 注文ID
deal 約定ID

⑤ 約定価格が違うことをエラーと思う

スリッページは通常の現象です。
完全一致しないことは珍しくありません。

実務での重要ポイント

EAの注文処理は、実際には次の流れで設計します。

OrderSend()
↓
retcode確認
↓
ログ出力
↓
ポジション管理

この設計にしておくと、EAのトラブル対応が格段に容易になります。

7. OrderSend()でよく発生するエラーと対処方法

OrderSend()を使用したEA開発では、注文が拒否されるケースが必ず発生します。
特に初心者が最初に作るEAでは、「注文が通らない」「EAがトレードしない」といった問題の多くが設定ミスまたは環境条件の不一致です。

この章では、実際のEA開発で頻発するエラー原因と、その具体的な対処方法を整理します。

7.1 Invalid volume(ロットサイズ不正)

エラーコード例

TRADE_RETCODE_INVALID_VOLUME

このエラーは、ロットサイズがブローカーの条件を満たしていない場合に発生します。

主な原因

  • 最小ロット未満
  • 最大ロット超過
  • ロットステップ不一致

最小ロット 0.01
ロットステップ 0.01

この環境で

volume = 0.015

は無効です。

対処方法

EAでは次の情報を取得しておくと安全です。

double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

そしてロットを計算するときは、stepに合わせて調整する必要があります。

7.2 Invalid price(価格不正)

エラーコード例

TRADE_RETCODE_INVALID_PRICE

原因

  • priceが未設定
  • Bid / Askの使用ミス
  • 指値注文の価格位置が不正

Buy Limit を現在価格より上に置いた

これは仕様違反となります。

対処方法

基本ルールを整理します。

注文 価格
Buy Ask
Sell Bid

また、予約注文では現在価格との位置関係を必ず確認します。

注文タイプ 価格位置
Buy Limit 現在価格より下
Sell Limit 現在価格より上
Buy Stop 現在価格より上
Sell Stop 現在価格より下

7.3 Invalid stops(SL / TP不正)

エラーコード例

TRADE_RETCODE_INVALID_STOPS

原因

  • SLが近すぎる
  • TPが近すぎる
  • SL / TPの方向ミス

ブローカーは最小ストップ距離を設定しています。

StopLevel = 20 points

この場合、20ポイント以内のSL / TPは拒否されます。

対処方法

EAでは次の情報を取得できます。

int stopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);

SL / TPを設定する際は、この値より大きく離す必要があります。

7.4 Trade disabled(取引不可)

エラーコード例

TRADE_RETCODE_TRADE_DISABLED

原因

  • シンボルが取引不可
  • マーケットが閉じている
  • 自動売買が無効

対処方法

次の設定を確認します。

  1. MT5の「自動売買」ボタンがON
  2. EA設定で「Algo Trading」許可
  3. 取引時間内

EA側では次のチェックも可能です。

bool tradeAllowed = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE);

7.5 Not enough money(証拠金不足)

エラーコード例

TRADE_RETCODE_NO_MONEY

原因

  • 証拠金不足
  • ロットサイズ過大

対処方法

注文前に証拠金チェックを行います。

OrderCalcMargin(...)

EAではリスク管理として必須です。

7.6 Off quotes / Requote

これは価格変動による注文拒否です。

原因

  • 市場の急変
  • スプレッド拡大
  • 流動性低下

特に

  • 指標発表
  • 週明け

などで起こりやすくなります。

対処方法

deviationを設定します。

request.deviation = 10;

ただし、大きすぎると不利な価格で約定する可能性があります。

7.7 EAがトレードしない場合のチェックリスト

EAがトレードしない場合、次の順番で確認すると原因を特定しやすくなります。

  1. Algo TradingがONか
  2. ログにエラーが出ていないか
  3. OrderSend()が実行されているか
  4. retcodeを確認しているか
  5. 価格取得が正しいか
  6. ロットサイズが有効か

ログに retcode を出しておくと、原因特定が格段に早くなります。

つまずきやすい点・注意点・よくある失敗

① Ask / Bidの使い分けミス

初心者が最も多くやるミスです。

② SL / TPの距離不足

ブローカー仕様を考慮していないケースです。

③ ロットサイズの不正

環境によって最小ロットは異なります。

ZeroMemory()忘れ

構造体のゴミデータが原因で失敗する場合があります。

retcodeを見ていない

EA開発では最大のトラブル原因です。

実務的なポイント

EA開発では、注文エラーを完全に防ぐことはできません。
そのため実運用では次の設計を行います。

注文
↓
retcode確認
↓
失敗なら再試行

このリトライ処理を実装することで、実際のトレード環境での安定性が大きく向上します。

8. OrderSend()を安全に使うためのEA設計ベストプラクティス

OrderSend()はEAの中核処理ですが、実運用では単純に注文を出すだけでは不十分です。
相場環境・サーバー応答・ブローカー仕様などの影響を受けるため、安定したEAを作るには注文処理の設計パターンを理解しておく必要があります。

ここでは、実務のEA開発でよく使われる 安全な注文処理の設計方法を整理します。

8.1 注文前チェックを必ず行う

EAは注文を出す前に、取引可能な状態かどうかを確認するべきです。

主にチェックする項目

  • 自動売買が許可されているか
  • 取引時間内か
  • スプレッドが大きすぎないか
  • 証拠金が足りているか

if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
   Print("自動売買が許可されていません");
   return;
}

スプレッドチェックの例

double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);

if(spread > 30)
{
   Print("スプレッドが大きすぎるため注文回避");
   return;
}

スプレッドフィルターは、特に

  • 指標発表
  • 週明け
  • 流動性低下

などで重要になります。

8.2 ポジション管理を行う

EAが無制限に注文を出すと、意図しない大量ポジションになる可能性があります。
そのため、注文前に現在のポジション数を確認します。

if(PositionsTotal() > 0)
{
   Print("既にポジションあり");
   return;
}

または、MagicNumberで管理する方法もあります。

for(int i=0;i<PositionsTotal();i++)
{
   ulong ticket = PositionGetTicket(i);
}

このようにして

  • 同時ポジション数制限
  • EA専用ポジション管理

を行います。

8.3 注文失敗時のリトライ処理

リアル口座では、次の理由で注文が失敗することがあります。

  • スリッページ
  • 価格更新
  • サーバー遅延
  • 一時的な通信エラー

そのため、EAでは再試行処理(Retry)を入れることが多いです。

int retry = 3;

while(retry > 0)
{
   if(OrderSend(request,result))
      break;

   retry--;
   Sleep(500);
}

ただし、無限ループは危険です。
最大回数を必ず制限します。

8.4 MagicNumberを必ず使用する

EAでは magic を使って注文を識別します。

request.magic = 10001;

これを設定しておくことで

  • 手動注文
  • 他EA注文
  • 現在EA注文

を区別できます。

ポジション管理では必須に近い項目です。

8.5 ログを必ず残す

EA開発では、ログがないと原因調査が困難になります。

最低限出力するべき情報

  • retcode
  • order
  • deal
  • price

Print("retcode=", result.retcode);
Print("order=", result.order);
Print("deal=", result.deal);
Print("price=", result.price);

このログは

  • バックテスト
  • フォワードテスト
  • 実口座

すべてで重要になります。

8.6 EAの注文処理の基本構造

実務のEAでは、注文処理は次の構造になります。

売買シグナル
↓
注文前チェック
↓
OrderSend()
↓
retcode確認
↓
ログ出力
↓
ポジション管理

この構造にしておくと

  • デバッグ
  • 運用
  • 改良

が非常にやりやすくなります。

つまずきやすい点・注意点・よくある失敗

① 注文条件チェックをしていない

EAが無制限に注文を出す原因になります。

② MagicNumberを使っていない

ポジション管理ができなくなります。

③ ログを出していない

EAが動かない原因を特定できません。

④ リトライ処理を入れていない

リアル環境では注文失敗が普通に起きます。

⑤ スプレッドフィルターがない

指標時に危険な価格で約定する可能性があります。

実務的な設計ポイント

安定したEAでは、注文処理は次の3要素で構成されます。

安全性
安定性
デバッグ性
  • 安全性 → 注文条件チェック
  • 安定性 → リトライ処理
  • デバッグ性 → ログ出力

この3つを実装しておくと、EAの品質は大きく向上します。

9. FAQ(よくある質問)

9.1 OrderSend()CTradeクラスはどちらを使うべきですか?

どちらでも注文は可能ですが、用途によって使い分けられます。

方法 特徴
OrderSend() 低レベルAPI。細かい制御が可能
CTrade ラッパークラス。コードが簡潔

初心者は CTrade を使う方がコードが短くなります。
一方で、EAを細かく制御したい場合は OrderSend() の方が柔軟です。

例(CTrade)

CTrade trade;
trade.Buy(0.1);

例(OrderSend)

OrderSend(request,result);

EAの内部処理を深く理解したい場合は、OrderSend()を理解しておく価値があります。

9.2 OrderSend()がtrueを返したのに注文が成立しません

OrderSend()の戻り値は、注文送信が成功したかどうかだけを示します。

実際の注文結果は

result.retcode

を確認する必要があります。

if(result.retcode == TRADE_RETCODE_DONE)

これが成立して初めて、注文成功と判断できます。

9.3 Buy注文とSell注文で価格が違うのはなぜですか?

FXでは

価格 意味
Bid 売値
Ask 買値

という2つの価格があります。

注文時の対応は次の通りです。

注文 使用価格
Buy Ask
Sell Bid

この仕組みはスプレッド(売買差)によるものです。

9.4 Invalid stopsエラーが出る原因は何ですか?

主な原因は次の3つです。

  1. SL / TPが近すぎる
  2. SL / TPの方向が逆
  3. ブローカーのStopLevel制限

StopLevelは次の関数で確認できます。

SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);

この値より離してSL/TPを設定する必要があります。

9.5 OrderSend()が実行されない原因は何ですか?

よくある原因は次の通りです。

  • Algo TradingがOFF
  • EA設定で自動売買が無効
  • ロジック条件が成立していない
  • エラーをログ確認していない

EAがトレードしない場合は、まずログ出力を確認することが重要です。

9.6 ZeroMemory()は必ず必要ですか?

強制ではありませんが、実務ではほぼ必須です。

構造体に残る未初期化データを防ぐためです。

ZeroMemory(request);
ZeroMemory(result);

これを入れておくことで、原因不明の注文失敗を防げます。

9.7 EAで注文管理を行うときの基本方法は?

EAでは通常、次の方法でポジションを管理します。

  1. MagicNumberを設定
  2. 現在ポジションを取得
  3. EA専用ポジションのみ処理

request.magic = 123456;

これにより

  • 手動トレード
  • 他EAのトレード

と区別できます。

9.8 OrderSend()で注文が不安定になるのはなぜですか?

リアル市場では次の要因があります。

  • 価格変動
  • サーバー遅延
  • スプレッド変化
  • 流動性低下

そのため、EAでは次の対策が一般的です。

  • deviation設定
  • リトライ処理
  • スプレッドフィルター

これらを実装することで、注文の安定性が向上します。

This website stores cookies on your computer. These cookies are used to provide a more personalized experience and to track your whereabouts around our website in compliance with the European General Data Protection Regulation. If you decide to to opt-out of any future tracking, a cookie will be setup in your browser to remember this choice for one year.

Accept or Deny