Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

Local Volatility vs Implied Volatility

Local volatility vs implied volatility: one is a number per quoted option, the other a surface fitted to the whole chain. What each gets wrong, with data.

Local volatility and implied volatility are two answers to the same question: which volatility number belongs inside a pricing model. Implied volatility is one number per quoted contract, the input that makes the Black-Scholes formula return that contract's market price. Local volatility is a surface, one volatility for every pair of spot level and future date, fitted to reproduce every quoted option at once.

Local volatility vs implied volatility: the short version

Implied volatility is a translator for quotes. Black-Scholes assumes one constant volatility for the life of the option, and the market disagrees with that assumption in plain sight: different strikes and different expiries on the same underlying price out at different implied vols. Instead of discarding the formula, the market inverts it one contract at a time, and each quote ends up with its own sigma. The inversion is a root-find on a monotone function, which how implied volatility is calculated walks through step by step.

Local volatility starts from the other end. It keeps one process for the underlying and lets the instantaneous volatility depend on where spot is and what time it is, written sigma(S, t). Bruno Dupire showed in 1994 that a continuum of European call prices across strike and maturity determines that function uniquely, and gives it in closed form from one partial derivative of call price in maturity over two in strike. The reading matters more than the algebra. A complete set of vanilla prices pins down exactly one local volatility surface, and that surface returns those vanilla prices by construction.

Implied volatility is a per-contract label on the data. Local volatility is a mechanism fitted to all of it at once. Neither one is a forecast. For the inputs that set a vanilla quote in the first place, see what determines an option price.

The shape a surface has to fit

Start with the cross-section across strikes. The panel below takes every SPY option during September 2026 with a converged implied volatility and non-zero traded volume, keeps expiries 20 to 45 days out, and averages implied vol in bands of strike relative to spot.

QuerySPY implied volatility by strike distance from spot, 20 to 45 day expiries, September 2026
strike_vs_spotiv_pctcontract_count
6 to 10% below spot20.441641
3 to 6% below16.752674
1 to 3% below14.512268
at the money12.972545
1 to 3% above11.962124
3 to 6% above11.242115
6 to 10% above spot12.031188
The exact SQL behind every number
SELECT
    bucket                      AS strike_vs_spot,
    round(avg(iv) * 100, 2)     AS iv_pct,
    count()                     AS contract_count
FROM
(
    SELECT
        iv,
        m,
        multiIf(m < -0.06, '6 to 10% below spot',
                m < -0.03, '3 to 6% below',
                m < -0.01, '1 to 3% below',
                m <=  0.01, 'at the money',
                m <=  0.03, '1 to 3% above',
                m <=  0.06, '3 to 6% above',
                '6 to 10% above spot')                            AS bucket
    FROM
    (
        SELECT
            toFloat64(implied_volatility)                             AS iv,
            toFloat64(strike_price) / toFloat64(underlying_close) - 1 AS m
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date >= '2026-09-01'
          AND date <  '2026-10-01'
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry BETWEEN 20 AND 45
          AND underlying_close > 0
          AND implied_volatility > 0
    )
    WHERE abs(m) <= 0.10
)
GROUP BY bucket
HAVING count() >= 50
ORDER BY min(m)
Run this yourself

Across the 7 bands, average implied volatility ran from 20.44% in the 6 to 10% below spot band to 12.03% in the 6 to 10% above spot band. One constant volatility cannot sit on all of those points at the same time, which is the whole reason a surface exists. The tilt from low strikes to high strikes is the skew, covered on its own in volatility skew. A local vol surface calibrated to this chain has to pass through every one of these bands, and it will.

Strike is only half of it: the maturity dimension

The same chain prices options at many expiries, and the implied vol attached to a fixed moneyness moves as the expiry moves. The next panel holds moneyness in two bands, at the money and roughly 5 to 8 percent below spot, then walks out the expiry ladder over the same month.

QuerySPY at-the-money and downside implied volatility across expiry bands, September 2026
expiry_bandatm_iv_pctdownside_iv_pctskew_spread_pts
7 to 21 days12.0922.2310.14
22 to 45 days13.0218.695.67
46 to 90 days14.0218.674.65
91 to 180 days15.118.483.38
181 to 365 days16.719.132.43
The exact SQL behind every number
SELECT
    band                                                  AS expiry_band,
    round(avgIf(iv, abs(m) <= 0.01) * 100, 2)             AS atm_iv_pct,
    round(avgIf(iv, m >= -0.08 AND m <= -0.05) * 100, 2)  AS downside_iv_pct,
    round((avgIf(iv, m >= -0.08 AND m <= -0.05)
           - avgIf(iv, abs(m) <= 0.01)) * 100, 2)         AS skew_spread_pts
