Convergence Dynamics for Binomial

Convergence of CRR (1979), Tian (1993) and Jarrow Rudd Binomial model using the RStudio fOptions Package by Diethelm Wuertz

Below we will examine the convergence behaviour of of the CRR, Tian and JR lattices. We do this we respect to an American put option. Barone-Adesi Whaley here is the closed-form solution. In reality, Barone-Adesis Whaley is an approximation although may appear here to be a proxy for true. Better to estimate true using a 15,000 step CRR tree. Amin and Khanna (1994) demonstrated that the Cox, Ross and Rubinstein (1979) tree converges to the true price. Broadie and Detemple (1996) used a 15,000-step binomial model to obtain “True values”. The binomial model is therefore acknowledged as a reliable workhorse and serves to benchmark other techniques. Below, we use https://rdrr.io/snippets/ to compile the R code

R code for fOptions package

## CRR - JR - TIAN Model Comparison:

# Hull's Example as Function of "n":

par(mfrow = c(2, 1), cex = 0.7)

steps = 100

CRROptionValue = JROptionValue = TIANOptionValue =

rep(NA, times = steps)

for (n in 3:steps) {

CRROptionValue[n] = CRRBinomialTreeOption(TypeFlag = "pa", S = 100,

X = 100, Time = 1, r = 0.05, b = 0.05, sigma = 0.2, n = n)@price

JROptionValue[n] = JRBinomialTreeOption(TypeFlag = "pa", S = 100,

X = 100, Time = 1, r = 0.05, b = 0.05, sigma = 0.2, n = n)@price

TIANOptionValue[n] = TIANBinomialTreeOption(TypeFlag = "pa", S = 100,

X = 100, Time = 2, r = 0.05, b = 0.05, sigma = 0.2, n = n)@price

}

plot(CRROptionValue[3:steps], type = "l", col = "red", ylab = "Option Value")

lines(JROptionValue[3:steps], col = "green")

lines(TIANOptionValue[3:steps], col = "blue")

# Add Result from BAW Approximation:

BAWValue = BAWAmericanApproxOption(TypeFlag = "p", S = 100, X = 100,

Time = 2, r = 0.05, b = 0.05, sigma = 0.2)@price

abline(h = BAWValue, lty = 3)

title(main = "Convergence")

data.frame(CRROptionValue, JROptionValue, TIANOptionValue)


## Plot CRR Option Tree:

# Again Hull's Example:

CRRTree = BinomialTreeOption(TypeFlag = "pa", S = 100, X = 100,

Time = 1, r = 0.05, b = 0.05, sigma = 0.2, n = 5)

BinomialTreePlot(CRRTree, dy = 1, cex = 0.8, ylim = c(-6, 7),

xlab = "n", ylab = "Option Value")

title(main = "Option Tree")

Tian (1993), Leisen Reimer (1996), Jarrow Rudd (1993) and Cox Ross and Rubinstein (1979) r functions spelled out

R User-Defined Functions implemented in Excel using the BERT add in

We examine below the convergence behaviour of the CRR, Tian, Jarrow Rudd and Leisen Reimer lattices. We do this we respect to an American call option. Broadie DeTemple (1996) Table 2 values are used here to proxy true for American options i.e. a 15,000 step CRR tree. Check Colab to inspect Table 2. Amin and Khanna (1994) demonstrated that the Cox, Ross and Rubinstein (1979) tree converges to the true price. Broadie and Detemple (1996) used a 15,000-step binomial model to capture “True values”. For the European analogue we used Black Scholes. It is clear that Leisen Reimer performs best for approximating the European option compared to peers. The results are less clear cut for the American option. R overall is efficient in terms of performance. It is used here to set up user a battery of defined functions in Excel applying the BERT add in

Cox, Ross and Rubinstein/Jarrow Rudd convergence to the Black Scholes model visualized using Python Code and Google Colab

Below we can observe the convergence of the Cox, Ross and Rubinsten (1979) model to the Black Scholes (1973) model. I follow the approach suggested by https://github.com/YuChenAmberLu


"""

https://bit.ly/2WP3cAl

https://github.com/YuChenAmberLu

"""

import math


from math import log, sqrt, pi, exp

from scipy.stats import norm


import matplotlib.pyplot as plt

from pandas import DataFrame


## define Cox_Ross_Rubinstein binomial model

def Cox_Ross_Rubinstein_Tree(S,K,T,r,sigma,N, Option_type):

u=math.exp(sigma*math.sqrt(T/N));

