Implied Volatility and Volatility Smile › Computing Implied Volatility

Michael BrenndoerferNovember 30, 202512 min read
Quantitative FinanceAll chapters
Part 5 of 15Stochastic Calculus and Pricing Theory
Chapter 32Implied Volatility and Volatility Smile › Computing Implied Volatility
Reading section 3 of 12 · Computing Implied Volatility · 12 minSection 3 of 12 · 12 min

Book contents

Section 3 of 12 · 12 min read

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 CBS(S,K,T,r,σIV)=CmktC^{BS}(S, K, T, r, \sigma_{IV}) = C^{mkt} cannot be solved analytically for σIV\sigma_{IV}. The Black-Scholes formula combines the cumulative normal distribution function, logarithms, and exponentials in ways that prevent algebraic isolation of σ\sigma. Therefore, we must use numerical methods. This is a root-finding problem: we seek the root of:

f(σ)=CBS(S,K,T,r,σ)−Cmkt=0f(\sigma) = C^{BS}(S, K, T, r, \sigma) - C^{mkt} = 0

The function f(σ)f(\sigma) measures the discrepancy between the theoretical price at volatility σ\sigma 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 f(σ)f(\sigma) is smooth, continuous, and monotonically increasing in σ\sigma. These properties ensure that root-finding algorithms will converge reliably. The components of the objective function are:

  • f(σ)f(\sigma): objective function to minimize (find zero)
  • σ\sigma: volatility parameter
  • CBS(… )C^{BS}(\dots): Black-Scholes pricing function
  • CmktC^{mkt}: 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:

σn+1=σn−f(σn)f′(σn)\sigma_{n+1} = \sigma_n - \frac{f(\sigma_n)}{f'(\sigma_n)}

The formula evaluates the error f(σn)f(\sigma_n) to measure the distance from zero and divides by the derivative f′(σn)f'(\sigma_n) to compute the adjustment needed. The ratio f(σn)/f′(σn)f(\sigma_n)/f'(\sigma_n) 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:

  • σn+1\sigma_{n+1}: updated volatility estimate
  • σn\sigma_n: current volatility estimate
  • f(σn)f(\sigma_n): error between theoretical and market price at current estimate
  • f′(σn)f'(\sigma_n): derivative of the error function with respect to volatility

For our problem, f(σ)=CBS(σ)−Cmktf(\sigma) = C^{BS}(\sigma) - C^{mkt}, so f′(σ)=∂CBS/∂σf'(\sigma) = \partial C^{BS}/\partial\sigma. 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:

V=∂C∂σ=ST⋅n(d1)\mathcal{V} = \frac{\partial C}{\partial \sigma} = S \sqrt{T} \cdot n(d_1)

Vega measures how sensitive the option price is to small changes in volatility. The formula reveals that vega is always positive (both SS, T\sqrt{T}, and the probability density n(d1)n(d_1) are positive), confirming that option prices increase with volatility. The magnitude of vega depends on the spot price SS, the square root of time T\sqrt{T}, and the probability density at d1d_1. Options that are at-the-money (where d1d_1 is close to zero and n(d1)n(d_1) is maximized) have the largest vega. The components of this formula are:

  • V\mathcal{V}: vega, the sensitivity of option price to volatility
  • SS: spot price
  • TT: time to expiration
  • d1d_1: standardized moneyness parameter
  • n(d1)=12πe−d12/2n(d_1) = \frac{1}{\sqrt{2\pi}} e^{-d_1^2/2}: standard normal probability density function evaluated at d1d_1

The probability density n(d1)n(d_1) is the bell-curve function evaluated at d1d_1. It peaks when d1=0d_1 = 0 and decays exponentially as d1d_1 moves away from zero in either direction. This explains why at-the-money options have the highest vega: they are precisely the options where d1d_1 is closest to zero.

Substituting vega into the Newton-Raphson update formula, we obtain:

σn+1=σn−CBS(σn)−CmktV(σn)\sigma_{n+1} = \sigma_n - \frac{C^{BS}(\sigma_n) - C^{mkt}}{\mathcal{V}(\sigma_n)}

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:

  • σn+1\sigma_{n+1}: new volatility estimate
  • σn\sigma_n: current volatility estimate
  • CBS(σn)C^{BS}(\sigma_n): Black-Scholes price calculated using σn\sigma_n
  • CmktC^{mkt}: observed market price
  • V(σn)\mathcal{V}(\sigma_n): vega calculated using σn\sigma_n

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 σa\sigma_a and σb\sigma_b such that f(σa)f(\sigma_a) and f(σb)f(\sigma_b) 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 σ\sigma (vega is always positive for vanilla options), we can always bracket the solution between σ=0\sigma = 0 (giving the intrinsic value) and some large σ\sigma (giving a price approaching SS for calls).

The bisection method repeatedly halves the interval, selecting the half that still brackets the root. At each step, we compute the midpoint σmid=(σa+σb)/2\sigma_{mid} = (\sigma_a + \sigma_b)/2 and evaluate f(σmid)f(\sigma_{mid}). If this value has the same sign as f(σa)f(\sigma_a), the root lies in the upper half, so we update σa=σmid\sigma_a = \sigma_{mid}. Otherwise, the root lies in the lower half, and we update σb=σmid\sigma_b = \sigma_{mid}. 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.

In[3]:
Code
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:

In[4]:
Code
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:

In[5]:
Code
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 converged

Let's test both methods on a sample option:

In[6]:
Code
# 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)
Out[7]:
Console
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:

In[8]:
Code
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)
Out[9]:
Visualization
Line chart comparing Newton-Raphson and bisection convergence, showing Newton-Raphson reaching the true implied volatility in 4 iterations versus roughly 50 for bisection.
Convergence speed comparison for an out-of-the-money call option (strike $105, spot $100, 6 months to expiration, 5% risk-free rate). Newton-Raphson converges in just 4 iterations with quadratic convergence, where correct digits double with each iteration. Bisection requires approximately 50 iterations for comparable accuracy by repeatedly halving the search interval. Newton-Raphson's dramatic speed advantage makes it ideal for practical trading applications, while bisection provides a robust fallback when vega becomes very small near expiration or for deep options.

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.

Out[10]:
Visualization
Line chart showing the pricing error function with three distinct tangent lines illustrating successive Newton-Raphson iterations converging to zero error.
Geometric interpretation of Newton-Raphson iteration for finding implied volatility. The main curve shows the pricing error function f(σ) = C^(BS)(σ) - C^(mkt), measuring the difference between theoretical and market prices. Starting from initial guess σ₀ = 0.80, each dashed tangent segment connects the current estimate to its next zero-crossing estimate. The sequence reaches the 23.27% implied volatility in three updates, illustrating rapid quadratic convergence.