Implied Volatility

Listen to a trader on the phone and you will rarely hear a dollar figure. You will hear something like "I'll sell you the March 100 calls at 19.5 vol." Nobody quotes option prices in dollars any more; the whole market quotes in volatility. The Black–Scholes formula is the dictionary that makes this possible — but it is being run backwards. Instead of feeding in a volatility and reading off a price, the market fixes the price (by trading it) and asks the formula: what \sigma would have produced this? That number is the implied volatility, and inverting the formula to find it is the subject of this page.

Formally: given everything else in the Black–Scholes formula — S_0, K, r, T — and an observed market price C^{\text{mkt}}, the implied volatility \sigma_{\text{imp}} is the value solving

C_{BS}(S_0, K, r, \sigma_{\text{imp}}, T) = C^{\text{mkt}}.

A single unknown, a single equation. It sounds like high-school algebra. It is not — and seeing exactly why is the first thing worth understanding.

Why there is no formula for the inverse

Solving an equation for one variable is easy when that variable is isolated. Here it is buried three layers deep: \sigma sits inside d_1 and d_2, which sit inside the cumulative normal \Phi(\cdot), which has no elementary closed-form inverse to begin with (it is itself defined by an integral with no antiderivative in elementary functions). There is simply no sequence of algebraic moves — no "divide both sides by \Phi" — that peels \sigma back out.

But the news is not all bad. The call price is a strictly increasing function of \sigma — its slope is exactly \text{vega} = \partial C/\partial\sigma = S_0\,\varphi(d_1)\sqrt{T} > 0 for every option with positive time left, where \varphi is the standard normal density. A strictly increasing, continuous function that runs from 0 (as \sigma \to 0) up to S_0 (as \sigma \to \infty) crosses every value in between exactly once. So a solution always exists, is always unique — and can always be found, just not written down. This is a job for a numerical root-finder, hunting for the zero of

f(\sigma) = C_{BS}(\sigma) - C^{\text{mkt}} = 0.

Worked example: two hand-cranked Newton steps

Take the familiar textbook option: S_0 = K = 100, r = 5\%, T = 1. Suppose it trades in the market at C^{\text{mkt}} = \$12.00. We know from the Black–Scholes page that a volatility of 20\% only produces C \approx \$10.45 — too cheap, so the market's implied vol must be higher than 20%. Newton's method finds it fast, using \sigma_{n+1} = \sigma_n - \dfrac{C_{BS}(\sigma_n) - C^{\text{mkt}}}{\text{vega}(\sigma_n)}.

Step 1 — start at \sigma_0 = 20\%. We already have C(\sigma_0) = 10.45, and at d_1 = 0.35 the density is \varphi(0.35) \approx 0.3752, so \text{vega}(\sigma_0) = 100 \times 0.3752 \times 1 \approx 37.52.

\sigma_1 = 0.20 - \frac{10.45 - 12.00}{37.52} = 0.20 + \frac{1.55}{37.52} \approx 0.2413.

Step 2 — check \sigma_1 = 24.13\%. Recomputing d_1 = 0.3279, d_2 = 0.0866, and reading off \Phi(0.3279) \approx 0.6293, \Phi(0.0866) \approx 0.5345, gives

C(\sigma_1) = 100(0.6293) - 95.12(0.5345) \approx \$12.09.

Nine cents off target after a single step, starting from a guess that was 21% wrong. A second Newton step (not shown) lands within a hundredth of a cent. This is why every pricing engine on every trading floor solves for implied vol with Newton's method (or a close relative) rather than a lookup table.

Coding the solver

Below is exactly the loop above, generalised and run to convergence. It reuses the Black–Scholes call price and its vega, then Newton-iterates on volatility instead of on price:

