Best ATR Stop Multiple Strategy

Author: ChaoZhang, Date: 2024-02-21 14:24:22



The Best ATR Stop Multiple strategy is a trend following strategy that uses multiples of the Average True Range (ATR) to set stop loss points and dynamically adjust risk. It can exit positions in a timely manner when price trends change to avoid huge losses.

Strategy Logic

The strategy first calculates the simple moving averages of fast and slow SMA periods. It goes long when the fast SMA crosses over the slow SMA, and goes short when the fast SMA crosses below the slow SMA.

After entering, it monitors the ATR value in real-time. The ATR represents the average volatility over a certain lookback period. The strategy allows us to set the ATR period (default 14) and multiplier (default 2). The system calculates the ATR value on entry, then multiplies it by the set multiplier as the stop distance.

For example, if the ATR after entry is 50 points, and the multiplier is set to 2, then the stop distance would be 100 points. If the price then moves more than 100 points, the stop loss order would be triggered. This allows timely stop losses to avoid excessive losses.

The strategy also considers trend determination. The long stop loss is only enabled when the buy signal matches an upward trend. The short stop loss matches a downward trend.

The stop loss lines are plotted on the chart so we can verify them in real-time. When stop loss conditions are triggered, corresponding positions are closed automatically by the system.

Advantage Analysis

The biggest advantage of this strategy is that it dynamically adjusts the stop loss distance and automatically modifies risk exposure based on market volatility changes. When volatility expands, the stop distance also increases, reducing the chance of stop loss being hit. In low volatility markets, the stop distance is reduced.

Compared to fixed stop loss distances, this approach effectively controls losses on a per trade basis while tracking trends. It ensures profit room as well as managing risk.

In addition, combining with trend determination, such stop loss methods can reduce the chance of being stopped out by whipsaws in consolidation zones.

Risk Analysis

The main risk of this strategy is the chance of prices pulling back in the short term during a position, triggering the stop loss. Especially if ATR period is too short, stop distances cannot fully filter out the impact of short term fluctuations.

Another risk is that prices may gap through the stop loss level in violent moves. This would require larger ATR multiplier settings, but that also means reduced profit potential.

Finally, the strategy does not consider the impact of afterhours and premarket trading on ATR values. This may lead to inaccurate ATR data calculation on opens or closes.

Optimization Directions

The strategy can be optimized in several aspects:

  1. Optimize ATR period parameters and test best combinations for different markets

  2. Compare fixed vs dynamic ATR multiples in terms of return

  3. Incorporate afterhours data into ATR calculation to reduce gaps on opens

  4. Set ATR conditions: only enable stops when ATR reaches certain levels, avoiding unnecessary stops in low volatility environments

  5. Incorporate more filters: major trends, volume/momentum indicators etc.


The Best ATR Stop Multiple Strategy effectively balances trend following and risk control by dynamically adjusting stop distances. Compared to fixed stops, it ensures profit potential while effectively capping losses.

Of course some risks remain, like price gaps and oversensitive stops. Further optimizations across multiple dimensions can improve robustness and returns.

start: 2024-01-01 00:00:00
end: 2024-01-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]

//This source code is subject to the terms of the Mozilla Public License 2.0 at

SystemName = "BEST ATR Stop Multiple Strategy"
TradeId = "BEST"

InitCapital = 100000
InitPosition = 100
InitCommission = 0.075
InitPyramidMax = 1
CalcOnorderFills = true
CalcOnTick = true
DefaultQtyType = strategy.fixed
DefaultQtyValue = strategy.fixed
Precision = 2

strategy(title=SystemName, shorttitle=SystemName, overlay=Overlay )

fastSMAperiod = input(defval=15, title='Fast SMA', type=input.integer, minval=2, step=1)
slowSMAperiod = input(defval=45, title='Slow SMA', type=input.integer, minval=2, step=1)

src = close
// Calculate moving averages
fastSMA = sma(src, fastSMAperiod)
slowSMA = sma(src, slowSMAperiod)

// Calculate trading conditions
enterLong  = crossover(fastSMA, slowSMA)
enterShort = crossunder(fastSMA, slowSMA)

// trend states
since_buy  = barssince(enterLong)
since_sell = barssince(enterShort)
buy_trend  = since_sell > since_buy
sell_trend = since_sell < since_buy 

is_signal = enterLong or enterShort

// get the entry price
entry_price = valuewhen(enterLong or enterShort, src, 0)

// Plot moving averages
plot(series=fastSMA, color=color.teal)

// Plot the entries
plotshape(enterLong,, location=location.belowbar,, size=size.small)
plotshape(enterShort,, location=location.abovebar,, size=size.small)

//======[ Trailing STOP ]======//

// use SL?
useSL = input(true, "Use stop Loss")
// ATR multiple Stop
stop_atr_length         = input(14,title="ATR Length", minval=1, type=input.integer)
stop_atr_mult           = input(2,title="ATR Multiple", minval=0.05, step=0.1, type=input.float)

// Global STOP

stop_price = 0.0, stop_price := nz(stop_price[1])

var stop_atr      = 0.0
var entry_stop_atr   = 0.0

stop_atr          := nz(atr(stop_atr_length))

if enterLong or enterShort
    entry_stop_atr := stop_atr * stop_atr_mult

// display the ATR value multiple
plotshape(enterLong, title='ATR Long Stop value', style=shape.labelup, 
 location=location.bottom,, transp=0, text='',, editable=true, size=size.small, show_last=1, size=size.small)

// var label atr_long_label = na
// var label atr_short_label = na
lapos_y_entry_up = lowest(30)
lapos_y_entry_dn = highest(30)

// text_label = "ATR value: " + tostring(stop_atr, '#.#') + "\n\nATR Multiple value: " + tostring(entry_stop_atr, '#.#')

// if enterLong

//     label.delete(atr_long_label)

//     atr_long_label :=, lapos_y_entry_up, text=text_label, 
//      xloc=xloc.bar_index, yloc=yloc.price,, style=label.style_labelup, textcolor=color.white, 
//      size=size.normal)    

// if enterShort

//     label.delete(atr_short_label)

//     atr_short_label :=, lapos_y_entry_dn, text=text_label, 
//      xloc=xloc.bar_index, yloc=yloc.price,, style=label.style_labeldown,, 
//      size=size.normal)    

// Determine trail stop loss prices
longStopPrice = 0.0, shortStopPrice = 0.0

longStopPrice := if useSL and buy_trend
    stopValue = entry_price - entry_stop_atr

shortStopPrice := if useSL and sell_trend
    stopValue = entry_price + entry_stop_atr


cond_long_stop_loss_hit  = useSL and buy_trend and crossunder(low, longStopPrice[1]) 

cond_short_stop_loss_hit = useSL and sell_trend and crossover(high, shortStopPrice[1]) 

// Plot stop loss values for confirmation
plot(series=useSL and buy_trend and low >= longStopPrice 
 ? longStopPrice : na,
 color=color.fuchsia, style=plot.style_cross,
 linewidth=2, title="Long Trail Stop")

plot(series=useSL and sell_trend and high <= shortStopPrice 
 ? shortStopPrice : na,
 color=color.fuchsia, style=plot.style_cross,
 linewidth=2, title="Short Trail Stop")

close_long  = cond_long_stop_loss_hit
close_short = cond_short_stop_loss_hit

// Submit entry orders
strategy.entry(TradeId + " L", long=true, when=enterLong)
strategy.close(TradeId + " L", when=close_long)

//if (enterShort)
strategy.entry(TradeId + " S", long=false, when=enterShort)
strategy.close(TradeId + " S", when=close_short)