◆ New — Strategy Validator, Code Fixer & Prop Compliance Checker are live. Try one free →
Home / Strategies / ATR Trailing Stop Strategy
Exit & Risk Management Strategies

ATR Trailing Stop Strategy

The ATR Trailing Stop Strategy uses Average True Range (ATR) to place a stop level that follows price by a volatility-scaled distance, widening when the market is choppy and tightening when it calms down. Traders use it mainly as an exit and trade-management rule, letting the stop ratchet in the direction of an open position while never moving against it. It is a tool for defining when a trade is "no longer valid" on your terms; it is not predictive and does not guarantee any outcome, and trading always carries the risk of loss.

How it works

Average True Range measures how much an instrument typically moves over a chosen lookback period, so it adapts to changing volatility instead of using a fixed point/pip distance. The strategy multiplies ATR by a factor (commonly around 2 to 3.5) to get a "trailing distance," then keeps a stop line that distance away from a reference price. For a long position the stop sits below the reference and is only allowed to move up (or stay flat) as price advances; for a short position it sits above and only moves down. The key mechanic is the ratchet: once the stop tightens, it never loosens again while the position is open. The reference can be the current close (as in the example below) or the highest high / lowest low since entry — the latter is the "chandelier" variant, which anchors the trail to the extreme rather than the close. When price closes through the trailing line, the strategy treats that as the exit signal. Because the distance is volatility-based, the same multiplier gives a wider stop in turbulent conditions and a narrower one in quiet ranges, which is the intent: it aims to sit outside ordinary noise while still defining a clear invalidation level. It says nothing about whether a trade will work out; it only standardizes how and when you step aside. Want to confirm your version behaves the way you intend? Paste your strategy into the ForexCodes Strategy Validator to get validated Pine Script v6 plus an automatic check for look-ahead bias, repainting, and intent mismatches before you take it live.

Entry rules

Exit rules

Risk notes

Pine v6 example

//@version=6
strategy("ATR Trailing Stop Strategy (Illustrative)", overlay = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 10)

// --- Inputs ---
atrLen  = input.int(14,  "ATR Length", minval = 1)
atrMult = input.float(3.0, "ATR Multiplier", minval = 0.1, step = 0.1)
maLen   = input.int(200, "Trend MA Length", minval = 1)

// --- Indicators (built-in namespaces) ---
atr = ta.atr(atrLen)
ma  = ta.sma(close, maLen)

// --- Direction bias for entries (example filter, not predictive) ---
longBias  = close > ma
shortBias = close < ma

// --- Trailing stop state (persists across bars) ---
var float longStop  = na
var float shortStop = na

// Candidate stop levels for this bar (close-referenced variant)
longCandidate  = close - atrMult * atr
shortCandidate = close + atrMult * atr

// --- Manage long trailing stop (ratchets up only) ---
if strategy.position_size > 0
    longStop := na(longStop) ? longCandidate : math.max(longStop, longCandidate)
else
    longStop := na

// --- Manage short trailing stop (ratchets down only) ---
if strategy.position_size < 0
    shortStop := na(shortStop) ? shortCandidate : math.min(shortStop, shortCandidate)
else
    shortStop := na

// --- Entries (managed by the trailing stop afterwards) ---
if strategy.position_size == 0 and longBias
    strategy.entry("Long", strategy.long)
    longStop := longCandidate
else if strategy.position_size == 0 and shortBias
    strategy.entry("Short", strategy.short)
    shortStop := shortCandidate

// --- Exits on a confirmed close through the trailing line ---
if strategy.position_size > 0 and not na(longStop) and close < longStop
    strategy.close("Long", comment = "ATR trail hit")
if strategy.position_size < 0 and not na(shortStop) and close > shortStop
    strategy.close("Short", comment = "ATR trail hit")

// --- Plots ---
plot(strategy.position_size > 0 ? longStop  : na, "Long Trail",  color = color.green, style = plot.style_linebr)
plot(strategy.position_size < 0 ? shortStop : na, "Short Trail", color = color.red,   style = plot.style_linebr)
plot(ma, "Trend MA", color = color.new(color.blue, 50))

Pitfalls

FAQ

Is the ATR trailing stop a complete strategy on its own?

Not really. It is an exit and trade-management rule. You still need an entry method and a direction bias (the example uses a moving-average filter). It standardises how you leave a trade and define invalidation; it does not decide which trades to take, and it makes no claim about outcomes.

What ATR length and multiplier should I use?

There is no universally correct setting. A 14-period ATR with a roughly 2 to 3.5 multiplier is a common starting range, but the right values depend on the instrument, timeframe, and how much noise you are willing to sit through. A larger multiplier gives more room (and a larger potential loss if hit); a smaller one tightens the stop but increases the chance of being shaken out. Test across conditions rather than tuning to one chart.

Why did my trailing stop seem to catch every top and bottom in the backtest?

That is usually a warning sign, not a feature. It often comes from reading values off unconfirmed bars or from look-ahead/repainting in how the level is computed or plotted. A stop that 'knew' the high in advance cannot be reproduced live. This is exactly the kind of intent mismatch and look-ahead bias the ForexCodes Strategy Validator is built to catch.

Educational & software only — not financial advice, not a recommendation to trade. Backtests are illustrative; past performance does not predict future results. Trading involves substantial risk of loss.

Catch the bug that compiles.Run auditGet Pro