Implicit Finite Difference Method (FDM) — Part 2
Walking through the Implicit FDM code for pricing a European call — from a 3×3 matrix to the fully generalized grid, step by step and hehe all the way!
We got a thousand-troop reinforcement in the previous post!!!!
No matter what Ax = b matrix equation is given to us,
we’ve got a function procedure that can crack them all wide open!!!!!
This is seriously full-on thousand-troop-reinforcement energy for real lolololololololololol
So now let’s price a European call with Implicit FDM!
For now, to keep the coding simple — that equation we derived earlier by splitting the grid into 5 pieces, the one that became a 3x3 matrix equation, you know that one~

Let’s try coding this up~
Wait no, not coding it — understanding the given code!
Let’s do that hehe
The code goes like this.

I did it in Python too! hehehe


My own studying of this code went like this.


This time, let’s study the code that generalizes so all f_i,j get derived
And for that, there’s one thing I want to nail down one more time
The Implicit FDM method
approximated the Black-Scholes PDE
with a central difference for the first derivative in S
and a forward difference for the first derivative in t
And when I worked it out

it came out like this,
and depending on how many pieces you chopped S into, the number of unknowns changed
Here the unknowns aren’t f_i+1, j but rather f_i,j+1, f_i,j, f_i,j-1
When we cut it into five pieces, these three were the unknowns
and we needed 3 equations to find those 3 unknowns… yeah
ahhhh haha so then if we cut it into 7, 5 unknowns show up?
And to find all 5 unknowns we’d need 5 equations?????
Let’s lightly look at how those five come about and move on

Just write it down and substitute, that should do it
The boundaries — j=0, j=7, i=i+1 will be the boundaries~~~ is what we’ll say (I won’t say exactly what i is)
If we write out the 5 equations that have boundary values

it’s these 5 equations,
and if we check just the unknowns here

these here are the unknowns, y’see??? So the unknown x-vector gets written with these, and we can write the matrix equation somethin’ like this~

We can write it somethin’ like this~…
Writing it like this, I kinda get the rule~
And through this process we find f_i,~~,
and through the next process we find f_i-1,~~,
and goiiiing back and back until i=0 is all done,
wouldn’t we end up finding all the f_i,j on the grid????
Ah…. and one thing to watch carefully — a_j, b_j, c_j needed in the matrix are not from 1 to 7 but from 2 to 6!!!! hehe
That is, not j=1, j=7 but from 2 to 6!!!!!!
From just above the boundary to just below the boundary is what’s needed~~~
Also, the shape of the matrix is somewhat worth paying attention to.

a, b, c get written in this kinda diagonal shape!!!~~
Alright then, let’s study the code that finds all f_i,j! hehehe


This one too — I did it in Python! hehehe


This right here is the code~!!!!
This is how I looked at this code!!!



From here we can also simply pull out the Greeks
We went over pulling out these Greeks in class too
Once you get the principle it’s ridiculously simple
so there’s no particular interpretation for this one lololol
Just “oh, so we can check the Greeks like this too~~~~”
something like that??????????????????
For detailed Greeks, here’s the link http://gdpresent.blog.me/220887482357

