MQL5 ENUM_ORDER_TYPEの基本|注文種類とMqlTradeRequest.typeの指定
MQL5でOrderSendを使う時は、MqlTradeRequestのtypeへ注文種類を指定します。
この注文種類を表す列挙型がENUM_ORDER_TYPEです。成行のBUY / SELLだけでなく、指値、逆指値、StopLimit、Close ByなどもENUM_ORDER_TYPEで指定します。
EAが注文しない、意図しない注文種別になる、指値と逆指値を間違える、StopLimitの価格指定が分からない、といった問題は、ENUM_ORDER_TYPEとMqlTradeRequest.typeの整理から確認すると原因を追いやすくなります。
このページでは、MQL5のENUM_ORDER_TYPEの基本を、注文種類、Buy系とSell系、指値と逆指値、StopLimit、MqlTradeRequest.type、注文種類ミスのログ確認に分けて整理します。
なお、このページはMQL5開発における技術確認を目的とした内容です。売買判断、推奨エントリー、推奨ロット、利益保証、損失回避保証を行うものではありません。
ENUM_ORDER_TYPEとは何か
ENUM_ORDER_TYPEは、MQL5で注文種類を表す列挙型です。
OrderSendで注文要求を送る時は、MqlTradeRequest構造体を作成し、その中のtypeへ注文種類を指定します。
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = 0.10;
request.type = ORDER_TYPE_BUY;
OrderSend(request, result);上記の例では、request.typeへORDER_TYPE_BUYを指定しています。
ただし、注文処理では、request.action、request.type、request.price、request.stoplimit、request.type_filling、request.type_timeなどを組み合わせて指定します。typeだけを見ても、注文要求全体が正しいとは限りません。
ENUM_ORDER_TYPEの主な種類
ENUM_ORDER_TYPEには、成行注文、指値注文、逆指値注文、StopLimit注文、Close By注文があります。
| 定数 | 分類 | 意味 |
|---|---|---|
| ORDER_TYPE_BUY | 成行系 | 買いの成行注文 |
| ORDER_TYPE_SELL | 成行系 | 売りの成行注文 |
| ORDER_TYPE_BUY_LIMIT | 指値系 | 買い指値注文 |
| ORDER_TYPE_SELL_LIMIT | 指値系 | 売り指値注文 |
| ORDER_TYPE_BUY_STOP | 逆指値系 | 買い逆指値注文 |
| ORDER_TYPE_SELL_STOP | 逆指値系 | 売り逆指値注文 |
| ORDER_TYPE_BUY_STOP_LIMIT | StopLimit系 | 買いStopLimit注文 |
| ORDER_TYPE_SELL_STOP_LIMIT | StopLimit系 | 売りStopLimit注文 |
| ORDER_TYPE_CLOSE_BY | 決済系 | 反対ポジションによるClose By注文 |
EA開発では、成行、指値、逆指値、StopLimitを混同しないことが重要です。
成行注文のBUY / SELL
成行注文では、ORDER_TYPE_BUYまたはORDER_TYPE_SELLを指定します。
BUYでは買い方向、SELLでは売り方向の注文要求を作ります。成行注文でTRADE_ACTION_DEALを使う場合、注文タイプと価格の扱いは銘柄の約定方式によって変わります。
bool SendMarketOrder(const ENUM_ORDER_TYPE order_type,
const double volume,
const ulong magic)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = volume;
request.type = order_type;
request.magic = magic;
request.comment = "EAFC_MARKET_ORDER";
if(order_type == ORDER_TYPE_BUY)
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
else if(order_type == ORDER_TYPE_SELL)
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
else
{
PrintFormat("[ORDER_TYPE_NG] type=%d reason=not_market_order", order_type);
return false;
}
ResetLastError();
bool ok = OrderSend(request, result);
PrintFormat("[ORDER_SEND_RESULT] ok=%s type=%s retcode=%u order=%I64u deal=%I64u comment=%s last_error=%d",
(ok ? "true" : "false"),
OrderTypeToText(order_type),
result.retcode,
result.order,
result.deal,
result.comment,
GetLastError());
return ok;
}BUYとSELLでは、確認する価格が異なります。ログでは、注文方向、type、price、Bid、Ask、retcodeを分けて出してください。
指値注文と逆指値注文の違い
指値注文と逆指値注文は、価格条件を指定して発注する保留注文です。
ただし、BUY_LIMIT、SELL_LIMIT、BUY_STOP、SELL_STOPでは、現在価格に対して置く価格の考え方が異なります。
| 注文種類 | 一般的な価格位置 | 確認ポイント |
|---|---|---|
| ORDER_TYPE_BUY_LIMIT | 現在価格より低い側 | 買い指値として妥当な価格か |
| ORDER_TYPE_SELL_LIMIT | 現在価格より高い側 | 売り指値として妥当な価格か |
| ORDER_TYPE_BUY_STOP | 現在価格より高い側 | 買い逆指値として妥当な価格か |
| ORDER_TYPE_SELL_STOP | 現在価格より低い側 | 売り逆指値として妥当な価格か |
価格位置が不正な場合、OrderCheckやOrderSendでエラーになる可能性があります。EAでは、注文種類ごとに現在価格との関係をログに残してください。
Buy系とSell系を分けて考える
ENUM_ORDER_TYPEは、Buy系とSell系で分けて整理すると確認しやすくなります。
| 方向 | 注文種類 | 用途 |
|---|---|---|
| Buy系 | ORDER_TYPE_BUY | 買い成行 |
| Buy系 | ORDER_TYPE_BUY_LIMIT | 買い指値 |
| Buy系 | ORDER_TYPE_BUY_STOP | 買い逆指値 |
| Buy系 | ORDER_TYPE_BUY_STOP_LIMIT | 買いStopLimit |
| Sell系 | ORDER_TYPE_SELL | 売り成行 |
| Sell系 | ORDER_TYPE_SELL_LIMIT | 売り指値 |
| Sell系 | ORDER_TYPE_SELL_STOP | 売り逆指値 |
| Sell系 | ORDER_TYPE_SELL_STOP_LIMIT | 売りStopLimit |
EA内部では、Buy方向かSell方向か、成行か保留注文か、指値か逆指値かを分けておくと、注文種類の取り違えを防ぎやすくなります。
注文タイプを文字列に変換する
ログ確認では、typeの数値だけを出すより、ORDER_TYPE_BUYのような文字列も併記した方が確認しやすくなります。
string OrderTypeToText(const ENUM_ORDER_TYPE type)
{
switch(type)
{
case ORDER_TYPE_BUY:
return "ORDER_TYPE_BUY";
case ORDER_TYPE_SELL:
return "ORDER_TYPE_SELL";
case ORDER_TYPE_BUY_LIMIT:
return "ORDER_TYPE_BUY_LIMIT";
case ORDER_TYPE_SELL_LIMIT:
return "ORDER_TYPE_SELL_LIMIT";
case ORDER_TYPE_BUY_STOP:
return "ORDER_TYPE_BUY_STOP";
case ORDER_TYPE_SELL_STOP:
return "ORDER_TYPE_SELL_STOP";
case ORDER_TYPE_BUY_STOP_LIMIT:
return "ORDER_TYPE_BUY_STOP_LIMIT";
case ORDER_TYPE_SELL_STOP_LIMIT:
return "ORDER_TYPE_SELL_STOP_LIMIT";
case ORDER_TYPE_CLOSE_BY:
return "ORDER_TYPE_CLOSE_BY";
}
return "ORDER_TYPE_UNKNOWN";
}注文ログでは、type=%dだけでなく、type_textも出すと、あとから注文種類を確認しやすくなります。
保留注文を作る時の基本
指値や逆指値などの保留注文では、TRADE_ACTION_PENDINGを使い、request.typeへ保留注文の種類を指定します。
bool SendPendingOrder(const ENUM_ORDER_TYPE order_type,
const double volume,
const double order_price,
const double sl,
const double tp,
const ulong magic)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_PENDING;
request.symbol = _Symbol;
request.volume = volume;
request.type = order_type;
request.price = order_price;
request.sl = sl;
request.tp = tp;
request.magic = magic;
request.comment = "EAFC_PENDING_ORDER";
if(!IsPendingOrderType(order_type))
{
PrintFormat("[ORDER_TYPE_NG] type=%s reason=not_pending_order",
OrderTypeToText(order_type));
return false;
}
ResetLastError();
bool ok = OrderSend(request, result);
PrintFormat("[PENDING_ORDER_SEND] ok=%s type=%s price=%.5f sl=%.5f tp=%.5f retcode=%u order=%I64u comment=%s last_error=%d",
(ok ? "true" : "false"),
OrderTypeToText(order_type),
request.price,
request.sl,
request.tp,
result.retcode,
result.order,
result.comment,
GetLastError());
return ok;
}
bool IsPendingOrderType(const ENUM_ORDER_TYPE type)
{
return (type == ORDER_TYPE_BUY_LIMIT ||
type == ORDER_TYPE_SELL_LIMIT ||
type == ORDER_TYPE_BUY_STOP ||
type == ORDER_TYPE_SELL_STOP ||
type == ORDER_TYPE_BUY_STOP_LIMIT ||
type == ORDER_TYPE_SELL_STOP_LIMIT);
}保留注文では、注文価格、SL、TP、stop level、freeze level、有効期限、type_timeを合わせて確認してください。
StopLimit注文の注意点
StopLimit注文では、request.priceとrequest.stoplimitの両方を使います。
ORDER_TYPE_BUY_STOP_LIMITやORDER_TYPE_SELL_STOP_LIMITでは、指定価格に到達した後、StopLimit価格に基づいてLimit注文が置かれる構造になります。
| 項目 | 意味 | 確認すること |
|---|---|---|
| request.type | StopLimitの注文種類 | BUY_STOP_LIMITかSELL_STOP_LIMITか |
| request.price | Stop条件の価格 | どの価格に到達したらLimit注文を置くか |
| request.stoplimit | Limit注文を置く価格 | Stop到達後に置かれるLimit価格 |
| request.type_time | 注文の有効期限種別 | GTC、当日、期限指定など |
| request.expiration | 期限指定時刻 | type_timeが期限指定の場合に確認 |
StopLimit注文は通常の指値や逆指値より確認項目が増えます。ログでは、priceとstoplimitを必ず分けて出してください。
PrintFormat("[STOP_LIMIT_REQUEST] type=%s price=%.5f stoplimit=%.5f sl=%.5f tp=%.5f",
OrderTypeToText(request.type),
request.price,
request.stoplimit,
request.sl,
request.tp);ORDER_TYPE_CLOSE_BYの扱い
ORDER_TYPE_CLOSE_BYは、反対方向のポジションを使ってポジションを決済するClose By注文です。
Hedging口座で反対ポジションを持つ構成では、Close Byが関係する場合があります。一方で、通常の成行決済やNetting口座の扱いとは異なるため、汎用EAへ安易に混ぜない方が安全です。
| 確認項目 | 内容 |
|---|---|
| 口座方式 | Hedging口座か、Netting口座か |
| 反対ポジション | 同一銘柄で反対方向のポジションがあるか |
| position | 決済対象ポジションのticket |
| position_by | 反対側ポジションのticket |
| ログ | CLOSE_BY_REQUEST、position、position_by、retcode |
Close Byを扱う場合は、通常決済と別ルートに分け、ログ名も分けておくと確認しやすくなります。
MqlTradeRequest.typeと他フィールドを混同しない
MqlTradeRequestでは、type以外にも複数の注文関連フィールドがあります。
type、type_filling、type_time、actionを混同すると、注文種類は正しいのに注文要求全体が不正になる場合があります。
| フィールド | 意味 | 例 |
|---|---|---|
| action | 取引操作の種類 | TRADE_ACTION_DEAL、TRADE_ACTION_PENDING、TRADE_ACTION_SLTPなど |
| type | 注文種類 | ORDER_TYPE_BUY、ORDER_TYPE_BUY_LIMITなど |
| type_filling | 約定方式 | ORDER_FILLING_FOK、ORDER_FILLING_IOC、ORDER_FILLING_RETURNなど |
| type_time | 注文の有効期限種別 | ORDER_TIME_GTC、ORDER_TIME_DAY、ORDER_TIME_SPECIFIEDなど |
| price | 注文価格 | 成行・保留注文・約定方式により扱いが変わる |
| stoplimit | StopLimit価格 | StopLimit注文で使用 |
注文処理では、request.typeだけでなく、action、price、type_filling、type_time、expiration、stoplimitをセットで確認してください。
注文種類ミスを防ぐログ設計
ENUM_ORDER_TYPEのミスは、注文前ログでかなり防ぎやすくなります。
OrderSend前に、注文種類、注文価格、現在価格、SL / TP、stop level、type_filling、type_timeを出しておくと、指値と逆指値の取り違えやStopLimit価格の指定漏れを追いやすくなります。
void PrintOrderRequestLog(const MqlTradeRequest &request)
{
double bid = SymbolInfoDouble(request.symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(request.symbol, SYMBOL_ASK);
PrintFormat("[ORDER_REQUEST] action=%d type=%s symbol=%s volume=%.2f price=%.5f stoplimit=%.5f sl=%.5f tp=%.5f bid=%.5f ask=%.5f filling=%d time_type=%d expiration=%s magic=%I64u comment=%s",
request.action,
OrderTypeToText(request.type),
request.symbol,
request.volume,
request.price,
request.stoplimit,
request.sl,
request.tp,
bid,
ask,
request.type_filling,
request.type_time,
TimeToString(request.expiration, TIME_DATE|TIME_SECONDS),
request.magic,
request.comment);
}注文要求ログは、OrderCheck前とOrderSend前に同じ形式で残すと、どの段階で値が変わったかを確認しやすくなります。
注文種類ごとの簡易チェック
注文種類ごとに現在価格との関係を確認するhelperを作ると、明らかな指定ミスを発注前に止めやすくなります。
bool ValidateOrderTypeAndPrice(const string symbol,
const ENUM_ORDER_TYPE type,
const double price)
{
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
if(type == ORDER_TYPE_BUY_LIMIT && price >= ask)
{
PrintFormat("[ORDER_TYPE_PRICE_NG] type=%s price=%.5f ask=%.5f reason=buy_limit_price_not_below_ask",
OrderTypeToText(type), price, ask);
return false;
}
if(type == ORDER_TYPE_SELL_LIMIT && price <= bid)
{
PrintFormat("[ORDER_TYPE_PRICE_NG] type=%s price=%.5f bid=%.5f reason=sell_limit_price_not_above_bid",
OrderTypeToText(type), price, bid);
return false;
}
if(type == ORDER_TYPE_BUY_STOP && price <= ask)
{
PrintFormat("[ORDER_TYPE_PRICE_NG] type=%s price=%.5f ask=%.5f reason=buy_stop_price_not_above_ask",
OrderTypeToText(type), price, ask);
return false;
}
if(type == ORDER_TYPE_SELL_STOP && price >= bid)
{
PrintFormat("[ORDER_TYPE_PRICE_NG] type=%s price=%.5f bid=%.5f reason=sell_stop_price_not_below_bid",
OrderTypeToText(type), price, bid);
return false;
}
PrintFormat("[ORDER_TYPE_PRICE_OK] type=%s price=%.5f bid=%.5f ask=%.5f",
OrderTypeToText(type), price, bid, ask);
return true;
}実際の判定では、銘柄仕様、stop level、freeze level、digits、point、スプレッドも合わせて確認してください。
OrderCheckと組み合わせる
注文種類と価格の簡易チェックを通過しても、取引サーバー側で受け付けられるとは限りません。
OrderSend前には、OrderCheckでMqlTradeRequestを確認し、retcode、comment、margin、margin_freeなどをログに残すと原因追跡がしやすくなります。
bool CheckRequestBeforeSend(const MqlTradeRequest &request)
{
MqlTradeCheckResult check = {};
ResetLastError();
bool ok = OrderCheck(request, check);
PrintFormat("[ORDER_CHECK] ok=%s type=%s retcode=%u comment=%s margin=%.2f margin_free=%.2f last_error=%d",
(ok ? "true" : "false"),
OrderTypeToText(request.type),
check.retcode,
check.comment,
check.margin,
check.margin_free,
GetLastError());
if(!ok)
return false;
if(check.retcode != 0)
return false;
return true;
}注文種類ミス、価格位置ミス、証拠金不足、stop level不足は、OrderSend前のログで分けて確認できるようにしてください。
よくあるミス
ENUM_ORDER_TYPE周辺では、次のようなミスが起きやすくなります。
| ミス | 起きる問題 | 確認方法 |
|---|---|---|
| BUY_LIMITとBUY_STOPを間違える | 価格位置が不正になり、注文が通らない | 現在Askとの関係をログに出す |
| SELL_LIMITとSELL_STOPを間違える | 価格位置が不正になり、注文が通らない | 現在Bidとの関係をログに出す |
| 成行注文なのにTRADE_ACTION_PENDINGを使う | actionとtypeが噛み合わない | request.actionとrequest.typeを同時にログ化する |
| StopLimitでstoplimitを入れ忘れる | StopLimit注文要求が不正になる | priceとstoplimitを分けてログ化する |
| type_fillingとtypeを混同する | 注文種類と約定方式を取り違える | type、type_filling、type_timeを別項目で確認する |
| ORDER_TYPE_CLOSE_BYを通常決済と混ぜる | 口座方式や反対ポジション確認が不足する | Close By専用の処理ルートへ分ける |
| ログに数値だけ出す | あとから注文種類が分かりにくい | OrderTypeToTextで文字列も出す |
注文処理の不具合調査では、OrderSendのretcodeだけでなく、OrderSend前のrequest内容も確認してください。
ログ出力例
注文種類を確認するログは、type、価格、現在Bid / Ask、retcodeを揃えると見やすくなります。
[ORDER_REQUEST] action=1 type=ORDER_TYPE_BUY_LIMIT symbol=GOLD volume=0.10 price=2345.00 stoplimit=0.00 sl=2340.00 tp=2355.00 bid=2350.10 ask=2350.15 filling=2 time_type=0 expiration=1970.01.01 00:00:00 magic=24016 comment=EAFC_PENDING_ORDER
[ORDER_TYPE_PRICE_OK] type=ORDER_TYPE_BUY_LIMIT price=2345.00 bid=2350.10 ask=2350.15
[ORDER_CHECK] ok=true type=ORDER_TYPE_BUY_LIMIT retcode=0 comment=Done margin=120.50 margin_free=9879.50 last_error=0
[PENDING_ORDER_SEND] ok=true type=ORDER_TYPE_BUY_LIMIT price=2345.00 sl=2340.00 tp=2355.00 retcode=10009 order=123456789 comment=Request executed last_error=0
上記はログ形式の例です。実際のretcode、価格、証拠金、注文可否は、口座、銘柄、約定方式、取引時間、ブローカー設定によって変わります。
関連ページ
ENUM_ORDER_TYPEは、MQL5の列挙型、注文関数、発注前チェック、OrderSend結果ログと合わせて確認すると理解しやすくなります。
| 関連ページ | 確認できること |
|---|---|
| MQL5列挙型・定数辞典 | ENUM_ORDER_TYPE、ENUM_TIMEFRAMES、ORDER_FILLINGなどの定数整理 |
| MQL5でEAの発注前チェックを作る考え方 | OrderSend前のspread、lot、margin、trading allowed確認 |
| MQL5 OrderSend結果ログを実コードで解説 | MqlTradeRequest、MqlTradeResult、TRADE_RETCODE確認 |
| MQL5注文・ポジション・履歴管理完全ガイド | Order、Position、Deal、History管理の全体像 |
| MQL5ロット・証拠金・銘柄仕様完全ガイド | volume step、stop level、銘柄仕様、証拠金確認 |
注文処理全体を確認する場合
ENUM_ORDER_TYPEは、BUY、SELL、指値、逆指値など、注文種類を指定するための列挙型です。MqlTradeRequestで注文を送る場合は、request.typeに注文種類を指定し、request.type_fillingでは約定方式を指定します。
| 確認したいこと | 確認するページ | 主な確認内容 |
|---|---|---|
| 注文関数と取引構造体の全体を確認したい | MQL5注文関数・取引構造体辞典 | OrderSend、OrderCheck、MqlTradeRequest、MqlTradeResult、注文処理全体の確認 |
| 注文種類と約定方式を分けて確認したい | MQL5 ORDER_FILLINGの違い | FOK、IOC、RETURN、type_filling、SYMBOL_FILLING_MODE、注文エラー確認 |
注文エラーを確認する時は、ORDER_TYPEとORDER_FILLINGを混同しないようにしてください。注文種類はrequest.type、約定方式はrequest.type_fillingとして分けてログに出すと、原因を追いやすくなります。
開発依頼前に整理したい情報
注文種類、指値・逆指値、StopLimit、Close By、注文エラーの調査を相談する場合は、次の情報を整理しておくと確認が進めやすくなります。
| 整理する情報 | 確認内容 |
|---|---|
| 対象EA | 新規EA、既存EA改修、注文処理追加、不具合調査のどれか |
| 注文種類 | 成行、指値、逆指値、StopLimit、Close Byのどれを使うか |
| 注文方向 | BUY系、SELL系、両方対応のどれか |
| 注文価格 | 現在価格からの距離、pips指定、価格指定、ライン指定など |
| SL / TP | 固定価格、pips指定、内部決済、トレーリング、建値移動など |
| 発注前チェック | spread、lot、margin、stop level、freeze level、trading allowed |
| ログ | request内容、OrderCheck結果、OrderSend結果、retcode、GetLastError |
| 口座方式 | Hedging / Netting、Close By利用有無 |
注文処理の不具合を相談する場合は、OrderSend後のretcodeだけでなく、OrderSend前のMqlTradeRequest内容を確認できるログを用意してください。
まとめ
ENUM_ORDER_TYPEは、MQL5で注文種類を指定するための列挙型です。
成行注文ではORDER_TYPE_BUY / ORDER_TYPE_SELL、指値注文ではORDER_TYPE_BUY_LIMIT / ORDER_TYPE_SELL_LIMIT、逆指値注文ではORDER_TYPE_BUY_STOP / ORDER_TYPE_SELL_STOPを使います。
StopLimit注文では、request.priceとrequest.stoplimitの両方を確認します。Close Byを扱う場合は、Hedging口座、position、position_byを分けて確認してください。
EA開発では、request.typeだけでなく、action、price、stoplimit、type_filling、type_time、SL / TP、OrderCheck、OrderSend結果をセットでログ化すると、注文種類ミスを追跡しやすくなります。
