,

How To Use the Average True Range (ATR) Indicator

Posted by

Updated May 2026: I’ve refreshed this ATR guide with clearer true range formulas, more practical notes on stop placement and position sizing, and an updated Python walkthrough.

Average True Range graphic introducing the ATR volatility indicator
ATR measures how much a market is moving, not which direction it should move next.
Table of Contents

    What Is the Average True Range Indicator?

    Average True Range, usually shortened to ATR, is a volatility indicator.

    It measures how much a market has been moving over a chosen number of bars. A high ATR means the market has been making larger moves. A low ATR means the market has been quieter.

    ATR does not tell you direction. A rising ATR can appear during a rally, a sell-off, or a chaotic two-way market. It only tells you that the size of the price movement has increased.

    That makes ATR useful for risk management. Traders often use it to think about stop distance, position size, volatility filters, and whether a market is too quiet or too active for a particular strategy.

    For example, a stop that makes sense when ATR is small may be far too tight when ATR is large. The same two-point stop can mean very different things on two different markets or even on the same market in two different volatility regimes.

    In this guide I’ll walk through the true range formula, how Wilder’s ATR smoothing works, how ATR% helps compare different markets, and how to calculate and plot ATR in Python.

    How Average True Range Is Calculated

    ATR begins with True Range.

    True Range tries to capture the full movement of the current bar, including any gap from the previous close. That is why it uses three possible distances and takes the largest one.

    Before the formulas, here are the symbols:

    H means the current high.

    L means the current low.

    Cprev means the previous close.

    TR means True Range.

    ATR means Average True Range.

    n means the ATR period.

    t means the current bar.

    TR_t = \max \left( H_t - L_t,\ |H_t - C_{t-1}|,\ |L_t - C_{t-1}| \right)

    True Range = the largest of current high – current low, current high – previous close, or current low – previous close

    The first part, high minus low, measures the current bar’s normal range.

    The second and third parts capture gaps from the previous close. This is why True Range can be larger than the simple high-low range. If a market gaps up or gaps down, ATR is designed to notice that movement.

    Wilder ATR smoothing

    Once True Range has been calculated, ATR smooths it over time. Wilder’s common method is a recursive smoothing formula.

    ATR_t = \left(\frac{(n - 1) \times ATR_{t-1} + TR_t}{n}\right)

    ATR of current bar = ((n – 1) × previous ATR + current True Range) / n

    This is similar in spirit to an exponential smoothing method, but Wilder’s version uses 1 / n as the smoothing factor.

    A 14-period ATR is common. On a daily chart, that means 14 daily bars. On a 5-minute chart, it means 14 five-minute bars. The logic is the same, but the trading use is very different.

    Average True Range Percent (ATR%)

    ATR is an absolute number. If a stock has an ATR of 5, that means it has recently been moving about 5 price units per bar, depending on the timeframe used.

    That is useful on one chart, but harder to compare across markets. A 5-point ATR means something very different on a $20 stock and a $500 stock.

    ATR% solves that by expressing ATR as a percentage of price.

    ATR\% = \frac{ATR}{Close} \times 100

    ATR% = ATR / current close × 100

    ATR% makes volatility easier to compare across different markets and price levels. It is especially useful when scanning a list of instruments or comparing a high-priced stock with a lower-priced one.

    How Traders Use ATR

    ATR is mainly a volatility tool. It tells you how much the market has been moving, not which direction it is likely to move next.

    That sounds simple, but it is useful. A market with a high ATR needs different risk handling from a market with a low ATR. The same stop size, position size or target can make sense in one volatility regime and be completely wrong in another.

    I use ATR as a way to ask: how much room does this market normally need to move?

    That question can help with stops, position sizing, breakout filters, volatility comparisons and avoiding trades when the market is too quiet or too jumpy.

    ATR for stop placement

    One common ATR use is stop placement.

    If a market normally moves around 2 points per bar, a 0.5-point stop may be too tight. If a market normally moves 0.2 points per bar, a 2-point stop may be too wide for the trade being attempted.

    A common method is to place a stop a multiple of ATR away from the entry. For example, a trader might use 1.5 × ATR or 2 × ATR as a rough volatility-adjusted stop distance.

    This does not mean ATR magically finds the correct stop. It only gives a volatility reference. Price structure still matters. A stop placed at 2 × ATR but sitting in the middle of obvious support or resistance may still be badly placed.

    ATR for position sizing

    ATR can also help with position sizing.

    A higher ATR means the market is moving more. If you trade the same number of contracts or shares during a high-ATR period, the money risk can be much larger than during a quiet period.

    For example, if one market has an ATR of 1 and another has an ATR of 5, the second market is moving roughly five times as much in price terms. If the position size is not adjusted, the risk may be very different even if the trade setup looks similar.

    This is why some traders reduce position size when ATR rises and increase it only when the volatility risk is lower. The goal is not to avoid volatility completely. It is to stop volatility from deciding the size of the loss for you.

    ATR for breakouts and quiet markets

    ATR can also help identify changing volatility conditions.

    A low ATR means the market has been quiet. That can happen before a breakout, but low ATR alone does not tell you which way price will move.

    A rising ATR after a breakout can suggest the market is expanding into a more active phase. That can support a breakout view if price structure agrees.

    The mistake is assuming that low ATR always means a big move is coming. Sometimes a quiet market stays quiet.

    ATR before major events

    ATR is less helpful when the next big move is likely to come from a scheduled event.

    For example, before earnings, a central-bank decision or a major economic release, the recent trading range may shrink while traders wait. ATR may fall, making the market look quieter than it really is.

    That can make ATR-based stops look too tight just before the event that blows the range open.

    This is where the wider calendar matters. ATR measures recent movement. It does not know that non-farm payrolls, an interest-rate decision or an earnings release is coming.

    How to Interpret ATR

    A rising ATR means recent price ranges are getting larger.

    A falling ATR means recent price ranges are getting smaller.

    That is all ATR says. It does not tell you whether the next move should be up or down.

    ATR readingWhat it showsHow I would read it
    ATR risingPrice ranges are expandingVolatility is increasing
    ATR fallingPrice ranges are contractingVolatility is decreasing
    High ATR after breakoutLarger ranges after a breakBreakout may have energy
    Low ATR before a breakQuiet market conditionsPossible compression, but no direction
    High ATR into event riskRecent or expected volatilityStops and size need care
    ATR spikeSudden range expansionCheck news, gaps or one-off event
    Common ATR readings and how traders interpret them

    ATR vs Bollinger Bands

    ATR and Bollinger Bands are both used in volatility analysis, but they measure volatility differently.

    ATR measures trading range. It looks at high, low and previous close to capture the size of recent price movement, including gaps.

    Bollinger Bands use standard deviation around a moving average. They measure how dispersed price is around its average.

    That means ATR is often more directly useful for stop placement and position sizing. Bollinger Bands are often used to study price stretching away from its average, squeeze setups and mean-reversion conditions.

    Neither of them is automatically better. They answer different volatility questions.

    ToolVolatility inputCommon useMain warning
    ATRTrue RangeStops, position sizing, volatility filtersNo direction signal
    ATR%ATR divided by priceCompare volatility across marketsStill backward-looking
    Bollinger BandsStandard deviationSqueeze, stretched price, mean reversionPrice can ride the band in trends
    Keltner ChannelsATR around a moving averageTrend, breakout and pullback contextBreakouts can fail
    ATR vs Bollinger Bands and related volatility tools

    ATR is also part of many volatility-channel tools. For example, Keltner Channels usually place bands a multiple of ATR above and below a moving average. Bollinger Bands, by contrast, use standard deviation around a moving average.

    ATR Pros and Cons

    ATR is useful because it gives traders a practical volatility number. It turns recent price movement into something that can be used for stop distance, position sizing and volatility comparison.

    Its biggest strength is also its limit. ATR is based on past price ranges. It adapts to volatility after it appears; it does not know what the next candle will do.

    StrengthWhy it helps
    Measures volatility directlyShows how much the market has been moving
    Includes gapsTrue Range captures movement from the previous close
    Useful for stopsHelps avoid using fixed stops in changing volatility
    Useful for position sizingHelps scale risk when markets move more or less
    Works across timeframesCan be used on daily, intraday or weekly charts
    Main strengths of the ATR indicator
    WeaknessWhy it matters
    No direction signalATR does not say whether price should rise or fall
    Backward-lookingIt reflects recent volatility, not future volatility
    Can be too low before eventsQuiet pre-event trading can understate upcoming risk
    Can spike after the damageATR may rise after a sharp move has already happened
    Needs price contextStop placement still needs support, resistance and structure
    Main limitations of the ATR indicator

    Quick ATR Takeaways Before We Code

    • ATR stands for Average True Range.
    • ATR measures volatility, not direction.
    • True Range uses the largest of high-low, high-previous close, or low-previous close.
    • ATR smooths True Range over a chosen number of bars.
    • A rising ATR means recent ranges are expanding.
    • A falling ATR means recent ranges are contracting.
    • ATR can help with stop placement and position sizing.
    • ATR% makes volatility easier to compare across different price levels.
    • ATR can be misleading before major scheduled events because recent ranges may be quiet before the move.
    • The Python tutorial below calculates True Range, ATR and ATR%, then plots ATR below a candlestick chart.

    Now we can build ATR ourselves. The Python section below calculates True Range, applies Wilder-style ATR smoothing, adds ATR%, and plots the result under a price chart.

    Coding ATR in Python and Plotting the Chart

    Now we can build ATR in Python.

    I am going to keep this as a step-by-step tutorial rather than dropping in one large script. Each Python-labelled block goes into the same file, in order. By the end, we will have downloaded market data, calculated True Range, ATR and ATR%, and plotted them below a candlestick chart.

    For this example I use META, as in the earlier version of this article, but with a more recent date range.

    Step 1: Install the Python libraries

    This guide assumes you already have Python installed and are using Visual Studio Code.

    Open a terminal in VS Code by clicking Terminal > New Terminal, then run:

    Bash
    python -m pip install yfinance pandas mplfinance matplotlib

    On some Windows machines, this version works instead:

    Bash
    py -m pip install yfinance pandas mplfinance matplotlib

    Step 2: Create the file and import the libraries

    Create a new Python file and save it as:

    atr_indicator.py

    At the top of the file, add:

    Python
    import pandas as pd
    import yfinance as yf
    import mplfinance as mpf
    from matplotlib.lines import Line2D
    

    pandas stores the market data in a table and handles the calculations.

    yfinance downloads the price data.

    mplfinance draws the candlestick chart.

    Line2D lets us create a clean legend for the ATR and ATR% lines.

    Step 3: Add the settings

    Next, add the settings near the top of the file.

    Python
    ticker = "META"
    chart_title = "Meta Platforms"
    
    start_date = "2025-05-01"
    end_date = "2026-05-01"
    
    atr_period = 14

    ticker is the Yahoo Finance symbol.

    chart_title is the title printed on the chart.

    The dates use YYYY-MM-DD format. yfinance treats the end date as a cut-off, so you can push it one trading day later if you want the most recent available bar included.

    atr_period controls how many bars are used in the ATR smoothing calculation.

    Step 4: Download the market data

    Now download the market data.

    Python
    data = yf.download(
        ticker,
        start=start_date,
        end=end_date,
        auto_adjust=True,
        progress=False,
        multi_level_index=False
    )
    
    if data.empty:
        raise RuntimeError("No data was downloaded. Check the ticker symbol and date range.")
    
    if isinstance(data.columns, pd.MultiIndex):
        data.columns = data.columns.get_level_values(0)
    
    data.index = pd.DatetimeIndex(data.index)

    This downloads open, high, low, close and volume data.

    auto_adjust=True keeps the price series adjusted where applicable.

    progress=False removes the download progress bar.

    multi_level_index=False keeps the columns easier to work with.

    The final line makes sure the index is treated as dates, which mplfinance expects when plotting.

    Step 5: Define the True Range and ATR functions

    Now define the functions that calculate True Range, ATR and ATR%.

    Python
    def calculate_true_range(data):
        high = data["High"]
        low = data["Low"]
        close = data["Close"]
    
        high_low = high - low
        high_prev_close = (high - close.shift(1)).abs()
        low_prev_close = (low - close.shift(1)).abs()
    
        true_range = pd.concat(
            [high_low, high_prev_close, low_prev_close],
            axis=1
        ).max(axis=1)
    
        return true_range
    
    
    def calculate_atr(data, period=14):
        true_range = calculate_true_range(data)
    
        atr = pd.Series(index=true_range.index, dtype="float64")
    
        # First ATR value: simple average of the first period of True Range values
        atr.iloc[period - 1] = true_range.iloc[:period].mean()
    
        # Wilder-style smoothing
        for i in range(period, len(true_range)):
            atr.iloc[i] = ((period - 1) * atr.iloc[i - 1] + true_range.iloc[i]) / period
    
        return atr
    
    
    def calculate_atr_percent(data, atr):
        return (atr / data["Close"]) * 100

    calculate_true_range() works out the largest of the three True Range components.

    calculate_atr() applies Wilder-style smoothing to True Range.

    calculate_atr_percent() converts ATR into a percentage of the closing price, which makes it easier to compare volatility across different price levels.

    Step 6: Calculate ATR and ATR%

    Now call the functions and add the results to the data table.

    Python
    data["True Range"] = calculate_true_range(data)
    data["ATR"] = calculate_atr(data, period=atr_period)
    data["ATR%"] = calculate_atr_percent(data, data["ATR"])
    
    plot_data = data.dropna(subset=["ATR", "ATR%"])

    Think of data as a spreadsheet. It already has Open, High, Low, Close and Volume columns. This step adds True Range, ATR and ATR%.

    dropna() removes the early blank rows before plotting. Those blanks appear because the ATR calculation needs enough bars before it can produce values.

    Step 7: Define the ATR chart lines

    Next we tell mplfinance how to draw ATR and ATR% below the price chart.

    Python
    atr_plots = [
        mpf.make_addplot(
            plot_data["ATR"],
            panel=2,
            color="green",
            width=1.2,
            ylabel="ATR"
        ),
        mpf.make_addplot(
            plot_data["ATR%"],
            panel=3,
            color="red",
            width=1.0,
            ylabel="ATR%"
        )
    ]

    The green line is ATR.

    The red line is ATR%.

    They are plotted in separate panels because ATR is measured in price units, while ATR% is measured as a percentage of price.

    Step 8: Create the chart

    Now create the candlestick chart.

    Python
    fig, axes = mpf.plot(
        plot_data,
        type="candle",
        style="yahoo",
        volume=True,
        addplot=atr_plots,
        panel_ratios=(3, 1, 1.2, 1.2),
        title=f"{chart_title} with ATR ({atr_period}) and ATR%",
        figsize=(11, 8),
        returnfig=True
    )
    
    fig.subplots_adjust(
        left=0.07,
        right=0.90,
        top=0.92,
        bottom=0.16,
        hspace=0.05
    )

    type="candle" gives us the candlestick chart.

    volume=True adds the volume panel.

    addplot=atr_plots adds the ATR and ATR% lines.

    panel_ratios controls the relative size of the price, volume, ATR and ATR% panels.

    subplots_adjust gives the chart extra room so the right-hand labels and angled dates are not clipped.

    Step 9: Add the legend and show the chart

    Finally, add a legend, save the image and show the chart.

    Python
    legend_items = [
        Line2D([], [], color="green", label="ATR"),
        Line2D([], [], color="red", label="ATR%")
    ]
    
    fig.legend(
        handles=legend_items,
        loc="center left",
        bbox_to_anchor=(0.04, 0.5),
        frameon=False
    )
    
    fig.savefig("atr_indicator_chart.png", dpi=150, bbox_inches="tight")
    
    mpf.show()

    fig.legend() adds a chart legend.

    fig.savefig() saves the chart as a PNG image in the same folder as the script.

    mpf.show() opens the chart window.

    Step 10: Run the script

    Save atr_indicator.py by pressing Ctrl+S.

    The easiest route is usually to click the play button in the top-right corner of VS Code. If that works, the chart window should open.

    You can also run it from the terminal. Open Terminal > New Terminal, move into the folder where you saved the script, then run:

    Bash
    python atr_indicator.py

    On some Windows setups, use:

    Bash
    py atr_indicator.py

    Your chart should show Meta candlesticks, volume, ATR and ATR% in separate panels.

    You can double check it with something like Yahoo Finance charts using their 14 period ATR with the same dates and you’ll see our green line is identical, which is always reassuring.

    VS Code screenshot showing a Python-generated Meta candlestick chart with volume, ATR and ATR percent panels
    Meta price chart with ATR and ATR% plotted from the Python script. ATR shows volatility in price units, while ATR% normalises the reading against the current price.

    The ATR% shown in the first chart is calculated as ATR divided by the current closing price. This makes the volatility reading easier to compare across different markets and price levels. A $10 ATR means something very different on a $100 stock than on a $1,000 stock, but ATR% puts both into percentage terms.

    A Different True Range Percent Approach

    The ATR% in the first chart is calculated as:

    ATR\% = \frac{ATR}{Close} \times 100

    ATR% = ATR / current close × 100

    That version is useful because it expresses volatility as a percentage of the current price. It lets you compare ATR across different markets and price levels.

    There is another useful calculation, but I would not call it ATR%. I would call it Current True Range as a percentage of ATR.

    This asks a different question:

    How large was the latest bar’s true range compared with the recent average true range?

    If the value is near 100%, the latest true range is close to normal for the lookback period. If it is near 200%, the latest true range is roughly twice the recent ATR. If it is several hundred percent, the market may have gapped or produced an unusually large bar.

    This can be useful when you want to spot unusually large candles, earnings gaps, shock moves, or sudden volatility breaks.

    TR\%ATR_t = \frac{TR_t}{ATR_t} \times 100

    Current True Range % of ATR = current true range / ATR × 100

    In Python, if we already have a calculate_true_range() function and an ATR column, the calculation is simple:

    Python
    def calculate_true_range_percent_of_atr(data, atr):
        true_range = calculate_true_range(data)
        return (true_range / atr) * 100

    Then add the new column like this:

    Python
    data["TR % of ATR"] = calculate_true_range_percent_of_atr(data, data["ATR"])

    Use the two percent calculations for different jobs:

    CalculationFormulaWhat it tells you
    ATR% of priceATR / Close × 100Shows ATR as a percentage of price, useful for comparing volatility across markets
    Current True Range % of ATRCurrent True Range / ATR × 100Shows whether the latest bar is unusually large compared with recent volatility
    Two different percentage views of ATR and True Range

    So after plugging that into our code, the red line in the chart now shows the current bar’s True Range as a percentage of recent ATR:

    VS Code screenshot showing a Python-generated Meta candlestick chart with ATR and current True Range as a percentage of ATR
    Meta price chart with ATR and current True Range as a percentage of ATR. The lower panel highlights bars where the latest true range was unusually large compared with recent average volatility.

    This second chart uses a different calculation from normal ATR%. Instead of dividing ATR by the current closing price, it compares the current bar’s True Range with the recent ATR.

    That makes the red line a “range shock” measure. A value around 100% means the latest bar is close to normal for the lookback period. A value around 200% means the bar is roughly twice the recent ATR. Large spikes can appear around earnings gaps, surprise news, macro events or other sudden volatility breaks.

    Practical ATR Examples

    A few examples make ATR easier to understand.

    Example 1: Stop distance

    Suppose a stock is trading around $100 and its 14-period ATR is 2. That tells us the stock has recently been moving about $2 per bar on average.

    A stop 20 cents away would probably be too tight for most swing setups, because normal movement could knock it out quickly. A stop based on 1.5 or 2 times ATR would give the trade more room, although the exact stop still needs to fit the chart structure.

    Example 2: Position sizing

    Now imagine two stocks.

    Stock A has an ATR of 1.

    Stock B has an ATR of 5.

    If you buy the same number of shares in both, Stock B carries much more price movement risk. ATR can help you reduce size in the more volatile market so the trade risk is not wildly different.

    Example 3: Event risk

    ATR is based on recent price ranges. It does not know that earnings, payrolls, inflation data or a central-bank decision is coming.

    If a market has been quiet before a major event, ATR may be low. That can make ATR-based stops look sensible just before volatility expands sharply. This is one reason I would never use ATR without checking the wider calendar.

    Final Thoughts on ATR

    ATR is useful because it gives traders a practical measure of recent volatility. It does not predict direction, but it can help with stop placement, position sizing, volatility filters and comparing different markets.

    The biggest mistake is treating ATR as if it knows what will happen next. It measures recent range. It does not know about the next earnings report, central-bank decision, payrolls release or surprise headline.

    I would use ATR as a risk and volatility tool first. The trade direction still needs to come from price structure, trend analysis, momentum, fundamentals, or whatever method you are actually testing.

    Further Reading

    Wilder, J. Welles. “New Concepts in Technical Trading Systems.” Trend Research, 1978.

    For related AlphaSquawk guides, see our ATR-based Keltner Channel guide, Bollinger Bands guide, and risk-management / stop-placement articles where relevant.