Black-Scholes formula practice problems [ Derivatives I studied #17 ]
So now we’re going to solve the problems in Chapter 13, and there’s one thing to point out before solving them.Black and …
gdpresent.blog.me



Python code
import numpy as np
import math
def Solve_SE(matA, matb):
rowA = len(matA)
colA = len(matA.T)
rowB = len(matb)
if (rowA != colA) | (rowB != colA):
raise NotImplementedError
else:
pass
L = np.zeros((rowA, colA))
U = np.zeros((rowA, colA))
for j in range(0, len(L.T)):
for i in range(0, len(L)):
if j==0:
L[i, j] = matA[i, j]
U[j, i] = matA[j, i] / L[0, 0]
else:
if i < j:
L[i, j] = 0
else:
Lsum = 0
for k in range(0, j):
Lsum = Lsum + L[i, k]*U[k, j]
L[i, j] = matA[i, j] - Lsum
if i < j:
U[j, i] = 0
elif i == j:
U[j, i] = 1
else:
Usum = 0
for k in range(0, i):
Usum = Usum + L[k, i]*U[j, k]
U[j, i] = (matA[j, i] - Usum) /L[j, j]
modB = np.zeros((3, len(matb.T)))
modB[0] = matb[0] / L[0, 0]
for i in range(0, len(modB)):
sumofB = 0
for k in range(0, i):
sumofB = sumofB + L[i, k]*modB[k]
modB[i] = (matb[i] - sumofB) / L[i, i]
x = np.zeros((3, len(modB.T)))
for no in range(len(x)-1, 0-1, -1):
sum=0
for i in range(0, len(x)):
sum = sum + U[no, i] * x[i]
x[no] = modB[no] - sum
return x
k=50; r=0.05; t=0.5; v=0.3; smax=100
m=4; n=4
ds = smax / m
dt = t/n
f = np.zeros((n+1, m+1))
for j in range(1, m):
f[n, j] = max(j*ds - k, 0)
for i in range(0, n+1):
f[i, 0] = max(0, 0)
for i in range(0, n+1):
f[i, m] = max(m*ds - k*math.exp(-r*(n-i)*dt), 0)
j=3
a3 = 0.5 * dt * (r*j - (v**2)*(j**2))
b3 = 1 + ((v*j)**2)*dt + r*dt
c3 = 0.5 * dt * (-r*j - (v**2)*(j**2))
j=2
a2 = 0.5 * dt * (r*j - (v**2)*(j**2))
b2 = 1 + ((v*j)**2)*dt + r*dt
c2 = 0.5 * dt * (-r*j - (v**2)*(j**2))
j=1
a1 = 0.5 * dt * (r*j - (v**2)*(j**2))
b1 = 1 + ((v*j)**2)*dt + r*dt
c1 = 0.5 * dt * (-r*j - (v**2)*(j**2))
matA = np.zeros((3, 3))
matA[0, 0] = b3; matA[0, 1] = a3; matA[0, 2] = 0
matA[1, 0] = c2; matA[1, 1] = b2; matA[1, 2] = a2
matA[2, 0] = 0; matA[2, 1] = c1; matA[2, 2] = b1
matb = np.zeros((3, 1))
matb[0] = f[4, 3] - c3*f[3, 4]
matb[1] = f[4, 2]
matb[2] = f[4, 1] - a1*f[3, 0]
matx = Solve_SE(matA, matb)
for i in range(len(matx)):
print('option price: ', round(float(matx[i]), 4))
import numpy as np
import math
def Solve_SE(matA, matb):
rowA = len(matA)
colA = len(matA.T)
rowB = len(matb)
if (rowA != colA) | (rowB != colA):
raise NotImplementedError
else:
pass
L = np.zeros((rowA, colA))
U = np.zeros((rowA, colA))
for j in range(0, len(L.T)):
for i in range(0, len(L)):
if j==0:
L[i, j] = matA[i, j]
U[j, i] = matA[j, i] / L[0, 0]
else:
if i < j:
L[i, j] = 0
else:
Lsum = 0
for k in range(0, j):
Lsum = Lsum + L[i, k]*U[k, j]
L[i, j] = matA[i, j] - Lsum
if i < j:
U[j, i] = 0
elif i == j:
U[j, i] = 1
else:
Usum = 0
for k in range(0, i):
Usum = Usum + L[k, i]*U[j, k]
U[j, i] = (matA[j, i] - Usum) /L[j, j]
modB = np.zeros((len(matb), 1))
modB[0] = matb[0] / L[0, 0]
for i in range(0, len(modB)):
sumofB = 0
for k in range(0, i):
sumofB = sumofB + L[i, k]*modB[k]
modB[i] = (matb[i] - sumofB) / L[i, i]
x = np.zeros((len(modB), 1))
for no in range(len(x)-1, 0-1, -1):
sum=0
for i in range(0, len(x)):
sum = sum + U[no, i] * x[i]
x[no] = modB[no] - sum
return x
k=50; r=0.05; t=0.5; v=0.3; smax=100
m=10; n=10
ds = smax / m
dt = t/n
matdim=m-2
f = np.zeros((n+1, m+1))
matA = np.zeros((matdim+1, matdim+1))
matb = np.zeros((matdim+1, 1))
A = np.zeros((matdim+1, 1))
B = np.zeros((matdim+1, 1))
C = np.zeros((matdim+1, 1))
for j in range(1, m):
f[n, j] = max(j*ds - k, 0)
for i in range(0, n+1):
f[i, 0] = max(0, 0)
for i in range(0, n+1):
f[i, m] = max(m*ds - k*math.exp(-r*(n-i)*dt), 0)
for j in range(m-1, 1-1, -1):
A[j-1] = 0.5 * dt * (r * j - (v ** 2) * (j ** 2))
B[j-1] = 1 + ((v * j) ** 2) * dt + r * dt
C[j-1] = 0.5 * dt * (-r * j - (v ** 2) * (j ** 2))
for i in range(n-1, 0-1, -1):
mm = matdim
for ii in range(0, matdim+1):
for jj in range(0, matdim+1):
if ii == jj +1:
matA[ii, jj] = C[mm]
elif ii == jj:
matA[ii, jj] = B[mm]
elif ii+1 == jj:
matA[ii, jj] = A[mm]
else:
matA[ii, jj] = 0
mm=mm-1
matb[0] = f[i+1, m-1] - C[matdim]*f[i,m]
matb[matdim] = f[i+1, 1] - A[0]*f[i,0]
for jj in range(matdim-1, 1-1, -1):
matb[jj] = f[i+1, jj+1]
matx = Solve_SE(matA, matb)
jj=m-1
for ii in range(len(matx)):
f[i, jj]=matx[ii]
jj=jj-1
for j in range(m+1):
print("stock price: ", j*ds, "option price: ", round(f[0, j], 2))
Originally written in Korean on my Naver blog (2016-12). Translated to English for gdpark.blog.