d=math.exp(-sigma*math.sqrt(T/N));

pu=((math.exp(r*T/N))-d)/(u-d);

pd=1-pu;

disc=math.exp(-r*T/N);


St = [0] * (N+1)

C = [0] * (N+1)

St[0]=S*d**N;

for j in range(1, N+1):

St[j] = St[j-1] * u/d;

for j in range(1, N+1):

if Option_type == 'P':

C[j] = max(K-St[j],0);

elif Option_type == 'C':

C[j] = max(St[j]-K,0);

for i in range(N, 0, -1):

for j in range(0, i):

C[j] = disc*(pu*C[j+1]+pd*C[j]);

return C[0]



## define Jarrow_Rudd binomial model

def Jarrow_Rudd_Tree(S,K,T,r,sigma,N, Option_type):

u=math.exp((r-(sigma**2/2))*T/N+sigma*math.sqrt(T/N));

d=math.exp((r-(sigma**2/2))*T/N-sigma*math.sqrt(T/N));

pu=0.5;

pd=1-pu;

disc=math.exp(-r*T/N);


St = [0] * (N+1)

C = [0] * (N+1)

St[0]=S*d**N;

for j in range(1, N+1):

St[j] = St[j-1] * u/d;

for j in range(1, N+1):

if Option_type == 'P':

C[j] = max(K-St[j],0);

elif Option_type == 'C':

C[j] = max(St[j]-K,0);

for i in range(N, 0, -1):

for j in range(0, i):

C[j] = disc*(pu*C[j+1]+pd*C[j]);

return C[0]


## input the current stock price and check if it is a number.

S = 100

K = 100

T = 1

r = 0.05

sigma = 0.2


binomial_model_pricing = {'Option' : ['Call', 'Put', 'Call', 'Put'],

'Price': [Cox_Ross_Rubinstein_Tree(S, K, T, r, sigma,1000,'C'), Cox_Ross_Rubinstein_Tree(S, K, T, r, sigma,1000,'P'),

Jarrow_Rudd_Tree(S, K, T, r, sigma,1000,'C'), Jarrow_Rudd_Tree(S, K, T, r, sigma,1000,'P')]}

binomial_model_pricing_frame = DataFrame(binomial_model_pricing, columns=[ 'Option', 'Price'],

index = ['Cox-Ross-Rubinstein','Cox-Ross-Rubinstein', 'Jarrow-Rudd', 'Jarrow-Rudd'])

binomial_model_pricing_frame


## call option with different steps

runs1 = list(range(10,1000,5))

CRR1 = []

JR1 = []


for i in runs1:

CRR1.append(Cox_Ross_Rubinstein_Tree(S, K, T, r, sigma,i ,'C'))

JR1.append(Jarrow_Rudd_Tree(S, K, T, r, sigma,i ,'C'))


plt.plot(runs1, CRR1, label='Cox_Ross_Rubinstein')

plt.plot(runs1, JR1, label=' Jarrow_Rudd')

plt.legend(loc='upper right')

plt.show()


## put option with different steps

runs2 = list(range(10,100,5))

CRR2 = []

JR2 = []


for i in runs2:

CRR2.append(Cox_Ross_Rubinstein_Tree(S, K, T, r, sigma,i ,'P'))

JR2.append(Jarrow_Rudd_Tree(S, K, T, r, sigma,i ,'P'))


plt.plot(runs2, CRR2, label='Cox_Ross_Rubinstein')

plt.plot(runs2, JR2, label=' Jarrow_Rudd')

plt.legend(loc='upper right')

plt.show()



## define two functions, d1 and d2 in Black-Scholes model

q = 0

def d1(S,K,T,r,q,sigma):

# change sigma*sqrt(T) to (sigma*sqrt(T))

return(log(S/K)+(r - q +sigma**2/2.)*T)/(sigma*sqrt(T))


def d2(S,K,T,r,q,sigma):

return d1(S,K,T,r,q,sigma)-sigma*sqrt(T)


## define the call options price function

def bs_call(S,K,T,r,q,sigma):


return S*exp(-q*T)*norm.cdf(d1(S,K,T,r,q,sigma))-K*exp(-r*T)*norm.cdf(d2(S,K,T,r,q,sigma))


## define the put options price function


def bs_put(S,K,T,r,q,sigma):

return K*exp(-r*T)-S*exp(-q*T)+bs_call(S,K,T,r,q,sigma)


c = bs_call(S,K,T,r,q,sigma)

p = bs_put(S,K,T,r,q,sigma)


print(c)

print(p)