// 入力パラメータ input double ATR_Multiplier = 1.5; // ATR乗数係数 input int ATR_Period = 7; // ATR期間 // グローバル変数 int atrHandle; // ATRインジケーターハンドル //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // ATRインジケーターハンドルを取得 atrHandle = iATR(_Symbol, _Period, ATR_Period); if(atrHandle == INVALID_HANDLE) { Print("Failed to create ATR handle"); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // インジケーターハンドルの解放 if(atrHandle != INVALID_HANDLE) IndicatorRelease(atrHandle); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // ポジションがあるか確認 bool hasPosition = false; for(int i = PositionsTotal()-1; i >= 0; i--) { if(PositionGetSymbol(i) == _Symbol) { hasPosition = true; ulong ticket = PositionGetInteger(POSITION_TICKET); ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); TrailStop(ticket, posType); } } } //+------------------------------------------------------------------+ //| トレーリングストップを実行 | //+------------------------------------------------------------------+ void TrailStop(ulong ticket, ENUM_POSITION_TYPE positionType) { double atr[1]; if(CopyBuffer(atrHandle, 0, 0, 1, atr) <= 0) { Print("Failed to get ATR value: ", GetLastError()); return; } double newStop = 0; double currentStop = PositionGetDouble(POSITION_SL); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); if(positionType == POSITION_TYPE_BUY) { newStop = bid - (atr[0] * ATR_Multiplier); newStop = NormalizeDouble(newStop, _Digits); // 現在のストップロスより有利な場合のみ更新 if(newStop > currentStop || currentStop == 0) ModifyStopLoss(ticket, newStop); } else if(positionType == POSITION_TYPE_SELL) { newStop = ask + (atr[0] * ATR_Multiplier); newStop = NormalizeDouble(newStop, _Digits); // 現在のストップロスより有利な場合のみ更新 if(newStop < currentStop || currentStop == 0) ModifyStopLoss(ticket, newStop); } } //+------------------------------------------------------------------+ //| ストップロスを変更 | //+------------------------------------------------------------------+ void ModifyStopLoss(ulong ticket, double newStop) { MqlTradeRequest request = {}; request.action = TRADE_ACTION_SLTP; request.position = ticket; request.symbol = _Symbol; request.sl = newStop; request.tp = PositionGetDouble(POSITION_TP); MqlTradeResult result = {}; if(OrderSend(request, result)) { Print("Stop loss updated to ", newStop); } } //+------------------------------------------------------------------+