How to "Fix" the ATR trailing stop in Pine Script

1.4k Views Asked by At

I would love your help.

I'm coding a trading strategy that goes **long** on the break of a 40-day high, and closes that long position when a trailing stop is hit. That trailing stop is 3*ATR which begins under the low of the entry candle and trails upwards.

My current problem is that I don't know how to 'fix' the ATR level when it trails up, to stop it going back down when the price goes down. Currently, when the price goes down, *the trailing stop also goes down with it*, meaning the stop is never hit! (please see the black lines on the uploaded image)

Screenshot of current plots

Do you know how I could code this so the trailing stop moves higher when the price goes higher, *but stays fixed when the price goes down* so the stop level can be hit to close the position?

Many thanks in advance for your help - Dave.

//@version=5 

strategy("Donchian Breakout - Trading",overlay=true, initial_capital=100000,currency=currency.GBP)

//Inputs
DonchHighLength=input.int(title="DonchHighLength",defval=20,step=10)
DonchLowLength=input.int(title="DonchLowLength",defval=20,step=10)
ATRLength=input.int(title="ATRLength", defval=20, step=1)
ATRx=input.int(title="ATRMultiple", defval=4, step=1)

//Variables
DonchHigh=ta.highest(close[1],DonchHighLength)
DonchLow=ta.lowest(close[1],DonchLowLength)
ATR=ta.atr(ATRLength)
ATRLongStop=low-(ATR*ATRx)
ATRShortStop=high+(ATR*ATRx)

//Plot
plot(DonchHigh,"Long", color.green)
plot(DonchLow,"Short", color.red)
plot(ATRLongStop, "LongStop", color.black)
plot(ATRShortStop, "ShortStop", color.black)

//Entry
EnterLong=close>DonchHigh  
EnterShort=close<DonchLow 

// Calculate position size
RiskEquity=0.02*strategy.equity
RiskPerTrade=EnterLong?((strategy.position_avg_price-ATRLongStop)*syminfo.pointvalue):((ATRShortStop-strategy.position_avg_price)*syminfo.pointvalue)
PosSize=RiskEquity/RiskPerTrade

//Entry orders
if strategy.position_size==0
    if EnterLong 
        strategy.entry("Long",strategy.long,qty=PosSize)
    
if strategy.position_size==0
    if EnterShort 
        strategy.entry("Short",strategy.short,qty=PosSize)

//Close strategy.position_size

strategy.close(id="Long", when=close<ATRLongStop[1])
strategy.close(id="Short", when=close>ATRShortStop[1])
3

There are 3 best solutions below

4
G.Lebret On BEST ANSWER

You should record your ATRLongStop value and modify your strategy.close only if the new Stop Loss value is greater than the actual one.

var StopLoss = 0.0
if strategy.position_size==0
    if EnterLong 
        strategy.entry("Long",strategy.long,qty=PosSize)
        StopLoss := 0.0
if ATRLongStop[1] > StopLoss
    StopLoss := ATRLongStop[1]
    strategy.close(id="Long", when=close<ATRLongStop[1])
2
Inerti4 On

I'm the question above yours on the list and also searching for a trailing-SL answer ! I found this ATR SL code for you by searching a bit, maybe you can adapt it to your own (I can do Frankenstein coding, but I'm a complete amateur, sorry haha)

//@version=2
//created by XPloRR 04-03-2018

strategy("XPloRR MA-Trailing-Stop Strategy",overlay=true, initial_capital=1000,default_qty_type=strategy.percent_of_equity,default_qty_value=100)

testStartYear = input(2005, "Start Year")
testStartMonth = input(1, "Start Month")
testStartDay = input(1, "Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)

testStopYear = input(2050, "Stop Year")
testStopMonth = input(12, "Stop Month")
testStopDay = input(31, "Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,0,0)

testPeriodBackground = input(title="Background", type=bool, defval=true)
testPeriodBackgroundColor = testPeriodBackground and (time >= testPeriodStart) and (time <= testPeriodStop) ? #00FF00 : na
bgcolor(testPeriodBackgroundColor, transp=97)

ema1Period = input(12, "Fast EMA Buy")
sma1Period = input(54, "Slow SMA Buy")
strength1 = input(52, "Minimum Buy Strength")

ema2Period = input(18, "Fast EMA Sell")
sma2Period = input(55, "Slow SMA Sell")
strength2 = input(100, "Minimum Sell Strength")

delta = input(8, "Trailing Stop (#ATR)")

testPeriod() =>
    time >= testPeriodStart and time <= testPeriodStop ? true : false

ema1val=ema(close,ema1Period)
sma1val=sma(close,sma1Period)
ema1strength=10000*(ema1val-ema1val[1])/ema1val[1]

ema2val=ema(close,ema2Period)
sma2val=sma(close,sma2Period)
ema2strength=10000*(ema2val-ema2val[1])/ema2val[1]

plot(ema1val,color=blue,linewidth=1)
plot(sma1val,color=orange,linewidth=1)
plot(ema2val,color=navy,linewidth=1)
plot(sma2val,color=red,linewidth=1)

long=crossover(ema1val,sma1val) and (ema1strength > strength1) 
short=crossunder(ema2val,sma2val) and (ema2strength < -strength2)

stopval=ema(close,6)
atr=sma((high-low),15)

inlong=0
buy=0
stop=0
if testPeriod()
    if (inlong[1])
        inlong:=inlong[1]
        buy:=close
        stop:=iff((stopval>(stop[1]+delta*atr)),stopval-delta*atr,stop[1])
    if (long) and (not inlong[1])
        strategy.entry("buy",strategy.long)
        inlong:=close
        buy:=close
        stop:=stopval-delta*atr
plot(buy,color=iff(close<inlong,red,lime),style=columns,transp=90,linewidth=1)
plot(stop,color=iff((short or (stopval<stop)) and (close<inlong),red,lime),style=columns,transp=60,linewidth=1)
if testPeriod()
    if (short or (stopval<stop)) and (inlong[1])
        strategy.close("buy")
        inlong:=0
        stop:=0
        buy:=0
0
W J On

Ahh, I was really hoping that this would work but this still does not work as it should, I dont understand why but this fix definitely isnt working as intended. Ive been racking my brains for days now trying to resolve this.

// Get inputs
atrLength = input(title="ATR", type=input.integer, defval=14, minval=1)
atrMultiplier = input(title="ATR Factor", type=input.float, defval=1.0, minval=0.1, step=0.1)

// Calculate data
atr = atr(atrLength)
LongStop = low-(atr*atrMultiplier)

//Plot
plot(LongStop, "LongStop", color.red)


// Add strategy logic
// Go long if the condition is met
var StopLoss = 0.0
if strategy.position_size==0
    if longCondition
        strategy.entry("Long", strategy.long)
        StopLoss := 0.0
if LongStop[1] > StopLoss
    StopLoss := LongStop[1]
    strategy.close(id="Long", when=close<LongStop[1]) 
    ```