Pine Script Average True Range (ATR)

Master this essential volatility indicator in TradingView's Pine Script for dynamic stop-loss placement, position sizing, and understanding market conditions.

Subscribe now @ $99/month

What is the Average True Range (ATR)?

The Average True Range (ATR) is a widely used volatility indicator developed by J. Welles Wilder Jr. (also the creator of RSI, ADX, and Parabolic SAR). Unlike other indicators that measure price direction, ATR quantifies market volatility by calculating the average of true ranges over a specified period. The "true range" accounts for gaps and limits to capture the full extent of price movement within a given period. A high ATR value indicates high volatility, while a low ATR value suggests low volatility.

In Pine Script, ATR is an indispensable tool not for generating buy/sell signals directly, but for risk management, position sizing, and adapting strategies to changing market conditions. It helps traders set objective stop-loss and take-profit levels that are appropriate for the current market's swing.

Components and Calculation

The calculation of ATR begins with the True Range (TR) for each period. The True Range is the greatest of the following three values:

  1. The distance between the current high and the current low: `High - Low`
  2. The absolute distance between the current high and the previous day's close: `abs(High - Close[1])`
  3. The absolute distance between the current low and the previous day's close: `abs(Low - Close[1])`

Once the True Range for each period is calculated, the Average True Range (ATR) is typically a Simple Moving Average (SMA) or, more commonly, an Exponential Moving Average (EMA) of these True Range values over a specified `length` (e.g., 14 periods).


`ATR = SMA (or EMA) of True Range over 'length' periods`

Basic Average True Range (ATR) Implementation in Pine Script

Pine Script v5 provides a convenient built-in function `ta.atr()` for calculating the Average True Range.

//@version=5
indicator("My Average True Range (ATR)", overlay=false, format=format.price) // overlay=false to plot in a separate pane

// Input for ATR length
length = input.int(14, title="ATR Length", minval=1)

// Calculate ATR value using the built-in function
// ta.atr uses (high, low, close) implicitly and applies an RMA (smoothed moving average) for smoothing
atrValue = ta.atr(length)

// Plot the ATR line
plot(atrValue, title="ATR", color=color.purple, linewidth=2)

// Optional: Add moving average of ATR to identify volatility trends
atrMA = ta.sma(atrValue, 20) // 20-period SMA of ATR
plot(atrMA, title="ATR MA", color=color.gray, linewidth=1, style=plot.style_line)

// Highlight background when ATR is significantly higher or lower than its average
bgcolor(atrValue > atrMA * 1.5 ? color.new(color.orange, 90) : na, title="High Volatility")
bgcolor(atrValue < atrMA * 0.7 ? color.new(color.blue, 90) : na, title="Low Volatility")
Volatility, Not Direction: Remember that ATR measures *how much* price is moving, not *which direction* it's moving. A rising ATR means prices are swinging more, while a falling ATR means they are quiet.

Practical ATR Trading Strategies

1. Dynamic Stop Loss Placement (Primary Use)

ATR is widely used to place stop-loss orders dynamically, adapting to current market volatility. This ensures your stop isn't too tight during volatile periods or too wide during quiet periods.

//@version=5
strategy("ATR Dynamic Stop Loss", overlay=true)

// Input for ATR length and Stop Loss Multiplier
atrLength = input.int(14, title="ATR Length", minval=1)
stopLossMultiplier = input.float(2.0, title="Stop Loss Multiplier", minval=0.1, step=0.1)

// Calculate ATR
atrValue = ta.atr(atrLength)

// Simple example entry (e.g., crossing a 20-period SMA)
maLength = input.int(20, title="Entry MA Length", minval=1)
maValue = ta.sma(close, maLength)

longCondition = ta.crossover(close, maValue)
shortCondition = ta.crossunder(close, maValue)

// Determine stop loss levels dynamically
longStopLoss = strategy.position_avg_price - (atrValue * stopLossMultiplier)
shortStopLoss = strategy.position_avg_price + (atrValue * stopLossMultiplier)

if (longCondition)
    strategy.entry("Long", strategy.long)

if (shortCondition)
    strategy.entry("Short", strategy.short)

// Apply dynamic stop losses
strategy.exit("Long Exit", from_entry="Long", stop=longStopLoss)
strategy.exit("Short Exit", from_entry="Short", stop=shortStopLoss)

// Plot stop loss levels on chart (optional)
plot(strategy.position_avg_price > 0 ? longStopLoss : na, "Long Stop Loss", color=color.red, style=plot.style_linebr, linewidth=1)
plot(strategy.position_avg_price < 0 ? shortStopLoss : na, "Short Stop Loss", color=color.red, style=plot.style_linebr, linewidth=1)

2. Position Sizing based on Volatility

