SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 2.4.1 Maxima and minimaConcept · 25 min
      2. 2.4.2 Concavity and the second derivativeConcept · 25 min
      3. 2.4.3 Newton's method with derivativesConcept · 30 min
      4. 2.4.4 Practice set: using derivativesPractice set · 25 min
      5. 2.4.5 Case study: convexity and risk aversionCase study · 30 min
      6. 2.4.6 Case study: implied volatility by Newton's methodCase study · 30 min

Level 2, Single-variable calculus 2.4 Using derivatives Lesson 6 of 6

Case studyLesson 2.4.6 in Level 2, Single-variable calculus. About 30 minutes.

Case study: implied volatility by Newton's method

The price as a function of volatility

A call option gives the right to buy a stock at a fixed price KK, the strike, at a fixed date, TT years away. The Black–Scholes formula prices it from the stock price SS and the interest rate rr (continuous, as a decimal). It also needs the volatility σ\sigma, the yearly standard deviation of the stock's log returns.

The Derivatives Modelling course derives the formula, and case study 2.6.5 rebuilds it as an integral. Here, take it as given:

c(σ)=S N(d1)−Ke−rTN(d2)d1=ln⁡(S/K)+(r+σ2/2) TσTd2=d1−σT\begin{gathered} c(\sigma) = S\,N(d_1) - K e^{-rT} N(d_2) \\[4pt] d_1 = \frac{\ln(S/K) + (r + \sigma^2/2)\,T}{\sigma\sqrt{T}} \\[4pt] d_2 = d_1 - \sigma\sqrt{T} \end{gathered}

NN is the standard normal cumulative distribution (Level 5; lesson 2.6.3 meets it as an area), norm.cdf in SciPy. Everything is known except σ\sigma, so this is a function of one variable, c(σ)c(\sigma).

For the option in the hook, S=K=100S = K = 100, T=0.5T = 0.5 and r=0.03r = 0.03:

σ\sigma0.00010.050.20.5150
c(σ)c(\sigma)1.48882.26846.371014.684028.1773100.0000

As σ\sigma shrinks to 0 the price falls to S−Ke−rT=1.4888S - Ke^{-rT} = 1.4888, the value of the option with no uncertainty. As σ\sigma grows it rises towards S=100S = 100. A market price outside that range has no implied volatility at all.

Vega: the derivative with respect to volatility

Newton's method needs the slope c′(σ)c'(\sigma). Options traders call it vega. Differentiating the formula with the chain rule (lesson 2.3.3) leads, after a cancellation, to a short result:

Rule: Vega

c′(σ)=ST  φ(d1)c'(\sigma) = S\sqrt{T}\;\varphi(d_1)

φ\varphi is the standard normal density, norm.pdf in SciPy. It is always positive, so vega is too: more volatility always makes a call worth more.

Because vega is positive, c(σ)c(\sigma) rises everywhere. So each market price has at most one implied volatility, and the sign of c(σ)−pricec(\sigma) - \text{price} says which side of it you are on.

Try it

At σ=20%\sigma = 20\% the call is worth 6.3710 and its vega is 27.7721. A central difference (lesson 2.2.2) with h=0.0001h = 0.0001 agrees.

The loop reproduces the table. The cell prints with f"{v:.4f}", four decimal places.

⌘/Ctrl + Enter runs the cell

Vega 27.77 is per unit of σ\sigma, a move from 0 to 100% volatility. Desks quote it per vol point, one percentage point: 0.2777, so each extra point adds about 28 cents.

Newton's method for implied volatility

Solve c(σ)−price=0c(\sigma) - \text{price} = 0. The step is lesson 2.4.3's, with vega as the slope:

Rule: Implied volatility by Newton

