Developed by the legendary technical analyst J. Welles Wilder Jr., the Average True Range (ATR) is a cornerstone indicator for measuring market volatility. A key characteristic of ATR is that it is not directional; it quantifies the degree of price movement or “choppiness” but does not indicate the trend’s direction.
The ATR calculation is based on the “True Range” (TR). The True Range aims to capture the full extent of price movement for a given period, including any price gaps that might occur when the market is closed (e.g., overnight or over a weekend).
For each period, the True Range (TR) is defined as the greatest of
the following three values: 1. The difference between the current
period’s High and its Low: 2. The absolute value of the difference between
the current period’s High and the previous period’s Close:
3. The absolute value of the difference between
the current period’s Low and the previous period’s Close:
So, for each period:
Once the True Range is calculated for each period, the Average True Range (ATR) is typically an N-period smoothed moving average of these TR values. J. Welles Wilder Jr. used a specific smoothing method (a form of exponential moving average) for his indicators, and this is generally what ATR calculations (including TA-Lib’s) employ. The common default period (N) for ATR is 14 periods.
Usage: ATR is a versatile tool used by traders and analysts in various aspects of trading:
Entry Price - (Multiplier × ATR)
Entry Price + (Multiplier × ATR)
The
Multiplier
is typically a value like 1.5, 2, 2.5, or 3,
chosen based on the trader’s risk tolerance and the asset’s
characteristics. This method helps prevent stops from being too close in
volatile markets (risking premature exit) or too wide in calm markets
(risking excessive loss).TA-Lib Function: The Technical Analysis Library (TA-Lib) provides a function to calculate ATR:
talib.ATR(high_prices, low_prices, close_prices, timeperiod=14)
high_prices
: An array or series of high prices.low_prices
: An array or series of low prices.close_prices
: An array or series of closing
prices.timeperiod
: The lookback period for the ATR calculation
(default is 14). TA-Lib’s ATR uses Wilder’s smoothing method.Code Example (Calculation & Plot with yfinance Data):
The following Python code demonstrates how to fetch HLC data using
yfinance
, calculate the ATR, and plot the price alongside
the ATR indicator.
import yfinance as yf
import talib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# --- 1. Data Fetching using yfinance ---
= "SPY" # Example: SPDR S&P 500 ETF Trust
ticker_symbol # Fetching a bit more data initially to ensure enough for indicator calculation start
= "2022-11-01" # Ensure enough data for lookback period
data_start_date = "2023-01-01" # Start plotting from here
plot_start_date = "2024-05-01"
data_end_date
try:
= yf.download(ticker_symbol, start=data_start_date, end=data_end_date, auto_adjust=False, progress=False)
data if isinstance(data.columns, pd.MultiIndex) and data.columns.nlevels > 1: # Droplevel based on user history
= data.columns.droplevel(level=1)
data.columns except Exception as e:
print(f"Error downloading data for {ticker_symbol}: {e}")
= pd.DataFrame() # Ensure data is an empty DataFrame on error
data
if data.empty or not all(col in data.columns for col in ['High', 'Low', 'Close']) or \
any(data[col].isnull().all() for col in ['High', 'Low', 'Close']):
print(f"Insufficient HLC data found for {ticker_symbol}. Exiting.")
else:
# Prepare data: ensure no NaNs in HLC for the period used by TA-Lib
= data[['High', 'Low', 'Close']].dropna()
hlc_data
= hlc_data['High']
high_prices = hlc_data['Low']
low_prices = hlc_data['Close'] # Name distinct from plotting close prices
close_prices_for_atr
# --- 2. Average True Range (ATR) Calculation ---
= 14 # Standard period for ATR
time_period_atr
# ATR needs HLC data and sufficient lookback period for smoothing.
# TA-Lib will output NaNs for the initial 'timeperiod' entries.
if len(close_prices_for_atr) > time_period_atr:
= talib.ATR(
atr_values
high_prices, low_prices, close_prices_for_atr,=time_period_atr
timeperiod
)= f"ATR({time_period_atr})"
indicator_name print(f"\n--- {indicator_name} - Average True Range for {ticker_symbol} ---")
= atr_values[~np.isnan(atr_values)]
valid_atr if len(valid_atr) >= 5:
print(f"Output {indicator_name} (last 5 valid): {valid_atr[-5:].round(2)}")
elif len(valid_atr) > 0:
print(f"Output {indicator_name} (all valid): {valid_atr.round(2)}")
else:
print(f"Output {indicator_name}: No valid ATR values calculated (all NaNs).")
# Filter data for the desired plotting period
= pd.Series(atr_values, index=hlc_data.index)
atr_series
= hlc_data[hlc_data.index >= plot_start_date]
plot_hlc_data = atr_series[plot_hlc_data.index]
plot_atr_values = plot_hlc_data.index
plot_date_index = plot_hlc_data['Close']
plot_close_prices
# --- 3. Plotting ---
if not plot_date_index.empty:
= plt.subplots(2, 1, figsize=(14, 10), sharex=True,
fig, axes ={'height_ratios': [3, 1]})
gridspec_kw
# Plot Price (using 'Close' from the plotting data slice)
0].plot(plot_date_index, plot_close_prices, label=f'{ticker_symbol} Close Price', color='blue')
axes[0].set_title(f'{ticker_symbol} Price and {indicator_name}')
axes[0].set_ylabel('Price')
axes[0].legend(loc='upper left')
axes[0].grid(True)
axes[
# Plot Average True Range
1].plot(plot_date_index, plot_atr_values, label=indicator_name, color='brown')
axes[1].set_ylabel('ATR Value')
axes[1].set_xlabel('Date')
axes[1].legend(loc='upper left')
axes[1].grid(True)
axes[
plt.tight_layout()
plt.show()else:
print(f"No data available for the plotting period starting {plot_start_date}.")
else:
print(f"\nSkipping ATR plot for {ticker_symbol}: Insufficient data (need > {time_period_atr} points after cleaning).")
if not hlc_data.empty:
print(f"Cleaned data available for {len(hlc_data)} periods. ATR period is {time_period_atr}.")
Explanation of the Code:
yfinance
for data, talib
for ATR, numpy
,
matplotlib.pyplot
for plotting, and
pandas
.yf.download()
retrieves High, Low, and Close (HLC)
data. Your preference for auto_adjust=False
and
droplevel
is incorporated. Basic error handling is
added.dropna()
on the selected columns to ensure clean input for
TA-Lib.time_period_atr
is set (commonly 14).if len(close_prices_for_atr) > time_period_atr:
ensures
sufficient data. TA-Lib’s ATR will produce NaN
values for
the initial timeperiod
due to its smoothing
calculation.talib.ATR()
computes the ATR values.plot_start_date
for a clearer chart if a longer history
was fetched. The ATR numpy array is converted to a Pandas Series with
the correct index for this alignment.plt.subplots(2, 1, ...)
creates two stacked subplots:
one for price and one for ATR.plt.tight_layout()
adjusts subplot spacing.plt.show()
displays the generated chart.By providing a clear measure of an asset’s typical price range, the ATR empowers traders to make more informed decisions regarding risk management, position sizing, and strategy selection in varying market conditions.