Explicit Finite Difference Method (FDM)

Can't solve Black-Scholes analytically? No sweat — we slice the (t, S) plane into a grid, lock down the boundary values, and sneak our way to the rest one point at a time.

Picking up right where we left off last time. So in the Black-Scholes PDE,

The Black-Scholes PDE: ∂f/∂t + rS ∂f/∂S + ½σ²S² ∂²f/∂S² − rf = 0

…for the terms sitting in there, we’ve now got all the “approximation formulas” for the 1st-order and 2nd-order derivatives prepped and ready.

OK then, quick reminder of what we’re actually trying to do. We can’t find an analytic solution $f(t,S)$ that solves this PDE. Why? Because that PDE is, in general, one of those PDEs you just can’t solve in closed form.

(Kind of like the Schrödinger equation in the nasty cases, maybe…?)

But we still want to know $f(t,S)$. That’s the whole problem. T_T

So what sneaky trick did we cook up?

Hand-drawn 3D axes t, S and f

Since we can’t just draw $f(t,S)$ as one function in a space like this — zzzip! —

Hand-drawn (t, S) plane with three points, each labelled ‘f value = ?’

let’s mark the function value at each $(t,S)$, one by one, like in the picture above!!! That’s the move.

Why this is even possible

Now, the reason this is even possible: options have this peculiar property — namely, the value of the option at maturity is $\max(S-k,\ 0)$. And because options have that going for them,

The (t, S) plane with the maturity line T circled: f value known for sure

at least along here, we can flat-out say $f = \max(S-k,\ 0)$. And also,

The same plane with the S = 0 axis circled too: f is 0 here

when $S=0$ like this, we can also say the option value is 0.

The same plane with the S_max row circled as well: fix one price S_max and the f values on that row are set

Also! Let’s set some upper bound on the underlying price $S$.

(There’s no way the underlying price actually shoots off to infinity, riiight??? So we can pin down some cap that’s high enough.)

So once we fix one max price for $S$, at $S_{\max}$, for all $t$ — since $S$ is always going to be bigger than $k$ there — the option value $f$ at each $t$ is

F = S_max − k e^(−r(Δt))

We can just say that!!!

So putting it all together,

Empty (t, S) axes

out of the giant pile of values we have to figure out, it turns out we’ve already found everything along the “boundary” — the one shaped like a backwards C….

OK so then, how do we find the inside?

Finding it for continuous $S$ and $t$? Impossible. (If we could do that, we’d basically be solving the PDE analytically (?).) So instead of aiming for continuously varying $S$ and $t$, let’s first find it “sparsely”!!!

Slicing up the plane

We’re going to slice up that coordinate plane: cut $S$ into $n$ equal pieces, cut $T$ into $m$ equal pieces. Same-size chunks. Equal divisions. And since the spacings are uniform, the spacing $\Delta S$ along the $S$-axis is

ΔS = (S_max − 0)/n

And on the $t$-axis, since we’re cutting from now up to maturity $T$ into $m$ chunks,

ΔT = (T − 0)/m

OK so now, how do we want to express the option price $f$? We’re not going to ask “when we’re at (t_1, S_1), the option value f(t_1, S_1) — how much is it~~~~?”

Instead, we go $i$ steps of $\Delta T$ in the $t$ direction and $j$ steps of $\Delta S$ in the $S$ direction, and we’ll ask “what’s the option value f_{i,j} there~~~~~~?”

(Don’t get spooked when $f_{i,j}$ shows up, heh heh heh heh.)

Ahhhhh OK so if we look at this whole setup as a picture,

The (t, S) plane cut into a grid: S_j = j × ΔS, t_i = iΔT

what we want to do is figure out every single f_{i,j} sitting at every dotted-line intersection.

But!!! Don’t forget — for all the f_{i,j} sitting on that backwards-C boundary over there, we already know the answer~~!!!

The grid with the known boundary points marked: the S_max row, the maturity column and the S = 0 row

Those dots right there. heh heh heh — kya kya kya.

Explicit FDM

Alright. Now let me actually get into Explicit FDM. In “Financial Engineering Programming I Studied,” among the FDM family, we’ll cover 3 flavors of FDM: Explicit FDM, Implicit FDM, Crank-Nicolson FDM — those 3, and Explicit FDM is the very first one!!!

First up, let’s get the dictionary definition out of the way.

Finite Difference Method: a method for numerically analyzing a PDE by approximating it as a difference equation. Or: a method for numerically getting the solution by carving the space governed by the differential equation into a small grid.

That’s the gist. From here on we get into the actual Explicit FDM procedure for cracking the PDE — and as for why it’s called “Explicit,” well, in like… 60 seconds??? you’ll just automatically get it.

First, in

The Black-Scholes PDE again

we’re going to “approximate” all the partial derivative terms of our troublemaker function. How?

The PDE with arrows from each derivative term to the kind of difference that approximates it

Like this — we substitute each term in this exact way.

The three difference approximations for ∂f/∂t, ∂f/∂S and ∂²f/∂S²

“Why backward for $t$ and central for $S$???” you ask?

Answer: so we can solve the thing “Explicitly”!!! That’s all I can tell you for now…. Huh??? About 40 seconds left. In 40 seconds you’ll just see it. ^^ heh heh

OK so if we sub each of those into the PDE (real talk, typing this out in the equation editor is total madness, but let me try once),

The PDE with the approximations substituted, then expanded term by term

I’ll only get that far in the equation editor — below this point my handwriting is gonna serve us better.

