Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

Heston Model and the Volatility Smile

A single volatility number cannot price a whole option chain. See how the Heston model lets variance wander, and what each parameter does to the smile.

The Heston model is an option pricing model that treats volatility as random rather than fixed. It carries two moving parts: the stock price, and the variance of that price, each with its own random shock. That second source of randomness is what lets a model produce a volatility smile at all. One constant volatility, the assumption inside Black-Scholes, can only draw a flat line across strikes, and no option chain has ever been flat.

Why one volatility number cannot fit an option chain

Implied volatility is the volatility input that makes a pricing formula return the price an option actually trades at. Invert it contract by contract, as our page on how implied volatility is calculated walks through, and one expiry gives back a curve across strikes rather than a level. The panel below takes every SPY contract with 20 to 45 days left to run over the first half of 2026, sorts them into 2% bands by the distance from strike to spot, and averages implied volatility inside each band.

QuerySPY implied volatility by strike distance, 20 to 45 days to expiry (Jan to Jun 2026)
The exact SQL behind every number
WITH
    (
        SELECT avg(implied_volatility)
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date BETWEEN '2026-01-02' AND '2026-06-30'
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry BETWEEN 20 AND 45
          AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.01
    ) AS atm_iv
SELECT
    concat(if(m_bucket > 0, '+', ''), toString(m_bucket), '%') AS moneyness,
    round(avg(iv) * 100, 2)                                    AS iv_pct,
    round((avg(iv) - atm_iv) * 100, 2)                          AS iv_vs_atm_pts,
    count()                                                     AS contracts
FROM
(
    SELECT
        implied_volatility AS iv,
        toInt16(round((toFloat64(strike_price) / toFloat64(underlying_close) - 1) * 50) * 2) AS m_bucket
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND date BETWEEN '2026-01-02' AND '2026-06-30'
      AND iv_converged = 1
      AND volume > 0
      AND days_to_expiry BETWEEN 20 AND 45
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.12
)
GROUP BY m_bucket
HAVING count() >= 100
ORDER BY m_bucket
Run this yourself

The -12% band, strikes far below spot, averaged 28.05% implied volatility, 11.61 volatility points above the at-the-money average for the same window. The +12% band on the call side averaged 15.56%. The bands in between trace the curve the effect is named for, and its sideways lean is volatility skew. A model with a single volatility parameter has no dial that reaches any of this: every strike prices off one distribution for the price at expiry, and inverting that model returns the same number at every strike, by construction.

What the Heston model changes

Heston keeps the stock's random shock and adds a second process for the variance. In words rather than symbols:

  • The stock's move over the next instant is a drift plus a random shock, scaled by the square root of current variance.
  • The variance's move is a pull toward a long-run level at a fixed speed, plus its own shock, scaled by a vol-of-vol parameter and the square root of current variance.
  • The two shocks are correlated, by a number between -1 and 1.

That square-root scaling is the Cox-Ingersoll-Ross form, and it does one job worth knowing: the variance shock shrinks toward nothing as variance approaches zero, which keeps variance from turning negative. When twice the speed times the long-run variance exceeds the square of the vol-of-vol, a condition named for Feller, variance stays strictly positive.

Variance itself is not observable. Its implied counterpart is, and it does not sit still. The panel below plots at-the-money implied volatility for two names, one reading per session, across the second quarter of 2026.

QueryDaily at-the-money implied volatility, SPY and NVDA (Apr to Jun 2026)
The exact SQL behind every number
SELECT
    toString(date)                                                        AS session_date,
    round(avgIf(implied_volatility, underlying_symbol = 'SPY') * 100, 2)  AS spy_atm_iv_pct,
    round(avgIf(implied_volatility, underlying_symbol = 'NVDA') * 100, 2) AS nvda_atm_iv_pct
FROM global_markets.options_greeks
WHERE underlying_symbol IN ('SPY', 'NVDA')
  AND date BETWEEN '2026-04-01' AND '2026-06-30'
  AND iv_converged = 1
  AND volume > 0
  AND days_to_expiry BETWEEN 20 AND 45
  AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.05
GROUP BY date
HAVING countIf(underlying_symbol = 'SPY') > 0
   AND countIf(underlying_symbol = 'NVDA') > 0
ORDER BY date
Run this yourself

