MQL5でinvalid stopsが出る理由|制限は2種類ある

MQL5で注文や決済条件の変更が invalid stops(リターンコード 10016)で弾かれる時、原因は「現在値に近すぎる」ことです。

ただし近すぎるかどうかを決める制限は1つではありません。よく紹介されるストップレベルのほかに、フリーズレベルという別の制限が存在します。片方だけ見ていると原因にたどり着けません。

(確認環境:MetaTrader 5 / Windows 11)

制限は2種類ある

定数 公式の説明 効く場面
SYMBOL_TRADE_STOPS_LEVEL Stop注文を置くための、現在値からの最小の距離(ポイント) 置く時
SYMBOL_TRADE_FREEZE_LEVEL 取引操作が凍結される距離(ポイント) 変更・取消する時

違いはここです。

  • ストップレベル — これより近い位置には置けない
  • フリーズレベル — 現在値がこの距離まで近づくと、既にある注文を触れなくなる

2つ目が見落とされます。「置けたのに、いざ動かそうとしたら変更できない」という症状はフリーズレベルです。約定寸前のポジションの損切りを慌てて動かそうとした時に出ます。

値を取得する

long stops  = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
long freeze = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL);

Print("stops=", stops, " freeze=", freeze, " point=", _Point);

どちらもポイント単位です。価格に直すには _Point を掛けます。

double min_dist = stops * _Point;

値は業者と銘柄ごとに違います。決め打ちせず、実行時に取得してください。同じ業者でも銘柄が変われば値が変わります。

置く前に確認する

double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl  = ask - 200 * _Point;

double min_dist = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;

if(ask - sl < min_dist)
  {
   sl = ask - min_dist;          // 最小距離まで押し出す
   Print("ストップレベルに合わせて調整しました");
  }

買いの場合、決済逆指値は現在値より下、決済指値は上です。方向を間違えていても同じエラーになります。距離を疑う前に向きを確認してください。

桁を揃えないと弾かれる

距離が足りていても、価格の小数点以下の桁が銘柄と合っていないと通りません。

sl = NormalizeDouble(sl, _Digits);

計算の途中で割り算や掛け算をすると、表示されない下の桁に端数が残ります。発注の直前に NormalizeDouble で丸めてください。これを入れるだけで解決する場合がかなりあります。

チェックの順番

  1. 向きは合っているか — 買いなら決済逆指値は現在値より下
  2. 桁は合っているか — NormalizeDouble(価格, _Digits)
  3. ストップレベル以上離れているか — 置く時
  4. フリーズレベルに入っていないか — 変更・取消する時
  5. 現在値は Bid か Ask か — 買いのエントリーは Ask、決済は Bid で判定される

5番目は見落としやすい項目です。2つの価格の違いはMT5で現在値のラインが消えた時の対処にまとめています。

結果を必ず確認する

戻り値を見ないと、設定できていないことに気づけません。

if(!trade.PositionModify(ticket, sl, tp))
   Print("変更失敗 retcode=", trade.ResultRetcode(),
         " ", trade.ResultRetcodeDescription());

ResultRetcodeDescription() がそのまま理由を返します。推測する前にこれを出してください。出力の見方はMQL5のPrintとログの場所にまとめました。

指標発表の前後で通らなくなる

ストップレベルは固定とは限りません。相場の状況によって広がることがあります。

普段は通っていた幅が指標発表の前後だけ弾かれる場合、コードの問題ではなくその時点の制限が広がっている可能性があります。値を取得してログに出しておくと、後から確認できます。

画面側から手動で設定する場合の手順と注意点はMT5の決済逆指値・決済指値の設定方法に、決済条件を2つ置く考え方はMT5にOCO注文はあるかにまとめています。

まとめ

  1. invalid stops(10016)は現在値に近すぎる時に出る
  2. 🔴 制限は2つ。置く時がストップレベル、変更・取消する時がフリーズレベル
  3. どちらもポイント単位。_Point を掛けて価格に直す
  4. 桁を NormalizeDouble で揃える。これだけで直ることがある
  5. 値は業者・銘柄ごとに違い、状況で広がる。実行時に取得する

EAではなく手動の注文で同じようなエラーが出た場合は、MT5が表示する文言別にMT5で注文できない時の確認|表示されるエラー別の原因で整理しています。

本記事はMQL5の仕様と実装方法を説明したものであり、特定の売買を推奨するものではありません。実口座で動かす前に必ずデモ口座で検証してください。投資判断はご自身の責任で行ってください。