ATR can be used to size positions so that the monetary risk per trade is consistent, regardless of the asset's volatility. In higher volatility, you trade fewer shares; in lower volatility, you trade more shares.

//@version=5
strategy("ATR Position Sizing Example", overlay=true)

// Inputs for ATR and risk management
atrLength = input.int(14, title="ATR Length", minval=1)
atrMultiplier = input.float(2.0, title="ATR Risk Multiplier", minval=0.1, step=0.1)
accountRiskPerTrade = input.float(1000.0, title="Max $ Risk Per Trade", minval=10) // Example: $1000 risk

// Calculate ATR
atrValue = ta.atr(atrLength)

// Calculate Risk Per Share (RPS) based on ATR
riskPerShare = atrValue * atrMultiplier

// Calculate position size (number of shares)
// Ensure riskPerShare is not zero to avoid division by zero
sharesToTrade = riskPerShare != 0 ? math.floor(accountRiskPerTrade / riskPerShare) : 0

// Simple example entry (e.g., crossing a 50-period SMA)
maLength = input.int(50, title="Entry MA Length", minval=1)
maValue = ta.sma(close, maLength)

longCondition = ta.crossover(close, maValue)
shortCondition = ta.crossunder(close, maValue)

// Enter trades with calculated position size
if (longCondition)
    strategy.entry("Long (Sized)", strategy.long, qty=sharesToTrade)

if (shortCondition)
    strategy.entry("Short (Sized)", strategy.short, qty=sharesToTrade)

// Dynamic Stop Loss based on ATR (as previously shown)
longStopLoss = strategy.position_avg_price - (atrValue * atrMultiplier)
shortStopLoss = strategy.position_avg_price + (atrValue * atrMultiplier)

strategy.exit("Long Exit", from_entry="Long (Sized)", stop=longStopLoss)
strategy.exit("Short Exit", from_entry="Short (Sized)", stop=shortStopLoss)

// Plot ATR in a separate pane for visualization
plot(atrValue, "ATR", color=color.purple, display=display.pane_only)

3. Volatility Filter for Trend-Following Strategies

ATR can help filter out choppy market conditions where trend-following strategies might struggle, or identify periods ripe for breakouts.

//@version=5
strategy("ATR Volatility Filter", overlay=true)

atrLength = input.int(14, title="ATR Length", minval=1)
atrValue = ta.atr(atrLength)

// Moving Average of ATR to smooth its readings
atrSMA = ta.sma(atrValue, 20)
atrThreshold = input.float(1.2, title="ATR Multiplier for Trending Filter", minval=1.0, step=0.1)

// Define "trending" period when ATR is above its average, suggesting higher volatility
isTrendingVolatility = atrValue > atrSMA * atrThreshold

// Simple trend-following entry (e.g., MA crossover)
fastMA = ta.ema(close, 10)
slowMA = ta.ema(close, 20)

longSignal = ta.crossover(fastMA, slowMA) and isTrendingVolatility
shortSignal = ta.crossunder(fastMA, slowMA) and isTrendingVolatility

if (longSignal)
    strategy.entry("Long Filtered", strategy.long)

if (shortSignal)
    strategy.entry("Short Filtered", strategy.short)

// Plot indicators in separate panes
plot(atrValue, "ATR", color=color.purple, display=display.pane_only)
plot(atrSMA, "ATR SMA", color=color.gray, display=display.pane_only)
plot(fastMA, "Fast MA", color=color.green, overlay=true)
plot(slowMA, "Slow MA", color=color.red, overlay=true)

bgcolor(isTrendingVolatility ? color.new(color.aqua, 90) : na, title="Trending Volatility Zone")

Optimizing ATR Performance

To get the most from the Average True Range in Pine Script:

Dynamic Risk Management: ATR provides a dynamic way to manage risk, making your stops and targets more intelligent by adapting to current market conditions rather than using fixed price points.

Common ATR Pitfalls

Conclusion

The Average True Range (ATR) is a fundamental and exceptionally useful technical indicator in Pine Script for TradingView. While it doesn't provide directional signals, its accurate measurement of market volatility is invaluable for intelligent risk management. By dynamically adjusting stop-loss levels, sizing positions appropriately, and filtering trading opportunities based on current market choppiness or trend strength, traders can significantly enhance the robustness of their strategies. By understanding its calculation, thoughtfully calibrating its parameters, and integrating it strategically with directional indicators and price action analysis, you can leverage the ATR to make more informed trading decisions and manage your risk effectively in varying market conditions.

Enhance Your Trading

Get a high-performance Pine Script analysis tool for actionable market insights, designed for traders on the move.

This strategy runs in live mode on TradingView, helping you identify potential opportunities.

Subscribe now @ $99/month