SPY opened the window at 20.39% on 2026-04-01 and closed it at 14.45% on 2026-06-30. NVDA ran from 36.83% to 38.22% across the same 62 sessions. Neither line holds still, and neither runs away: both wander and keep returning to a neighbourhood. Pricing both ends of that picture takes a starting level plus a long-run level with a speed for the pull between them.

What each Heston parameter does to the surface

Mean reversion and the long-run level shape the term structure

An option's value depends on the average variance expected over its life, not on the variance today. For a contract expiring next week, today's variance dominates that average; for one expiring in a year, the long-run level dominates. The speed parameter sets how fast the expectation travels between them, which fixes how steeply implied volatility slopes from the front of the calendar to the back.

QueryNear-the-money implied volatility by time to expiry (Jan to Jun 2026)
The exact SQL behind every number
SELECT
    tenor,
    round(avgIf(implied_volatility, underlying_symbol = 'SPY') * 100, 2)  AS spy_iv_pct,
    round(avgIf(implied_volatility, underlying_symbol = 'NVDA') * 100, 2) AS nvda_iv_pct
FROM
(
    SELECT
        implied_volatility,
        underlying_symbol,
        days_to_expiry,
        multiIf(
            days_to_expiry <= 7,   '1 to 7 days',
            days_to_expiry <= 21,  '8 to 21 days',
            days_to_expiry <= 45,  '22 to 45 days',
            days_to_expiry <= 90,  '46 to 90 days',
            days_to_expiry <= 180, '91 to 180 days',
                                   '181 to 365 days') AS tenor
    FROM global_markets.options_greeks
    WHERE underlying_symbol IN ('SPY', 'NVDA')
      AND date BETWEEN '2026-01-02' AND '2026-06-30'
      AND iv_converged = 1
      AND volume > 0
      AND days_to_expiry BETWEEN 1 AND 365
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.02
)
GROUP BY tenor
HAVING countIf(underlying_symbol = 'SPY') > 0
   AND countIf(underlying_symbol = 'NVDA') > 0
ORDER BY min(days_to_expiry)
Run this yourself

Near-the-money SPY contracts in the 1 to 7 days bucket averaged 17.05% over the first half of 2026, against 18.77% in the 181 to 365 days bucket. NVDA printed 41.22% and 44.94% across the same two buckets. A one-number model prices every tenor off the same volatility. Heston gives the front and the back their own levels, with the speed parameter governing the shape between. More of these curves sit on our IV term structure page.

Vol of vol bends the smile

Vol of vol is the volatility of the variance itself. Set it to zero and variance follows a smooth path: the term structure can still slope, but the smile across strikes goes flat. Turn it up and the distribution of the price at expiry gains weight in both tails, which lifts strikes far from spot above strikes near it. How far variance travels in practice differs by underlying, and the panel below measures that travel directly.

QueryHow far at-the-money implied volatility itself travelled (Jan to Jun 2026)
The exact SQL behind every number
SELECT
    symbol,
    round(min(daily_iv) * 100, 2)                   AS low_iv_pct,
    round(max(daily_iv) * 100, 2)                   AS high_iv_pct,
    round((max(daily_iv) - min(daily_iv)) * 100, 2) AS swing_pts
FROM
(
    SELECT
        underlying_symbol      AS symbol,
        date,
        avg(implied_volatility) AS daily_iv
    FROM global_markets.options_greeks
    WHERE underlying_symbol IN ('SPY', 'AAPL', 'MSFT', 'NVDA', 'AMZN', 'KO')
      AND date BETWEEN '2026-01-02' AND '2026-06-30'
      AND iv_converged = 1
      AND volume > 0
      AND days_to_expiry BETWEEN 20 AND 45
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.05
    GROUP BY symbol, date
)
GROUP BY symbol
ORDER BY swing_pts DESC
Run this yourself

AMZN covered the widest range in the panel: at-the-money implied volatility as low as 28.21% and as high as 74.42%, 46.22 volatility points apart over six months. KO covered the narrowest, at 10.75 points. Vega, the price sensitivity to volatility that our vega page defines, measures the level of the surface. Under stochastic volatility, two contracts with matching vega can behave differently when the shape moves instead of the level.

Correlation tilts the smile into a skew

The correlation between the stock's shock and the variance's shock turns a symmetric smile into a lopsided one. Under a negative correlation, paths where the stock falls are paths where variance rises, and the left tail of the distribution at expiry carries more weight than the right. Put-side implied volatility then prices above call-side implied volatility at the same distance from spot.

