トレイリングストップとブレイクイーブンを併用するために

変更箇所はたったの2行

トレイリングストップ関数とブレイクイーブン関数はどちらも自作ライブラリに包含されていますが、両方を併用するとトレイリングストップが打ち消されて、ブレイクイーブンが常に適用されてしまう問題があることが分かりました。

トレイリングストップとブレイクイーブンを併用したいという声が複数ありましたので、併用できるようにコードを変更します。

1// 変更前
2if(NormalizeDouble(oStopLoss, digits) != NormalizeDouble(oPrice + stop, digits)){ // 買い
3if(NormalizeDouble(oStopLoss, digits) != NormalizeDouble(oPrice - stop, digits)){ // 売り
1// 変更後
2if(oStopLoss == 0.0 || NormalizeDouble(oStopLoss, digits) < NormalizeDouble(oPrice + stop, digits)){ // 買い
3if(oStopLoss == 0.0 || NormalizeDouble(oStopLoss, digits) > NormalizeDouble(oPrice - stop, digits)){ // 売り

変更前のコードは、現在の損切り価格とブレイクイーブン後の損切り価格が不一致ならば、ブレイクイーブン後の損切り価格に変更するロジックになっています。

この場合、トレイリングストップで損切り価格を随時変更すると、上記条件が成立してしまうので、ブレイクイーブン後の損切り価格に戻っちゃうというわけです。

これを避けるために、変更後のコードでは、現在の損切り価格がブレイクイーブン後の損切り価格よりマイナス方向にあるか、そもそも損切り設定していない(oStopLoss == 0.0)場合のみ、ブレイクイーブン後の損切り価格に変更するようにしています。

これで併用できるようになります。アップロードしているライブラリも近いうちに最新化しますね。

なお、コードの抜粋だけだと分かりにくいでしょうから、変更前後の関数もそれぞれ載せておきます。

01//+------------------------------------------------------------------+
02//|【関数】ブレイクイーブン(トレイリングストップ関数と併用NG)      |
03//|                                                                  |
04//|【引数】 IN OUT  引数名             説明                          |
05//|        --------------------------------------------------------- |
06//|         ○      aMagic             マジックナンバー              |
07//|         ○      aMoveExecPips      ストップ変更開始位置(pips)  |
08//|         ○      aMoveStopPips      ストップ変更幅(pips)        |
09//|                                                                  |
10//|【戻値】なし                                                      |
11//|                                                                  |
12//|【備考】なし                                                      |
13//+------------------------------------------------------------------+
14void breakeven(int aMagic, double aMoveExecPips, double aMoveStopPips)
15{
16  for(int i = 0; i < OrdersTotal(); i++){
17    // オーダーが1つもなければ処理終了
18    if(OrderSelect(i, SELECT_BY_POS) == false){
19      break;
20    }
21 
22    string oSymbol = OrderSymbol();
23 
24    // 別EAのオーダーはスキップ
25    if(oSymbol != Symbol() || OrderMagicNumber() != aMagic){
26      continue;
27    }
28 
29    int oType = OrderType();
30 
31    // 待機オーダーはスキップ
32    if(oType != OP_BUY && oType != OP_SELL){
33      continue;
34    }
35 
36    int digits = (int)MarketInfo(oSymbol, MODE_DIGITS);
37 
38    double oPrice      = NormalizeDouble(OrderOpenPrice(), digits);
39    double oStopLoss   = NormalizeDouble(OrderStopLoss(), digits);
40    double oTakeProfit = NormalizeDouble(OrderTakeProfit(), digits);
41    int    oTicket     = OrderTicket();
42 
43    double exec = NormalizeDouble(aMoveExecPips * gPipsPoint, digits);
44    double stop = NormalizeDouble(aMoveStopPips * gPipsPoint, digits);
45 
46    double price;
47 
48    if(oType == OP_BUY){
49      price = MarketInfo(oSymbol, MODE_BID);
50 
51      if(price >= oPrice + exec){
52        // 何度もmodifyしないためのif文
53        if(NormalizeDouble(oStopLoss, digits) != NormalizeDouble(oPrice + stop, digits)){
54          PrintFormatLog(__FILE__, __FUNCTION__, " Attempted to change the stoploss price of the LONG opend order. " + DoubleToStr(oStopLoss, digits) + " -> " + DoubleToStr(oPrice + stop, digits));
55          orderModifyReliable(oTicket, 0.0, NormalizeDouble(oPrice + stop, digits), oTakeProfit, 0, gArrowColor[oType]);
56        }
57      }
58    }else if(oType == OP_SELL){
59      price = MarketInfo(oSymbol, MODE_ASK);
60 
61      if(price <= oPrice - exec){
62        // 何度もmodifyしないためのif文
63        if(NormalizeDouble(oStopLoss, digits) != NormalizeDouble(oPrice - stop, digits)){
64          PrintFormatLog(__FILE__, __FUNCTION__, " Attempted to change the stoploss price of the SHORT opend order. " + DoubleToStr(oStopLoss, digits) + " -> " + DoubleToStr(oPrice - stop, digits));
65          orderModifyReliable(oTicket, 0.0, NormalizeDouble(oPrice - stop, digits), oTakeProfit, 0, gArrowColor[oType]);
66        }
67      }
68    }
69  }
70}
01//+------------------------------------------------------------------+
02//|【関数】ブレイクイーブン(トレイリングストップ関数と併用OK)      |
03//|                                                                  |
04//|【引数】 IN OUT  引数名             説明                          |
05//|        --------------------------------------------------------- |
06//|         ○      aMagic             マジックナンバー              |
07//|         ○      aMoveExecPips      ストップ変更開始位置(pips)  |
08//|         ○      aMoveStopPips      ストップ変更幅(pips)        |
09//|                                                                  |
10//|【戻値】なし                                                      |
11//|                                                                  |
12//|【備考】なし                                                      |
13//+------------------------------------------------------------------+
14void breakeven2(int aMagic, double aMoveExecPips, double aMoveStopPips)
15{
16  for(int i = 0; i < OrdersTotal(); i++){
17    // オーダーが1つもなければ処理終了
18    if(OrderSelect(i, SELECT_BY_POS) == false){
19      break;
20    }
21 
22    string oSymbol = OrderSymbol();
23 
24    // 別EAのオーダーはスキップ
25    if(oSymbol != Symbol() || OrderMagicNumber() != aMagic){
26      continue;
27    }
28 
29    int oType = OrderType();
30 
31    // 待機オーダーはスキップ
32    if(oType != OP_BUY && oType != OP_SELL){
33      continue;
34    }
35 
36    int digits = (int)MarketInfo(oSymbol, MODE_DIGITS);
37 
38    double oPrice      = NormalizeDouble(OrderOpenPrice(), digits);
39    double oStopLoss   = NormalizeDouble(OrderStopLoss(), digits);
40    double oTakeProfit = NormalizeDouble(OrderTakeProfit(), digits);
41    int    oTicket     = OrderTicket();
42 
43    double exec = NormalizeDouble(aMoveExecPips * gPipsPoint, digits);
44    double stop = NormalizeDouble(aMoveStopPips * gPipsPoint, digits);
45 
46    double price;
47 
48    if(oType == OP_BUY){
49      price = MarketInfo(oSymbol, MODE_BID);
50 
51      if(price >= oPrice + exec){
52        // 何度もmodifyしないためのif文
53        if(oStopLoss == 0.0 || NormalizeDouble(oStopLoss, digits) < NormalizeDouble(oPrice + stop, digits)){
54          PrintFormatLog(__FILE__, __FUNCTION__, " Attempted to change the stoploss price of the LONG opend order. " + DoubleToStr(oStopLoss, digits) + " -> " + DoubleToStr(oPrice + stop, digits));
55          orderModifyReliable(oTicket, 0.0, NormalizeDouble(oPrice + stop, digits), oTakeProfit, 0, gArrowColor[oType]);
56        }
57      }
58    }else if(oType == OP_SELL){
59      price = MarketInfo(oSymbol, MODE_ASK);
60 
61      if(price <= oPrice - exec){
62        // 何度もmodifyしないためのif文
63        if(oStopLoss == 0.0 || NormalizeDouble(oStopLoss, digits) > NormalizeDouble(oPrice - stop, digits)){
64          PrintFormatLog(__FILE__, __FUNCTION__, " Attempted to change the stoploss price of the SHORT opend order. " + DoubleToStr(oStopLoss, digits) + " -> " + DoubleToStr(oPrice - stop, digits));
65          orderModifyReliable(oTicket, 0.0, NormalizeDouble(oPrice - stop, digits), oTakeProfit, 0, gArrowColor[oType]);
66        }
67      }
68    }
69  }
70}

MT4の無料プログラミング講座

メルマガ登録して、MT4のプログラミング講座を無料で受けちゃおう!

超豪華プレゼントも盛りだくさん♪

MT4プログラミングを習得すると、オリジナルEA運用、作成代行、商品販売等、複数の収入源を手に入れられるよ。副業に最適だね!

↓↓↓ 詳細はこちら ↓↓↓

アイキャッチ

>

エターナル・パートナーPRO ~MT4裁量トレード支援ツール~ 「MT4は裁量トレーダーに優しくない」そう思ったことありませんか?もっと快適にトレードするための強力な売買ツールが必要だと考え、開発したのが「エターナル・パートナーPRO」です。元々は自分自身のために開発したツールですので、手抜き無しのガチものです。既に200名近い方に手に取っていただき、喜びの声が続々と届いております。ぜひご覧ください!

CTR IMG