Newton-Raphson Method

We ditch bisection and let Newton-Raphson chase down implied volatility by hopping along tangent lines until it zeros in on the answer.

So as I mentioned last time, I’m trying to find implied volatility, and I already took one swing at it with the bisection method. Now let’s go again โ€” this time with Newton-Raphson.

But before we touch any code, let’s figure out how Newton-Raphson actually sneaks up on a solution.

What’s the algorithm? How does it cook up an approximation?

Let’s walk through it.

How Newton-Raphson works

Here’s the idea.

Hand-drawn curve y = f(x) crossing the x-axis, with the starting point x_1 marked on the axis and a dashed line up to the curve

Step one: pick any $x_1$ and plug it into the function.

(In practice you wouldn’t pick just anything. You’d pick something as close to the solution as you can guess. For efficiency, for economy, for not wasting your life, etc., etc.~)

Plug it in โ€” and oh god, $f(x_1)$ is huge. Way off. So $x_1$ is clearly not our solution.

The same curve with the tangent line drawn at x_1; where it meets the x-axis is marked x_2

So from the point $(x_1, f(x_1))$, draw the tangent line. Take the x-intercept of that tangent line and call it $x_2$. Plug $x_2$ back into $f(x)$.

Is $f(x_2)$ still ridiculously far from 0? Or are we getting close?

The same curve with a second tangent line drawn at x_2; its x-intercept x_3 is closer to the root

Still off? Cool. Draw the tangent line at $(x_2, f(x_2))$, take its x-intercept, call it $x_3$, judge again, and keep going~~~~ and going~~~~ and going~~~~

Done~

Honestly mind-blowing. And honestly โ€” kind of insane that someone thought of this in the first place.

OK now write it down

So we kinda get the vibe. Now we have to turn it into formulas, because the computer doesn’t speak English (or Korean, or whatever), it speaks math.

The computer is basically asking us:

“hey jerk โ€” x_n to x_{n+1}, what’s the rule? How do I get from one to the other??”

OK. The tangent line at the point (x_n, f(x_n)) is:

The tangent line at that point: y = f’(x_n)(x_{n+1} - x_n) + f(x_n)

Undeniable. Slope is $f'(x_n)$, line passes through (x_n, f(x_n)) โ€” that’s literally just point-slope form.

And $x_{n+1}$ is the $x$ where this tangent line hits $y = 0$. Set $y = 0$, solve for $x$, and:

Algebra: put y = 0 in the tangent line equation and solve it for x_{n+1}

Boom. That’s the recurrence.

Easy!!!!

Let’s play

Let’s use this on our usual suspect:

The equation x^3 - 5x^2 + 3x - 2.7 = 0

(Why is it ALWAYS this one???? Because I already wrote the function for it last time^^ heh heh heh if you want a different example, you write it^^^^)

Ugh, but… we need a new function. Specifically, we need one for the derivative. Ughhhhhh ;_;

OK OK OK OK. The derivative of that thing is something an 11th grader can do in their sleep. Bang it out. Then on to the code.

Handwritten VBA function f(x) that returns x^3 - 5x^2 + 3x - 2.7

This one’s the function we used for bisection last time~~

Handwritten VBA function f_d(x) that returns the derivative 3x^2 - 10x + 3, with a margin note on why Newton-Raphson needs it

This one is just the derivative of it โ€” differentiated by hand and dropped into a function.

Handwritten VBA sub that solves the equation with the Newton-Raphson loop, with margin notes on each step

Easy, right? We literally just used the principle we walked through above:

Algebra solving the tangent line for x_{n+1}, same as before

That’s it. heh.

Now the actual implied vol part

OK, now using Newton-Raphson, let’s go extract the implied volatility of an option.

Wait hold on. Newton-Raphson needs $f(x)$ AND $f'(x)$, right? So before we sprint ahead, there’s something worth thinking about.

Plot of the option price from the BS formula rising with sigma, crossed by the horizontal line of the market price; the sigma at the crossing is the one we want to find

I drew option price as an increasing function of $\sigma$ โ€” is that actually right?

Yeah, it should be. An option’s downside is capped (the payoff never goes below zero), so more volatility only adds to its value. I mentioned this somewhere before โ€” over here, I think.

Anyway. What we want is the $\sigma$ at the intersection point over there. That is:

$$\text{BS\_formula}(\sigma) - \text{market price} = 0$$

Let’s call the left side $f(\sigma)$:

$$f(\sigma) = \text{BS\_formula}(\sigma) - \text{market price}$$

We want $f(\sigma) = 0$. And the derivative we need for Newton-Raphson is $f'(\sigma)$:

$$f'(\sigma) = \text{BS\_formula}'(\sigma) - 0$$

The market price is a constant, so its derivative with respect to $\sigma$ is 0.

So what I’m trying to say is โ€”

The derivative f’(sigma) is exactly the partial derivative of f with respect to sigma, which is vega

THAT is the thing!!!! The derivative we need for Newton-Raphson is vega!!!

Eek!!! AND!!! We’ve already learned about vega before!!!

OK so. Now in our $y = f(x)$ Newton-Raphson recurrence,

The Newton-Raphson recurrence for x_{n+1} in terms of x_n, f and f’

the relationship between these โ€” how do we use it here~~

Based on everything above, we can just write it like this:

The same recurrence written for implied volatility: sigma_{n+1} from sigma_n, the BS formula minus the market price, and vega

Let’s code it

Time to actually code it up and find the implied volatility.

VBA code: the Black-Scholes function BS and the vega function

VBA code: the Newton-Raphson implied volatility function and its test sub, with the printed results in the Immediate window

In the output you’ll see a bunch of implied volatility values โ€” that’s because I tried it with a bunch of different initial volatility values. They all converge to the same number.

But โ€” you might be feeling a little uneasy about that initial volatility, right? And if you plug in something absurdly large there, vega comes out as 0, and the code just dies.

So picking the initial volatility appropriately turns out to matter.

Apparently there’s a lot of research on this. But it’s not what I’m focused on right now, so I’ll skip it. I just plugged in some arbitrary value.

(Honestly, just using the historical volatility is probably fine too.)

Anyway, let’s keep moving heh heh

Handwritten VBA code: the vega function and the Newton-Raphson implied volatility function, with margin notes

Handwritten VBA code: a test sub that calls the implied volatility function

Python version!

import math
import scipy as sp
import scipy.stats

norm = sp.stats.norm(loc=0, scale=1)

def BS(S, k, r, sigma, t, opOption):
    d1 = (math.log(S / k) + r * t) / (sigma * math.sqrt(t)) + 0.5 * sigma * math.sqrt(t)
    d2 = d1 - (sigma * math.sqrt(t))
    if opOption == True:
        bi = 1
    else:
        bi = -1
    BS = bi * (S*norm.cdf(bi*d1) - k*math.exp(-r*t)*norm.cdf(bi*d2))
    return BS

def vega(S, k, r, sigma, t):
    d1 = (math.log(S / k) + (r * t)) / (sigma * math.sqrt(t)) + 0.5 * sigma * math.sqrt(t)
    vega = S*math.sqrt(t) * norm.pdf(d1)
    return vega

def IV_using_NewtonRaphson(S, k, r, t, real_price, opOption):
    epsilon = 0.0000000000001
    sigma = 1
    bs_value = BS(S=S, k=k, r=r, sigma=sigma, t=t, opOption=opOption)
    while abs(bs_value - real_price) > epsilon:
        bs_value = BS(S=S, k=k, r=r, sigma=sigma, t=t, opOption=opOption)
        diff = real_price - bs_value
        vega_value = vega(S=S, k=k, r=r, sigma=sigma, t=t)
        sigma = sigma + (diff/vega_value)
    return sigma

S=50; k=50; r=0.1; t=0.5
real_price = 2.5
opOption=True
IV_using_NewtonRaphson(S=S, k=k, r=r, t=t, real_price=real_price, opOption=opOption)

PyCharm screenshot: the folded Python code and the console output 0.050041632022373904


Heads-up. The figures here are the original notes, slips and all. A few things to watch for:

  • In the derivation pictures, the step needs a minus sign: from $f'(x_n)(x_{n+1} - x_n) = -f(x_n)$ it follows that $x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}$, and for the volatility $\sigma_{n+1} = \sigma_n - \frac{BS(\sigma_n) - \text{market price}}{\text{vega}(\sigma_n)}$. The code in the post subtracts, as it should.
  • In the handwritten Solve sub, the last Debug.Print should format the solution x_n, not c.
  • In the VBA BS function, IIf(callput, 1, -1) should use the parameter: IIf(opOption, 1, -1). As written, callput is an empty, undeclared variable, so bi is always -1 and the function prices the put: the 1.2751106577 in the Immediate window is the put’s implied volatility, while the call’s is about 0.3964. In the vega function, s + Sqr(t) should be s * Sqr(t).

Comments

Discussion happens via GitHub Discussions. You'll need a GitHub account to comment.