QueryPut-side versus call-side implied volatility, 20 to 45 days (Jan to Jun 2026)
The exact SQL behind every number
SELECT
    underlying_symbol                                                    AS symbol,
    round(avgIf(iv, ratio <= 0.95) * 100, 2)                             AS otm_put_iv_pct,
    round(avgIf(iv, ratio >= 1.05) * 100, 2)                             AS otm_call_iv_pct,
    round((avgIf(iv, ratio <= 0.95) - avgIf(iv, ratio >= 1.05)) * 100, 2) AS put_minus_call_pts
FROM
(
    SELECT
        underlying_symbol,
        implied_volatility                                    AS iv,
        toFloat64(strike_price) / toFloat64(underlying_close) AS ratio
    FROM global_markets.options_greeks
    WHERE underlying_symbol IN ('SPY', 'AAPL', 'MSFT', 'NVDA', 'AMZN', 'KO')
      AND date BETWEEN '2026-01-02' AND '2026-06-30'
      AND iv_converged = 1
      AND volume > 0
      AND days_to_expiry BETWEEN 20 AND 45
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.20
)
GROUP BY underlying_symbol
HAVING countIf(ratio <= 0.95) > 0
   AND countIf(ratio >= 1.05) > 0
ORDER BY put_minus_call_pts DESC
Run this yourself

Over the first half of 2026, SPY showed the widest gap in the panel: contracts struck at least 5% below spot averaged 27% against 14.76% for contracts struck at least 5% above, 12.23 volatility points apart. At the other end, MSFT printed 3.9 points on the same measurement. One correlation parameter per underlying is what covers that whole range of tilts.

Starting variance sets the level

The fifth parameter is the variance the model starts from today. It lifts or drops the whole surface without much changing its shape, which is why it gets refitted most often: it keeps the model on the market's current level while the other four carry the geometry.

What the model buys, and what it costs

The purchase is a surface that bends in two directions from five interpretable numbers, priced quickly. Heston values European options through a characteristic function and one numerical integral, with no simulation required, which makes fitting a whole chain in a fraction of a second practical. The costs are worth stating plainly.

  • The five parameters are calibrated, fitted to observed option prices rather than measured from anything.
  • A calibration is a snapshot. Refit tomorrow and the numbers move, which means the model's constants are not constant.
  • One parameter set rarely fits every expiry at once. Observed smiles at the very short end bend more sharply than this variance process can bend.
  • Prices in the market gap. Variance and spot both move continuously here, and a gap has to be absorbed by the fitted numbers.

One caveat matters for readers arriving from the volatility pages. The variance process describes the dynamics that price options, which is a different object from the volatility a stock goes on to realise. The distance between the two is the subject of implied volatility versus realised volatility.

Where the model still misses

Extensions exist for each gap. Bates keeps Heston's variance and adds jumps to the price process, which steepens the short-dated smile. Rough volatility models keep random variance and swap the driver for paths rougher than standard Brownian motion, matching the very short end more closely. Neither removes the calibration problem: both add parameters that have to be fitted to a moment and refitted afterwards.

FAQ

What is the Heston model in simple terms?

It is an option pricing model in which volatility is random. Variance follows its own path with a pull toward a long-run level, and its randomness is correlated with the stock's, which lets the model price a curved volatility smile instead of a flat line.

Why does Black-Scholes give a flat volatility smile?

It assumes one constant volatility, which fixes one distribution for the price at expiry. Every strike is priced from that same distribution, and inverting the formula hands back the same volatility at every strike. The flat line is an output of the assumption, not a finding about markets.

What do the five Heston parameters mean?

Starting variance sets today's level of the surface. Long-run variance sets where variance is pulled over time, and the mean-reversion speed sets how fast that pull acts. Vol of vol sets the curvature of the smile, and the correlation between the two shocks sets its tilt.

Does the Heston model fit real option prices?

It fits the middle of a typical surface closely and has a harder time at the very short end, where observed smiles bend more sharply than its variance process allows. Fitted parameters also change from one day to the next, which makes calibration a repeated exercise rather than a one-time measurement.


Every panel above ships with the SQL that produced it, ready to be repointed at another name or another window. To ask one of these questions in plain English against options data, open the Strasmore terminal.