Implied Volatility and Volatility Smile › Computing Implied Volatility
Quantitative FinanceAll chapters Implied Volatility and Volatility Smile › Computing Implied VolatilityOne section · Sections in this chapter3 / 12 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
The equation cannot be solved analytically for . The Black-Scholes formula combines the cumulative normal distribution function, logarithms, and exponentials in ways that prevent algebraic isolation of . Therefore, we must use numerical methods. This is a root-finding problem: we seek the root of:
The function measures the discrepancy between the theoretical price at volatility and the target market price. When this discrepancy equals zero, we have found our implied volatility. The structure of this problem is particularly favorable for numerical methods because is smooth, continuous, and monotonically increasing in . These properties ensure that root-finding algorithms will converge reliably. The components of the objective function are:
- : objective function to minimize (find zero)
- : volatility parameter
- : Black-Scholes pricing function
- : target market price
Several root-finding algorithms can solve this problem. The two most common are the Newton-Raphson method and the bisection method.
The Newton-Raphson Method
Newton-Raphson is an iterative algorithm that uses both the function value and its derivative to make intelligent updates. The intuition is geometric. At each iteration, we approximate the function by its tangent line at the current point and move to where that tangent line crosses zero. When the function is reasonably well-behaved, this linear approximation improves with each iteration, leading to rapid convergence. The update formula is:
The formula evaluates the error to measure the distance from zero and divides by the derivative to compute the adjustment needed. The ratio has a natural interpretation: it measures how far we need to travel along the tangent line to reach zero. The negative sign ensures we move in the direction that reduces the function value when it's positive. Each component plays a specific role:
- : updated volatility estimate
- : current volatility estimate
- : error between theoretical and market price at current estimate
- : derivative of the error function with respect to volatility
For our problem, , so . Since the market price is a constant (we observe it from the market), its derivative is zero, and the derivative of our objective function equals the derivative of the Black-Scholes price with respect to volatility. This derivative is precisely vega, which we studied in Chapter 7 on the Greeks:
Vega measures how sensitive the option price is to small changes in volatility. The formula reveals that vega is always positive (both , , and the probability density are positive), confirming that option prices increase with volatility. The magnitude of vega depends on the spot price , the square root of time , and the probability density at . Options that are at-the-money (where is close to zero and is maximized) have the largest vega. The components of this formula are:
- : vega, the sensitivity of option price to volatility
- : spot price
- : time to expiration
- : standardized moneyness parameter
- : standard normal probability density function evaluated at
The probability density is the bell-curve function evaluated at . It peaks when and decays exponentially as moves away from zero in either direction. This explains why at-the-money options have the highest vega: they are precisely the options where is closest to zero.
Substituting vega into the Newton-Raphson update formula, we obtain:
The numerator is the pricing error: how much the Black-Scholes price at our current volatility estimate exceeds (or falls short of) the market price. The denominator is vega, which tells us how much the price changes per unit change in volatility. The ratio gives us the volatility adjustment needed to eliminate the pricing error under a linear approximation. Each term serves a distinct purpose:
- : new volatility estimate
- : current volatility estimate
- : Black-Scholes price calculated using
- : observed market price
- : vega calculated using
Newton-Raphson converges quickly (quadratically) when it works, but it can fail to converge if the initial guess is poor or if vega becomes very small (deep in-the-money or out-of-the-money options with short expiries). Quadratic convergence means the number of correct digits roughly doubles with each iteration. For example, if you have 2 correct digits after one iteration, you will have approximately 4 after the next, then 8, then 16. This rapid convergence makes Newton-Raphson extremely efficient when it succeeds.
The Bisection Method
Bisection is more robust but slower. It requires bracketing the solution between two values and such that and have opposite signs. The intermediate value theorem guarantees that a continuous function that changes sign must cross zero somewhere in the interval. Since the Black-Scholes price is monotonically increasing in (vega is always positive for vanilla options), we can always bracket the solution between (giving the intrinsic value) and some large (giving a price approaching for calls).
The bisection method repeatedly halves the interval, selecting the half that still brackets the root. At each step, we compute the midpoint and evaluate . If this value has the same sign as , the root lies in the upper half, so we update . Otherwise, the root lies in the lower half, and we update . Either way, we have halved the interval containing the root.
Bisection converges linearly, adding roughly one bit of precision per iteration. This means that to achieve machine precision (about 16 decimal digits), we need roughly 53 iterations. While slower than Newton-Raphson, bisection is guaranteed to converge as long as we start with a valid bracket, making it an excellent fallback method for difficult cases.
Implementation
Let's implement both methods and compare their performance.
import numpy as np
from scipy.stats import norm
def black_scholes_call(S, K, T, r, sigma):
"""
Compute Black-Scholes European call option price.
"""
if sigma <= 0 or T <= 0:
return max(S - K * np.exp(-r * T), 0)
d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
def vega(S, K, T, r, sigma):
"""
Compute vega (sensitivity of option price to volatility).
"""
if sigma <= 0 or T <= 0:
return 0
d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
return S * np.sqrt(T) * norm.pdf(d1)The Newton-Raphson implementation uses vega directly:
def implied_vol_newton(
S,
K,
T,
r,
market_price,
initial_guess=0.2,
tolerance=1e-8,
max_iterations=100,
):
"""
Compute implied volatility using Newton-Raphson method.
"""
sigma = initial_guess
for i in range(max_iterations):
price = black_scholes_call(S, K, T, r, sigma)
v = vega(S, K, T, r, sigma)
if v < 1e-10: # Vega too small, switch to bisection
return implied_vol_bisection(S, K, T, r, market_price)
diff = price - market_price
if abs(diff) < tolerance:
return sigma
sigma = sigma - diff / v
# Keep sigma positive
sigma = max(sigma, 1e-6)
raise ValueError("Newton-Raphson did not converge")The bisection method provides a robust fallback:
def implied_vol_bisection(
S,
K,
T,
r,
market_price,
sigma_low=0.001,
sigma_high=5.0,
tolerance=1e-8,
max_iterations=100,
):
"""
Compute implied volatility using bisection method.
"""
for i in range(max_iterations):
sigma_mid = (sigma_low + sigma_high) / 2
price_mid = black_scholes_call(S, K, T, r, sigma_mid)
if abs(price_mid - market_price) < tolerance:
return sigma_mid
if price_mid < market_price:
sigma_low = sigma_mid
else:
sigma_high = sigma_mid
return sigma_mid # Return best estimate even if not fully convergedLet's test both methods on a sample option:
# Market parameters
S = 100 # Stock price
K = 105 # Strike price
T = 0.5 # 6 months to expiry
r = 0.05 # 5% risk-free rate
# Suppose the market price is $5.50
market_price = 5.50
# Compute implied volatility using both methods
iv_newton = implied_vol_newton(S, K, T, r, market_price)
iv_bisection = implied_vol_bisection(S, K, T, r, market_price)
# Verify by repricing
reprice = black_scholes_call(S, K, T, r, iv_newton)Market price: $5.50 Implied volatility (Newton-Raphson): 0.2327 (23.27%) Implied volatility (Bisection): 0.2327 (23.27%) Repriced with IV: $5.5000 Difference: $0.00000000
The Newton-Raphson and bisection methods both converge to the same implied volatility. When we reprice the option using this implied volatility, we get a price that matches the market price to within numerical precision. This demonstrates that the root-finding problem is well-posed. Given a valid market price within the no-arbitrage bounds, a unique implied volatility exists that exactly reproduces that price. The Newton-Raphson method typically converges in 3-5 iterations, while bisection requires more iterations but guarantees convergence.
Comparing Convergence Speed
Newton-Raphson typically converges in 3-5 iterations, while bisection requires roughly 50 iterations for similar precision. Let's visualize the convergence:
def implied_vol_newton_trace(
S, K, T, r, market_price, initial_guess=0.2, max_iterations=20
):
"""
Newton-Raphson with convergence trace for visualization.
"""
sigma = initial_guess
trace = [sigma]
for i in range(max_iterations):
price = black_scholes_call(S, K, T, r, sigma)
v = vega(S, K, T, r, sigma)
if v < 1e-10:
break
diff = price - market_price
sigma = sigma - diff / v
sigma = max(sigma, 1e-6)
trace.append(sigma)
if abs(diff) < 1e-12:
break
return trace
def implied_vol_bisection_trace(
S, K, T, r, market_price, sigma_low=0.001, sigma_high=5.0, max_iterations=50
):
"""
Bisection with convergence trace for visualization.
"""
trace = []
for i in range(max_iterations):
sigma_mid = (sigma_low + sigma_high) / 2
trace.append(sigma_mid)
price_mid = black_scholes_call(S, K, T, r, sigma_mid)
if price_mid < market_price:
sigma_low = sigma_mid
else:
sigma_high = sigma_mid
return trace
# Generate traces
# Reuse parameters from earlier
S = 100
K = 105
T = 0.5
r = 0.05
market_price = 5.50
newton_trace = implied_vol_newton_trace(S, K, T, r, market_price)
bisection_trace = implied_vol_bisection_trace(S, K, T, r, market_price)
true_iv = implied_vol_newton(S, K, T, r, market_price)
Newton-Raphson reaches the true value in about 4 iterations, while bisection is still oscillating around the true value after 50 iterations. For practical applications involving thousands of option prices, the speed difference matters significantly.
