Logo
OFFLINEPIXEL
/ pinescript-strategies / pine-script-historical-volatility

$ Pinescript Historical Volatility

Master this statistical measure of price fluctuation in TradingView's Pinescript, crucial for risk management, option pricing, and understanding market phases.

500+ Clients Helped
100% Satisfaction
Live Trading Ready
⚠️
Trading financial markets carries risk. All content (PineScript code, indicators, strategies) on this website is for educational purposes only. Past performance is not indicative of future results. By using any code or information from this site, you agree that you are solely responsible for your trading decisions. The author disclaims all liability for any losses incurred. To gain from experts experiences, You can always try our Invite Only Scripts
01

What is Historical Volatility (HV)?

Historical Volatility (HV) is a statistical measure that quantifies the degree of variation of a security's price returns over a specific past period. Unlike indicators like Average True Range (ATR) which measure average price movement, HV specifically uses standard deviation of logarithmic returns to represent volatility as a percentage. It indicates how much price has deviated from its average over time, effectively showing how "jumpy" or "calm" an asset has been.

HV is crucial for risk management, particularly in options trading (where it's compared to implied volatility), and for understanding different market phases. High HV suggests unpredictable, large price swings, while low HV suggests stable, smaller price movements.

In Pinescript, calculating and interpreting Historical Volatility allows traders and investors to adapt their strategies based on the current market's inherent risk and opportunity profile.

02

Components and Calculation

The calculation of Historical Volatility involves several statistical steps, typically annualized for consistency across different assets and timeframes:

  1. Logarithmic Returns: For each period, calculate the natural logarithm of the current closing price divided by the previous closing price. This normalizes percentage changes.
    `Log Return = math.log(close / close[1])`
  2. Standard Deviation of Log Returns: Calculate the standard deviation of these logarithmic returns over a specified `length` (e.g., 20 periods for 20 trading days).
    `StdDev_Log_Returns = ta.stdev(Log Return, length)`
  3. Annualization: To compare volatility across different assets or timeframes, the daily (or per-period) standard deviation is annualized. This involves multiplying by the square root of the number of periods in a year.
    * For daily data, typically `math.sqrt(252)` (representing 252 trading days in a year). * For weekly data, `math.sqrt(52)`. * For monthly data, `math.sqrt(12)`.
    `Annualized HV = StdDev_Log_Returns * math.sqrt(Annualization Factor)`
  4. Convert to Percentage: The result is often multiplied by 100 to express it as a percentage.
    `Historical Volatility (%) = Annualized HV * 100`
03

Basic Historical Volatility (HV) Implementation in Pinescript

pine-script@terminal
//@version=5
indicator("My Historical Volatility (HV)", overlay=false, format=format.percent) // overlay=false to plot in a separate pane

// Input for HV length (number of periods for standard deviation)
length = input.int(20, title="HV Length", minval=2) // Minval 2 needed for log return calculation

// Input for annualization factor
// 252 for daily trading days, 365 for calendar days (if using daily candles)
// 52 for weekly, 12 for monthly
annualizationFactor = input.int(252, title="Annualization Factor (e.g., 252 for daily)", minval=1)

// Calculate Logarithmic Returns
// Handle first bar case (close[1] will be NaN)
logReturn = math.log(close / close[1])

// Calculate Standard Deviation of Log Returns
// Use `fixnan` to handle the first `length-1` bars where stdev would be NaN
stdevLogReturns = ta.stdev(logReturn, length)

// Annualize the Standard Deviation
annualizedHV = stdevLogReturns * math.sqrt(annualizationFactor)

// Convert to percentage
historicalVolatility = annualizedHV * 100

// Plot the Historical Volatility line
plot(historicalVolatility, title="Historical Volatility (%)", color=color.blue, linewidth=2)

// Optional: Add moving average of HV to identify trends in volatility
hvMA = ta.sma(historicalVolatility, 20) // 20-period SMA of HV
plot(hvMA, title="HV SMA", color=color.gray, linewidth=1, style=plot.style_line)

// Highlight background when HV is significantly higher or lower than its average
bgcolor(historicalVolatility > hvMA * 1.2 ? color.new(color.red, 90) : na, title="High HV")
bgcolor(historicalVolatility < hvMA * 0.8 ? color.new(color.green, 90) : na, title="Low HV")
$ ✓ Compiled successfully
04

Percentage Volatility

Percentage Volatility

HV expresses volatility as a percentage, directly comparable across different assets, unlike ATR which is in absolute price units.

05

Practical Historical Volatility (HV) Trading Strategies

06

1. Volatility Regimes (Mean Reversion of Volatility)

pine-script@terminal
//@version=5
strategy("HV Volatility Regimes", overlay=true)

length = input.int(20, title="HV Length", minval=2)
annualizationFactor = input.int(252, title="Annualization Factor", minval=1)
hvUpperThreshold = input.float(30.0, title="High HV Threshold (%)", minval=10.0, step=1.0)
hvLowerThreshold = input.float(15.0, title="Low HV Threshold (%)", minval=5.0, step=1.0)

logReturn = math.log(close / close[1])
stdevLogReturns = ta.stdev(logReturn, length)
historicalVolatility = stdevLogReturns * math.sqrt(annualizationFactor) * 100

plot(historicalVolatility, "Historical Volatility", color.blue, display=display.pane_only)
hline(hvUpperThreshold, "High Vol Threshold", color.red, linestyle=hline.style_dashed, display=display.pane_only)
hline(hvLowerThreshold, "Low Vol Threshold", color.green, linestyle=hline.style_dashed, display=display.pane_only)

// Conditions for Volatility Expansion/Contraction
isHighHV = historicalVolatility > hvUpperThreshold
isLowHV = historicalVolatility < hvLowerThreshold

// Strategy Entry/Exit based on volatility shifts
// Example: Enter long when volatility is low and breaks out bullishly
// And short when volatility is high and reverses bearishly
maFast = ta.ema(close, 10)
maSlow = ta.ema(close, 20)

// Anticipate bullish breakout after low volatility
if (isLowHV[1] and ta.crossover(maFast, maSlow))
    strategy.entry("Long (Vol Expand)", strategy.long)

// Anticipate bearish reversal after high volatility
if (isHighHV[1] and ta.crossunder(maFast, maSlow))
    strategy.entry("Short (Vol Contract)", strategy.short)

// Basic exit logic
strategy.close("Long (Vol Expand)", when=ta.crossunder(maFast, maSlow))
strategy.close("Short (Vol Contract)", when=ta.crossover(maFast, maSlow))
$ ✓ Compiled successfully
07

2. Options Trading (Implied Volatility vs. Historical Volatility)

pine-script@terminal
//@version=5
indicator("HV for Options Context", overlay=false, format=format.percent)

length = input.int(20, title="HV Length", minval=2)
annualizationFactor = input.int(252, title="Annualization Factor", minval=1)

logReturn = math.log(close / close[1])
stdevLogReturns = ta.stdev(logReturn, length)
historicalVolatility = stdevLogReturns * math.sqrt(annualizationFactor) * 100

plot(historicalVolatility, "Historical Volatility (%)", color=color.blue, linewidth=2)

// To compare with Implied Volatility (IV), you would need to input IV manually or via external data.
// For demonstration, let's assume a hypothetical IV input.
// Note: This 'impliedVol' input is purely for illustration; real IV comes from option chain data.
impliedVol = input.float(na, title="Implied Volatility (%) (Manual Input for Demo)", group="Options Context")

// Plot the hypothetical Implied Volatility for visual comparison
plot(not na(impliedVol) ? impliedVol : na, "Implied Volatility", color=color.orange, linewidth=2)

// Determine if options are relatively expensive or cheap based on IV vs HV
areOptionsExpensive = historicalVolatility > 0 and impliedVol > historicalVolatility * 1.2 // IV is 20% higher than HV
areOptionsCheap = historicalVolatility > 0 and impliedVol < historicalVolatility * 0.8 // IV is 20% lower than HV

bgcolor(areOptionsExpensive ? color.new(color.red, 90) : na, title="Options Potentially Expensive")
bgcolor(areOptionsCheap ? color.new(color.green, 90) : na, title="Options Potentially Cheap")

alertcondition(areOptionsExpensive, "Options Expensive", "Implied Volatility is high relative to Historical Volatility.")
alertcondition(areOptionsCheap, "Options Cheap", "Implied Volatility is low relative to Historical Volatility.")
$ ✓ Compiled successfully
08

3. Dynamic Stop Loss & Position Sizing

pine-script@terminal
//@version=5
strategy("HV Dynamic Risk Management", overlay=true)

length = input.int(20, title="HV Length", minval=2)
annualizationFactor = input.int(252, title="Annualization Factor", minval=1)
hvStopLossMultiplier = input.float(1.5, title="HV Stop Loss Multiplier", minval=0.1, step=0.1) // e.g., 1.5x HV
accountRiskPerTrade = input.float(1000.0, title="Max $ Risk Per Trade", minval=10)

logReturn = math.log(close / close[1])
stdevLogReturns = ta.stdev(logReturn, length)
historicalVolatility = stdevLogReturns * math.sqrt(annualizationFactor) // Not converting to % for calculation

// Simple entry: crossing a 20-period SMA
maLength = input.int(20, "Entry MA Length", minval=1)
maValue = ta.sma(close, maLength)

longCondition = ta.crossover(close, maValue)
shortCondition = ta.crossunder(close, maValue)

// Calculate dynamic stop loss
// Ensure historicalVolatility is not zero to prevent division by zero
longStopLossPercentage = historicalVolatility * hvStopLossMultiplier
shortStopLossPercentage = historicalVolatility * hvStopLossMultiplier

longStopPrice = strategy.position_avg_price * (1 - longStopLossPercentage)
shortStopPrice = strategy.position_avg_price * (1 + shortStopLossPercentage)

// Calculate dynamic position size
// Risk_per_share = Entry Price * HV * Multiplier
// Qty = Account Risk / Risk_per_share
qtyToTrade = 0
if (historicalVolatility > 0)
    riskPerShare = close * historicalVolatility * hvStopLossMultiplier
    qtyToTrade := math.floor(accountRiskPerTrade / riskPerShare)
    qtyToTrade := math.max(1, qtyToTrade) // Ensure at least 1 share

if (longCondition)
    strategy.entry("Long HV", strategy.long, qty=qtyToTrade)

if (shortCondition)
    strategy.entry("Short HV", strategy.short, qty=qtyToTrade)

// Apply dynamic stop losses
strategy.exit("Long Exit", from_entry="Long HV", stop=longStopPrice)
strategy.exit("Short Exit", from_entry="Short HV", stop=shortStopPrice)

plot(historicalVolatility * 100, "HV %", color=color.purple, display=display.pane_only) // Plot as percentage for viewing
plot(strategy.position_avg_price > 0 ? longStopPrice : na, "Long Stop", color=color.red, style=plot.style_linebr)
plot(strategy.position_avg_price < 0 ? shortStopPrice : na, "Short Stop", color=color.green, style=plot.style_linebr)
$ ✓ Compiled successfully
09

Optimizing Historical Volatility Performance

To get the most from Historical Volatility in Pinescript:

  • Parameter Tuning:
    • `Length`: The period for calculating standard deviation. Common values are 20 (for daily charts, representing a month) or 252 (for annual volatility). Shorter lengths are more reactive to recent price swings, longer lengths provide a smoother, broader view.
    • `Annualization Factor`: Crucial for consistency. Ensure it matches your chart's timeframe (e.g., 252 for daily, 52 for weekly).
  • Combine with Directional Indicators: HV tells you *how much* prices are moving, not *where*. Always combine it with trend-following or momentum indicators (e.g., moving averages, MACD, ADX) to confirm the direction of the market before acting on HV signals.
  • Contextual Interpretation: HV levels are relative to the asset. What's "high" volatility for a stable large-cap stock might be "low" for a highly speculative cryptocurrency. Analyze historical HV ranges for the specific asset.
  • Volatility Spikes and Contractions: The cyclical nature of volatility (expansion followed by contraction, and vice-versa) is a powerful concept. Look for HV reaching historical extremes as potential turning points for volatility itself, which can precede price reversals or strong breakouts.
  • Options Trading Integration (External): For serious options trading, compare HV with implied volatility data from an options provider. HV helps determine if current market prices for options are cheap or expensive.
10

Volatility as a Cycle

Volatility as a Cycle

Markets often alternate between periods of low volatility (sideways, accumulation) and high volatility (trending, distribution). HV helps you understand where you are in this cycle.

11

Common Historical Volatility Pitfalls

  • Not a Directional Signal: The most critical mistake is using HV to predict future price direction. It measures past price *movement*, not future direction.
  • Lagging Indicator: HV is based on past data and calculations, making it a lagging indicator. It reflects what has *already happened*.
  • Sensitivity to Outliers: Extreme price swings (e.g., flash crashes, news events) can cause temporary spikes in HV that might not be representative of the underlying volatility regime.
  • Parameter Dependency: The HV value can change significantly depending on the `length` and `annualizationFactor` chosen, requiring careful selection and consistency.
  • Not a Standalone Indicator: HV is a powerful analytical tool but should always be part of a comprehensive trading system that includes trend analysis, risk management, and confirmation from other indicators.
12

Conclusion

Conclusion

Historical Volatility (HV) is a fundamental statistical measure in Pinescript for TradingView, providing a quantifiable understanding of an asset's price variability. By measuring the annualized standard deviation of logarithmic returns, it offers valuable insights into market behavior, aiding in crucial aspects like risk management, position sizing, and adapting strategies to changing volatility regimes. While it does not predict price direction, its ability to signal periods of volatility expansion (preceding breakouts) or contraction (preceding reversals/consolidation) is invaluable. By understanding its calculation, thoughtfully tuning its parameters, and integrating it strategically with directional indicators and robust risk management practices, you can leverage Historical Volatility to enhance your trading decisions and navigate various market environments with greater precision.

Enhance Your Trading

Get a high-performance Pinescript 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.

Get Pinescript Strategy