問題のポイント
EA決済するときに、ハマったポイントがあったので書いておきます。

オーダー決済すると「インデックス番号の再計算」が行われます。
この再計算は、0から連番になるように再計算されています。
これを把握していないと、複数ポジションの決済でハマります。
ループ処理する際、何か理由がない限りは「0」から初めますよね。
単純な例で書くと、こんな感じですね。
(今はマジックナンバー、シンボルなど無視します)
for(i=0; i<OrdersTotal(); i++){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
}
}
これの何が問題かというと、決済したい2つ目以降のポジションで問題が発生します。
インデックス番号の再計算
1つ目のポジションを決済した瞬間に、インデックス番号の再計算が行われるため、こんな感じになっちゃいます。
初期値 | 再計算後 | 「i」値 | |
---|---|---|---|
index 0 | index 0 | i = 0 → 1 | |
iindex 1 | index 1 | i = 1 → 2 | |
index 2 | index 2 を決済 | (欠番) | i = 2 → 3 |
index 3 | → | index 2 | (飛ばされる) |
index 4 | → | index 3 | i = 3 → 4 |
index 5 | → | index 4 | i = 4 → 5 |
: | : | : | : |
「index 2」の注文を決済したとすると、上記ループで、次は「index 3」をOrderSelectします。
しかし、このときの「index 3」は、元々の「index 4」が再計算されて、繰り上がった注文です。
本来、次に処理したいはずの元々の「index 3」は再計算されて、「index 2」に繰り上がっているため、以降、永遠にOrderSelectされず、処理が飛ばされることになります。

元々の「index 3」も決済対象だったとしたら、
決済されずに残ってしまいます。
以降、ループ終了まで、同じ問題が発生します。
これ、知らないとハマっちゃいます。
解決策

解決策は簡単で「最後尾」から決済していくだけです。
for(i=OrdersTotal()-1; i>=0; i--){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
}
}
インデックス番号の再計算で影響が出るのは、決済した注文よりも後ろの注文になります。そのため、最後尾から先頭に向かって処理すると、問題が発生しません。
決済するたびに「i」の値をマイナスして戻してあげる方法もありますが、最後尾から処理した方が簡単です。
決済ループは、最後尾から先頭に向かって処理しましょう。