複数のポジションを持つEAに使う
ナンピン等を行うEAの場合、複数のポジションを持つことになります。複数のポジションを纏めて1つの動きになるようなEAの場合、一括決済が必要になることがあります。
そんな時のために、複数のポジションを全て決済する関数を紹介します。
01 | //+------------------------------------------------------------------+ |
02 | //|【関数】指定マジックナンバーのポジション全決済 | |
03 | //| | |
04 | //|【引数】 IN OUT 引数名 説明 | |
05 | //| --------------------------------------------------------- | |
06 | //| ○ aMagic マジックナンバー | |
07 | //| ○ aSlippage 許容スリッページ | |
08 | //| △ aComment 対象コメント | |
09 | //| | |
10 | //|【戻値】なし | |
11 | //| | |
12 | //|【備考】△:既定値あり | |
13 | //+------------------------------------------------------------------+ |
14 | void allOrderClose( int aMagic, int aSlippage, string aComment = "" ) |
15 | { |
16 | for ( int i = OrdersTotal() - 1; i >= 0; i--){ |
17 | if (OrderSelect(i, SELECT_BY_POS) == false ){ |
18 | break ; |
19 | } |
20 |
21 | if (OrderSymbol() != Symbol() || OrderMagicNumber() != aMagic){ |
22 | continue ; |
23 | } |
24 |
25 | if (aComment != "" && OrderComment() != aComment){ |
26 | continue ; |
27 | } |
28 |
29 | int type = OrderType(); |
30 |
31 | if (type != OP_BUY && type != OP_SELL){ |
32 | continue ; |
33 | } |
34 |
35 | int ticket = OrderTicket(); |
36 |
37 | Print( "Attempted allOrderClose(" + aMagic + ", " + aSlippage + ", Comment:" + aComment + ")" ); |
38 |
39 | bool result = orderCloseReliable(ticket, OrderLots(), OrderClosePrice(), aSlippage); |
40 |
41 | if (result == false ){ |
42 | Print( "allOrderClose: Ticket #" , ticket, ", failed to close" ); |
43 | } |
44 | } |
45 | } |
上記の関数を「OrderHandle.mqh」に追加しました。
特に難しい仕組みはありません。OrdersTotal()で現在持っているオーダー数を取得し、約定済のオーダー(ポジション)だけに絞り込んだ上で、仕切り注文関数を繰り返し実行するだけです。
ただし、注意しなければならないことが1つあります。それは、ポジションを決済するまたは待機注文を削除すると、その注文より後に出した注文のインデックスが1だけ小さくなることです。そのため、複数のポジションを決済するか複数の待機注文を削除する場合は、後の注文から順(降順)に処理する必要があります。古いものから順(昇順)に処理すると、1つずつ注文がスキップされることになります。
例えば、0,1,2という3つのポジションがあったと仮定しましょう。0番のポジションを決済した時に、残りの1,2が0,1になります。そして、次の1番のポジションを決済しようとするので、結果として0(最初の1)のポジションが決済されずに残ることになります。
また、注文時のコメントが引数にあるのには疑問を抱くかもしれません。これは、同じマジックナンバーのポジションの中で各ポジションを識別しなければならない時に、その識別用にコメントを使うことがあるためです。まぁ普段はあまり使いませんので、気にしなくても良いかと思います。
上記の関数とほぼ同じ作りで、複数の待機注文を全て削除(取消し)する関数も作れます。
01 | //+------------------------------------------------------------------+ |
02 | //|【関数】指定マジックナンバーの待機注文全削除 | |
03 | //| | |
04 | //|【引数】 IN OUT 引数名 説明 | |
05 | //| --------------------------------------------------------- | |
06 | //| ○ aMagic マジックナンバー | |
07 | //| △ aComment 対象コメント | |
08 | //| | |
09 | //|【戻値】なし | |
10 | //| | |
11 | //|【備考】△:既定値あり | |
12 | //+------------------------------------------------------------------+ |
13 | void allOrderDelete( int aMagic, string aComment = "" ) |
14 | { |
15 | for ( int i = OrdersTotal() - 1; i >= 0; i--){ |
16 | if (OrderSelect(i, SELECT_BY_POS) == false ){ |
17 | break ; |
18 | } |
19 |
20 | if (OrderSymbol() != Symbol() || OrderMagicNumber() != aMagic){ |
21 | continue ; |
22 | } |
23 |
24 | if (aComment != "" && OrderComment() != aComment){ |
25 | continue ; |
26 | } |
27 |
28 | int type = OrderType(); |
29 |
30 | if (type == OP_BUY || type == OP_SELL){ |
31 | continue ; |
32 | } |
33 |
34 | int ticket = OrderTicket(); |
35 |
36 | Print( "Attempted allOrderDelete(" + aMagic + ", Comment:" + aComment + ")" ); |
37 |
38 | bool result = orderDeleteReliable(ticket); |
39 |
40 | if (result == false ){ |
41 | Print( "allOrderDelete: Ticket #" , ticket, ", failed to delete" ); |
42 | } |
43 | } |
44 | } |