FROM
(
    SELECT
        iv,
        m,
        dte,
        multiIf(dte <=  21, '7 to 21 days',
                dte <=  45, '22 to 45 days',
                dte <=  90, '46 to 90 days',
                dte <= 180, '91 to 180 days',
                '181 to 365 days')                                    AS band
    FROM
    (
        SELECT
            toFloat64(implied_volatility)                             AS iv,
            toFloat64(strike_price) / toFloat64(underlying_close) - 1 AS m,
            days_to_expiry                                            AS dte
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date >= '2026-09-01'
          AND date <  '2026-10-01'
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry BETWEEN 7 AND 365
          AND underlying_close > 0
          AND implied_volatility > 0
    )
)
GROUP BY band
HAVING countIf(abs(m) <= 0.01) >= 50
   AND countIf(m >= -0.08 AND m <= -0.05) >= 50
ORDER BY min(dte)
Run this yourself

At the 7 to 21 days band, at-the-money implied vol averaged 12.09% against 22.23% for the downside band, a gap of 10.14 volatility points. At the 181 to 365 days band the two readings were 16.7% and 19.13%, a gap of 2.43 points. The downside band sits above the at-the-money band at the front of the ladder and still sits above it at the back. Hold on to that: long-dated index smiles are not flat. The level across maturities has its own guide in the IV term structure.

A calibrated surface is a snapshot

Dupire's surface is recovered from one day's quotes. The panel below tracks the same two readings week by week from the start of January 2026 through the end of September 2026.

QuerySPY at-the-money implied volatility and downside skew spread, week by week, 2026
39 rows (showing 20)
weekweek_labelatm_iv_pctskew_spread_pts
2026-01-05Jan 512.716.48
2026-01-12Jan 1213.286.35
2026-01-19Jan 1914.576.76
2026-01-26Jan 2614.036.98
2026-02-02Feb 216.046.53
2026-02-09Feb 915.997.06
2026-02-16Feb 1616.596.66
2026-02-23Feb 2316.257.22
2026-03-02Mar 218.97.57
2026-03-09Mar 921.297.03
2026-03-16Mar 1620.735.91
2026-03-23Mar 2323.466.16
2026-03-30Mar 3021.985.55
2026-04-06Apr 617.787.23
2026-04-13Apr 1315.075.46
2026-04-20Apr 20165.92
2026-04-27Apr 2715.156.12
2026-05-04May 414.985.75
2026-05-11May 1115.445.99
2026-05-18May 1814.955.96
The exact SQL behind every number
SELECT
    toString(week_start)                                 AS week,
    formatDateTime(week_start, '%b %e')                  AS week_label,
    round(avgIf(iv, abs(m) <= 0.01) * 100, 2)            AS atm_iv_pct,
    round((avgIf(iv, m >= -0.08 AND m <= -0.05)
           - avgIf(iv, abs(m) <= 0.01)) * 100, 2)        AS skew_spread_pts
FROM
(
    SELECT
        toMonday(date)                                            AS week_start,
        toFloat64(implied_volatility)                             AS iv,
        toFloat64(strike_price) / toFloat64(underlying_close) - 1  AS m
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND date >= '2026-01-05'
      AND date <  '2026-10-01'
      AND iv_converged = 1
      AND volume > 0
      AND days_to_expiry BETWEEN 20 AND 45
      AND underlying_close > 0
      AND implied_volatility > 0
)
GROUP BY week_start
HAVING countIf(abs(m) <= 0.01) >= 20
   AND countIf(m >= -0.08 AND m <= -0.05) >= 20
ORDER BY week_start
Run this yourself

Over 39 weekly observations, the at-the-money average read 12.71% in the week of Jan 5 and 13.55% in the week of Sep 28, with the downside gap finishing at 6 points. Recalibrate on Monday and the surface differs from Friday's.

That is awkward for a model whose volatility is a deterministic function of spot and clock time. In local vol, tomorrow's volatility is already settled once you know where spot goes. Volatility that wanders on its own schedule is what a second random driver is for, which is the move the Heston model makes.

Where the two models disagree: the forward smile

A calibrated local vol model reprices every option it was fitted to, inside numerical error. That is the construction, and it is also the limitation: the model adds nothing about those vanillas that their own quotes did not already say. The disagreement with other models lives in payoffs that depend on the surface the market will be quoting at some future date.

A forward-starting option fixes its strike later, at whatever spot turns out to be on a fixing date. A cliquet is a chain of them. A one-year monthly cliquet pays the sum of twelve monthly returns, each one capped and floored. Pricing it needs the smile in force one month out, two months out, eleven months out, none of which is quoted today.

Part of that is pinned by today's quotes. Forward volatility levels follow arithmetically from the term structure: total variance to twelve months, minus total variance to eleven months, leaves the variance of the twelfth month. The panel below extracts that curve from the SPY monthly expiries in the last week of September 2026.

