エキスパート: eaBreakeven

 

eaBreakeven:

このエキスパートアドバイザーは、逆指値をユーザ定義の損益分岐点に移動します。

作者: Alexey Lopatin

 

エラー:

  1. ループを逆にすべきである。
  2. PositionSelectを コードから削除すべきである。

 
fxsaber:

間違いだ:

  1. ループを逆にすべきである。
  2. PositionSelectはコードから削除されるべきである。


スタジオへの引数。

 
Alexey Lopatin:

議論をお願いします。

ループの説明に時間がかかります。また、PositionGetSymbolの後のPositionSelectは、LastErrorがOKなら、すでに選択されているので不要です。しかし、PositionSelectもヘッジ口座では悪です。

最良の選択肢は、上記のものの代わりに常にこれを使用することです。

if (PositionGetTicket(i))


また、POSITION_PRICE_CURRENT を使って、任意のポジションの方向の latest_price を取得することもできます。


そして、この条件

if(latest_price.bid-price_open>=Breakeven*point && new_stoploss>stoploss && latest_price.bid-new_stoploss>stop_level)

この条件は、(二重の特殊性により)何も変更する必要がない場合でも発動することができます。


一般的には、もう少しコンパクトに、エラーなく書き換えることができます。私ならMT4スタイルにします。

#include <MT4Orders.mqh>     //https://www.mql5.com/ja/code/16006
#include <Price_Compare.mqh> //https://www.mql5.com/ja/code/16169

input int    Breakeven           = 15;           //損益分岐点
input int    Distance            = 5;            //ポジションのオープン価格からのブレイクイーブンの距離。
input int    MagicNumber         = 16112017;     //マジックナンバー
input bool   EnableSound         = true;         //ブレークイーブンが設定されたときにサウンドを再生するかどうかを設定する。
input string SoundFile           = "alert1.wav"; //サウンドファイル名

void OnTick()
{
  DoBreakeven();
}

double GetNewStopLoss()
{
  const double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT);  
  const double stop_level = SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_STOPS_LEVEL) * point;
  
  const double price_open = OrderOpenPrice();
  const double latest_price = OrderClosePrice();  
  const double stoploss = OrderStopLoss();

  double new_stoploss = 0;
  
  //--- 損益分岐点より利益が大きい場合、損切りは損益分岐点価格+距離で移動する。 
  return(((OrderType() == OP_BUY)  && (CP(latest_price - price_open, point) >= Breakeven * point) &&
                                      (CP(new_stoploss = price_open + Distance * point, point) > stoploss) &&
                                      (CP(latest_price - new_stoploss, point) > stop_level)) ||
         ((OrderType() == OP_SELL) && (CP(price_open - latest_price, point) >= Breakeven * point) &&
                                      ((CP(new_stoploss = price_open - Distance * point, point) < stoploss) || !stoploss) &&
                                      (CP(new_stoploss - latest_price, point) > stop_level))
         ? NormalizeDouble(new_stoploss, (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS)) : 0);
}

void DoBreakeven()
{
//ブレークイーブンが負の場合、ブレークイーブン機能を無効にする。
  if (Breakeven >= 0)      
  //ポジションのループ
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (!MagicNumber || (OrderMagicNumber() == MagicNumber)))
      {
        const double new_stoploss = GetNewStopLoss();
        
        if (new_stoploss)      
        {
          if (!OrderModify(OrderTicket(), OrderOpenPrice(), new_stoploss, OrderTakeProfit(), OrderExpiration()))
            Print(GetLastError());
          else if(EnableSound)
            PlaySound(SoundFile);
        }
      }
}
 

例を示してくれてありがとう。いつも自分にとって新しいことを学ぶのは嬉しいものです。

しかし、ここで、なぜポジションセレクトが ヘッジ口座で悪なのか知りたいのですが?

 
Alexey Lopatin:

しかし、ここで興味深いのは、なぜハッシュカウントのPositionSelectが悪なのか、ということだ。

なぜなら、シンボルはポジションを一意に定義しないからだ。

 
caolyhuynh:
 
5000000
 
caolyhuynh: