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.
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_bucketThe -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.
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 dateSPY 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.
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)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.
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 DESCAMZN 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.
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 DESCOver 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.