The Complete ATR Guide
Dynamic Position Sizing with Volatility
ATR (Average True Range) is an indicator J. Welles Wilder introduced in his 1978 book New Concepts in Technical Trading Systems(the same book that gave us RSI).
ATR doesn't tell you direction — it only tells you how volatile the market is right now. But it's the risk-management core that real pros use: the 1983 Turtle system, Bill Dunn's DUNN Capital (19% CAGR over 40 years), and essentially every CTA on the planet sizes positions with ATR.
1. What Is ATR? The Math Behind It
Start with True Range — the volatility of a single candle is the largest of three values:
TR = max(
high − low, // intra-candle range
abs(high − close_prev), // high vs. previous close
abs(low − close_prev) // low vs. previous close
)Why factor in the previous close? Because of gaps — a candle might print high=100 and low=98 (looks calm), but the prior close was 105, so the real move is 7 points (105 down to 98).
ATR is just the average of TR over the last N candles (default N = 14):
ATR(14) = a smoothed moving average (RMA) of the last 14 True Range values2. Use #1: Dynamic Stop-Losses (the most common)
The problem with fixed stops: a flat 1% stop gets whipsawed in high-volatility BTC and is way too loose in quiet markets. ATR stops adjust automatically.
//@version=5
strategy("ATR Dynamic Stop", overlay=true)
atrLength = input.int(14, "ATR Period")
atrMult = input.float(2.0, "Stop ATR Multiplier")
atr = ta.atr(atrLength)
// Entry (using EMA cross as demo)
ema9 = ta.ema(close, 9)
ema21 = ta.ema(close, 21)
if (ta.crossover(ema9, ema21))
strategy.entry("Long", strategy.long)
if (ta.crossunder(ema9, ema21))
strategy.entry("Short", strategy.short)
// === Dynamic stop ===
longStop = strategy.position_avg_price - atr * atrMult
shortStop = strategy.position_avg_price + atr * atrMult
strategy.exit("LongExit", "Long", stop=longStop)
strategy.exit("ShortExit", "Short", stop=shortStop)
plot(atr, "ATR", color=color.purple, display=display.pane)Typical ATR multipliers:
- 1.5x: tight stop — good for chop and scalping
- 2x: the standard (this is what the Turtles used)
- 3x: wide stop — gives swing trades room to breathe
- 4–5x: very wide — for ultra-long-term holds
3. Use #2: The Turtle Position Formula (the one worth learning)
This is the heart of the 1983 Turtle system. For background, see CTA Trend Following + the Turtles.
The principle: every trade risks exactly 1% of the account. You use ATR to measure the stop distance, then back out position size from it.
Dollar risk = account equity × 1%
Stop distance = ATR × 2
Position size = dollar risk / stop distance
Example:
Account = $10,000
ATR = $500
Dollar risk = $100
Stop distance = $1,000
Position size = $100 / $1,000 = 0.1 BTC//@version=5
strategy("Turtle Position Sizing", overlay=true,
initial_capital=10000, default_qty_type=strategy.fixed)
atrLength = input.int(20, "ATR Period (Turtle original uses 20)")
riskPct = input.float(1.0, "Risk Per Trade %")
atrMult = input.float(2.0, "Stop ATR Multiplier")
atr = ta.atr(atrLength)
// Position size = risk amount / stop distance
riskAmount = strategy.equity * riskPct / 100
stopDistance = atr * atrMult
positionQty = riskAmount / stopDistance
// Entry
if (ta.crossover(close, ta.highest(high, 20)[1]))
strategy.entry("Long", strategy.long, qty=positionQty)
if (ta.crossunder(close, ta.lowest(low, 20)[1]))
strategy.entry("Short", strategy.short, qty=positionQty)
// Dynamic stop
strategy.exit("LongStop", "Long",
stop=strategy.position_avg_price - atr * atrMult)
strategy.exit("ShortStop", "Short",
stop=strategy.position_avg_price + atr * atrMult)
plot(atr, "ATR", color=color.purple)4. Use #3: Breakout Filtering (kill the fakeouts)
A lot of breakout strategies get fooled by fakeouts — price briefly takes out the prior high, then immediately rolls back.
The fix: require the breakout magnitude to be greater than ATR × N before it counts as real:
//@version=5
strategy("ATR Breakout Filter", overlay=true)
prevHigh = ta.highest(high, 20)[1]
atr = ta.atr(14)
breakoutFilter = atr * 0.5 // must break at least 50% ATR
// True breakout: close ≥ 0.5 ATR above prior high
trueBreakout = close > prevHigh + breakoutFilter
if (trueBreakout)
strategy.entry("Long", strategy.long)5. Use #4: Gauging Trend Strength
Rising ATR = volatility is expanding = usually a strong trend or a major event. Falling ATR = the market is quiet = chop or consolidation.
A useful trick: compare ATR against its own long-term average.
atr = ta.atr(14)
atrMa = ta.sma(atr, 50)
highVol = atr > atrMa * 1.5 // 50% above avg volatility
lowVol = atr < atrMa * 0.6 // 40% below avg volatility
// Run trend strategy in high vol
// Run grid / mean reversion in low vol
bgcolor(highVol ? color.new(color.red, 90) : na, title="High Vol")
bgcolor(lowVol ? color.new(color.blue, 90) : na, title="Low Vol")6. ATR vs. Other Volatility Indicators
| Indicator | Properties | Best for |
|---|---|---|
| ATR | Absolute-price volatility, includes gaps | Position sizing, dynamic stops |
| Standard Deviation (σ) | Statistical volatility, assumes normality | Channel indicators like Bollinger Bands |
| Historical Volatility (HV) | Annualized σ, comparable across assets | Options pricing |
| Implied Volatility (IV) | Market's expectation of future volatility | Options strategies |
7. Common Mistakes
Wrong: treating ATR as a signal
Some people build strategies like "ATR rising → go long" or "ATR falling → go short." That's backwards. ATR is volatility; it has no directional meaning. You still need a trend or entry/exit rule on top.
Wrong: treating ATR as a percentage
ATR is an absolute price value, not a percent. BTC at $30k with ATR=$500 is 1.67% volatility; BTC at $60k with the same $500 ATR is only 0.83%. Normalize before comparing across timeframes or price regimes.
Wrong: making the period too short
People shorten the ATR period to 5 thinking "it'll be more responsive." The result: ATR whips around on the last 1–2 extreme candles and your stops jump everywhere. Stick with the default 14, or 20.
Wrong: same ATR multiplier for every asset
BTC and altcoins behave very differently. Rough guidance:
- BTC: ATR × 2–3
- ETH / large-cap alts: ATR × 2–2.5
- Small-cap alts: ATR × 3–4 (need extra room for the noise)
Get started
Want to bake ATR-based risk control straight into your strategy? TVSBot pipes Pine signals to your exchange and can size positions dynamically on every fill.
Start free trial8. Three Key Takeaways
- ATR is a translator: it converts abstract volatility into concrete dollars so you can size positions, place stops, and run real risk control.
- The Turtle position formula was revolutionary in 1983: 1% risk per trade, ATR-based dynamic sizing — still the industry standard four decades later.
- ATR has no direction — don't use it as a signal. Its value is in letting your strategy adapt to the regime.