MQL5 OrderCheckで証拠金・ロット・StopLevelを確認する方法
OrderCheckは、MQL5で注文リクエストを送信する前に、証拠金、ロット、価格、SL/TP距離、注文条件などを確認するための重要な関数です。
ただし、OrderCheckを呼び出すだけで、EAの発注前チェックがすべて安全になるわけではありません。実際のEAでは、OrderCheckの前に銘柄仕様、最小ロット、最大ロット、volume step、StopLevel、FreezeLevel、BUY / SELL価格、証拠金、スプレッド、取引可否を確認し、OrderCheckの後にはOrderSendやCTradeの結果も別に確認する必要があります。
特に、EA開発でよく起きる「ロット不正」「証拠金不足」「invalid stops」「SL/TPの距離不足」「FreezeLevelによる変更失敗」「OrderCheckは通ったのにOrderSendで失敗する」といった問題は、OrderCheck単体ではなく、発注前チェック全体として整理すると切り分けやすくなります。
このページでは、MQL5のOrderCheckを使って、証拠金、ロット、volume step、StopLevel、FreezeLevel、invalid stops、OrderCalcMargin、SymbolInfo、MqlTradeRequest、MqlTradeCheckResult、retcode、ログ確認を整理します。
なお、このページはMT5 / MQL5のEA開発、発注前チェック、注文失敗の切り分けを目的とした技術記事です。売買判断、推奨エントリー、推奨ロット、推奨銘柄、利益保証、損失回避保証を行うものではありません。
- OrderCheckとは何か
- OrderCheckを発注前チェックのどこに置くか
- OrderCalcMarginとOrderCheckの使い分け
- OrderCalcMarginで必要証拠金を確認する例
- volume min / max / stepを確認する
- ロットをvolume stepへ丸める例
- BUY / SELL価格の基準を確認する
- 価格とdigitsを確認する例
- StopLevelとFreezeLevelを分けて確認する
- StopLevelを確認する例
- FreezeLevelを確認する場面
- MqlTradeRequestへ入れる値を確認する
- OrderCheckの基本コード例
- MqlTradeCheckResultで見る項目
- retcodeをログで分類する
- OrderCheckが通ってもOrderSendが失敗する理由
- OrderSend後の結果も確認する
- invalid stopsが出る時の確認順序
- よくある不具合と確認順序
- CTradeを使う場合の注意点
- ログ設計の基本
- 発注前チェックを関数化する時の考え方
- バックテストで確認すること
- 開発依頼前に整理したい情報
- 実務チェックリスト
- よくある質問
- 関連ページ
- まとめ
OrderCheckとは何か
OrderCheckは、MqlTradeRequestで作成した注文リクエストをサーバーへ送信する前に、注文条件として問題がないかを確認するための関数です。
OrderCheckを使うと、発注前にMqlTradeCheckResultを受け取り、retcode、必要証拠金、余剰証拠金、コメントなどを確認できます。これにより、OrderSendを実行する前に、明らかな条件不備をログへ残しやすくなります。
| 項目 | 役割 | 確認する内容 |
|---|---|---|
MqlTradeRequest | 注文リクエスト | symbol、volume、price、SL、TP、type、type_filling、magicなど |
OrderCheck() | 注文前チェック | リクエスト内容が発注条件として妥当か |
MqlTradeCheckResult | チェック結果 | retcode、margin、margin_free、commentなど |
OrderSend() | 実際の発注 | 注文送信後のretcode、order、deal、commentなど |
OrderCheckは、発注前の確認に役立ちますが、実際の約定を保証するものではありません。OrderCheckが通っても、価格変動、スプレッド拡大、約定方式、type_filling、FreezeLevel、サーバー側制約などにより、OrderSendで失敗する場合があります。
OrderCheckを発注前チェックのどこに置くか
OrderCheckは、発注前チェックの最後に近い位置で使うのが基本です。
なぜなら、ロット、価格、SL/TP、deviation、type_filling、magic、commentなどをMqlTradeRequestへ入れた後でないと、注文リクエスト全体の妥当性を確認できないためです。
| 工程 | 主な確認内容 | 代表ログ |
|---|---|---|
| シグナル判定 | BUY / SELL候補があるか | SIGNAL |
| フィルター確認 | スプレッド、時間帯、最大ポジション数、外部停止など | FILTER_CHECK |
| 銘柄仕様確認 | digits、point、tick size、volume min / max / step | SYMBOL_SPEC |
| ロット確認 | 最小ロット、最大ロット、volume stepへの丸め | LOT_CHECK |
| 価格確認 | BUYはAsk、SELLはBid、現在価格、丸め | PRICE_CHECK |
| SL/TP確認 | StopLevel、FreezeLevel、SL/TP方向、距離 | STOPS_CHECK |
| 証拠金確認 | OrderCalcMargin、余剰証拠金、必要証拠金 | MARGIN_CHECK |
| リクエスト作成 | MqlTradeRequestへ値を設定 | REQUEST_BUILD |
| OrderCheck | 注文リクエスト全体の事前確認 | ORDER_CHECK |
| OrderSend / CTrade | 実際の注文送信と結果確認 | ORDER_SEND |
OrderCheckを最初に呼び出すのではなく、EA側で整えられる条件を先に整え、その結果として作成したMqlTradeRequestをOrderCheckへ渡す流れにすると、ログの意味が分かりやすくなります。
OrderCalcMarginとOrderCheckの使い分け
証拠金だけを確認したい場合は、OrderCalcMarginが使いやすい場面があります。
OrderCalcMarginは、指定した銘柄、注文方向、ロット、価格に対して必要証拠金を計算します。一方、OrderCheckは、MqlTradeRequest全体を対象に、証拠金やリクエスト内容をまとめて確認します。
| 確認方法 | 主な役割 | 確認できる内容 |
|---|---|---|
SymbolInfoDouble() / SymbolInfoInteger() | 銘柄仕様を取得する | volume step、point、digits、StopLevel、FreezeLevelなど |
OrderCalcMargin() | 必要証拠金を計算する | 指定ロットで必要な証拠金 |
OrderCheck() | 注文リクエスト全体を事前確認する | retcode、margin、margin_free、commentなど |
OrderSend() / CTrade | 実際の注文結果を確認する | retcode、order、deal、commentなど |
実務では、OrderCalcMarginで概算の必要証拠金を確認し、ロットやSL/TPを整えた後、OrderCheckでリクエスト全体を確認する流れが扱いやすいです。どちらか一方だけに寄せるのではなく、役割を分けて使うと、証拠金不足なのか、リクエスト内容の不備なのかを切り分けやすくなります。
OrderCalcMarginで必要証拠金を確認する例
OrderCalcMarginを使うと、注文方向、銘柄、ロット、価格に対して必要証拠金を確認できます。
bool CheckRequiredMargin(const string symbol,
const ENUM_ORDER_TYPE order_type,
const double volume)
{
double price = 0.0;
if(order_type == ORDER_TYPE_BUY)
price = SymbolInfoDouble(symbol, SYMBOL_ASK);
else if(order_type == ORDER_TYPE_SELL)
price = SymbolInfoDouble(symbol, SYMBOL_BID);
else
return false;
double margin = 0.0;
ResetLastError();
bool ok = OrderCalcMargin(order_type, symbol, volume, price, margin);
int last_error = GetLastError();
double free_margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
Print("MARGIN_CHECK",
" symbol=", symbol,
" type=", order_type,
" volume=", DoubleToString(volume, 2),
" price=", DoubleToString(price, (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS)),
" ok=", ok ? "Y" : "N",
" required=", DoubleToString(margin, 2),
" free=", DoubleToString(free_margin, 2),
" last_error=", last_error);
if(!ok)
return false;
return (free_margin > margin);
}この例では、OrderCalcMarginで必要証拠金を確認し、口座の余剰証拠金と比較しています。実際のEAでは、現在のポジション数、追加エントリー予定、ナンピン余力、最大ロット、リスク制限も合わせて確認することがあります。
OrderCalcMarginは便利ですが、SL/TPの距離、type_filling、取引許可、StopLevelなどをすべて確認する関数ではありません。そのため、証拠金確認だけで発注可否を確定せず、OrderCheckやOrderSend結果も別に確認してください。
volume min / max / stepを確認する
EAの発注前チェックでは、ロットが銘柄仕様に合っているかを確認します。
MT5では、銘柄ごとに最小ロット、最大ロット、ロット刻みが設定されています。たとえば、最小ロットが0.01、volume stepが0.01の銘柄もあれば、最小ロットやstepが異なる銘柄もあります。
| 項目 | MQL5定数 | 確認内容 |
|---|---|---|
| 最小ロット | SYMBOL_VOLUME_MIN | この値未満のロットは不正になる |
| 最大ロット | SYMBOL_VOLUME_MAX | この値を超えるロットは不正になる |
| ロット刻み | SYMBOL_VOLUME_STEP | 指定ロットをstepに合わせて丸める必要がある |
| ロット上限 | SYMBOL_VOLUME_LIMIT | 同一方向の合計ロット制限を確認する場合がある |
ロット不正は、OrderCheckやOrderSendの失敗原因になりやすい項目です。固定ロット、複利ロット、分割エントリー、ナンピン、コピーEAのロット倍率を使う場合は、最終的に発注するロットがvolume stepに合っているかを確認してください。
ロットをvolume stepへ丸める例
ロットを計算した後は、銘柄のvolume stepに合わせて丸めます。
double NormalizeVolumeByStep(const string symbol, const double raw_volume)
{
double min_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
if(step <= 0.0)
return 0.0;
double volume = raw_volume;
if(volume < min_volume)
volume = min_volume;
if(volume > max_volume)
volume = max_volume;
volume = MathFloor(volume / step) * step;
int digits = 2;
if(step < 0.01)
digits = 3;
if(step < 0.001)
digits = 4;
volume = NormalizeDouble(volume, digits);
Print("LOT_CHECK",
" symbol=", symbol,
" raw=", DoubleToString(raw_volume, 4),
" normalized=", DoubleToString(volume, digits),
" min=", DoubleToString(min_volume, digits),
" max=", DoubleToString(max_volume, digits),
" step=", DoubleToString(step, digits));
return volume;
}この例では、最小ロットと最大ロットの範囲に収めたうえで、volume stepに合わせてロットを丸めています。実際には、丸め方法を切り捨てにするのか、四捨五入にするのか、最小ロット未満を発注しないのかは、EAの仕様として決めておく必要があります。
BUY / SELL価格の基準を確認する
OrderCheckやOrderCalcMarginへ渡す価格は、注文方向に合わせて確認します。
一般的に、BUY注文ではAsk、SELL注文ではBidを基準にします。価格の取り違えは、発注前チェックやSL/TP距離確認の結果に影響します。
| 注文方向 | 基準価格 | 主な確認内容 |
|---|---|---|
| BUY | SYMBOL_ASK | 買い注文の発注価格、SLは下側、TPは上側 |
| SELL | SYMBOL_BID | 売り注文の発注価格、SLは上側、TPは下側 |
EA内では、価格取得、digits、point、tick size、NormalizeDoubleを組み合わせて、発注価格とSL/TP価格を整えます。小数桁やtick sizeの扱いが不十分だと、見た目には正しそうでもサーバー側で不正価格として扱われる場合があります。
価格とdigitsを確認する例
double GetOrderPrice(const string symbol, const ENUM_ORDER_TYPE order_type)
{
double price = 0.0;
if(order_type == ORDER_TYPE_BUY)
price = SymbolInfoDouble(symbol, SYMBOL_ASK);
else if(order_type == ORDER_TYPE_SELL)
price = SymbolInfoDouble(symbol, SYMBOL_BID);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
price = NormalizeDouble(price, digits);
Print("PRICE_CHECK",
" symbol=", symbol,
" type=", order_type,
" price=", DoubleToString(price, digits),
" digits=", digits);
return price;
}このように、価格とdigitsをログに出しておくと、OrderCheckやOrderSendで価格関連の失敗が起きた時に原因を追いやすくなります。
StopLevelとFreezeLevelを分けて確認する
StopLevelとFreezeLevelは混同しやすい項目です。
StopLevelは、現在価格からSL / TP / pending order価格までに必要な最小距離に関係します。FreezeLevelは、現在価格に近い注文やポジションの変更が制限される範囲に関係します。
| 項目 | MQL5定数 | 主な意味 |
|---|---|---|
| StopLevel | SYMBOL_TRADE_STOPS_LEVEL | SL / TPや指値・逆指値注文に必要な最小距離 |
| FreezeLevel | SYMBOL_TRADE_FREEZE_LEVEL | 現在価格に近い注文やポジション変更が制限される範囲 |
| Point | SYMBOL_POINT | 価格単位を距離へ換算するために使う |
| Digits | SYMBOL_DIGITS | 価格の小数桁を整えるために使う |
invalid stopsが出る場合は、SL / TPの方向が間違っているのか、距離が不足しているのか、価格丸めが不適切なのか、StopLevelが足りないのか、FreezeLevelにかかっているのかを分けて確認します。
StopLevelを確認する例
bool CheckStopsDistance(const string symbol,
const ENUM_ORDER_TYPE order_type,
const double entry_price,
const double sl,
const double tp)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
int stops_level = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
double min_distance = stops_level * point;
bool ok = true;
if(order_type == ORDER_TYPE_BUY)
{
if(sl > 0.0 && (entry_price - sl) < min_distance)
ok = false;
if(tp > 0.0 && (tp - entry_price) < min_distance)
ok = false;
}
else if(order_type == ORDER_TYPE_SELL)
{
if(sl > 0.0 && (sl - entry_price) < min_distance)
ok = false;
if(tp > 0.0 && (entry_price - tp) < min_distance)
ok = false;
}
Print("STOPS_CHECK",
" symbol=", symbol,
" type=", order_type,
" entry=", DoubleToString(entry_price, digits),
" sl=", DoubleToString(sl, digits),
" tp=", DoubleToString(tp, digits),
" stops_level=", stops_level,
" min_distance=", DoubleToString(min_distance, digits),
" ok=", ok ? "Y" : "N");
return ok;
}StopLevel確認では、BUYとSELLでSL / TPの方向が逆になります。BUYのSLはentryより下、TPは上です。SELLのSLはentryより上、TPは下です。この方向を間違えると、距離以前に注文条件として不正になります。
FreezeLevelを確認する場面
FreezeLevelは、新規注文よりも、注文変更、SL / TP変更、決済、指値・逆指値注文の変更で問題になることがあります。
たとえば、ポジションに対してSLを後から設定するEA、トレーリングストップ、建値移動、分割決済、pending orderの価格変更を行うEAでは、FreezeLevelを確認しておく必要があります。
| 処理 | FreezeLevelの影響 | 確認ログ |
|---|---|---|
| SL / TP変更 | 現在価格に近すぎると変更できない場合がある | FREEZE_CHECK |
| トレーリングストップ | 価格が近い状態で頻繁に変更しようとして失敗する | TRAIL_MODIFY_SKIP |
| 建値移動 | 変更先SLが制限範囲に入る場合がある | BE_MODIFY_CHECK |
| pending order変更 | 注文価格やSL/TP変更が拒否される場合がある | PENDING_MODIFY_CHECK |
FreezeLevelによる失敗は、OrderCheckの段階だけではなく、ポジション保有後の変更処理で表面化することがあります。そのため、発注前チェックと保有後の変更チェックを分けてログ化してください。
MqlTradeRequestへ入れる値を確認する
OrderCheckは、MqlTradeRequestの内容を確認します。そのため、OrderCheck前にrequestへ入れる値が正しいかを確認する必要があります。
| request項目 | 確認内容 | 注意点 |
|---|---|---|
action | TRADE_ACTION_DEALなど | 成行注文か、pending orderか、変更かを分ける |
symbol | 対象銘柄 | チャート銘柄と発注銘柄が一致しているか |
volume | 発注ロット | volume min / max / stepへ合わせる |
type | ORDER_TYPE_BUY / ORDER_TYPE_SELLなど | 価格、SL、TP方向と一致させる |
price | 発注価格 | BUYはAsk、SELLはBidを基準にする |
sl | 損切り価格 | 方向、StopLevel、FreezeLevelを確認する |
tp | 利確価格 | 方向、StopLevel、FreezeLevelを確認する |
deviation | 許容スリッページ | 銘柄や戦略に合わせて設定する |
magic | Magic Number | EA・ロジック・コピー対象の識別に使う |
comment | 注文コメント | 履歴確認用の補助情報として使う |
type_filling | 約定方式 | 銘柄やブローカーで許可される方式を確認する |
requestを作ったら、OrderCheckの前にログへ出すと、注文失敗時の切り分けがしやすくなります。特に、volume、price、sl、tp、magic、type_fillingは確認対象として重要です。
OrderCheckの基本コード例
bool CheckTradeRequest(MqlTradeRequest &request)
{
MqlTradeCheckResult check;
ZeroMemory(check);
ResetLastError();
bool ok = OrderCheck(request, check);
int last_error = GetLastError();
Print("ORDER_CHECK",
" ok=", ok ? "Y" : "N",
" retcode=", check.retcode,
" balance=", DoubleToString(check.balance, 2),
" equity=", DoubleToString(check.equity, 2),
" margin=", DoubleToString(check.margin, 2),
" margin_free=", DoubleToString(check.margin_free, 2),
" margin_level=", DoubleToString(check.margin_level, 2),
" comment=", check.comment,
" last_error=", last_error);
if(!ok)
return false;
if(check.retcode != TRADE_RETCODE_DONE &&
check.retcode != TRADE_RETCODE_PLACED)
{
Print("ORDER_CHECK_BLOCK",
" retcode=", check.retcode,
" comment=", check.comment);
return false;
}
return true;
}OrderCheckの戻り値とMqlTradeCheckResultのretcodeは、どちらも確認します。関数呼び出し自体の成否と、取引チェック結果は分けて考えると、ログの意味が整理しやすくなります。
MqlTradeCheckResultで見る項目
MqlTradeCheckResultには、注文前チェックの結果が入ります。特に確認したいのは、retcode、margin、margin_free、margin_level、commentです。
| 項目 | 意味 | 確認目的 |
|---|---|---|
retcode | チェック結果コード | 注文前チェックの結果を判定する |
balance | 残高 | 口座状態の確認 |
equity | 有効証拠金 | 含み損益込みの状態を確認 |
margin | 必要証拠金 | 発注後に必要な証拠金を確認 |
margin_free | 余剰証拠金 | 発注後の余力を確認 |
margin_level | 証拠金維持率 | 発注後の余力確認 |
comment | サーバー側コメント | 拒否理由や補足情報を確認 |
retcodeだけでなく、commentもログに出してください。retcodeだけでは原因が分かりにくい場合でも、commentとrequest内容を合わせて見ると、ロット、証拠金、価格、StopLevel、取引制限のどれが原因か判断しやすくなります。
retcodeをログで分類する
OrderCheckやOrderSendの結果をログで見る時は、retcodeを単なる数値として出すだけでなく、分類しておくと確認しやすくなります。
| 分類 | 見方 | 確認すること |
|---|---|---|
| 成功系 | 注文可能または注文受付 | OrderSendへ進むか、結果を確認する |
| 証拠金系 | 資金不足、必要証拠金不足 | ロット、余剰証拠金、追加ポジション余力を確認する |
| ロット系 | volume不正、範囲外、step不一致 | SYMBOL_VOLUME_MIN / MAX / STEPを確認する |
| 価格系 | 価格不正、requote、価格変動 | Bid / Ask、digits、deviation、tickを確認する |
| Stop系 | invalid stops、距離不足 | StopLevel、FreezeLevel、SL / TP方向を確認する |
| 取引制限系 | 市場クローズ、取引不可、銘柄制限 | 取引時間、SYMBOL_TRADE_MODE、セッションを確認する |
retcodeの意味を本文やログで分類しておくと、注文失敗時に「何を直すべきか」が分かりやすくなります。たとえば、証拠金不足ならロットや余剰証拠金、invalid stopsならSL/TP距離、価格系ならBid / Askやdeviationを確認します。
OrderCheckが通ってもOrderSendが失敗する理由
OrderCheckが通った場合でも、OrderSendやCTradeの注文が必ず成功するわけではありません。
OrderCheckからOrderSendまでの間に価格が変わることがあります。また、サーバー側の約定方式、type_filling、スプレッド拡大、取引時間、FreezeLevel、通信状態、ブローカー側制約により、実際の注文が失敗する場合があります。
| 原因 | 起きること | 確認方法 |
|---|---|---|
| 価格変動 | OrderCheck時の価格とOrderSend時の価格が変わる | check_price、send_price、Bid / Askをログに残す |
| スプレッド拡大 | 発注直前に条件が悪化する | spreadをOrderCheck前後で確認する |
| type_filling不一致 | 銘柄が許可しない約定方式を指定する | SYMBOL_FILLING_MODEとrequest.type_fillingを確認する |
| StopLevel変化 | SL/TP距離が足りなくなる | StopLevelと現在価格を再確認する |
| 取引時間外 | チェック時点と送信時点で取引可否が変わる | セッション、サーバー時間、銘柄取引状態を確認する |
| 通信・サーバー応答 | OrderSend自体が失敗する | GetLastError、result.retcode、commentを確認する |
そのため、OrderCheckの結果だけで完了扱いにせず、OrderSendまたはCTradeの結果も必ずログに残します。発注前チェックログと発注結果ログを分けておくことで、どの段階で失敗したのかを判断できます。
OrderSend後の結果も確認する
OrderCheck後にOrderSendを実行した場合は、MqlTradeResultの内容を確認します。
bool SendCheckedOrder(MqlTradeRequest &request)
{
if(!CheckTradeRequest(request))
return false;
MqlTradeResult result;
ZeroMemory(result);
ResetLastError();
bool sent = OrderSend(request, result);
int last_error = GetLastError();
Print("ORDER_SEND",
" sent=", sent ? "Y" : "N",
" retcode=", result.retcode,
" order=", result.order,
" deal=", result.deal,
" volume=", DoubleToString(result.volume, 2),
" price=", DoubleToString(result.price, (int)SymbolInfoInteger(request.symbol, SYMBOL_DIGITS)),
" comment=", result.comment,
" last_error=", last_error);
if(!sent)
return false;
return true;
}OrderCheckとOrderSendは、別の段階としてログに出します。OrderCheckで止まったのか、OrderSendで止まったのか、OrderSendは成功したが約定内容が想定と違うのかを分けることが重要です。
invalid stopsが出る時の確認順序
invalid stopsが出る時は、SL/TPの距離だけでなく、方向、価格、丸め、StopLevel、FreezeLevelを順番に確認します。
| 順番 | 確認項目 | 確認内容 |
|---|---|---|
| 1 | 注文方向 | BUYかSELLかを確認する |
| 2 | 基準価格 | BUYはAsk、SELLはBidを使っているか |
| 3 | SL / TP方向 | BUYのSLは下、TPは上。SELLのSLは上、TPは下 |
| 4 | StopLevel | 現在価格から必要距離を満たしているか |
| 5 | FreezeLevel | 変更処理時に制限範囲へ入っていないか |
| 6 | digits / tick size | 価格丸めが銘柄仕様に合っているか |
| 7 | ログ | entry、sl、tp、distance、min_distanceを確認する |
invalid stopsは、SL/TPの距離だけを広げれば解決するとは限りません。価格の基準や方向を間違えている場合、距離を広げても解決しないことがあります。
よくある不具合と確認順序
| 症状 | 主な原因候補 | 確認するログ |
|---|---|---|
| ロット不正 | volume min / max / stepに合っていない | LOT_CHECK |
| 証拠金不足 | 必要証拠金が余剰証拠金を超えている | MARGIN_CHECK / ORDER_CHECK |
| invalid stops | SL/TP方向、StopLevel、価格丸めの不備 | STOPS_CHECK |
| OrderCheck失敗 | request内容や取引条件の不備 | ORDER_CHECK |
| OrderSend失敗 | 価格変動、type_filling、取引制限、通信状態 | ORDER_SEND |
| CTradeで失敗 | CTradeのResultRetcode確認不足 | CTRADE_RESULT |
| Magicが違う | request.magicやCTradeのMagic設定漏れ | MAGIC_SET |
発注失敗の調査では、いきなりOrderSendのretcodeだけを見るのではなく、ロット、価格、SL/TP、証拠金、OrderCheck、OrderSendの順にログを確認すると、原因を絞り込みやすくなります。
CTradeを使う場合の注意点
CTradeを使う場合でも、OrderCheck相当の発注前チェックは必要です。
CTradeは注文処理を簡潔に書ける一方で、内部で作られるリクエスト内容を十分に意識しないまま使うと、ロット、SL/TP、Magic Number、deviation、type_fillingの確認が不足する場合があります。
| CTradeで確認する項目 | 確認方法 | 注意点 |
|---|---|---|
| Magic Number | SetExpertMagicNumber() | 発注前に意図したMagicを設定する |
| deviation | SetDeviationInPoints() | 価格変動許容範囲を確認する |
| type_filling | 銘柄仕様に合わせる | 約定方式不一致に注意する |
| ResultRetcode | ResultRetcode() | 注文結果を必ず確認する |
| ResultComment | ResultComment() | 失敗理由の確認に使う |
CTradeを使う場合も、発注前にSymbolInfo、ロット、StopLevel、証拠金を確認し、発注後にResultRetcode、ResultOrder、ResultDeal、ResultCommentを確認してください。
ログ設計の基本
OrderCheck関連のログは、発注失敗の原因を切り分けるために重要です。
ログを出す時は、単に「OrderCheck failed」とだけ出すのではなく、どの値で、どの段階で、どの理由で止まったのかを分けて記録します。
| ログ名 | 主な内容 | 目的 |
|---|---|---|
SYMBOL_SPEC | digits、point、volume min / max / step、StopLevel | 銘柄仕様の確認 |
LOT_CHECK | raw lot、normalized lot、min、max、step | ロット不正の切り分け |
PRICE_CHECK | Bid、Ask、entry price、digits | 価格基準の確認 |
STOPS_CHECK | entry、SL、TP、distance、StopLevel | invalid stopsの切り分け |
MARGIN_CHECK | required margin、free margin、volume | 証拠金不足の確認 |
REQUEST_BUILD | requestへ入れた値 | OrderCheck前の内容確認 |
ORDER_CHECK | check.retcode、margin、comment | 発注前チェック結果の確認 |
ORDER_SEND | result.retcode、order、deal、comment | 実際の注文結果の確認 |
ログ名を固定しておくと、Expertsログから検索しやすくなります。たとえば、invalid stopsを調べる場合はSTOPS_CHECK、証拠金不足を調べる場合はMARGIN_CHECK、OrderSendの失敗を調べる場合はORDER_SENDを確認します。
発注前チェックを関数化する時の考え方
OrderCheck周辺の処理は、1つの大きな関数にまとめすぎると保守しにくくなります。
実務では、銘柄仕様確認、ロット補正、価格取得、SL/TP確認、証拠金確認、request作成、OrderCheck、OrderSendを分けておくと、後からログや条件を追加しやすくなります。
| 責務 | 関数例 | 戻り値の考え方 |
|---|---|---|
| 銘柄仕様取得 | LoadSymbolSpec() | 取得成功 / 失敗、spec構造体 |
| ロット補正 | NormalizeVolumeByStep() | 補正済みロット、不正時は0 |
| 価格取得 | GetOrderPrice() | BUY / SELLに応じた価格 |
| SL/TP確認 | CheckStopsDistance() | 距離OK / NG、理由ログ |
| 証拠金確認 | CheckRequiredMargin() | 余力OK / NG、必要証拠金ログ |
| request作成 | BuildTradeRequest() | MqlTradeRequestへ値を設定 |
| OrderCheck | CheckTradeRequest() | 発注前チェックOK / NG |
| OrderSend | SendCheckedOrder() | 送信結果OK / NG |
責務を分けると、OrderCheckで止まったのか、ロット補正で止まったのか、StopLevelで止まったのかをログから判断しやすくなります。また、将来CTrade版、MqlTradeRequest版、コピーEA版、ナンピンEA版へ展開する時も、部品を再利用しやすくなります。
バックテストで確認すること
OrderCheck関連の実装は、バックテストでも確認できます。ただし、Strategy Testerの条件や銘柄仕様によって、実運用と完全に同じ結果になるとは限りません。
バックテストでは、OrderCheckの成否だけでなく、ロット、証拠金、StopLevel、スプレッド、OrderSend結果をログで確認します。
| 確認項目 | 見る内容 | 確認場所 |
|---|---|---|
| 銘柄仕様 | volume min / max / step、StopLevel、digits | Expertsログ |
| ロット補正 | 計算ロットと発注ロットの差 | LOT_CHECK |
| 証拠金 | 必要証拠金、余剰証拠金 | MARGIN_CHECK / ORDER_CHECK |
| SL/TP距離 | entry、SL、TP、StopLevel | STOPS_CHECK |
| OrderCheck | retcode、margin、comment | ORDER_CHECK |
| OrderSend | result.retcode、order、deal | ORDER_SEND |
| 検証条件 | 銘柄、時間足、期間、スプレッド、setファイル | テスト条件メモ |
バックテストでOrderCheck関連ログを確認する時は、成功時ログを出しすぎるとログが膨大になります。必要に応じて、初回のみ、失敗時のみ、一定間隔のみ、またはsummary形式で出力するなど、検証目的に合わせて調整してください。
開発依頼前に整理したい情報
EAの発注前チェックやOrderCheck周辺の改修を相談する場合は、事前に必要な情報を整理しておくと、仕様の確認がスムーズになります。
| 整理項目 | 記入例 | 確認理由 |
|---|---|---|
| 対象EA | 通常EA、ナンピンEA、コピーEA、半裁量EA | 発注前チェックの範囲が変わるため |
| 対象銘柄 | USDJPY、EURUSD、XAUUSDなど | volume stepやStopLevelが銘柄ごとに異なるため |
| ロット計算方式 | 固定ロット、複利、倍率、コピー倍率 | ロット補正の仕様が変わるため |
| SL / TP設定 | 固定pips、ATR、内部決済、SLなしなど | StopLevel確認の必要範囲が変わるため |
| OrderCheckの扱い | 発注前に必ず確認、失敗時は発注停止 | 安全側の停止条件を決めるため |
| OrderCalcMarginの扱い | 必要証拠金を事前ログ化 | 証拠金不足の切り分けに使うため |
| ログ項目 | LOT_CHECK、STOPS_CHECK、ORDER_CHECKなど | 問い合わせ時に原因を追うため |
| OrderSend後の確認 | retcode、order、deal、comment | 実際の発注結果を確認するため |
注文失敗の調査では、EA設定、setファイル、銘柄、時間足、発注方向、ロット、SL/TP、Expertsログ、OrderCheckログ、OrderSendログを合わせて確認してください。口座番号、認証情報、個人情報、APIキーなどは共有しないようにしてください。
実務チェックリスト
- OrderCheckを呼ぶ前に、SymbolInfoで銘柄仕様を確認した
- 最小ロット、最大ロット、volume stepを確認した
- 計算ロットをvolume stepへ丸めた
- BUYはAsk、SELLはBidを基準に価格を設定した
- digits、point、tick sizeを考慮して価格を整えた
- StopLevelを確認し、SL / TP距離が不足していないか確認した
- FreezeLevelが関係する変更処理では、制限範囲を確認した
- OrderCalcMarginで必要証拠金を確認した
- MqlTradeRequestへ入れるvolume、price、sl、tp、magic、commentを確認した
- OrderCheckのretcode、margin、margin_free、commentをログに出した
- OrderCheckが通った後も、OrderSendまたはCTradeの結果を確認した
- OrderSend結果のretcode、order、deal、commentをログに出した
- invalid stopsが出る時は、方向、距離、価格丸め、StopLevelを順番に確認した
- バックテストでは、最終損益だけでなくExpertsログも確認した
よくある質問
OrderCheckだけで証拠金不足を完全に防げますか?
OrderCheckは発注前チェックに有効ですが、実際の注文成功を保証するものではありません。価格変動、スプレッド拡大、取引制限、サーバー応答などにより、OrderCheck後のOrderSendで失敗する場合があります。証拠金確認ではOrderCalcMargin、OrderCheck、OrderSend結果を分けて確認してください。
OrderCalcMarginとOrderCheckはどちらを使えばよいですか?
証拠金だけを事前に見たい場合はOrderCalcMarginが扱いやすいです。MqlTradeRequest全体を確認したい場合はOrderCheckを使います。実務では、OrderCalcMarginで必要証拠金を確認し、ロットやSL/TPを整えた後にOrderCheckを行う流れが分かりやすいです。
invalid stopsが出る時は何を確認しますか?
SL/TPの方向、BUY / SELLの基準価格、StopLevel、FreezeLevel、digits、point、tick size、価格丸めを確認します。単にSL/TP幅を広げるだけではなく、BUYのSLは下側、SELLのSLは上側という方向が正しいかも確認してください。
ロット不正はどこで確認しますか?
SymbolInfoDoubleでSYMBOL_VOLUME_MIN、SYMBOL_VOLUME_MAX、SYMBOL_VOLUME_STEPを取得し、発注ロットが範囲内でstepに合っているか確認します。固定ロット、複利ロット、コピー倍率、ナンピン倍率を使う場合は、最終的に発注するロットをログに出してください。
OrderCheckが通ったのにOrderSendで失敗するのはなぜですか?
OrderCheckからOrderSendまでの間に価格やスプレッドが変化することがあります。また、type_filling、取引時間、サーバー側制約、FreezeLevel、通信状態などで失敗する場合もあります。OrderCheckログとOrderSendログを分けて確認してください。
関連ページ
| 関連テーマ | 確認ページ | 確認できること |
|---|---|---|
| OrderCheckの基本 | MQL5 OrderCheckの使い方 | OrderCheckの基本構文とMqlTradeCheckResultの確認 |
| 注文構造 | MQL5注文関数・取引構造体辞典 | OrderSend、MqlTradeRequest、MqlTradeResultの整理 |
| ロット・証拠金 | MQL5ロット・証拠金・銘柄仕様完全ガイド | ロット、証拠金、銘柄仕様、volume stepの確認 |
| CTrade | MQL5標準ライブラリ・CTrade完全ガイド | CTradeでの注文、決済、ResultRetcode確認 |
| 注文・ポジション・履歴 | MQL5注文・ポジション・履歴管理完全ガイド | 注文、ポジション、約定履歴の確認 |
| ログ設計 | MQL5デバッグ・ログファースト開発完全ガイド | 発注失敗やretcode確認のためのログ設計 |
| バックテスト | MT5ストラテジーテスター・最適化完全ガイド | Strategy Testerでの検証条件とログ確認 |
| EA自作前確認 | 自動売買EAを自作する前に確認すること | EA開発前に整理する仕様と検証項目 |
| ログ確認 | EAのログを問い合わせ前に確認する方法 | 問い合わせ前にExpertsログで確認する項目 |
| 開発・改修相談 | 開発・改修の相談ページ | OrderCheckや発注前チェックを含むEA開発相談前の整理 |
まとめ
OrderCheckは、MQL5でEAの注文リクエストを送信する前に、証拠金やリクエスト内容を確認するための重要な関数です。
ただし、OrderCheckだけで発注前チェックが完了するわけではありません。実務では、SymbolInfoによる銘柄仕様確認、volume min / max / stepによるロット確認、BUY / SELL価格の確認、StopLevelとFreezeLevelの確認、OrderCalcMarginによる証拠金確認、MqlTradeRequestの内容確認、OrderCheck、OrderSend結果確認を分けて整理します。
ロット不正、証拠金不足、invalid stops、type_filling不一致、価格変動、OrderSend失敗は、それぞれ確認する場所が異なります。ログでは、LOT_CHECK、MARGIN_CHECK、STOPS_CHECK、REQUEST_BUILD、ORDER_CHECK、ORDER_SENDのように段階を分けると、原因を追いやすくなります。
EA開発や改修では、OrderCheckを単独の関数として扱うのではなく、発注前チェック全体の中に組み込み、OrderSendやCTradeの結果まで含めて確認してください。これにより、発注失敗時の原因調査、バックテスト確認、問い合わせ対応を整理しやすくなります。
