🐈
MQL5でトレーリングストップ機能をつける方法
//--- トレーリングストップで利確
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