Skip to content

Technical indicators

Historical Volatility (HV)

Realised volatility, on the same yearly scale as option prices quote it.

Historical Volatility takes the standard deviation of the bar-to-bar returns over a window and scales it up to a year, so 10 means price has been moving as if it would vary by about 10% over a year. Unlike the standard deviation of closes, it measures the size of moves, not how far price wandered, so it compares across instruments and timeframes.

High values mean wide swings and low values a quiet market. Volatility tends to cluster and then return to its own average, so a very low reading often comes before a breakout, and a spike tends to fade. Option traders compare it with implied volatility.

return = ln(CLOSE / previous CLOSE)
HV = 100 × sample standard deviation of the last `periods` returns × √(bars per year)

For bars of a day or shorter, bars per year is tradingDaysPerYear times the bars in a day. For longer bars it is the calendar year, so weekly bars count 52. Use 252 trading days for FX and stocks, which close at weekends, and 365 for crypto, which trades every day. The standard deviation divides by periods − 1, the textbook estimator, so it reads slightly higher than one that divides by periods.

Call: historicalVolatility(periods, tradingDaysPerYear)

Setting Chart default
periods: Periods 20
tradingDaysPerYear: Trading Days Per Year 252

What you get: a number.

Warm-up: with historicalVolatility(20, 252), it asks for 0 bars of history and a run-up of 21, and its first value came on bar 21 of the example data.

Historical Volatility drawn by its own code on example prices

The prices are made up, hourly, and the same on every page, so the chart shows how the indicator behaves, not how a market behaved.

function onIntervalClose() {
const hv = historicalVolatility(20, 252);
const average = sma(20);
// Trade only once the market is moving
if (hv !== null && average !== null && hv > 8 && CLOSE > average && OPEN_POSITIONS_COUNT === 0) {
openPosition("BUY", { quantity: 10000, stopLossPips: 30 });
}
}