%pylab inline
lecture = 13
import sys
sys.path.append("lib")
import fmt
import sympy as sp
import pandas as pd
from IPython.display import display
assert sp.__version__ == "0.7.5", "Need sympy version 0.7.5 to render properly"
sp.init_printing(use_latex = True)
Populating the interactive namespace from numpy and matplotlib
ea△t={12σ2x2j△t△x2−rxj△t2△x}e−ilm△x+{1−σ2x2j△t△x2−r△t}+{12σ2x2j△t△x2+rxj△t2△x}eilm△x
ea△t=1−r△t+σ2x2j△t△x2⋅2sin2(lm△x/2)+irxj△t△xsin(lm△x)
r>0,△t<△x2σ2x2max,△t<σ2r2.
The first condition is trivial (until the FED decrees all rates to be negative!)
The last condition does not have much impact in practice unless the volatility is very small.
So the important one is the second condition, which is what we went through last lecture.
dSt=rStdt+√νtStdW1tdνt=κ(θ−νt)+ξ√νtdW2t⟨dW1t,dW2t⟩=ρdt
∂u∂t+rS∂u∂S+[κ(θ−ν)−λν]∂u∂ν+12νS2∂2u∂S2+ρξνS∂2u∂S∂ν+12ξ2ν∂2u∂ν2−ru=0
ui,k+1−ui,k△t=14σ2x2i{ui+1,k−2ui,k+ui−1,k△x2+ui+1,k+1−2ui,k+1+ui−1,k+1△x2}+12rxi{ui+1,k−ui−1,k2△x+ui+1,k+1−ui−1,k+12△x}−12r{ui,k+ui,k+1}=12D⋅(ui,k+ui,k+1)
where D⋅ui,k can be considered as the Crank-Nicolson finite difference operator on ui,k.
(1+12△tD)⋅ui,k+1=(1−12△tD)⋅ui,k
This is also applicable when the spatial variable xi is a vector.
For the one spatial variable case, the operator D involves three points in one time slice.
For two dimension case (the Heston model above), the operator will involve five points in one time slice.
So instead of solving a tridiagonal system, now the linear system has five nonzero diagonals, whcih is much more costly to solve.
(1+12△tD1)⋅˜u1i,k+1=(1−12△tD1)⋅ui,k(1+12△tD2)⋅˜u2i,k+1=(1−12△tD2)⋅˜u1i,k⋮(1+12△tDn)⋅˜uni,k+1=(1−12△tDn)⋅˜un−1i,k
and set
ui+1,k=˜uni,k
import numpy as np
from scipy.stats import norm
import time
#Black and Scholes
def BlackScholesFormula(type, S0, K, r, sigma, T):
dtmp1 = np.log(S0 / K)
dtmp2 = 1.0/(sigma * np.sqrt(T))
sigsq = 0.5 * sigma * sigma
d1 = dtmp2 * (dtmp1 + T * (r + sigsq))
d2 = dtmp2 * (dtmp1 + T * (r - sigsq))
if type=="C":
return S0 * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
else:
return K * np.exp(-r * T) * stats.cdf(-d2) - S0 * norm.cdf(-d1)
K = 100.0
r = 0.05
sigma = 0.35
T = 1
putCall ='C'
Smin = 0.0
Smax = 200.0
ns = 201
Ss = np.linspace(Smin, Smax, ns, endpoint=True)
Ss = Ss[1:-1]
#print Ss
t=time.time()
px = BlackScholesFormula(putCall, Ss, K, r, sigma, T)
elapsed=time.time()-t
print px
print "Elapsed Time:", elapsed
#idx = 200-1
#print Ss[idx]
#print px[idx]
payoff = clip(Ss-K, 0.0, 1e600)
#print "payoff = ", payoff
figure(figsize=[10, 4])
subplot(1, 2, 1)
plot(Ss, payoff)
xlabel('Stock', fontsize=14);
title('Payoff' , fontsize=16);
subplot(1, 2, 2)
plot(Ss, px)
xlabel('Stock', fontsize=14);
title('Analytical Solution' , fontsize=16);
[ 1.28766561e-39 5.53362091e-29 1.53135787e-23 5.00445199e-20 1.68889238e-17 1.46407871e-15 5.18474263e-14 9.78800798e-13 1.16276880e-11 9.70067620e-11 6.13310850e-10 3.10394648e-09 1.30958867e-08 4.75053666e-08 1.51752856e-07 4.35044961e-07 1.13639156e-06 2.73830396e-06 6.14907826e-06 1.29773535e-05 2.59235792e-05 4.93116756e-05 8.97803630e-05 1.57147519e-04 2.65452935e-04 4.34175578e-04 6.89611730e-04 1.06639082e-03 1.60909722e-03 2.37395905e-03 3.43056014e-03 4.86352770e-03 6.77414796e-03 9.28186285e-03 1.25256040e-02 1.66649252e-02 2.18809002e-02 2.83767600e-02 3.63782504e-02 4.61336992e-02 5.79137892e-02 7.20110398e-02 8.87390076e-02 1.08431222e-01 1.31439872e-01 1.58134278e-01 1.88899163e-01 2.24132765e-01 2.64244808e-01 3.09654380e-01 3.60787729e-01 4.18076027e-01 4.81953109e-01 5.52853236e-01 6.31208890e-01 7.17448635e-01 8.11995048e-01 9.15262759e-01 1.02765660e+00 1.14956987e+00 1.28138275e+00 1.42346084e+00 1.57615385e+00 1.73979446e+00 1.91469728e+00 2.10115801e+00 2.29945271e+00 2.50983725e+00 2.73254683e+00 2.96779573e+00 3.21577708e+00 3.47666283e+00 3.75060382e+00 4.03772986e+00 4.33815003e+00 4.65195304e+00 4.97920754e+00 5.31996271e+00 5.67424873e+00 6.04207739e+00 6.42344276e+00 6.81832181e+00 7.22667519e+00 7.64844792e+00 8.08357019e+00 8.53195807e+00 8.99351435e+00 9.46812932e+00 9.95568151e+00 1.04560385e+01 1.09690578e+01 1.14945874e+01 1.20324666e+01 1.25825269e+01 1.31445924e+01 1.37184810e+01 1.43040045e+01 1.49009696e+01 1.55091783e+01 1.61284289e+01 1.67585161e+01 1.73992318e+01 1.80503657e+01 1.87117056e+01 1.93830378e+01 2.00641481e+01 2.07548214e+01 2.14548427e+01 2.21639973e+01 2.28820712e+01 2.36088511e+01 2.43441252e+01 2.50876830e+01 2.58393160e+01 2.65988176e+01 2.73659834e+01 2.81406114e+01 2.89225024e+01 2.97114597e+01 3.05072897e+01 3.13098016e+01 3.21188080e+01 3.29341245e+01 3.37555702e+01 3.45829676e+01 3.54161424e+01 3.62549242e+01 3.70991457e+01 3.79486436e+01 3.88032578e+01 3.96628321e+01 4.05272138e+01 4.13962537e+01 4.22698063e+01 4.31477298e+01 4.40298856e+01 4.49161390e+01 4.58063586e+01 4.67004164e+01 4.75981879e+01 4.84995522e+01 4.94043912e+01 5.03125907e+01 5.12240391e+01 5.21386286e+01 5.30562539e+01 5.39768133e+01 5.49002078e+01 5.58263413e+01 5.67551209e+01 5.76864561e+01 5.86202595e+01 5.95564461e+01 6.04949339e+01 6.14356432e+01 6.23784968e+01 6.33234201e+01 6.42703407e+01 6.52191888e+01 6.61698966e+01 6.71223986e+01 6.80766314e+01 6.90325338e+01 6.99900465e+01 7.09491123e+01 7.19096758e+01 7.28716834e+01 7.38350835e+01 7.47998261e+01 7.57658631e+01 7.67331477e+01 7.77016349e+01 7.86712814e+01 7.96420452e+01 8.06138857e+01 8.15867639e+01 8.25606420e+01 8.35354837e+01 8.45112537e+01 8.54879183e+01 8.64654447e+01 8.74438014e+01 8.84229580e+01 8.94028851e+01 9.03835545e+01 9.13649388e+01 9.23470118e+01 9.33297481e+01 9.43131232e+01 9.52971137e+01 9.62816968e+01 9.72668506e+01 9.82525541e+01 9.92387868e+01 1.00225529e+02 1.01212762e+02 1.02200468e+02 1.03188629e+02 1.04177229e+02] Elapsed Time: 0.000999927520752
from scipy import sparse
import scipy.sparse.linalg.dsolve as linsolve
class BS_FDM_explicit:
def __init__(self,
r,
sigma,
maturity,
Smin,
Smax,
Fl,
Fu,
payoff,
nt,
ns):
self.r = r
self.sigma = sigma
self.maturity = maturity
self.Smin = Smin
self.Smax = Smax
self.Fl = Fl
self.Fu = Fu
self.nt = nt
self.ns = ns
self.dt = float(maturity)/nt
self.dx = float(Smax-Smin)/(ns+1)
self.xs = Smin/self.dx
self.u = empty((nt + 1, ns))
self.u[0,:] = payoff
## Building Coefficient matrix:
A = sparse.lil_matrix((self.ns, self.ns))
for j in xrange(0, self.ns):
xd = j + 1 + self.xs
sx = self.sigma * xd
sxsq = sx * sx
dtmp1 = self.dt * sxsq
dtmp2 = self.dt * self.r
A[j,j] = 1.0 - dtmp1 - dtmp2
dtmp1 = 0.5 * dtmp1
dtmp2 = 0.5 * dtmp2 * xd
if j > 0:
A[j,j-1] = dtmp1 - dtmp2
if j < self.ns - 1:
A[j,j+1] = dtmp1 + dtmp2
self.A = A.tocsr()
### Building bc_coef:
nxl = 1 + self.xs
sxl = self.sigma * nxl
nxu = self.ns + self.xs
sxu = self.sigma * nxu
self.blcoef = 0.5 * self.dt * (sxl * sxl - self.r * nxl)
self.bucoef = 0.5 * self.dt * (sxu * sxu + self.r * nxu)
def solve(self):
for i in xrange(0, m):
self.u[i+1,:] = self.A * self.u[i,:]
self.u[i+1,0] += self.blcoef * self.Fl[i]
self.u[i+1,self.ns-1] += self.bucoef * self.Fu[i]
return self.u
dx = (Smax - Smin)/(ns-1)
print "ns =", ns
print "dx =", dx
print "sigma =", sigma
dt_max = dx*dx/(sigma*sigma*Smax*Smax)
print "by CFL, dt <", dt_max
mt_min = int(T/dt_max)+1
print "mt_min ~= ", mt_min
ns = 201 dx = 1.0 sigma = 0.35 by CFL, dt < 0.000204081632653 mt_min ~= 4900
n = ns-2
X = linspace(0.0, Smax, n+2)
X = X[1:-1]
payoff = clip(X-K, 0.0, 1e600)
#print "payoff = ", payoff
m = 4555
Fl = zeros((m+1,))
Fu = Smax - K*exp(-r * linspace(0.0, T, m+1))
t = time.time()
bs1 = BS_FDM_explicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs1.solve()
elapsed=time.time()-t
print "Elapsed Time1:", elapsed
##print px_fd_mat.shape
nrow = len(px_fd_mat[:,1])
print px_fd_mat[nrow-1,:]
figure(figsize=[15, 4]);
subplot(1, 3, 1)
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 4560
Fl = zeros((m+1,))
Fu = Smax - K*exp(-r * linspace(0.0, T, m+1))
t = time.time()
bs2 = BS_FDM_explicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs2.solve()
elapsed=time.time()-t
print "Elapsed Time2:", elapsed
subplot(1, 3, 2)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 4565
Fl = zeros((m+1,))
Fu = Smax - K*exp(-r * linspace(0.0, T, m+1))
t = time.time()
bs3 = BS_FDM_explicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs3.solve()
elapsed=time.time()-t
print "Elapsed Time3:", elapsed
subplot(1, 3, 3)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f' % m, fontsize=16);
Elapsed Time1: 0.0460000038147 [ 4.07772413e-23 1.58474399e-20 1.73965059e-18 8.74535265e-17 2.49568562e-15 4.58093482e-14 5.87935695e-13 5.60665034e-12 4.16258352e-11 2.49732862e-10 1.24803027e-09 5.32745593e-09 1.98368066e-08 6.55753768e-08 1.95342914e-07 5.31044478e-07 1.33172299e-06 3.10914675e-06 6.81146334e-06 1.40982161e-05 2.77310391e-05 5.21031331e-05 9.39269921e-05 1.63093911e-04 2.73710967e-04 4.45312032e-04 7.04229658e-04 1.08510517e-03 1.63250565e-03 2.40260928e-03 3.46491532e-03 4.90393153e-03 6.82079120e-03 9.33475279e-03 1.25845383e-02 1.67294712e-02 2.19503804e-02 2.84502447e-02 3.64545569e-02 4.62113982e-02 5.79912176e-02 7.20863197e-02 8.88100703e-02 1.08495836e-01 1.31495676e-01 1.58178815e-01 1.88929915e-01 2.24147190e-01 2.64240376e-01 3.09628608e-01 3.60738215e-01 4.18000478e-01 4.81849371e-01 5.52719318e-01 6.31042986e-01 7.17249139e-01 8.11760571e-01 9.14992136e-01 1.02734890e+00 1.14922439e+00 1.28099903e+00 1.42303865e+00 1.57569319e+00 1.73929554e+00 1.91416052e+00 2.10058402e+00 2.29884230e+00 2.50919136e+00 2.73186658e+00 2.96708236e+00 3.21503195e+00 3.47588741e+00 3.74979962e+00 4.03689847e+00 4.33729310e+00 4.65107220e+00 4.97830447e+00 5.31903906e+00 5.67330611e+00 6.04111737e+00 6.42246685e+00 6.81733144e+00 7.22567170e+00 7.64743254e+00 8.08254400e+00 8.53092204e+00 8.99246929e+00 9.46707585e+00 9.95462009e+00 1.04549694e+01 1.09679810e+01 1.14935027e+01 1.20313735e+01 1.25814247e+01 1.31434803e+01 1.37173575e+01 1.43028680e+01 1.48998182e+01 1.55080097e+01 1.61272404e+01 1.67573046e+01 1.73979938e+01 1.80490973e+01 1.87104022e+01 1.93816947e+01 2.00627597e+01 2.07533816e+01 2.14533451e+01 2.21624346e+01 2.28804354e+01 2.36071337e+01 2.43423168e+01 2.50857736e+01 2.58372947e+01 2.65966726e+01 2.73637021e+01 2.81381802e+01 2.89199068e+01 2.97086840e+01 3.05043172e+01 3.13066146e+01 3.21153874e+01 3.29304500e+01 3.37516204e+01 3.45787194e+01 3.54115716e+01 3.62500049e+01 3.70938507e+01 3.79429437e+01 3.87971226e+01 3.96562292e+01 4.05201090e+01 4.13886111e+01 4.22615879e+01 4.31388956e+01 4.40203938e+01 4.49059452e+01 4.57954165e+01 4.66886774e+01 4.75856011e+01 4.84860639e+01 4.93899457e+01 5.02971292e+01 5.12075005e+01 5.21209489e+01 5.30373665e+01 5.39566484e+01 5.48786928e+01 5.58034006e+01 5.67306756e+01 5.76604244e+01 5.85925560e+01 5.95269824e+01 6.04636179e+01 6.14023794e+01 6.23431862e+01 6.32859600e+01 6.42306247e+01 6.51771066e+01 6.61253340e+01 6.70752380e+01 6.80267498e+01 6.89798084e+01 6.99343360e+01 7.08903187e+01 7.18475437e+01 7.28064348e+01 7.37654549e+01 7.47290004e+01 7.56839518e+01 7.66677184e+01 7.75754125e+01 7.86933146e+01 7.92584878e+01 8.12530925e+01 7.96565621e+01 8.68588532e+01 7.30811291e+01 1.07990554e+02 3.30302708e+01 1.99034047e+02 -1.48175809e+02 5.65252293e+02 -8.46307420e+02 1.86517555e+03 -3.16154189e+03 5.84112652e+03 -9.68847278e+03 1.60815607e+04 -2.49405793e+04 3.75380247e+04 -5.31645025e+04 7.17829508e+04 -9.05316708e+04 1.06627979e+05 -1.14453853e+05 1.09689360e+05 -8.78344405e+04 4.96751069e+04] Elapsed Time2: 0.0450000762939 Elapsed Time3: 0.0410001277924
Smax = 120
n = ns-2
X = linspace(0.0, Smax, n+2)
X = X[1:-1]
payoff = clip(X-K, 0.0, 1e600)
#print "payoff = ", payoff
m = 4570
Fl = zeros((m+1,))
Fu = zeros((m+1,))
t = time.time()
bs1 = BS_FDM_explicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs1.solve()
elapsed=time.time()-t
print "Elapsed Time1:", elapsed
##print px_fd_mat.shape
nrow = len(px_fd_mat[:,1])
print px_fd_mat[nrow-1,:]
figure(figsize=[15, 4]);
subplot(1, 3, 1)
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 4573
Fl = zeros((m+1,))
Fu = zeros((m+1,))
t = time.time()
bs2 = BS_FDM_explicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs2.solve()
elapsed=time.time()-t
print "Elapsed Time2:", elapsed
subplot(1, 3, 2)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 4580
Fl = zeros((m+1,))
Fu = zeros((m+1,))
t = time.time()
bs3 = BS_FDM_explicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs3.solve()
elapsed=time.time()-t
print "Elapsed Time3:", elapsed
subplot(1, 3, 3)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f' % m, fontsize=16);
Elapsed Time1: 0.0460000038147 [ 1.01704397e-28 5.07283379e-26 7.18984489e-24 4.68830891e-22 1.74072660e-20 4.16234095e-19 6.95467412e-18 8.61238308e-17 8.26824165e-16 6.37765319e-15 4.06932208e-14 2.20044937e-13 1.02914359e-12 4.23570647e-12 1.55695816e-11 5.17651596e-11 1.57382418e-10 4.41714179e-10 1.15387760e-09 2.82564962e-09 6.52727942e-09 1.43015144e-08 2.98649516e-08 5.96924592e-08 1.14628045e-07 2.12191890e-07 3.79775698e-07 6.58934313e-07 1.11098825e-06 1.82414722e-06 2.92234764e-06 4.57596663e-06 7.01453177e-06 1.05414905e-05 1.55510379e-05 2.25469294e-05 3.21631260e-05 4.51860447e-05 6.25781067e-05 8.55022075e-05 1.15346670e-04 1.53750189e-04 2.02626238e-04 2.64186378e-04 3.40961911e-04 4.35823312e-04 5.51996896e-04 6.93078223e-04 8.63041768e-04 1.06624646e-03 1.30743677e-03 1.59173903e-03 1.92465290e-03 2.31203775e-03 2.76009409e-03 3.27534000e-03 3.86458272e-03 4.53488566e-03 5.29353117e-03 6.14797920e-03 7.10582258e-03 8.17473908e-03 9.36244092e-03 1.06766222e-02 1.21249047e-02 1.37147828e-02 1.54535680e-02 1.73483331e-02 1.94058580e-02 2.16325751e-02 2.40345184e-02 2.66172723e-02 2.93859255e-02 3.23450254e-02 3.54985376e-02 3.88498080e-02 4.24015289e-02 4.61557096e-02 5.01136502e-02 5.42759210e-02 5.86423455e-02 6.32119876e-02 6.79831445e-02 7.29533428e-02 7.81193390e-02 8.34771256e-02 8.90219392e-02 9.47482747e-02 1.00649901e-01 1.06719884e-01 1.12950607e-01 1.19333799e-01 1.25860566e-01 1.32521423e-01 1.39306324e-01 1.46204708e-01 1.53205527e-01 1.60297295e-01 1.67468123e-01 1.74705766e-01 1.81997660e-01 1.89330975e-01 1.96692647e-01 2.04069434e-01 2.11447949e-01 2.18814709e-01 2.26156179e-01 2.33458809e-01 2.40709078e-01 2.47893532e-01 2.54998828e-01 2.62011762e-01 2.68919314e-01 2.75708677e-01 2.82367293e-01 2.88882878e-01 2.95243460e-01 3.01437400e-01 3.07453417e-01 3.13280617e-01 3.18908511e-01 3.24327033e-01 3.29526565e-01 3.34497943e-01 3.39232480e-01 3.43721975e-01 3.47958722e-01 3.51935520e-01 3.55645682e-01 3.59083036e-01 3.62241932e-01 3.65117244e-01 3.67704370e-01 3.69999230e-01 3.71998265e-01 3.73698434e-01 3.75097207e-01 3.76192563e-01 3.76982977e-01 3.77467420e-01 3.77645341e-01 3.77516663e-01 3.77081772e-01 3.76341503e-01 3.75297128e-01 3.73950345e-01 3.72303264e-01 3.70358392e-01 3.68118620e-01 3.65587208e-01 3.62767768e-01 3.59664251e-01 3.56280934e-01 3.52622398e-01 3.48693515e-01 3.44499436e-01 3.40045570e-01 3.35337570e-01 3.30381318e-01 3.25182908e-01 3.19748632e-01 3.14084962e-01 3.08198542e-01 3.02096154e-01 2.95784760e-01 2.89271303e-01 2.82563285e-01 2.75666908e-01 2.68592676e-01 2.61338692e-01 2.53939079e-01 2.46326719e-01 2.38712943e-01 2.30562309e-01 2.23293232e-01 2.13339863e-01 2.09528451e-01 1.90671166e-01 2.06361812e-01 1.43753470e-01 2.52562922e-01 -3.99580310e-03 4.94288821e-01 -5.19976227e-01 1.40031289e+00 -2.18719234e+00 4.21080703e+00 -6.85231546e+00 1.14799447e+01 -1.77278041e+01 2.67320910e+01 -3.78361940e+01 5.10864915e+01 -6.44524111e+01 7.58680118e+01 -8.14990126e+01 7.80272499e+01 -6.25720798e+01 3.52918730e+01] Elapsed Time2: 0.0469999313354 Elapsed Time3: 0.047000169754
from scipy import sparse
import scipy.sparse.linalg.dsolve as linsolve
class BS_FDM_implicit:
def __init__(self,
r,
sigma,
maturity,
Smin,
Smax,
Fl,
Fu,
payoff,
nt,
ns):
self.r = r
self.sigma = sigma
self.maturity = maturity
self.Smin = Smin
self.Smax = Smax
self.Fl = Fl
self.Fu = Fu
self.nt = nt
self.ns = ns
self.dt = float(maturity)/nt
self.dx = float(Smax-Smin)/(ns+1)
self.xs = Smin/self.dx
self.u = empty((nt + 1, ns))
self.u[0,:] = payoff
## Building Coefficient matrix:
A = sparse.lil_matrix((self.ns, self.ns))
for j in xrange(0, self.ns):
xd = j + 1 + self.xs
sx = self.sigma * xd
sxsq = sx * sx
dtmp1 = self.dt * sxsq
dtmp2 = self.dt * self.r
A[j,j] = 1.0 + dtmp1 + dtmp2
dtmp1 = -0.5 * dtmp1
dtmp2 = -0.5 * dtmp2 * xd
if j > 0:
A[j,j-1] = dtmp1 - dtmp2
if j < self.ns - 1:
A[j,j+1] = dtmp1 + dtmp2
self.A = linsolve.splu(A)
self.rhs = empty((self.ns, ))
### Building bc_coef:
nxl = 1 + self.xs
sxl = self.sigma * nxl
nxu = self.ns + self.xs
sxu = self.sigma * nxu
self.blcoef = 0.5 * self.dt * (- sxl * sxl + self.r * nxl)
self.bucoef = 0.5 * self.dt * (- sxu * sxu - self.r * nxu)
def solve(self):
for i in xrange(0, m):
self.rhs[:] = self.u[i,:]
self.rhs[0] -= self.blcoef * self.Fl[i]
self.rhs[self.ns-1] -= self.bucoef * self.Fu[i]
self.u[i+1,:] = self.A.solve(self.rhs)
return self.u
Smax = 200
n = ns-2
X = linspace(0.0, Smax, n+2)
X = X[1:-1]
payoff = clip(X-K, 0.0, 1e600)
m = 4555
Fl = zeros((m+1,))
Fu = Smax - K*exp(-r * linspace(0.0, T, m+1))
t = time.time()
bs1 = BS_FDM_implicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs1.solve()
elapsed=time.time()-t
print "Elapsed Time1:", elapsed
#print px_fd_mat.shape
figure(figsize=[15, 4]);
subplot(1, 3, 1)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 1000
Fl = zeros((m+1,))
Fu = Smax - K*exp(-r * linspace(0.0, T, m+1))
t = time.time()
bs2 = BS_FDM_implicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs2.solve()
elapsed=time.time()-t
print "Elapsed Time2:", elapsed
subplot(1, 3, 2)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 100
Fl = zeros((m+1,))
Fu = Smax - K*exp(-r * linspace(0.0, T, m+1))
t = time.time()
bs3 = BS_FDM_implicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs3.solve()
elapsed=time.time()-t
print "Elapsed Time3:", elapsed
subplot(1, 3, 3)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
print px_fd_mat[nrow-1,:]
Elapsed Time1: 0.0649998188019 Elapsed Time2: 0.0190000534058 Elapsed Time3: 0.00699996948242 [ 2.98641926e-21 7.95294389e-19 6.07132757e-17 2.16141936e-15 4.46125332e-14 6.06271497e-13 5.90512355e-12 4.38258315e-11 2.59592502e-10 1.27238057e-09 5.31142971e-09 1.93277995e-08 6.24868999e-08 1.82323286e-07 4.86411656e-07 1.19954343e-06 2.75978915e-06 5.97002567e-06 1.22239975e-05 2.38272713e-05 4.44331425e-05 7.96114517e-05 1.37564347e-04 2.29997480e-04 3.73148280e-04 5.88965351e-04 9.06425082e-04 1.36296400e-03 2.00599845e-03 2.89449764e-03 4.10057163e-03 5.71103357e-03 7.82889451e-03 1.05747499e-02 1.40880193e-02 1.85280050e-02 2.40747384e-02 3.09295924e-02 3.93156382e-02 4.94777381e-02 6.16823668e-02 7.62171638e-02 9.33902216e-02 1.13529124e-01 1.36979747e-01 1.64104854e-01 1.95282487e-01 2.30904205e-01 2.71373176e-01 3.17102172e-01 3.68511464e-01 4.26026688e-01 4.90076661e-01 5.61091218e-01 6.39499062e-01 7.25725659e-01 8.20191211e-01 9.23308698e-01 1.03548203e+00 1.15710433e+00 1.28855625e+00 1.43020460e+00 1.58240089e+00 1.74548019e+00 1.91976005e+00 2.10553959e+00 2.30309872e+00 2.51269751e+00 2.73457569e+00 2.96895229e+00 3.21602540e+00 3.47597205e+00 3.74894819e+00 4.03508884e+00 4.33450820e+00 4.64730004e+00 4.97353796e+00 5.31327594e+00 5.66654874e+00 6.03337257e+00 6.41374561e+00 6.80764873e+00 7.21504618e+00 7.63588627e+00 8.07010218e+00 8.51761268e+00 8.97832294e+00 9.45212526e+00 9.93889993e+00 1.04385160e+01 1.09508320e+01 1.14756967e+01 1.20129500e+01 1.25624237e+01 1.31239419e+01 1.36973221e+01 1.42823756e+01 1.48789083e+01 1.54867214e+01 1.61056120e+01 1.67353733e+01 1.73757958e+01 1.80266675e+01 1.86877743e+01 1.93589007e+01 2.00398302e+01 2.07303457e+01 2.14302298e+01 2.21392656e+01 2.28572363e+01 2.35839265e+01 2.43191215e+01 2.50626084e+01 2.58141760e+01 2.65736149e+01 2.73407182e+01 2.81152810e+01 2.88971013e+01 2.96859798e+01 3.04817200e+01 3.12841285e+01 3.20930149e+01 3.29081921e+01 3.37294765e+01 3.45566877e+01 3.53896488e+01 3.62281863e+01 3.70721305e+01 3.79213151e+01 3.87755775e+01 3.96347584e+01 4.04987026e+01 4.13672580e+01 4.22402765e+01 4.31176133e+01 4.39991273e+01 4.48846808e+01 4.57741397e+01 4.66673732e+01 4.75642541e+01 4.84646585e+01 4.93684656e+01 5.02755581e+01 5.11858218e+01 5.20991457e+01 5.30154219e+01 5.39345454e+01 5.48564144e+01 5.57809297e+01 5.67079952e+01 5.76375175e+01 5.85694058e+01 5.95035723e+01 6.04399313e+01 6.13784001e+01 6.23188981e+01 6.32613474e+01 6.42056721e+01 6.51517989e+01 6.60996564e+01 6.70491758e+01 6.80002898e+01 6.89529337e+01 6.99070444e+01 7.08625609e+01 7.18194239e+01 7.27775760e+01 7.37369617e+01 7.46975269e+01 7.56592194e+01 7.66219884e+01 7.75857847e+01 7.85505608e+01 7.95162703e+01 8.04828685e+01 8.14503119e+01 8.24185583e+01 8.33875669e+01 8.43572980e+01 8.53277132e+01 8.62987752e+01 8.72704478e+01 8.82426958e+01 8.92154852e+01 9.01887830e+01 9.11625570e+01 9.21367761e+01 9.31114100e+01 9.40864295e+01 9.50618059e+01 9.60375116e+01 9.70135196e+01 9.79898040e+01 9.89663392e+01 9.99431006e+01 1.00920064e+02 1.01897207e+02 1.02874505e+02 1.03851938e+02]
Smax = 120
n = ns-2
X = linspace(0.0, Smax, n+2)
X = X[1:-1]
payoff = clip(X-K, 0.0, 1e600)
m = 4555
Fl = zeros((m+1,))
Fu = zeros((m+1,))
t = time.time()
bs1 = BS_FDM_implicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs1.solve()
elapsed=time.time()-t
print "Elapsed Time1:", elapsed
#print px_fd_mat.shape
figure(figsize=[15, 4]);
subplot(1, 3, 1)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 1000
Fl = zeros((m+1,))
Fu = zeros((m+1,))
t = time.time()
bs2 = BS_FDM_implicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs2.solve()
elapsed=time.time()-t
print "Elapsed Time2:", elapsed
subplot(1, 3, 2)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
m = 100
Fl = zeros((m+1,))
Fu = zeros((m+1,))
t = time.time()
bs3 = BS_FDM_implicit(r, sigma, T, Smin, Smax, Fl, Fu, payoff, m, n)
px_fd_mat = bs3.solve()
elapsed=time.time()-t
print "Elapsed Time3:", elapsed
subplot(1, 3, 3)
nrow = len(px_fd_mat[:,1])
plot(X, px_fd_mat[nrow-1,:])
xlabel('Stock', fontsize=14);
title('nx = %.f'%m, fontsize=16);
print px_fd_mat[nrow-1,:]
Elapsed Time1: 0.0629999637604 Elapsed Time2: 0.0190000534058 Elapsed Time3: 0.00899982452393 [ 7.86391997e-26 2.43630771e-23 2.17528767e-21 9.09456815e-20 2.21047505e-18 3.54181257e-17 4.06680009e-16 3.55313181e-15 2.47154878e-14 1.41799741e-13 6.90208717e-13 2.91621919e-12 1.08981438e-11 3.65882728e-11 1.11800634e-10 3.14357643e-10 8.20959540e-10 2.00717719e-09 4.62568425e-09 1.01075920e-08 2.10483475e-08 4.19585339e-08 8.03800929e-08 1.48488656e-07 2.65321208e-07 4.59783507e-07 7.74601788e-07 1.27138672e-06 2.03697314e-06 3.19118575e-06 4.89615859e-06 7.36730436e-06 1.08859900e-05 1.58139276e-05 2.26092360e-05 3.18440739e-05 4.42236828e-05 6.06066236e-05 8.20259326e-05 1.09710872e-04 1.45108906e-04 1.89907492e-04 2.46055265e-04 3.15782142e-04 4.01617915e-04 5.06408855e-04 6.33331909e-04 7.85906063e-04 9.68000495e-04 1.18383919e-03 1.43800172e-03 1.73541999e-03 2.08137073e-03 2.48146367e-03 2.94162538e-03 3.46807874e-03 4.06731814e-03 4.74608068e-03 5.51131338e-03 6.37013683e-03 7.32980557e-03 8.39766541e-03 9.58110837e-03 1.08875253e-02 1.23242571e-02 1.38985441e-02 1.56174758e-02 1.74879390e-02 1.95165671e-02 2.17096898e-02 2.40732837e-02 2.66129244e-02 2.93337411e-02 3.22403726e-02 3.53369270e-02 3.86269431e-02 4.21133563e-02 4.57984671e-02 4.96839136e-02 5.37706478e-02 5.80589157e-02 6.25482418e-02 6.72374173e-02 7.21244924e-02 7.72067733e-02 8.24808223e-02 8.79424628e-02 9.35867870e-02 9.94081690e-02 1.05400280e-01 1.11556106e-01 1.17867972e-01 1.24327569e-01 1.30925975e-01 1.37653695e-01 1.44500684e-01 1.51456391e-01 1.58509791e-01 1.65649421e-01 1.72863426e-01 1.80139595e-01 1.87465404e-01 1.94828057e-01 2.02214531e-01 2.09611616e-01 2.17005958e-01 2.24384105e-01 2.31732543e-01 2.39037742e-01 2.46286193e-01 2.53464452e-01 2.60559173e-01 2.67557150e-01 2.74445350e-01 2.81210949e-01 2.87841363e-01 2.94324281e-01 3.00647696e-01 3.06799929e-01 3.12769658e-01 3.18545941e-01 3.24118239e-01 3.29476437e-01 3.34610862e-01 3.39512300e-01 3.44172009e-01 3.48581737e-01 3.52733727e-01 3.56620734e-01 3.60236024e-01 3.63573389e-01 3.66627143e-01 3.69392131e-01 3.71863730e-01 3.74037843e-01 3.75910904e-01 3.77479872e-01 3.78742226e-01 3.79695962e-01 3.80339584e-01 3.80672096e-01 3.80692997e-01 3.80402265e-01 3.79800354e-01 3.78888175e-01 3.77667089e-01 3.76138892e-01 3.74305803e-01 3.72170448e-01 3.69735846e-01 3.67005398e-01 3.63982863e-01 3.60672354e-01 3.57078312e-01 3.53205495e-01 3.49058961e-01 3.44644053e-01 3.39966381e-01 3.35031804e-01 3.29846420e-01 3.24416543e-01 3.18748691e-01 3.12849567e-01 3.06726049e-01 3.00385168e-01 2.93834095e-01 2.87080130e-01 2.80130679e-01 2.72993250e-01 2.65675428e-01 2.58184871e-01 2.50529291e-01 2.42716442e-01 2.34754109e-01 2.26650094e-01 2.18412206e-01 2.10048248e-01 2.01566006e-01 1.92973243e-01 1.84277682e-01 1.75487001e-01 1.66608823e-01 1.57650706e-01 1.48620136e-01 1.39524521e-01 1.30371177e-01 1.21167330e-01 1.11920100e-01 1.02636504e-01 9.33234429e-02 8.39876998e-02 7.46359341e-02 6.52746771e-02 5.59103273e-02 4.65491469e-02 3.71972583e-02 2.78606405e-02 1.85451268e-02 9.25640199e-03]