// Standard normal cdf (Abramowitz–Stegun) and pdf. function Phi(x: number): number { const t = 1 / (1 + 0.2316419 * Math.abs(x)); const d = 0.3989422804014327 * Math.exp(-(x * x) / 2); const p = d * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429)))); return x >= 0 ? 1 - p : p; } function phi(x: number): number { return 0.3989422804014327 * Math.exp(-(x * x) / 2); } function bsCall(S0: number, K: number, r: number, sigma: number, T: number): number { const v = sigma * Math.sqrt(T); const d1 = (Math.log(S0 / K) + (r + 0.5 * sigma * sigma) * T) / v; const d2 = d1 - v; return S0 * Phi(d1) - K * Math.exp(-r * T) * Phi(d2); } function vega(S0: number, K: number, r: number, sigma: number, T: number): number { const v = sigma * Math.sqrt(T); const d1 = (Math.log(S0 / K) + (r + 0.5 * sigma * sigma) * T) / v; return S0 * phi(d1) * Math.sqrt(T); } // Newton's method: find sigma so bsCall(...) matches the market price. function impliedVol(S0: number, K: number, r: number, T: number, marketPrice: number): number { let sigma = 0.20; // starting guess for (let n = 1; n <= 20; n++) { const diff = bsCall(S0, K, r, sigma, T) - marketPrice; if (Math.abs(diff) < 1e-8) break; sigma = sigma - diff / vega(S0, K, r, sigma, T); } return sigma; } const S0 = 100, K = 100, r = 0.05, T = 1, marketPrice = 12.00; let sigma = 0.20; for (let n = 1; n <= 6; n++) { const price = bsCall(S0, K, r, sigma, T); const diff = price - marketPrice; console.log(`step ${n}: sigma = ${(sigma * 100).toFixed(4)}% price = ${price.toFixed(4)} diff = ${diff.toFixed(4)}`); if (Math.abs(diff) < 1e-8) break; sigma = sigma - diff / vega(S0, K, r, sigma, T); } console.log(`implied vol ≈ ${(sigma * 100).toFixed(4)}% (via impliedVol: ${(impliedVol(S0, K, r, T, marketPrice) * 100).toFixed(4)}%)`);

Watch the diff column collapse toward zero in three or four steps — the same quadratic convergence that made Newton's method so effective on any well-behaved root-finding problem.

When Newton misbehaves: the safety net

Newton's weak point here is exactly the same as everywhere else: it needs \text{vega} \ne 0, and vega gets tiny for options deep in or deep out of the money, or very close to expiry. A near-zero vega means a near-flat tangent — the update step \text{diff}/\text{vega} can rocket the guess miles away, sometimes into a negative or absurdly large volatility. The industrial-strength fix is the same hybrid idea used everywhere in root-finding: fall back on bisection, which cannot be derailed, whenever Newton wanders outside a sane bracket like [0.1\%, 500\%].

function Phi2(x: number): number { const t = 1 / (1 + 0.2316419 * Math.abs(x)); const d = 0.3989422804014327 * Math.exp(-(x * x) / 2); const p = d * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429)))); return x >= 0 ? 1 - p : p; } function callPrice(S0: number, K: number, r: number, sigma: number, T: number): number { const v = sigma * Math.sqrt(T); const d1 = (Math.log(S0 / K) + (r + 0.5 * sigma * sigma) * T) / v; const d2 = d1 - v; return S0 * Phi2(d1) - K * Math.exp(-r * T) * Phi2(d2); } // Bisection is slower but immune to the tiny-vega blow-up: bracket, then squeeze. function impliedVolBisect(S0: number, K: number, r: number, T: number, marketPrice: number): number { let lo = 0.001, hi = 5.0; // 0.1% to 500% — a comically wide, always-safe bracket for (let n = 1; n <= 60; n++) { const mid = (lo + hi) / 2; if (callPrice(S0, K, r, mid, T) > marketPrice) hi = mid; else lo = mid; } return (lo + hi) / 2; } // A deep out-of-the-money option: vega here is a whisper, not a shout. const S0 = 100, K = 160, r = 0.05, T = 0.25, marketPrice = 0.35; const iv = impliedVolBisect(S0, K, r, T, marketPrice); console.log(`deep-OTM implied vol ≈ ${(iv * 100).toFixed(3)}%`); console.log(`check: bsCall at that vol = ${callPrice(S0, K, r, iv, T).toFixed(4)} (target ${marketPrice})`);

Production systems typically start with a Newton or Newton-like step (secant, Brent's method) for speed, then quietly switch to bisection the moment a step looks unsafe — exactly the hybrid philosophy behind general-purpose root-finders.

It is worth pausing on how strong the uniqueness guarantee really is. Vega S_0\varphi(d_1)\sqrt{T} is a product of three manifestly positive quantities (for T > 0), so it can never be zero or negative — the call price curve, plotted against \sigma, only ever climbs, never levels off or turns back down. Combine that with the two endpoints, C \to \max(S_0 - Ke^{-rT}, 0) as \sigma \to 0 and C \to S_0 as \sigma \to \infty, and any market price strictly between those two no-arbitrage bounds is guaranteed to have one and only one \sigma that produces it. This is precisely bisection's favourite setting: a strictly monotone, continuous function with a guaranteed sign change — the implied-vol problem is, in a sense, the friendliest root-finding problem in all of finance.

Newton and bisection will both happily grind away on a bad input and either crash into a boundary or hand you a nonsense answer. Two traps to know: