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:
- The distance between the current high and the current low: `High - Low`
- The absolute distance between the current high and the previous day's close: `abs(High - Close[1])`
- 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")
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.
- Long Position Stop Loss: `Entry Price - (ATR * Multiplier)`
- Short Position Stop Loss: `Entry Price + (ATR * Multiplier)`
- A common multiplier is 2 or 3 (e.g., 2 * ATR from your entry).
//@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.
- Calculate Risk per Share (RPS): `ATR * Multiplier`
- Calculate Number of Shares: `(Account Risk / RPS)` (Account Risk is your desired maximum dollar risk per trade).
//@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.
- Strategy Enhancement: Only activate trend-following strategies (e.g., moving average crossovers) when ATR is rising or above a certain threshold, indicating a potentially strong trend.
- Consolidation Detection: When ATR is low and relatively flat, it signals a period of consolidation. This might be a good time for range-bound strategies or to prepare for a potential breakout once volatility expands.
//@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:
- Parameter Tuning: The default `length` of 14 is a good starting point for daily charts, representing roughly two trading weeks. Shorter lengths (e.g., 7) will make ATR more reactive to recent volatility, while longer lengths (e.g., 20 or 26) will provide a smoother, less noisy measure of volatility.
- Multiplier Calibration: The `multiplier` used for stop-loss or profit target placement is critical. Backtest different multipliers (e.g., 1.5, 2.0, 2.5, 3.0) to find what works best for your specific asset, timeframe, and risk tolerance. More volatile assets might require larger multipliers.
- Timeframe Adaptability: ATR is timeframe-dependent. An ATR value on a daily chart will be vastly different from a 5-minute chart. Ensure your `length` and `multiplier` are calibrated for the timeframe you are using.
- Combine with Directional Indicators: ATR is not a directional indicator. Always use it in conjunction with other indicators (e.g., moving averages, MACD, RSI) that tell you *which way* the market is likely to move. ATR helps with *how much* it moves.
- Trailing Stop Loss: ATR can be used to create trailing stop losses, allowing you to capture more of a trend while still protecting against sharp reversals. As price moves in your favor, the ATR-based stop also moves.
Common ATR Pitfalls
- Not a Directional Signal: The biggest mistake is trying to derive buy/sell signals directly from ATR. It tells you nothing about the future direction of price.
- Lag: ATR is a lagging indicator. It measures *past* volatility, which may or may not continue into the future.
- Interpretation Subjectivity: Deciding on the "correct" ATR multiplier or threshold for volatility filtering can be subjective and requires backtesting and experience.
- False Signals in Extreme Conditions: Very sudden spikes in volatility (e.g., due to news events) can cause ATR to jump, leading to very wide stops that might be impractical. Conversely, extended periods of extremely low volatility can lead to very tight stops that get hit prematurely.
- Not a Standalone Indicator: ATR is a risk management and market condition tool. It's not a complete trading system on its own and must be integrated into a comprehensive strategy.
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