(“My handwriting is gonna serve us better.” = “I’m too lazy to keep typing this in the equation editor.”) Synonyms. Honestly when am I ever gonna finish typing all that, lol

Handwritten algebra solving for f_{i−1,j} = a_j f_{i,j+1} + b_j f_{i,j} + c_j f_{i,j−1}

Yay~~~~~ all cleaned up~~~~~

When we “approximate” the PDE in this form, we can find every single $f_{i,j}$. Let’s see why. If we think of that tidied-up equation simply as

F_{i−1,j} = (some coef.) f_{i,j+1} + (some coef.) f_{i,j} + (some coef.) f_{i,j−1}

— this form — then

Handwritten note: f_{i−1,j} and f_{i,j+1}, f_{i,j−1}, f_{i,j}, their relative positions on the grid look like

this!!!!

F_{i−1,j} one step left of the column f_{i,j+1}, f_{i,j}, f_{i,j−1}, which are one step apart

Each one sits at a spot like this in the grid!!!

Aha!!! So the option value at an arbitrary position — $i$ along $t$ and $j$ along $S$ — is the sum, with appropriate coefficients, of three values sitting at $j+1$, $j$, $j-1$ at the $i+1$ position in $t$!!

F_{i,j} with arrows from f_{i+1,j+1}, f_{i+1,j} and f_{i+1,j−1}

What I’m saying is, $f_{i,j}$ is just the right blend of those 3 option values $f_{i+1,j+1}$, $f_{i+1,j}$, $f_{i+1,j-1}$ sitting over there!!!

Whoa, hold on though — don’t we also not know those 3 values??!?

Nope… we know the boundary.

Grid: from the known boundary, the column one step before maturity gets filled

Because we know the boundary, this process lets us find every $f$ value one step back in $t$. ha.

Then using those values we just found,

The next column back gets filled from the one before

we can find the one a step further back.

And so on, all the way back

Same logic, keeeeep going back — trivial from here, right??!?

OK so — getting a feel for why this FDM is called Explicit FDM in the first place???

In econ there’s a term for a cost measured exactly as it visibly shows up. In English it’s called an “explicit cost,” and in the same spirit, I think this FDM got its name because $f_{i,j}$ is determined explicitly from the visible “$f_{\text{maturity}, j}$ values.”

Coding it up

Alright, let’s actually code this thing up. I’ll do it for a European Call. Since it’s a European call, the boundary condition at $t = \text{maturity}(T)$ is $\max(\Delta S \cdot j - k,\ 0)$, right???? OK let’s go.

Handwritten VBA program (top half) with margin notes

Handwritten VBA program (bottom half) and the check of the coefficients a_j, b_j, c_j

I actually went and coded this myself!!!

The VBA program in the editor and its Immediate window output

I mentioned this above when we were doing concepts, but when you plug in the boundary conditions in the code,

Sketch of where the boundary loops write their values

notice how I plug them in like this. And I know I covered it once before way back, but I’ll briefly redo array declarations one more time.

Handwritten note on ways to declare an array in VBA

OK so now, instead of just one value like $f_{3,3}$, let’s set the code up so that we get out every $f_{i,j}$ across the whole grid.

Handwritten VBA program for the whole grid (top half) with margin notes

Handwritten VBA program for the whole grid (bottom half) with margin notes

I’ll code this one up too!!!

The full-grid VBA program and its output: option prices for S = 0, 25, 50, 75, 100

Surprisingly simple, right??!? Surprisingly easy. But — the Implicit FDM and Crank-Nicolson FDM coming up next are not gonna be a pushover.

Hehehe. Alright, see you next time heh

Python version

k=50; r=0.05; t=0.5; v=0.3; smax=100
m=4; n=4
ds = smax/m
dt=t/n
import pandas as pd
import math
df = pd.DataFrame(index=[x for x in range(n+1)],
                  columns=[y for y in range(m+1)])
for j in range(1, m):
    df.loc[n, j] = max(j * ds - k, 0)
for i in range(0, n+1):
    df.loc[i, 0] = max(0, 0)
for i in range(0, n+1):
    df.loc[i, m] = max(m*ds - k*math.exp(-r*(n-i)*dt), 0)
for i in range(n-1, 0-1, -1):
    for j in range(m-1, 1-1, -1):
        C = 0.5 * dt * (-r * j + (v**2)*(j**2))
        B = 1 - ((v*j)**2)*dt - r*dt
        A = 0.5 * dt * (r*j + (v**2)*(j**2))
        df.loc[i, j] = C*df.loc[i+1, j-1] + B*df.loc[i+1, j] + A*df.loc[i+1, j+1]
for j in range(0, m+1):
    print('stock price : ', j*ds, "option price: ", round(df.loc[0, j], 2))

The Python version in PyCharm with the same output


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

  • In the one-step VBA example (handwritten and typed), the a3 term needs the node above, f(4,4): f33 = a3f(4,4) + b3f(4,3) + c3*f(4,2) prints 25.31 rather than 23.81, the same value the full-grid program gives for that node.
  • In the difference pictures, the central difference for $\frac{\partial f}{\partial S}$ divides by $2\Delta S$ (not $2\Delta t$), and the second derivative is $\frac{\partial^2 f}{\partial S^2}$.
  • At the upper boundary, the call is worth $S_{max} - K e^{-r(T-t)}$, with the time to maturity $T - t$ in the exponent, as in the code’s Exp(-r*(n-i)*dt).

Comments

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