What Determines an Option's Price?
What determines an option's price? Five inputs you can look up, plus volatility. We reprice one real AAPL call and rank each input by dollars. See the ranking.
What determines an option's price is a short list of inputs, and only one of them cannot be looked up. Spot, strike, time to expiry, the short interest rate, and any dividends paid along the way are all observable: you read them off a screen or off the contract itself. Volatility is the residual, the single number a pricing model has to solve for, and it is where nearly all of the daylight between two quotes on the same stock sits.
The five inputs you can look up, and the one you cannot
- Spot: what the underlying trades at right now. Observable to the penny, all session long.
- Strike: fixed in the contract from the day it is listed. Observable and permanently still.
- Time to expiry: a date subtraction. Observable, and it only travels one way.
- The short interest rate: the cost of carrying the position to expiry, taken from the front end of the curve. Observable, and slow.
- Dividends: scheduled cash leaving the underlying between today and expiry, read off the dividend calendar. Observable for the near dates, estimated for the far ones.
- Volatility: how much the underlying is expected to move between now and expiry. Not observable anywhere.
Feed the first five of those plus a volatility into a pricing model and it hands back a premium. Run the model the other way, hand it the premium the market is showing, and it hands back the volatility that reproduces that premium. That reverse solve is the implied volatility, and how implied volatility is calculated walks through the search step by step.
One real contract, tracked day by day
The panel below pins a single AAPL call by rule: within 3% of the money on the pinned session, 25 to 45 days from expiry, and the heaviest volume of that group. It then follows that same contract back across the month before. The premium column is the contract's daily close, and the iv_pct column is the volatility solved out of that close.
| session_date | as_of_pretty | contract | premium | iv_pct | spot_vs_strike_pct |
|---|---|---|---|---|---|
| 2026-08-17 | Aug 17 | O:AAPL261016C00340000 | 2.45 | 24.2 | -10.3 |
| 2026-08-18 | Aug 18 | O:AAPL261016C00340000 | 3.18 | 23.9 | -8.8 |
| 2026-08-19 | Aug 19 | O:AAPL261016C00340000 | 4.9 | 24.4 | -6.8 |
| 2026-08-20 | Aug 20 | O:AAPL261016C00340000 | 3.51 | 24.2 | -8.2 |
| 2026-08-21 | Aug 21 | O:AAPL261016C00340000 | 2.99 | 24.3 | -8.9 |
| 2026-08-24 | Aug 24 | O:AAPL261016C00340000 | 2.86 | 24.1 | -8.7 |
| 2026-08-25 | Aug 25 | O:AAPL261016C00340000 | 2.68 | 24.6 | -9.1 |
| 2026-08-26 | Aug 26 | O:AAPL261016C00340000 | 3.3 | 25.2 | -8.3 |
| 2026-08-27 | Aug 27 | O:AAPL261016C00340000 | 3.35 | 23.7 | -7.4 |
| 2026-08-28 | Aug 28 | O:AAPL261016C00340000 | 4.36 | 23.2 | -5.8 |
| 2026-08-31 | Aug 31 | O:AAPL261016C00340000 | 3.35 | 23.4 | -6.8 |
| 2026-09-01 | Sep 1 | O:AAPL261016C00340000 | 5.75 | 24 | -4.4 |
| 2026-09-02 | Sep 2 | O:AAPL261016C00340000 | 5.72 | 24.5 | -4.5 |
| 2026-09-03 | Sep 3 | O:AAPL261016C00340000 | 6.42 | 24.1 | -3.6 |
| 2026-09-04 | Sep 4 | O:AAPL261016C00340000 | 3.9 | 24 | -5.9 |
| 2026-09-08 | Sep 8 | O:AAPL261016C00340000 | 3.15 | 25.7 | -7 |
| 2026-09-09 | Sep 9 | O:AAPL261016C00340000 | 2.76 | 23.5 | -6.4 |
| 2026-09-10 | Sep 10 | O:AAPL261016C00340000 | 5.52 | 25.8 | -4.2 |
| 2026-09-11 | Sep 11 | O:AAPL261016C00340000 | 6.99 | 23.5 | -2.2 |
| 2026-09-14 | Sep 14 | O:AAPL261016C00340000 | 7.12 | 25.4 | -2.3 |
The exact SQL behind every number
WITH pin AS
(
SELECT ticker
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
AND startsWith(lower(toString(option_type)), 'c')
AND date = toDate('2026-09-16')
AND iv_converged = 1
AND volume > 0
AND days_to_expiry BETWEEN 25 AND 45
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.03
ORDER BY volume DESC, ticker ASC
LIMIT 1
)
SELECT
toString(g.date) AS session_date,
formatDateTime(g.date, '%b %e') AS as_of_pretty,
any(g.ticker) AS contract,
round(toFloat64(any(g.option_close)), 2) AS premium,
round(100 * any(g.implied_volatility), 1) AS iv_pct,
round(100 * (toFloat64(any(g.underlying_close)) / toFloat64(any(g.strike_price)) - 1), 1) AS spot_vs_strike_pct
FROM global_markets.options_greeks AS g
WHERE g.ticker IN (SELECT ticker FROM pin)
AND g.date BETWEEN toDate('2026-08-17') AND toDate('2026-09-16')
AND g.iv_converged = 1
AND g.volume > 0
GROUP BY g.date
ORDER BY g.date ASCAcross the 22 sessions in the panel, the premium went from $2.45 on Aug 17 to $6.37 on Sep 16, while the solved volatility moved from 24.2% to 22.8%. Most of the inputs were nearly still over that stretch. The strike never moves at all, the rate moved in basis points, and time ran down by one session a day. The inputs left in play are spot, which the spot_vs_strike_pct column measures against the strike, and the volatility.
What happens when one input moves
Telling a reader that volatility matters more than the rate is cheap. The panel below ranks it instead. It takes that contract's quoted inputs on the last session above, prices the call with a plain European model, then shocks one input at a time and prices it again: spot up 1%, volatility up 5 points, one day of decay, the short rate up 100 basis points, and a 2% annual dividend yield added where the base case assumed none. Everything else is frozen on every row, so each line is one input's own contribution.
| input_shifted | new_premium | premium_change | change_pct |
|---|---|---|---|
| Volatility +5 points | 8.25 | 1.876 | 29.45 |
| Spot +1% | 7.86 | 1.492 | 23.43 |
| Dividend yield 2% a year | 6.14 | -0.226 | -3.55 |
| One day of decay | 6.21 | -0.158 | -2.48 |
| Short rate +100 bp | 6.48 | 0.11 | 1.72 |
| Base case (quoted inputs) | 6.37 | 0 | 0 |
The exact SQL behind every number
WITH
pin AS
(
SELECT
toFloat64(underlying_close) AS s,
toFloat64(strike_price) AS k,
days_to_expiry / 365.0 AS t,
implied_volatility AS v,
risk_free_rate AS r
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
AND startsWith(lower(toString(option_type)), 'c')
AND date = toDate('2026-09-16')
AND iv_converged = 1
AND volume > 0
AND days_to_expiry BETWEEN 25 AND 45
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.03
ORDER BY volume DESC, ticker ASC
LIMIT 1
),
shocked AS
(
SELECT
sc.1 AS input_shifted,
sc.2 AS spot_multiplier,
sc.3 AS vol_add,
sc.4 AS day_add,
sc.5 AS rate_add,
sc.6 AS div_yield,
s,
k,
t,
v,
r
FROM pin
ARRAY JOIN
[
('Base case (quoted inputs)', 1.0, 0.0, 0.0, 0.0, 0.0),
('Spot +1%', 1.01, 0.0, 0.0, 0.0, 0.0),
('Volatility +5 points', 1.0, 0.05, 0.0, 0.0, 0.0),
('One day of decay', 1.0, 0.0, -1.0, 0.0, 0.0),
('Short rate +100 bp', 1.0, 0.0, 0.0, 0.01, 0.0),
('Dividend yield 2% a year', 1.0, 0.0, 0.0, 0.0, 0.02)
] AS sc
),
priced AS
(
SELECT
input_shifted,
(log(s / k) + (r + (v * v) / 2) * t) / (v * sqrt(t)) AS d1_base,
d1_base - v * sqrt(t) AS d2_base,
s * 0.5 * (1 + erf(d1_base / sqrt(2))) - k * exp(-r * t) * 0.5 * (1 + erf(d2_base / sqrt(2))) AS base_premium,
s * spot_multiplier AS s_new,
v + vol_add AS v_new,
t + day_add / 365.0 AS t_new,
r + rate_add AS r_new,
(log(s_new / k) + (r_new - div_yield + (v_new * v_new) / 2) * t_new) / (v_new * sqrt(t_new)) AS d1_new,
d1_new - v_new * sqrt(t_new) AS d2_new,
s_new * exp(-div_yield * t_new) * 0.5 * (1 + erf(d1_new / sqrt(2))) - k * exp(-r_new * t_new) * 0.5 * (1 + erf(d2_new / sqrt(2))) AS new_premium_exact
FROM shocked
)
SELECT
input_shifted,
round(new_premium_exact, 2) AS new_premium,
round(new_premium_exact - base_premium, 3) AS premium_change,
round(100 * (new_premium_exact - base_premium) / base_premium, 2) AS change_pct
FROM priced
ORDER BY abs(new_premium_exact - base_premium) DESCThe base case, the model's price at the quoted inputs, is $6.37. Against that, the largest single mover is Volatility +5 points, worth $1.876 of premium, or 29.45% of the contract. Second is Spot +1% at $1.492. The smallest of the five shocks, Short rate +100 bp, moves the premium 1.72%.
Sit with that ranking for a moment. A 1% move in the stock is an ordinary morning, and five points of volatility is an ordinary week, and on this contract the two land in the same neighbourhood of dollars. One day of decay is small next to either at a one month maturity, and inside the final week it stops being small. The rate, the input argued about most in the abstract, sits near the bottom at this horizon. Option rho, the rate sensitivity, is thin for short-dated contracts and grows with time to expiry. Every one of these sensitivities has a name and a letter, and the option greeks explained takes them one at a time.
The dividend row, and where early exercise lives
The dividend row is where a model with no dividend input quietly goes wrong. Cash leaving the underlying on the ex date lowers the forward price the option is struck against, by the present value of the dividends falling before expiry. A model told to assume no dividends is pricing against a forward that sits too high, and it prints a call that is too expensive. Put call parity shows the same arithmetic from the other side: the call, the put, the strike and the forward only balance once the dividend stream is inside the relationship.
The 2% shock above is a round number. Here is the real schedule it stands in for.
| ex_date | ex_pretty | cash_amount | annual_yield_pct |
|---|---|---|---|
| 2023-08-11 | Aug 11, 2023 | 0.24 | 0.54 |
| 2023-11-10 | Nov 10, 2023 | 0.24 | 0.52 |
| 2024-02-09 | Feb 9, 2024 | 0.24 | 0.51 |
| 2024-05-10 | May 10, 2024 | 0.25 | 0.55 |
| 2024-08-12 | Aug 12, 2024 | 0.25 | 0.46 |
| 2024-11-08 | Nov 8, 2024 | 0.25 | 0.44 |
| 2025-02-10 | Feb 10, 2025 | 0.25 | 0.44 |
| 2025-05-12 | May 12, 2025 | 0.26 | 0.49 |
| 2025-08-11 | Aug 11, 2025 | 0.26 | 0.46 |
| 2025-11-10 | Nov 10, 2025 | 0.26 | 0.39 |
| 2026-02-09 | Feb 9, 2026 | 0.26 | 0.38 |
| 2026-05-11 | May 11, 2026 | 0.27 | 0.37 |
| 2026-08-10 | Aug 10, 2026 | 0.27 | 0.35 |
The exact SQL behind every number
SELECT
toString(d.ex_dividend_date) AS ex_date,
formatDateTime(d.ex_dividend_date, '%b %e, %Y') AS ex_pretty,
round(toFloat64(any(d.cash_amount)), 4) AS cash_amount,
round(100 * any(d.frequency) * toFloat64(any(d.cash_amount)) / toFloat64(any(p.close)), 2) AS annual_yield_pct
FROM global_markets.stocks_dividends AS d
INNER JOIN
(
SELECT
date,
close
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= toDate('2023-06-01')
) AS p ON p.date = d.ex_dividend_date
WHERE d.ticker = 'AAPL'
AND d.ex_dividend_date >= toDate('2023-06-01')
AND d.ex_dividend_date <= toDate('2026-09-30')
GROUP BY d.ex_dividend_date
ORDER BY d.ex_dividend_date ASCThe most recent payment in the panel is $0.27 a share, with an ex date of Aug 10, 2026, annualizing to 0.35% of that session's close. That is well under the 2% used in the shock, so the dividend line in the sensitivity table is generous for this name. The panel holds 13 payments, and AAPL's dividend history carries the full record.
Early exercise lives in this same row. An American call on a dividend payer can be worth more exercised the day before an ex date than held: the holder gives up the remaining time value and collects the dividend instead, and once the dividend is the larger of the two amounts, exercising is the larger of the two outcomes. A European formula has no way to express that choice, so it leaves out the value of the right to exercise early, which pushes the opposite way to the dividend adjustment itself. Desks price American options on dividend payers with a model that allows exercise at every step, rather than with one closed-form equation.
Why the dollar price hides all of this
A premium quoted in dollars folds six inputs into one number and says nothing about which of them moved. The same contract can print the same dollars on two days with two different implied volatilities, once spot and time have shifted underneath it. Two contracts on one stock at one instant can print very different dollars while carrying the same volatility view. The panel below averages the solved volatility across every near-the-money AAPL contract on the pinned session, grouped by how much time each one has left.
| dte_bucket | contracts | iv_pct |
|---|---|---|
| 1 to 7 days | 71 | 28.2 |
| 8 to 21 days | 103 | 24.6 |
| 22 to 45 days | 55 | 25.3 |
| 46 to 90 days | 14 | 26.9 |
| 91 to 180 days | 36 | 26.6 |
| over 180 days | 82 | 28.5 |
The exact SQL behind every number
SELECT
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',
'over 180 days') AS dte_bucket,
count() AS contracts,
round(100 * avg(implied_volatility), 1) AS iv_pct
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
AND date = toDate('2026-09-16')
AND iv_converged = 1
AND volume > 0
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05
GROUP BY dte_bucket
ORDER BY min(days_to_expiry) ASCNear-the-money contracts with 1 to 7 days left carried an average solved volatility of 28.2%, against 28.5% out at over 180 days, across 6 maturity buckets. The front bucket alone holds 71 contracts. That shape across horizons is the term structure of volatility, and a dollar price shows none of it. Quoting the volatility instead puts every contract on a single axis, the convention laid out in how options are quoted in volatility.
Model and data notes
- The repricing panel uses a European Black Scholes call, ACT/365 year fractions, the implied volatility stored against that contract for that session, and the stored short rate. The base case carries no dividend, which is the whole point of the dividend row.
- Each shock is applied on its own with every other input frozen at the base case. Rows are ordered by the size of the premium change, so the base case lands last.
- Volatility is read only where the solver converged and the contract actually traded that session.
- The pinned contract is selected by call flag, moneyness and volume rather than by name, and the call flag is matched case-insensitively so a feed writing the type as a single letter still resolves.
FAQ
What are the inputs to an option pricing model?
Spot, strike, time to expiry, the short interest rate, and the dividends expected before expiry, plus a volatility. The first five are look-ups. Volatility is the one input no quote tells you directly, which is why it gets solved out of the price instead.
Which input moves an option's price the most?
On the contract repriced above, Volatility +5 points topped the ranking at $1.876 of premium, with Spot +1% next at $1.492. Spot and volatility trade places at the top for a near-the-money contract with weeks left, while the rate sits near the bottom at that horizon.
Do dividends raise or lower a call option's price?
A dividend expected before expiry lowers a call's value and raises a put's. The cash leaves the underlying on the ex date, and the forward price the option is struck against drops with it. A model that assumes no dividends will overprice calls on dividend payers.
Why do options get quoted in volatility instead of dollars?
A dollar premium mixes every input together, which leaves two dollar quotes incomparable across strikes, maturities and days. Volatility strips the observable inputs back out and leaves the one number traders genuinely disagree about.
What is implied volatility in one sentence?
It is the volatility input that makes a pricing model return exactly the price the market is showing, found by searching rather than read off a screen.
Every panel here opens to the exact SQL beneath it. Change a shock size, change the ticker, and the ranking recomputes for a contract you care about. The same question can be asked in plain English on the Strasmore terminal.