Back to blog
methodology

How to chart realized vs implied volatility

16 October 2026 5 min read

Quick answer

To chart realized vs implied volatility, plot the VIX against the annualized volatility of S&P 500 daily log returns over the next 21 trading days, so each VIX reading is compared with the period it forecast. The gap is the volatility risk premium. From 2016 to 2026 it averaged 3.6 points, but using trailing instead of forward realized volatility gets its sign wrong on about 24% of days.

To chart realized vs implied volatility, plot the VIX against the annualized volatility of S&P 500 daily log returns over 21 trading days, then shift the realized line back so each VIX reading sits next to the 21 days it was forecasting. The gap between the two lines is the volatility risk premium. From November 2016 to September 2026 the VIX averaged 18.69 and realized volatility 15.05, a gap of 3.6 points, and the VIX came in above the volatility that actually followed on 84% of days.

Most charts of this kind skip the shift. They compare today's VIX with the last month's realized volatility, which measures something different, and on almost a quarter of days it gets the sign of the premium wrong.

What the two lines measure

The VIX is a market-implied, annualized estimate of S&P 500 volatility over the next 30 calendar days, built by Cboe from index option prices using the variance-swap formula. You do not calculate it; you download it.

Realized volatility is what the index actually did. Take daily log returns, ln(close today / close yesterday), and annualize their volatility with the square root of 252 trading days. A daily volatility of 1% becomes 15.87% a year. Thirty calendar days is about 21 trading days, so 21 is the usual window. It is an approximation, and worth stating in the caption.

There is one choice to make: whether to subtract the mean return before squaring. A sample standard deviation subtracts it. A variance swap, which is what the VIX formula prices, pays on squared returns without subtracting it. Over a 21-day window the difference is small (on the window ending 15 October 2026 it was 10.00% without the mean against 10.06% with it), but pick one and label it. We use the variance-swap form below to match how the VIX is built.

Why the alignment decides the answer

The VIX on a given day is a forecast. The realized volatility that tests it is the next 21 trading days, which you only know a month later. A trailing 21-day realized line is the month that already happened.

Over a long sample the two versions agree on average. From November 2016 to September 2026 the mean premium was 3.64 points measured against trailing volatility and 3.63 against forward volatility. That is why the shortcut looks harmless. Day to day, though, the two versions disagree on whether implied volatility was above or below realized on 23.6% of the 2,471 days in the sample. Three dates from that sample show how:

  • 21 February 2020: VIX 17.08, trailing realized 13.26. The trailing chart says options were rich by 3.8 points. The next 21 trading days realized 88.05.
  • 8 April 2025: VIX 52.33, trailing realized 31.83, forward realized 39.13. Both say implied was above realized, but the trailing gap (20.5 points) is half again as large as the real one (13.2).
  • 21 April 2025: VIX 33.82, trailing realized 47.01. The trailing chart says options were cheap by 13.2 points. The next 21 trading days realized 18.81, so the VIX was 15.0 points above what followed.

Each of those is the same pattern: trailing volatility reflects the shock that has just passed, while the VIX is pricing the month ahead. Around turning points those are opposite things.

How to build the chart

Get two daily series. The VIX closing values are published by Cboe and mirrored on FRED as VIXCLS. For the index, FRED's SP500 series carries the daily S&P 500 close. Use the index rather than an ETF so you are measuring the same thing the options are written on.

Join them on date, compute daily log returns, and for each date calculate realized volatility over the next 21 returns. Then plot:

  • Top panel: VIX and forward realized volatility on one axis, in annualized percent.
  • Bottom panel: the spread, VIX minus forward realized, as bars or a filled area, colored by sign.

The last 21 trading days of the forward line cannot exist yet. Leave that stretch blank, or draw the trailing line there in a different style and say so. As of 14 October 2026 the VIX closed at 16.87 and trailing 21-day realized volatility was 10.06%, a gap of about 6.8 points. Whether that was the real premium will not be known until the 21st trading day after it, 12 November.

import math

def realized_vol(log_returns):
    """Annualized realized vol in percent, variance-swap style (no mean subtracted)."""
    n = len(log_returns)
    return math.sqrt(sum(r * r for r in log_returns) / n * 252) * 100

def vix_vs_realized(dates, closes, vix, window=21):
    """dates/closes: S&P 500 index closes, oldest first. vix: {date: VIX close}.
    Returns rows of (date, VIX, trailing RV, forward RV)."""
    r = [math.log(closes[i] / closes[i - 1]) for i in range(1, len(closes))]
    rows = []
    for i, d in enumerate(dates):
        if d not in vix:
            continue
        # r[i - 1] is the return into dates[i]
        trailing = realized_vol(r[i - window:i]) if i >= window else None
        forward = realized_vol(r[i:i + window]) if i + window <= len(r) else None
        rows.append((d, vix[d], trailing, forward))
    return rows

Feed it the full history in one go rather than a recent slice, so every forward window is complete where it should be and empty where it should be.

Mistakes that distort the gap

  • Mixing units. The VIX is already annualized and in percent. Realized volatility must be annualized with the square root of 252 and multiplied by 100 before the two share an axis.
  • Annualizing with 365. The returns are trading-day returns, so the factor is 252.
  • Averaging the two lines first and differencing after. Compute the spread per day, then smooth it if you need to.
  • Calling the gap a profit. A positive premium means implied volatility exceeded what followed. It does not mean a short-volatility trade made that much; the losses in early 2020 came from days like 21 February, when the premium turned out to be deeply negative.

The VIX is a 30-day point on a curve. For the full shape across expiries, see how to chart implied volatility term structure, and for where today's implied level sits in its own history, IV rank and IV percentile. The same forecast-versus-outcome test applies to single stocks around earnings, which the earnings expected move post covers.

Where Quadesto fits

Quadesto charts series like the VIX and the S&P 500 from connected sources such as FRED, and the method above is the part to get right in any tool: forward-align the realized line, keep the units annualized, and leave the unknown month blank. You can start free.

Ready to try Quadesto?

Connect your data. AI builds the charts. Embed anywhere.

Get Started Free
realized volatilityimplied volatilityvixvolatility risk premiumpython