Indicators··7 min read

Time-of-Day Average Volatility Curve

0 references, link-verified · inline [n] markersEditor of record: Shane CantyStandards review editorial standard · audit log

This indicator tracks and displays the average volatility for each hour of the trading day, revealing intraday volatility patterns. Day traders and scalpers use volatility curves to identify when price ranges historically expand and contract, allowing them to adjust position sizing and risk management to match expected market activity at each time of day. The indicator accumulates volatility data (measured via ATR or standard deviation) across multiple bars within each hour and averages it over the session, producing a rolling profile of volatility behavior across the 24-hour clock.

//@version=6
indicator("Time-of-Day Volatility Curve", overlay=false)

// ===== INPUTS =====
atrLen = input(14, "ATR Length", minval=1)
volMethod = input.string("ATR", "Volatility Method", options=["ATR", "StdDev"])
showBand = input(true, "Show High/Low Band")
bandAlpha = input(40, "Band Transparency", minval=0, maxval=100)

// ===== VOLATILITY CALCULATION =====
atr = ta.atr(atrLen)
stddev = ta.stdev(close, atrLen)
vol = volMethod == "ATR" ? atr : stddev

h = hour

// ===== PERSISTENT HOUR-OF-DAY TRACKING =====
// Sum and count of volatility for each hour (0-23)
var hourlySum = array.new<float>(24, 0.0)
var hourlyCount = array.new<int>(24, 0)
var hourlyHigh = array.new<float>(24, 0.0)
var hourlyLow = array.new<float>(24, na)

// Update current hour with new volatility value
currSum = hourlySum.get(h)
currCount = hourlyCount.get(h)
hourlySum.set(h, currSum + vol)
hourlyCount.set(h, currCount + 1)

// Track high and low for each hour
currHigh = hourlyHigh.get(h)
hourlyHigh.set(h, math.max(currHigh, vol))

currLow = hourlyLow.get(h)
if na(currLow)
    hourlyLow.set(h, vol)
else
    hourlyLow.set(h, math.min(currLow, vol))

// ===== CALCULATE AVERAGES =====
// Average volatility for the current hour
h_count = hourlyCount.get(h)
hourAvg = h_count > 0 ? hourlySum.get(h) / h_count : na

// Daily average across all 24 hours
totalSum = 0.0
totalCount = 0
for i = 0 to 23
    totalSum += hourlySum.get(i)
    totalCount += hourlyCount.get(i)

dailyAvg = totalCount > 0 ? totalSum / totalCount : na

// ===== PLOT MAIN CURVE =====
plot(hourAvg, "Hour Average Volatility", color=color.new(color.blue, 0), linewidth=2)
plot(dailyAvg, "Daily Average", color=color.new(color.gray, 50), linewidth=1, linestyle=linestyle.dashed)

// ===== PLOT OPTIONAL BAND =====
if showBand
    h_high = hourlyHigh.get(h)
    h_low = hourlyLow.get(h)
    plot(h_high, "Hour High", color=color.new(color.green, bandAlpha), linewidth=1)
    plot(h_low, "Hour Low", color=color.new(color.red, bandAlpha), linewidth=1)

// ===== INFO LABEL =====
var label infoLabel = na
label.delete(infoLabel)
hourStr = str.format("{0:00d}:00", h)
infoLabel := label.new(
    bar_index,
    hourAvg,
    str.format("{0} - Avg: {1}", hourStr, str.tostring(hourAvg, "0.00")),
    yloc=yloc.price,
    bgcolor=color.new(color.blue, 80),
    textcolor=color.white,
    size=size.small
)

How the code works

The indicator maintains two persistent arrays for each of the 24 hours of the day: hourlySum stores the cumulative volatility within each hour, and hourlyCount tracks how many bars have occurred in that hour. On each new bar, the code identifies the current hour using the hour function, then adds the current bar's volatility (measured as ATR or standard deviation, selectable via input) to that hour's running total and increments the count.

To obtain the average volatility for the current hour, the code divides that hour's cumulative sum by the number of bars seen so far. The daily average is calculated by summing all 24 hourly totals and dividing by the total bar count across the entire day. Optional high and low tracks are maintained to show the range of volatility within each hour, providing context for how consistent (or volatile) the volatility itself is at that time.

The main plot displays the current hour's average volatility as a blue line, updated on every bar. A dashed gray line shows the daily average for reference, allowing traders to see immediately whether the current hour's typical volatility is above or below the day's mean. Labels update in real time to show the hour and its average value.