QueryForward volatility embedded in the SPY monthly expiry curve, last week of September 2026
expiry_dateexpiry_labelspot_iv_pctforward_iv_pct
2026-11-20Nov 20, 202614.0914.76
2026-12-18Dec 18, 202614.5415.36
2027-01-15Jan 15, 202714.7515.35
2027-03-19Mar 19, 202715.7917.45
2027-09-17Sep 17, 202717.8519.61
The exact SQL behind every number
SELECT
    toString(expiration_date)                      AS expiry_date,
    formatDateTime(expiration_date, '%b %e, %Y')   AS expiry_label,
    round(iv * 100, 2)                             AS spot_iv_pct,
    round(sqrt((dte * iv * iv - prev_dte * prev_iv * prev_iv)
               / (dte - prev_dte)) * 100, 2)       AS forward_iv_pct
FROM
(
    SELECT
        expiration_date,
        iv,
        dte,
        lagInFrame(iv)  OVER (ORDER BY expiration_date) AS prev_iv,
        lagInFrame(dte) OVER (ORDER BY expiration_date) AS prev_dte
    FROM
    (
        SELECT
            expiration_date,
            avg(toFloat64(implied_volatility)) AS iv,
            avg(days_to_expiry)                AS dte
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date >= '2026-09-24'
          AND date <  '2026-10-01'
          AND iv_converged = 1
          AND volume > 0
          AND underlying_close > 0
          AND implied_volatility > 0
          AND days_to_expiry BETWEEN 10 AND 400
          AND toDayOfWeek(expiration_date) = 5
          AND toDayOfMonth(expiration_date) BETWEEN 15 AND 21
          AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.01
        GROUP BY expiration_date
        HAVING count() >= 20
    )
)
WHERE prev_dte > 0
  AND dte > prev_dte
  AND dte * iv * iv > prev_dte * prev_iv * prev_iv
ORDER BY expiration_date
Run this yourself

Spot implied vol at the Nov 20, 2026 expiry averaged 14.09%, while the forward leg ending there came out at 14.76%. At the back of the 5 expiries shown, Sep 17, 2027, the spot reading was 17.85% and the forward leg 19.61%. Any model fitted to this chain matches those levels.

The forward smile is the part that stays unpinned, and here the two families split:

  • Vanilla puts and calls in the calibration set: matched by construction under local vol, with no new information added.
  • European payoffs on the terminal distribution at a calibrated maturity: matched, since the surface fixes those marginal distributions.
  • Forward-starting payoffs such as cliquets and forward-start calls: model-dependent, and a local vol model's forward smile flattens as the fixing date moves out.
  • Barriers and autocallables: model-dependent, since they read the path and the smile at future times.

A one-year cliquet priced on the calibrated local vol surface and the same cliquet priced on a stochastic vol model fitted to identical vanillas return different premiums. The spread between them is model risk, not a quote. No vanilla in the chain can settle it, since both models fit all of them exactly.

Why stochastic local volatility exists

The industry answer is to run both at once. A stochastic local volatility model (SLV) carries a stochastic variance process of the Heston type and multiplies its volatility by a leverage function in spot and time. That leverage function is solved numerically, through the forward equation, until the model's vanilla prices land back on the market's. The exact vanilla fit survives, and the forward smile comes from the stochastic component, where it does not collapse with maturity. A mixing weight sets how much of the dynamics each side contributes, and that weight is the dial a desk marks its exotics against.

The forward smile is still not observable. SLV turns the assumption into a parameter rather than burying it inside a construction, which is the practical reason neither canonical model retired the other.

FAQ

Is local volatility the same as implied volatility?

No. Implied volatility is a single number attached to one quoted option, the volatility that makes Black-Scholes match that quote. Local volatility is a function of spot and time fitted to the entire quoted surface, and the two coincide only in the degenerate case of a perfectly flat surface.

What does Dupire's formula actually do?

It inverts a surface of European call prices into the unique instantaneous volatility function consistent with all of them. The inputs are the sensitivity of call price to maturity and the second sensitivity to strike, and the output is one surface that reprices every vanilla it was built from.

Why does a local volatility model misprice a cliquet?

A cliquet references the smile at future fixing dates. A calibrated local vol model produces forward smiles that flatten as the fixing date moves out, while index smiles observed in the market stay tilted at long maturities, as the expiry-band panel above shows.

If local volatility gets the forward smile wrong, why use it?

It is exact on vanillas by construction, and as a one-factor model it calibrates and prices quickly. Desks also keep it as the reference point for measuring how much of an exotic's value rests on a forward-dynamics assumption, and as the backbone inside stochastic local volatility.


Every panel here carries the SQL that produced it. Open one, swap the ticker or the expiry band, and ask the same question on the Strasmore terminal.

#volatility#local volatility#dupire#volatility smile#pricing models