Risk-neutral discounting
Discount the (expected) inner values at maturity step by step to arrive at the present
value.
In Python this might take on the form seen in the function binomial_py. This function
uses NumPy ndarray objects as the basic data structure and implements three different
nested loops to accomplish the three steps just sketched:
In [ 65 ]: import numpy as np
def binomial_py(strike):
”’ Binomial option pricing via looping.
Parameters
==========
strike : float
strike price of the European call option
”’
# LOOP 1 - Index Levels
S = np.zeros((M + 1 , M + 1 ), dtype=np.float64)
# index level array
S[ 0 , 0 ] = S0
z1 = 0
for j in xrange( 1 , M + 1 , 1 ):
z1 = z1 + 1
for i in xrange(z1 + 1 ):
S[i, j] = S[ 0 , 0 ] * (u ** j) * (d ** (i * 2 ))
# LOOP 2 - Inner Values
iv = np.zeros((M + 1 , M + 1 ), dtype=np.float64)
# inner value array
z2 = 0
for j in xrange( 0 , M + 1 , 1 ):
for i in xrange(z2 + 1 ):
iv[i, j] = max(S[i, j] - strike, 0 )
z2 = z2 + 1
# LOOP 3 - Valuation
pv = np.zeros((M + 1 , M + 1 ), dtype=np.float64)
# present value array
pv[:, M] = iv[:, M] # initialize last time point
z3 = M + 1
for j in xrange(M - 1 , - 1 , - 1 ):
z3 = z3 - 1
for i in xrange(z3):
pv[i, j] = (q * pv[i, j + 1 ] +
( 1 - q) * pv[i + 1 , j + 1 ]) * df
return pv[ 0 , 0 ]
This function returns the present value of a European call option with parameters as
specified before:
In [ 66 ]: %time round(binomial_py( 100 ), 3 )
Out[66]: CPU times: user 4.18 s, sys: 312 ms, total: 4.49 s
Wall time: 3.64 s
10.449
We can compare this result with the estimated value the Monte Carlo function
bsm_mcs_valuation returns:
In [ 67 ]: %time round(bsm_mcs_valuation( 100 ), 3 )
Out[67]: CPU times: user 133 ms, sys: 0 ns, total: 133 ms
Wall time: 126 ms
10.318
The values are similar. They are only “similar” and not the same since the Monte Carlo
valuation as implemented with bsm_mcs_valuation is not too precise, in that different sets