Heston model and volatility smile explanation
One volatility number no fit price full option chain. See how Heston model allow variance to change and wetin each parameter dey do to the volatility smile shape.
Heston model and volatility
Heston model na one option pricing model wey dey treat volatility as something wey dey change randomly, no be fixed number. E get two moving parts: the stock price, and the variance of that price, and each one get im own random shock.
Na that second source of randomness dey allow the model produce wetin dem dey call volatility smile. One constant volatility, wey be the assumption inside Black-Scholes, fit only draw flat line across strikes, and no option chain don ever be flat before.
Why one volatility number no fit work for option chain
Implied volatility na the volatility input wey dey make pricing formula give the price wey option dey trade. If you invert am contract by contract, as our page on how implied volatility is calculated show, one expiry go give you curve across strikes instead of just one level. The panel wey dey down so take every SPY contract wey get twenty to forty-five days left for the first half of 2026, arrange dem into two percent bands based on distance from strike to spot, and calculate the average 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, wey be strikes far below spot, get average of 28.05% implied volatility, wey be 11.61 volatility points higher than the at-the-money average for the same window. The +12% band for the call side get average of 15.56%. The bands wey dey between trace the curve wey give the effect im name, and the sideways lean na wetin dem dey call volatility skew. Model wey get only one volatility parameter no get way to reach all this: every strike dey price based on one distribution for the price at expiry, and if you invert that model, e go return the same number for every strike, because na so dem build the model.
Wetin the Heston model change
Heston model dey keep the random shock of the stock and e dey add second process for the variance. If we wan explain am with word instead of symbol:
- The movement of the stock for the next small time na drift plus one random shock, wey we scale with the square root of the current variance.
- The movement of the variance na pull towards one long-run level with fixed speed, plus e own shock, wey we scale with one vol-of-vol parameter and the square root of the current variance.
- The two shocks get correlation, with one number wey dey between minus one and one.
That square-root scaling na the Cox-Ingersoll-Ross form, and e get one work wey e dey do wey important: the variance shock dey shrink go zero as variance sef dey approach zero, and this one dey stop the variance make e no turn negative. When two times the speed times the long-run variance pass the square of the vol-of-vol, one condition wey dem name after Feller, the variance go stay strictly positive.
We no fit see variance directly. But we fit see the implied counterpart, and e no dey stay one place. The panel wey dey down here plot the at-the-money implied volatility for two names, one reading per session, throughout 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 open the window for 20.39% on 2026-04-01 and close am for 14.45% on 2026-06-30. NVDA move from 36.83% go 38.22% across the same 62 sessions. No be say any of the line stay one place, and no be say dem run go anywhere: both of dem dey wander and dey return back to one neighbourhood. To price both ends of that picture, you need starting level plus long-run level with speed for the pull wey dey between dem.
Wetin each Heston parameter dey do to the surface
Mean reversion and long-run level dey shape the term structure
Option value dey depend on the average variance wey dem expect over the life of the contract, no be the variance wey dey ground today. For contract wey go expire next week, today variance dey control that average; for one wey go expire for one year, the long-run level dey control am. The speed parameter dey set how fast the expectation dey move between the two, wey come fix how steep the implied volatility go slope from the front of the calendar go 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 for the 1 to 7 days bucket average 17.05% over the first half of 2026, against 18.77% for the 181 to 365 days bucket. NVDA print 41.22% and 44.94% across the same two buckets. One-number model dey price every tenor based on the same volatility. Heston dey give the front and the back dia own levels, with the speed parameter wey dey govern the shape wey dey between dem. More of these curves dey for our IV term structure page.
Vol of vol dey bend the smile
Vol of vol na the volatility of the variance itself. If you set am to zero, variance go follow smooth path: the term structure fit still slope, but the smile across strikes go flat. If you turn am up, the distribution of the price at expiry go get more weight for both tails, wey dey lift strikes wey far from spot pass strikes wey near am. How far variance dey travel for real life dey differ by underlying, and the panel wey dey down here dey measure 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 cover the widest range for the panel: at-the-money implied volatility as low as 28.21% and as high as 74.42%, wey be 46.22 volatility points apart over six months. KO cover the narrowest, at 10.75 points. Vega, the price sensitivity to volatility wey our vega page define, dey measure the level of the surface. Under stochastic volatility, two contracts wey get matching vega fit behave differently when the shape move instead of the level.
Correlation dey tilt the smile make e turn skew
The correlation between the stock shock and the variance shock dey turn symmetric smile into one wey dey lopsided. Under negative correlation, paths wey the stock fall na paths wey variance dey rise, and the left tail of the distribution at expiry dey carry more weight pass the right. Put-side implied volatility come price higher pass call-side implied volatility for 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 show the widest gap for the panel: contracts wey strike at least five percent below spot average 27% against 14.76% for contracts wey strike at least five percent above, wey be 12.23 volatility points apart. For the other side, MSFT print 3.9 points on the same measurement. One correlation parameter per underlying na wetin dey cover that whole range of tilts.
Starting variance dey set the level
The fifth parameter na the variance wey the model start from today. E dey lift or drop the whole surface without changing the shape too much, na why dem dey refit am pass others: e dey keep the model on the market current level while the other four dey carry the geometry.
Wetin the model dey buy, and how much e dey cost
The purchase na surface wey dey bend for two directions from five numbers wey person fit explain, and dem dey price am sharp-sharp. Heston dey use characteristic function and one numerical integral take value European options, e no need simulation, so e dey easy to fit one full chain for inside small time. The cost dey clear.
- Dem dey calibrate the five parameters, dem dey fit am to option prices wey dem see for market instead of say dem measure am from something.
- Calibration na just one snapshot. If you refit am tomorrow, the numbers go move, wey mean say the constants for the model no be constant.
- One parameter set rarely fit every expiry at the same time. The smiles wey dem see for the very short end dey bend pass wetin this variance process fit handle.
- Prices for market dey gap. Variance and spot dey move continuously for here, and the fitted numbers must absorb any gap wey show.
One warning dey important for readers wey come from the volatility pages. The variance process dey describe the dynamics wey dey price options, and that one different from the volatility wey stock go eventually realise. The difference between the two na the topic of implied volatility versus realised volatility.
Where the model still misses
Extensions dey for every gap. Bates model dey keep Heston variance and add jumps to the price process, wey dey make the short-dated smile steep well. Rough volatility models dey keep random variance and change the driver to paths wey rough pass standard Brownian motion, so e fit match the very short end well. None of dem remove the calibration problem: both of dem dey add parameters wey you must fit to a moment and refit again later.
FAQ
Wetin be the Heston model for simple grammar?
Na one model wey dem dey use price option wey volatility dey change anyhow. Variance dey follow ein own road wey dey pull go one long-run level, and the way e dey change dey correlate with the stock price. This one make the model fit price one curved volatility smile instead of one flat line.
Why Black-Scholes dey give flat volatility smile?
E dey assume say volatility constant, wey mean say e fix one distribution for the price when the option expire. Dem dey use that same distribution price every strike, and if you invert the formula, you go still get the same volatility for every strike. That flat line na wetin the assumption produce, no be wetin dem discover for market.
Wetin the five Heston parameters mean?
Starting variance set the level of the surface for today. Long-run variance set where variance dey pull go as time dey go, and the mean-reversion speed set how fast that pull dey work. Vol of vol set how the smile go curve, and the correlation between the two shocks set how the smile go tilt.
The Heston model dey fit real option prices?
E dey fit the middle of one typical surface well, but e dey hard for the very short end, where the smiles wey we see dey bend pass wetin the variance process allow. The parameters wey dem fit change from one day to another, so calibration na work wey you must dey do every time, no be one-time measurement.
Every panel wey dey up so come with the SQL wey produce am, ready make you point am go another name or another window. To ask one of these questions for plain English against options data, open the Strasmore terminal.