Reading it on the chart

Look for the blue line (hour average) rising and falling across the trading session. Peaks in the curve correspond to times when price historically moves with greater range; valleys show times of typically lower activity. The dashed gray line marks the daily norm; when the blue line is above it, that hour has been more volatile than average. When below, it has been calmer.

Over multiple trading days, a pattern emerges: many markets see heightened volatility at the open, a period of consolidation mid-session, and a second spike near the close. Currency markets and equities often show similar patterns, though the exact shape depends on the specific instrument and session (US equities, for example, show distinct morning and afternoon volatility regimes).

Day traders and scalpers use this curve to decide when to increase position size (peak volatility hours) or reduce it (quiet periods). A trader might also use the high and low band to identify when volatility is unusually compressed or extended, signaling potential breakout or mean-reversion setups. Note that the curve improves in accuracy as more days accumulate in the indicator's arrays; initial readings after a chart load or after noon on a new day may be sparse.

Limitations

The indicator measures historical volatility averaged over whatever period the indicator has been active on the chart. It does not reset daily by default; it accumulates all data ever computed, meaning the curve includes data from different calendar dates, seasons, and market conditions. For equity markets, the same 2 PM hour might be marked as high-volatility even if earnings season has passed. To produce meaningful curves specific to a particular market regime (low-volatility summer, post-inflation spike, etc.), the chart must be loaded fresh or the input arrays manually reset.

The indicator does not account for gaps outside trading hours; it groups bars by the hour value in the ticker's native time zone, which may not align with the trader's local time or the session definition (e.g., overnight futures trading in Asia). Forex pairs traded around the clock will show volatility distributed across all 24 hours, while equity indices might show activity only in their regular session windows, leaving the off-hours slots empty.

ATR is a lagging volatility estimator; a sudden market shock will not register on the curve until after it has occurred. The indicator is therefore useful for typical, recurring patterns but will not warn of anomalies. Finally, because the indicator persists data via var arrays, changing the ATR length or volatility method during a session will not retroactively recompute prior bars; it recalculates only from the point of the change forward.

Key definitions

ATR (Average True Range): A volatility measure that averages the "true range" (the greatest of current high/low distance, high/previous close, or low/previous close) over a specified number of periods; commonly set to 14 bars. [1]

Hour of Day: The calendar hour in which a bar closes, ranging from 0 (midnight) to 23 (11 PM), determined by the chart's time zone setting. [2]

Standard Deviation: A statistical measure of how far price deviates from its mean; used as an alternative volatility estimator when price action is non-trending.

Intraday Volatility Curve: A profile showing how average volatility varies across the hours of the trading session, revealing recurring patterns of high and low activity.

Persistence Array: A variable declared with var in Pine Script that retains its value across bars, allowing data to accumulate over time without reset.

References

  • Wilder, J. Welles, "New Concepts in Technical Trading Systems," Trend Research Ltd (1978). [foundational ATR definition] [1]

  • TradingView, "Pine Script Reference Manual: hour()," TradingView Documentation (2025). Https://www.tradingview.com/pine-script-reference/ [2]

  • Investopedia, "Intraday Trading: Definition and Best Practices," Investopedia (2024). [describes intraday volatility patterns in equities and forex]

  • CME Group, "Crude Oil Futures Contract Specifications," CME Group (2025). Https://www.cmegroup.com/markets/energy/crude-oil/wti.contractSpecs.html [reference for energy market session definitions]

  • Hull, John C., "Options, Futures, and Other Derivatives," Pearson (10th ed., 2018). [standard volatility measurement theory]

  • Federal Reserve Economic Data (FRED), "VIX Index," St. Louis Federal Reserve (2025). Https://fred.stlouisfed.org/series/VIXCLS [example of official volatility indexing methodology]


Educational research on historical data only. Not investment advice, not a signal, and never a performance promise. Past results do not predict future performance. Every reference is link-verified before publication and every paper is re-audited weekly against the library's editorial standard.

Last reviewed by the PropLedger research pipeline: 2026-10-11. Educational research on historical data, not financial advice.

Educational research on historical data only. Not investment advice, not a signal, and never a performance promise. Past results do not predict future performance. Every reference is link-verified before publication and every paper is re-audited weekly against the library's editorial standard. Found an error? Email support@prop-ledger.org and the paper is corrected or withdrawn.