MQL5でポジションを決済する方法|OrderCloseは無い
先に結論です。MQL4の OrderClose はMQL5に存在しません。MQL4から移ってきて最初に詰まるのがここです。
MQL5ではCTrade クラスの PositionClose を使うのがいちばん短く書けます。保有中のポジションは PositionsTotal と PositionGetTicket で列挙します。
(確認環境:MetaTrader 5 / Windows 11)
最小のコード
#include <Trade\Trade.mqh>
CTrade trade;
void CloseAll()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
trade.PositionClose(ticket);
}
}
#include <Trade\Trade.mqh> は標準ライブラリなので、追加のファイルを用意する必要はありません。
🔴 ループは必ず後ろから回す
上のコードで i-- にしているのには理由があります。
ポジションを閉じると、その分リストが詰まってインデックスがずれます。前から回すと、閉じた直後の1件を飛ばします。
| 回し方 | 結果 |
|---|---|
for(i=0; i<PositionsTotal(); i++) |
🔴 1つ飛ばしになる |
for(i=PositionsTotal()-1; i>=0; i--) |
正しく全部閉じる |
「全部閉じたはずなのに半分残る」という症状は、ほぼこれが原因です。ループ条件に PositionsTotal() を直接書いている場合は特に起きます。閉じるたびに上限が減るためです。
PositionGetTicket は選択も兼ねている
公式リファレンスによると、PositionGetTicket はチケットを返すと同時に、そのポジションを操作対象として選択します。
つまり、呼んだ直後であれば PositionGetString や PositionGetDouble がそのまま使えます。
ulong ticket = PositionGetTicket(i);
string sym = PositionGetString(POSITION_SYMBOL);
long magic = PositionGetInteger(POSITION_MAGIC);
double profit = PositionGetDouble(POSITION_PROFIT);
別途 PositionSelect を呼ぶ必要はありません。ただし時間が経ってから参照する場合は、最新の情報を得るために選択し直すことが推奨されています。
対象を絞って閉じる
全部閉じるより、条件で絞る方が実用的です。
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
// 自分のEAが建てたものだけ
if(PositionGetInteger(POSITION_MAGIC) != MyMagic)
continue;
// このチャートの銘柄だけ
if(PositionGetString(POSITION_SYMBOL) != _Symbol)
continue;
trade.PositionClose(ticket);
}
マジックナンバーで絞らないと、手動で建てたポジションや他のEAのポジションまで閉じます。複数のEAを同じ口座で動かしている場合、ここを抜かすと事故になります。
一部だけ閉じる
数量を指定すれば部分決済になります。
trade.PositionClosePartial(ticket, 0.05);
指定できる数量には最小取引単位と刻み幅の制限があります。銘柄仕様を超えた値を渡すと拒否されます。画面側からの操作はMT5の分割決済(部分利確)のやり方にまとめています。
🔴 口座タイプで前提が変わる
公式リファレンスによると、ネッティング口座では1つの銘柄につきポジションは常に1つだけです。ヘッジング口座では同じ銘柄で複数持てます。
| 口座タイプ | 同一銘柄のポジション | ループの意味 |
|---|---|---|
| ネッティング | 常に1つ | 銘柄数だけ回る |
| ヘッジング | 複数 | 建てた回数だけ回る |
ヘッジング口座で書いたコードをネッティング口座で動かすと、想定した件数だけ回りません。口座タイプは ACCOUNT_MARGIN_MODE で確認できます。
失敗した時に原因を見る
PositionClose は成否を返します。失敗を黙って無視すると、閉じたつもりで残ります。
if(!trade.PositionClose(ticket))
Print("決済失敗 ticket=", ticket,
" retcode=", trade.ResultRetcode(),
" ", trade.ResultRetcodeDescription());
よく出るのは取引時間外と価格の制限に引っかかっているケースです。後者はMQL5でinvalid stopsが出る理由で扱っています。出力の確認方法はMQL5のPrintとログの場所にまとめました。
何に使うか
決済のコードは、時間で区切って自動的に閉じる仕組みの中核になります。時刻の取り方と組み合わせる形はMQL5で一定時間ごとに処理する方法に、考え方はMT5で決済だけを自動化する方法にまとめています。
標準機能でまとめて閉じたいだけなら、コードを書く必要はありません。MT5で複数ポジションをまとめて決済する方法を参照してください。
まとめ
- MQL5に
OrderCloseは無い。CTrade::PositionCloseを使う - 🔴 ループは後ろから回す。前から回すと1つ飛ばしになる
PositionGetTicketは選択も兼ねる- マジックナンバーと銘柄で必ず絞る
- 🔴 ネッティング口座は1銘柄1ポジション。件数の前提が変わる
決済用のEAを入れたのに手動のポジションが閉じない場合は、マジックナンバーの扱いが原因のことがあります。MT5の決済用EAが手動ポジションに効かない理由にまとめました。
本記事はMQL5の仕様と実装方法を説明したものであり、特定の売買を推奨するものではありません。実口座で動かす前に必ずデモ口座で検証してください。投資判断はご自身の責任で行ってください。


