🐈

MQL5でトレーリングストップ機能をつける方法

2023/10/07に公開
//--- トレーリングストップで利確
input string TrailingStop_Comment = "■トレーリングストップで利確■";
input int     TrailingStopActivationPoints = 300; // トレーリングストップの発動条件ポイント(points)
input int     TrailingStopDistancePoints   = 100;  // トレーリングストップのトレール幅ポイント(points)
void TrailingStop_mode(int side)
  {
   double trailingStopActivationDistance = TrailingStopActivationPoints * _Point;
   double trailingStopAdjustmentDistance = TrailingStopDistancePoints * _Point;
   double stoplossPrice = get_stoploss_price(side);
   MqlTick last_tick;
   SymbolInfoTick(_Symbol,last_tick);
   double Ask=last_tick.ask;
   double Bid=last_tick.bid;
   double currentClose = side==0?Bid:Ask;
   double base_price = position_average_price(side);

// Calculate new stop loss price based on trailing stop logic
   double newStoplossPrice = (side == 0) ? currentClose - trailingStopAdjustmentDistance : currentClose + trailingStopAdjustmentDistance;

// If the current stop loss price is 0 and trailing stop conditions are met, adjust the stop loss
   if(stoplossPrice == 0)
     {
      if((side == 0 && currentClose > base_price + trailingStopActivationDistance) ||
         (side == 1 && currentClose < base_price - trailingStopActivationDistance))
        {
         position_stop_modify(side, newStoplossPrice);

        }
     }
// If the current stop loss price is not 0, adjust it based on trailing stop logic
   else
     {
      if((side == 0 && currentClose > stoplossPrice + trailingStopAdjustmentDistance) ||
         (side == 1 && currentClose < stoplossPrice - trailingStopAdjustmentDistance))
        {
         position_stop_modify(side, newStoplossPrice);
        }
     }
  }

double get_stoploss_price(int side)
  {
   double stoplossPrice = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      if("" != PositionGetSymbol(i))
        {
         if(PositionGetInteger(POSITION_TYPE) == side)
           {
            if(Symbol() == PositionGetString(POSITION_SYMBOL))
              {
               if(PositionGetInteger(POSITION_MAGIC) == MagicNumber)
                 {
                  double sl = PositionGetDouble(POSITION_SL);
                  if(stoplossPrice == 0 || (side == 0 && sl < stoplossPrice) || (side == 1 && sl > stoplossPrice))
                    {
                     stoplossPrice = sl;
                    }
                 }
              }
           }
        }
     }
   return stoplossPrice;
  }
double position_average_price(int side)
{
   double lots_sum = 0;
   double price_sum = 0;
   double average_price = 0;
   
   for(int i=PositionsTotal()-1; i>=0; i--)
   {
      if("" != PositionGetSymbol(i))
      {
         if(PositionGetInteger(POSITION_TYPE)==side)
         {
            if(Symbol()==PositionGetString(POSITION_SYMBOL))
            {
               if(PositionGetInteger(POSITION_MAGIC)==MagicNumber)
               {
                  lots_sum += PositionGetDouble(POSITION_VOLUME);
                  price_sum += PositionGetDouble(POSITION_PRICE_OPEN) * PositionGetDouble(POSITION_VOLUME);
               }
            }
         }
      }
   }
   
   if(lots_sum > 0)
   {
      average_price = price_sum / lots_sum;
   }

   return NormalizeDouble(average_price, _Digits);
}


#include <Trade\Trade.mqh>
CTrade iTrade;
void position_stop_modify(int side, double price)
  {
   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      if("" != PositionGetSymbol(i))
        {
         if(PositionGetInteger(POSITION_TYPE)==side)
           {
            if(Symbol()==PositionGetString(POSITION_SYMBOL))
              {
               if(PositionGetInteger(POSITION_MAGIC)==MagicNumber)
                 {
                  bool result = iTrade.PositionModify(PositionGetInteger(POSITION_TICKET), price,0); // ポジションのストップロス価格を変更
                 }
              }
           }
        }
     }
  }

クラスを使わない方法

void position_stop_modify(int side, double price)
{
 for(int i=PositionsTotal()-1; i>=0; i--)
   {
    if("" != PositionGetSymbol(i))
      {
       if(PositionGetInteger(POSITION_TYPE)==side)
         {
          if(Symbol()==PositionGetString(POSITION_SYMBOL))
            {
             if(PositionGetInteger(POSITION_MAGIC)==MagicNumber)
               {
               if(price > PositionGetDouble(POSITION_SL) + 1 * _Point || price < PositionGetDouble(POSITION_SL) - 1 * _Point )
                position_modify(PositionGetInteger(POSITION_TICKET),price,0);
               }
            }
         }
      }
   }
}

void position_modify(ulong position_ticket,double sl = 0,double tp = 0){
 MqlTradeRequest req = {};
 MqlTradeResult res = {};

 req.action  =TRADE_ACTION_SLTP;
 req.symbol  =Symbol();
 req.magic   =MagicNumber;
 if(sl!=0){req.sl      =sl;}
 if(tp!=0){req.tp      =tp;}
 req.position=position_ticket;
 
 bool order_result = OrderSend(req, res);

 if(order_result == false)
   {
    Print(res.retcode);
   }
} 

Discussion