MQL4でポジション情報を扱うときは、`OrderSelect()`で1つ選んでから`OrderLots()`や`OrderOpenPrice()`のような関数で値を取り出す、
という1本の流れでした。
ところがMQL5で同じ感覚で`OrderSelect()`を探すと、様子が違います。
MQL5にも`OrderSelect()`という関数は存在しますが、
これは「現在有効な予約注文(指値・逆指値)」だけを選ぶ関数で、
保有中のポジションは対象外です。
この記事では、MQL5で保有中のポジション情報を取得する基本の流れ(`PositionSelect`または`PositionGetTicket`→`PositionGetDouble`/`PositionGetInteger`)を、
MQL4の`OrderSelect()`との違いを踏まえて解説します。
MQL4のOrderSelectは1つで3役、MQL5は3つに分かれている
MQL4の`OrderSelect()`は、保有中のポジション・有効な予約注文・決済済みの履歴を、
`SELECT_BY_POS`の`pool`引数(`MODE_TRADES`か`MODE_HISTORY`)を切り替えるだけで、
すべて同じ関数で扱えました。
MQL5では、この3つが完全に別の関数群に分かれています。
保有中のポジション: PositionSelect() / PositionGetTicket() + PositionGetDouble()等 有効な予約注文 : OrderSelect() + OrderGetDouble()等 決済済みの履歴 : HistorySelect() + HistoryDealGetDouble()等
名前が似ている`OrderSelect()`がMQL5にも存在するせいで、
「ポジション情報が`OrderSelect()`で取れない」
と最初に戸惑うポイントです。
この記事では、このうち最も使用頻度が高い「保有中のポジション」
を扱う`PositionSelect`系を扱います。
PositionSelectで通貨ペア単位のポジションを選択する
最もシンプルなのは、通貨ペアを指定してポジションを選択する`PositionSelect()`です。
bool PositionSelect( string symbol //対象の通貨ペア );
指定した通貨ペアに保有中のポジションがあれば`true`を返し、
以後の`PositionGetDouble()`/`PositionGetInteger()`/`PositionGetString()`がそのポジションの値を返すようになります。
ポジションがなければ`false`が返り、以後の`PositionGetXXX()`系は無効な値(0や空文字)を返すので、
必ず戻り値をチェックしてください。
if(PositionSelect(_Symbol))
{
double volume = PositionGetDouble(POSITION_VOLUME); //ロット数
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);//平均建値
double sl = PositionGetDouble(POSITION_SL); //損切り価格
double tp = PositionGetDouble(POSITION_TP); //利確価格
long posType = PositionGetInteger(POSITION_TYPE); //POSITION_TYPE_BUY or POSITION_TYPE_SELL
long magic = PositionGetInteger(POSITION_MAGIC); //マジックナンバー
Print("保有ロット=", volume, " 建値=", openPrice, " SL=", sl, " TP=", tp);
}
else
{
Print(_Symbol, "の保有ポジションはありません。");
}
`PositionGetDouble()`/`PositionGetInteger()`は、
それぞれ「値を返す性質の異なるプロパティ」ごとに専用の関数として分かれています。
主なプロパティは以下のとおりです。
PositionGetDouble()で取れる主なプロパティ POSITION_VOLUME ロット数 POSITION_PRICE_OPEN 平均建値 POSITION_SL 損切り価格 POSITION_TP 利確価格 POSITION_PRICE_CURRENT 現在値 POSITION_PROFIT 評価損益 PositionGetInteger()で取れる主なプロパティ POSITION_TICKET ポジションチケット番号 POSITION_TIME 建玉時刻 POSITION_TYPE 売買種別(POSITION_TYPE_BUY / POSITION_TYPE_SELL) POSITION_MAGIC マジックナンバー
ヘッジ口座では PositionSelect だけでは足りない
`PositionSelect(symbol)`は、その通貨ペアに保有ポジションが1つだけであることを前提にした関数です。
MQL5は「ネッティング」だけでなく「ヘッジ」モードの口座にも対応しており、
ヘッジ口座では同じ通貨ペアに買いと売りのポジションを同時に持てます。
この場合、`PositionSelect(symbol)`はどちらか一方(内部的な選択ルールに依存)しか選択できません。
同じ通貨ペアの複数ポジションを漏れなく扱いたい場合は、`PositionsTotal()`でポジション総数を取得し、
`PositionGetTicket(index)`でインデックスから1件ずつ選択しながらループするのが確実です。
int PositionsTotal(); ulong PositionGetTicket( int index //ポジションリスト内でのインデックス(0から) );
`PositionGetTicket(index)`は、そのインデックスのポジションのチケット番号を返すと同時に、
そのポジションを以後の`PositionGetXXX()`の対象として選択状態にします。
マジックナンバーで自分のEAが持つポジションだけに絞り込むと、以下のようになります。
int total = PositionsTotal();
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;//何らかの理由で選択に失敗した場合はスキップ
if(PositionGetString(POSITION_SYMBOL) != _Symbol)
continue;//対象の通貨ペアでなければスキップ
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber)
continue;//自分のEAのポジションでなければスキップ
//ここまで来れば、このポジションはPositionGetDouble()等で参照可能
}
ループの添字を`total – 1`から`0`へ向かって減らしているのは、
ループ中にポジションを決済して総数が変わっても、まだ処理していないインデックスがずれないようにするためです(MQL4のOrder系ループでもよく使われる定石と同じ考え方です)。
実際に動くコード全体
ここまでの内容をまとめた、保有中の全ポジション情報をExpertsログに出力する、
実際にMetaEditorでコンパイルできるスクリプトです。
//+------------------------------------------------------------------+
//| PositionInfoDemo.mq5 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.00"
#property script_show_inputs
input long MagicFilter = 0;//マジックナンバーで絞り込む(0なら全ポジション対象)
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
int total = PositionsTotal();
Print("保有ポジション数: ", total);
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);//このインデックスのポジションを選択状態にする
if(ticket == 0)
continue;
if(MagicFilter != 0 && PositionGetInteger(POSITION_MAGIC) != MagicFilter)
continue;//マジックナンバーが一致しなければスキップ
string symbol = PositionGetString(POSITION_SYMBOL);
double volume = PositionGetDouble(POSITION_VOLUME);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double sl = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
double profit = PositionGetDouble(POSITION_PROFIT);
long type = PositionGetInteger(POSITION_TYPE);
string typeText = (type == POSITION_TYPE_BUY) ? "BUY" : "SELL";
PrintFormat("#%d %s %s Lot=%.2f Open=%.5f SL=%.5f TP=%.5f Profit=%.2f",
(int)ticket, symbol, typeText, volume, openPrice, sl, tp, profit);
}
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MetaTrader 5の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「スクリプト」を選び、名前を「PositionInfoDemo」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- MT5の「ナビゲーター」パネルからスクリプトを探し、ポジションを保有している状態のチャートへドラッグ&ドロップする
- 「ツール」→「オプション」→「エキスパートアドバイザ」タブでログ出力が有効になっていることを確認し、「表示」→「ツールボックス」の「エキスパート」タブでポジション情報が出力されていれば成功です
コピペしてコンパイルが通らないときに確認すること
- 拡張子が「.mq5」になっているか(スクリプト作成ウィザードで種類を「Script」にしているか)
- `ulong`型の変数に`int`のフォーマット指定子`%d`をそのまま渡していないか(このコードでは`(int)ticket`とキャストしています。キャストを外すとコンパイル警告が出ることがあります)
まとめ
MQL5で保有中のポジション情報を取得するには、MQL4の`OrderSelect()`のような単一の万能関数はなく、
通貨ペア単位なら`PositionSelect()`、複数ポジションを漏れなく扱うなら`PositionsTotal()`+`PositionGetTicket()`でループし、
`PositionGetDouble()`/`PositionGetInteger()`/`PositionGetString()`で値を取り出す、
という流れになります。
ヘッジ口座で同じ通貨ペアに複数ポジションを持つ運用をする場合は、
`PositionSelect(symbol)`だけに頼らずチケットベースのループを使うようにしてください。
コメント