Technical Analysis · Volatility / Risk Management

The Complete ATR Guide
Dynamic Position Sizing with Volatility

2026-06-03·10 min read·Risk Core

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:

text
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):

text
ATR(14) = a smoothed moving average (RMA) of the last 14 True Range values
ATR is denominated in price, not percent
ATR isn't a percentage — it's an absolute price value. BTC at $60k might have an ATR around $1,500; ETH at $3k around $80. The reading means "the average candle moves about $1,500." That property is the whole reason ATR works for risk management — it translates volatility into a concrete dollar amount.

2. 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.

pine
//@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.

text
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
Why this approach was revolutionary
In 1983, most traders sized by "fixed share count" or "fixed dollar amount." The Turtles pioneered ATR-based dynamic sizing — positions automatically shrink in volatile markets and grow in quiet ones. That keeps expected loss per trade constant across instruments and regimes. A genuine 1983 paradigm shift.
pine
//@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:

pine
//@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.

pine
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")
Strategy switching in practice
A more advanced move: let ATR auto-switch your strategy — run trend following in high volatility, grid or mean-reversion in low volatility. That makes your system adapt to the market regime. See the "Advanced: grid + trend filter" section in the Grid Trading guide.

6. ATR vs. Other Volatility Indicators

IndicatorPropertiesBest for
ATRAbsolute-price volatility, includes gapsPosition sizing, dynamic stops
Standard Deviation (σ)Statistical volatility, assumes normalityChannel indicators like Bollinger Bands
Historical Volatility (HV)Annualized σ, comparable across assetsOptions pricing
Implied Volatility (IV)Market's expectation of future volatilityOptions 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

Ready to ship what you just learned?

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 trial

8. Three Key Takeaways

  1. ATR is a translator: it converts abstract volatility into concrete dollars so you can size positions, place stops, and run real risk control.
  2. The Turtle position formula was revolutionary in 1983: 1% risk per trade, ATR-based dynamic sizing — still the industry standard four decades later.
  3. ATR has no direction — don't use it as a signal. Its value is in letting your strategy adapt to the regime.