σn+1=σn−c(σn)−pricec′(σn)\sigma_{n+1} = \sigma_n - \frac{c(\sigma_n) - \text{price}}{c'(\sigma_n)}

The height above the market price, divided by vega, is how far to move the volatility.

Try it

From σ0=0.2\sigma_0 = 0.2, the first step lands on 0.222648 and the second on 0.2226413, already correct to about ten digits. The implied volatility is 22.26%.

brentq (lesson 1.3.2) confirms it from the bracket [0.0001,5][0.0001, 5].

⌘/Ctrl + Enter runs the cell

Two things make this easy. At the money the price curve is almost a straight line: vega barely changes, from 27.36 at 10% to 27.77 at 20% and 30%. And the start, 20%, is close to the answer.

Check yourself
The market price of the option rises from $7.00 to $7.50. What happens to its implied volatility?

Deep out of the money: where Newton breaks

Now take a strike of 150, 50% above the stock price, with the same SS, TT and rr. The call trades at $2.00. At 20% volatility the formula gives only 0.0149, and vega is 0.7564: the curve is almost flat there.

Newton's step divides the gap by that tiny slope. From 20% the first step lands on 282%, the second on −9.87%-9.87\%, a negative volatility, and the third on 916,440,330%. The answer is 44.78%.

Try it

Three plain Newton steps from 20% for the strike-150 call. The second step is already meaningless: a volatility cannot be negative.

⌘/Ctrl + Enter runs the cell

The shape of the curve

For this option c(σ)c(\sigma) is S-shaped. It is flat near 0, bends up, and later bends down: c′′≈70.54c'' \approx 70.54 at 30% and −5.45-5.45 at 200%. So it has an inflection point (lesson 2.4.2), and there vega, the slope, is at its largest.

Rule: A good start: the inflection point

σ∗=2 ∣ln⁡(S/K)+rT∣T\sigma^* = \sqrt{\frac{2\,\lvert \ln(S/K) + rT \rvert}{T}}

Vega is largest at σ∗\sigma^*, where c(σ)c(\sigma) changes from concave up to concave down. Started there, Newton's method moves towards the answer at every step and never overshoots.

Lesson 2.4.3 explains why, with concavity. If the answer is below σ∗\sigma^*, the start is to its right on a rising, concave-up curve, and each tangent lies below the curve. If the answer is above, the start is to its left on a concave-down stretch, where each tangent lies above the curve.

Either way, no step jumps past the answer. For strike 150, σ∗=1.2497\sigma^* = 1.2497, or 125%. From there the guesses are 0.535213, 0.456067, 0.447934 and 0.447826: four steps, all from the right.

The call price against volatility for two strikes. At strike 100 one step from 20% lands almost on the answer. At strike 150 the tangent at 20% is nearly flat and shoots past the answer, while steps from the inflection point walk down to it.

Try it

The first line checks that a grid of volatilities from 1% to 300% has its largest vega at 1.25, next to σ∗\sigma^*. The next two lines show c′′c'' changing sign, by the second central difference of lesson 2.4.2.

Then Newton's method runs from σ∗\sigma^*.

⌘/Ctrl + Enter runs the cell

A safety net: keep a bracket

When ln⁡(S/K)+rT=0\ln(S/K) + rT = 0, the formula gives σ∗=0\sigma^* = 0, where the price formula divides by zero. Production code therefore also keeps a bracket, as in lesson 2.4.3. Since c(σ)c(\sigma) rises, [0.01,3][0.01, 3] brackets any volatility from 1% to 300%.

Try it

safe_newton from lesson 2.4.3 solves the strike-150 call on [0.01,3][0.01, 3] in 6 steps. brentq needs 14 iterations for the same answer.

The last lines ask for a price of 1.40 on the strike-100 call, below its floor of 1.4888. There is no sign change, and brentq refuses.

⌘/Ctrl + Enter runs the cell
Exercise

Implied volatility

Write implied_vol(price, S, K, T, r, sigma0=0.2, tol=1e-10). It returns the implied volatility of a call by Newton's method from sigma0, with the price and vega formulas above.

  • Stop when a step moves σ\sigma by less than tol.
  • If a step makes σ\sigma zero or negative, raise ValueError: the start was too far from the answer.

The tests check the example above, a strike-120 call at $1.50 (about 23.60%), and that your answer reprices the option. They also try the strike-150 call at $2.00: from 20% it must raise ValueError, and from σ∗≈1.2497\sigma^* \approx 1.2497 it must return about 44.78%.

See the tests
import math

from scipy.stats import norm


def _call(S, K, T, r, sigma):
    d1 = (math.log(S / K) + (r + sigma**2 / 2) * T) / (sigma * math.sqrt(T))
    return S * norm.cdf(d1) - K * math.exp(-r * T) * norm.cdf(d1 - sigma * math.sqrt(T))


def test_at_the_money():
    """A 6-month at-the-money call at $7.00 implies about 22.26%"""
    expect_close(implied_vol(7.0, 100, 100, 0.5, 0.03), 0.22264129444955746, what="implied_vol(7.0, ...)", rel=1e-8)


def test_out_of_the_money():
    """Strike 120 at $1.50 implies about 23.60%"""
    expect_close(implied_vol(1.5, 100, 120, 0.5, 0.03), 0.23596239715145917, what="implied_vol(1.5, K=120)", rel=1e-6)


def test_reprices():
    """The answer reprices the option: a 1-year call at $12.00"""
    sigma = implied_vol(12.0, 100, 95, 1.0, 0.02)
    expect_close(_call(100, 95, 1.0, 0.02, sigma), 12.0, what="call price at your volatility", rel=1e-9)


def test_round_trip():
    """Price an option at 35%, then recover 35%"""
    price = _call(50, 55, 0.25, 0.01, 0.35)
    expect_close(implied_vol(price, 50, 55, 0.25, 0.01), 0.35, what="recovered volatility", rel=1e-8)


def test_deep_out_of_the_money_good_start():
    """Strike 150 at $2.00, started at the inflection point 1.2497, implies about 44.78%"""
    expect_close(implied_vol(2.0, 100, 150, 0.5, 0.03, sigma0=1.2497), 0.4478258393239575, what="implied_vol(2.0, K=150, sigma0=1.2497)", rel=1e-8)


def test_deep_out_of_the_money_bad_start():
    """Strike 150 at $2.00 from 20%: a step goes negative, so ValueError"""
    try:
        implied_vol(2.0, 100, 150, 0.5, 0.03)
    except ValueError:
        return
    raise AssertionError("expected ValueError: from 20% the second Newton step gives a negative volatility")

Summary card

  • The Black–Scholes call price c(σ)c(\sigma) rises with volatility, from max⁡(S−Ke−rT,0)\max(S - Ke^{-rT}, 0) towards SS. A price outside that range has no implied volatility.
  • Its derivative, vega, is STφ(d1)>0S\sqrt{T}\varphi(d_1) > 0, usually quoted per vol point.
  • Implied volatility solves c(σ)=pricec(\sigma) = \text{price} by Newton's method: σn+1=σn−c(σn)−pricevega\sigma_{n+1} = \sigma_n - \frac{c(\sigma_n) - \text{price}}{\text{vega}}.
  • Deep out of the money, vega is tiny at low volatility and Newton from 20% can shoot to a negative volatility. Start at the inflection point σ∗=2∣ln⁡(S/K)+rT∣/T\sigma^* = \sqrt{2\lvert\ln(S/K) + rT\rvert/T}, and keep a bracket as a fallback.

Free further reading

Optional. This lesson covers what you need; these add more examples and practice. All are free to read.