I use a strategy with 2 levels for TP based on ATR bands. First TP is 40% of total position, second TP is 20 %, the remaining 40% goes on until strategy reverses from long to short and viceversa. So far, no problems.
Then after the 2nd TP is taken, I want to set a SL using a third value on ATR. The problem is that sometimes it works, sometimes not.
A screenshot:
`strategy('Strategy', initial_capital=100, precision=4, default_qty_type=strategy.percent_of_equity, commission_type=strategy.commission.percent, commission_value=0.02, slippage=0, margin_long = 2, margin_short = 2,default_qty_value=100, overlay=false)
start = timestamp(input(2024, 'start year'), input(1, 'start month'), input(1, 'start day'), input(1, 'start hour'), 00)
end = timestamp(input(2026, 'end year'), input(1, 'end month'), input(1, 'end day'), 00, 00)
//---------
//EMA Slope
//---------
//define slope inputs
average = input.string(title='Source MA Type', defval='EMA', options=['EMA', 'SMA'], group = "Slope inputs")
len = input.int(130, minval=1, title='Source MA Length', group = "Slope inputs")
slopeFlen = input(6, title='Fast Slope MA Length', group = "Slope inputs")
slopeSlen = input(11, title='Slow Slope MA Length', group = "Slope inputs")
//Variables
out = if average == 'EMA'
ta.ema(close, len)
else
ta.sma(close, len)
slp = ta.change(out) / out
emaslopeF = ta.ema(slp, slopeFlen)
emaslopeS = ta.ema(slp, slopeSlen)
//plot
plot(slp*100, color=color.rgb(145, 35, 139), title = 'Slope', linewidth = 2)
plot(emaslopeF*100, color=color.rgb(59, 226, 255), title = 'EMA Slope fast',linewidth = 2)
plot(emaslopeS*100, color=color.rgb(88, 45, 187), title = 'EMA Slope slow', linewidth = 2)
percentTPATR= input.int(defval = 40, title = " Percent amount of 1st TP on ATR ", group = "Partial TP and SL quantity")
percent2TPATR= input.int(defval = 20, title = " Percent amount of 2nd TP on ATR ", group = "Partial TP and SL quantity")
//---
//ATR
//---
//Input settings for 1st TP
atrPeriod = input.int(title='ATR Period', defval=14, minval=1, group="ATR Bands Settings on First TP")
atrMultiplier = input.float(title='ATR Band Scale Factor', defval=1.4, step=0.1, minval=0.01, group="ATR Bands Settings on First TP")
atrSourceRef = "close"
//Calcs
atr = ta.atr(atrPeriod)
upline = close + atrMultiplier*atr[0]
bottomline = close - atrMultiplier*atr[0]
//Input settings for 2nd TP
atrPeriod2 = input.int(title='ATR Period', defval=14, minval=1, group="ATR Bands Settings on Second TP")
atrMultiplier2 = input.float(title='ATR Band Scale Factor', defval=4, step=0.1, minval=0.01, group="ATR Bands Settings on Second TP")
atrSourceRef2 = "close"
//Calcs
atr2 = ta.atr(atrPeriod2)
upline2 = close + atrMultiplier2*atr2[0]
bottomline2 = close - atrMultiplier2*atr2[0]
//Input settings for SL after 2nd TP
atrPeriod3 = input.int(title='ATR Period', defval=14, minval=1, group="ATR Bands Settings on SL after 2 TP")
atrMultiplier3 = input.float(title='ATR Band Scale Factor', defval=2, step=0.1, minval=0.01, group="ATR Bands Settings on SL after 2 TP")
atrSourceRef3 = "close"
//Calcs
atr3 = ta.atr(atrPeriod3)
upline3 = close + atrMultiplier3*atr3[0]
bottomline3 = close - atrMultiplier3*atr3[0]
//-------------------------
//Entry and exit conditions
//-------------------------
ConditionEntryL = emaslopeF > emaslopeS
ConditionEntryS = emaslopeF < emaslopeS
//Entry conditions
if time > start and time < end
if ConditionEntryL
strategy.entry('Long', direction=strategy.long)
if time > start and time < end
if ConditionEntryS
strategy.entry('Short', direction=strategy.short)
//------------------------------
//get ATR values on entry for TP
//------------------------------
//get ATR values on entry for 1st TP
var float fixedBottomline = 0
var float fixedUpline = 0
if nz(ConditionEntryL[1]) and strategy.position_size > 0 and strategy.position_size[1] <= 0
fixedUpline := upline
if nz(ConditionEntryS[1]) and strategy.position_size < 0 and strategy.position_size[1] >= 0
fixedBottomline := bottomline
//get ATR values on entry for 2nd TP
var float fixedBottomline2 = 0
var float fixedUpline2 = 0
if nz(ConditionEntryL[1]) and strategy.position_size > 0 and strategy.position_size[1] <= 0
fixedUpline2 := upline2
if nz(ConditionEntryS[1]) and strategy.position_size < 0 and strategy.position_size[1] >= 0
fixedBottomline2 := bottomline2
//get ATR values on entry for SL after 2 TP
var float fixedBottomline3 = 0
var float fixedUpline3 = 0
if nz(ConditionEntryL[1]) and strategy.position_size > 0 and strategy.position_size[1] <= 0
fixedUpline3 := upline3
if nz(ConditionEntryS[1]) and strategy.position_size < 0 and strategy.position_size[1] >= 0
fixedBottomline3 := bottomline3
//-------------
//Exit Strategy
//-------------
if time > start and time < end
if strategy.position_size > 0
strategy.exit("Long ATR 40% Take Profit", disable_alert=true, limit=fixedUpline, qty_percent=percentTPATR)
strategy.exit("Long ATR 20% Take Profit", disable_alert=true, limit=fixedUpline2, qty_percent=percent2TPATR)
if high >= fixedUpline2
strategy.exit("Long SL", from_entry="Long", stop=fixedUpline3) //I'm not sure if this is correct
if time > start and time < end
if strategy.position_size < 0
strategy.exit("Short ATR 40% Take Profit", disable_alert=true, limit=fixedBottomline, qty_percent=percentTPATR)
strategy.exit("Short ATR 20% Take Profit", disable_alert=true, limit=fixedBottomline2, qty_percent=percent2TPATR)
if low <= fixedBottomline2
strategy.exit("ShortSL", from_entry="Short", stop=fixedBottomline3) //I'm not sure if this is correct
`
I think that the stop-loss condition is properly calculated after the second TP and that it is dynamically adjusted.
Exit conditions need to be evaluated based on the price crossing your stop level, and the strategy.exit() should trigger the stop when the condition is met.
Make sure that the strategy.exit() for stop-loss is placed after the second TP. If the stop-loss is placed too early, it may conflict with the TPs.
stop condition for the SL is triggered based on the price crossing the SL level, not just the condition for hitting the second TP.