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.
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.
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.
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.
The strategy can be optimized in several aspects:
Optimize ATR period parameters and test best combinations for different markets
Compare fixed vs dynamic ATR multiples in terms of return
Incorporate afterhours data into ATR calculation to reduce gaps on opens
Set ATR conditions: only enable stops when ATR reaches certain levels, avoiding unnecessary stops in low volatility environments
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.
/*backtest 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"}] */ //@version=4 //@author=Daveatt //This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ 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 Overlay=true 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(series=slowSMA, color=color.orange) // Plot the entries plotshape(enterLong, style=shape.circle, location=location.belowbar, color=color.green, size=size.small) plotshape(enterShort, style=shape.circle, location=location.abovebar, color=color.red, 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]) // STOP ATR 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, color=color.green, transp=0, text='', textcolor=color.navy, 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 := label.new(bar_index, lapos_y_entry_up, text=text_label, // xloc=xloc.bar_index, yloc=yloc.price, color=color.green, style=label.style_labelup, textcolor=color.white, // size=size.normal) // if enterShort // label.delete(atr_short_label) // atr_short_label := label.new(bar_index, lapos_y_entry_dn, text=text_label, // xloc=xloc.bar_index, yloc=yloc.price, color=color.red, style=label.style_labeldown, textcolor=color.black, // 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 else 0 shortStopPrice := if useSL and sell_trend stopValue = entry_price + entry_stop_atr else 999999 ////////////////////////////////////////////////////////////////////////////////////////// //*** STOP LOSS HIT CONDITIONS TO BE USED IN ALERTS ***// ////////////////////////////////////////////////////////////////////////////////////////// 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)