ポジションを決済するには、どのポジションに対して処理するのかをOrderSelect関数で決める必要があります。口座の中には、裁量トレードや他のEAによるポジションが混在している可能性も十分にあります。

OrderSelect
OrderSelect関数は、単体で使うものではありません。この後に続く決済、指値の変更、損切り・利確値の修正など、さまざまな注文操作の前提となるとても重要な関数です。
Definition
|
1 2 3 4 5 |
bool OrderSelect( int index, // index or order ticket int select, // flag int pool=MODE_TRADES // mode ); |
選択に成功すると true、失敗すると false を返します。失敗した理由は GetLastError() で確認できます。
Reference: OrderSelect – MQL4 Reference
Parameters
index:
インデックスかチケット番号を指定して注文を特定します。どちらを指定したかは、次の select で明示します。
- インデックス:注文の一覧に0から順番に振られている番号
- チケット番号:OrderSend関数の戻り値などで得られる、注文ごとの番号
どちらも状況によって変わることがあり、常に固定ではありません(詳しくは注意点で解説します)。そのため、マジックナンバーや通貨ペアなど別の条件でも絞り込むのが安全です。
select:
index にインデックスとチケット番号のどちらを指定したのかを明示します。
- SELECT_BY_POS:インデックスで選択
- SELECT_BY_TICKET:チケット番号で選択
pool=MODE_TRADES:
省略可能な引数で、注文をどちらの一覧から探すかを指定します。省略した場合は MODE_TRADES になります。
| 指定値 | 一覧 | 含まれる注文 |
| MODE_TRADES | trading pool | 保有中のポジション 待機注文 |
| MODE_HISTORY | history pool | 決済済みの注文 取り消した注文 |
注意したいのは、pool が使われるのは SELECT_BY_POS のときだけという点です。SELECT_BY_TICKET でチケット番号を指定した場合、pool は無視され、決済済みの注文でも選択できてしまいます。決済済みかどうかは、OrderCloseTime() が0かどうかで判定します(0なら未決済)。
Sample Code
チケット番号から選択する例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
int Ticket = 1234; // OrderSend()の戻り値などで保存したチケット番号 int MagicNumber = 56789; if(OrderSelect(Ticket, SELECT_BY_TICKET) == true){ // チケット指定ではpoolが無視されるため、決済済みでないかを確認する if(OrderCloseTime() == 0 && OrderMagicNumber() == MagicNumber){ // 通貨ペア、売り買い、その他の条件から目的のポジションか確認する // 手仕舞い処理など } } else{ Print("OrderSelect returned the error of ",GetLastError()); } |
インデックスから選択する例
インデックスを使う場合は、OrdersTotal()関数で保有ポジションと待機注文の合計数を取得し、1件ずつ選択しながら条件に合う注文を探します。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
int MagicNumber = 56789; // 決済で番号がずれても取りこぼさないよう、後ろから順に調べる for(int i = OrdersTotal() - 1; i >= 0; i--){ if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue; if(OrderMagicNumber() != MagicNumber) continue; if(OrderSymbol() != Symbol()) continue; if(OrderType() == OP_BUY){ // 目的のポジションが選択できれば、手仕舞い処理など } } |
ループを i++ ではなく i– で回しているのは、ループの中で決済したときに番号がずれるためです。理由は次の注意点で説明します。
注意点(チケット番号とインデックスは変わる)
チケット番号が変わるケース
チケット番号は注文ごとの番号ですが、部分決済をすると、残ったロットは新しいチケット番号の注文として作り直されます。また、待機注文が約定したときにも新しい番号に変わったという検証報告があります(MQL4のOrderSelect関数を正しく理解する)。OrderSend関数の戻り値を変数に保存して使い回すだけだと、こうした場面で目的の注文を見失います。
部分決済や指値注文を使わないという割り切りも現実的な選択肢ですが、それでもMT4を再起動すると、EAが変数に保存していたチケット番号は消えてしまいます。VPSのセキュリティパッチ適用などで、再起動は意外とよく起こります。
対策としては、決済や注文変更の直前に、マジックナンバーや通貨ペアなどの条件で保有中の注文を探し直し、チケット番号を取り直すのが確実です。
インデックスがずれるケース
インデックスは、一覧に入った順に0から振られる連番です。途中の注文が決済されると、後ろの注文の番号が1つずつ繰り上がります。たとえば4つのポジションA〜Dを持っていて、index 0のAを決済すると次のようになります。
| 状態 | index 0 | index 1 | index 2 | index 3 |
| 決済前 | A | B | C | D |
| Aを決済した後 | B | C | D | - |
i++ で前から回していると、Aを決済した直後に i が1に進むため、index 0に繰り上がったBが調べられないまま飛ばされます。後ろから i– で回せば、決済で番号が動くのは調べ終わった側だけなので、取りこぼしが起きません。
また、SELECT_BY_POS で取得できる注文の並び順は、取引サーバーから受け取った順で、並び替えは保証されていません。「最初の注文が一番古い」といった前提は置かず、必要な条件はその都度確認するようにします。
References:
OrderSelect – MQL4 Reference
OrdersTotal – MQL4 Reference
OrderMagicNumber – MQL4 Reference
MQL4のOrderSelect関数を正しく理解する




















