# Binomail Option Pricing Model
## Binomial Tree Model
### Assumption
$$ Stock \ price \ at \ t=0: \ S_0=50 $$
$$ Excercise\ price:\ K=52$$
$$ Risk\ free\ rate:\ r=5\% $$
$$ Volitility:\ \sigma=30\%$$
$$ Time\ period:\ T=2$$
```pythonscript
S0 = 50
sigma = 0.3
K = 52
T = 2
r = 0.05
```
Δt is time step. For example, when Δt = 1 month, there are 12 * 2 = 24 steps in 2 years.
Before construct a binomial tree, it is necessary to compute the extent of the upward and downward of stock price under risk-neutral measure.
$$ u = e^{\sigma\sqrt{\Delta t}}$$
$$ d = e^{-\sigma\sqrt{\Delta t}} = \frac{1}{u}$$
Also we have to calculate the probability of upward and downward.
$$risk-neutral\ probability\ =\ p\ =\ \frac{e^{r\Delta t}-d}{u-d}$$
### Import library
``` pythonscript
import math
import numpy as np
import random
import matplotlib.pyplot as plt
```
### Define a function to calculate u, d, p in different number of steps.
``` pythonscript
def udp(t):
u = math.exp(sigma*np.sqrt(2/t))
d = math.exp(-sigma*np.sqrt(2/t))
p = (math.exp(r * 2/t) - d) / (u - d)
return (u, d, p)
```
### Define a function to calculate the price of the option.
``` pythonscript
def pricing(t, OptionType):
u = udp(t)[0]
d = udp(t)[1]
p = udp(t)[2]
S = []
for i in range(0, t + 1):
St = S0 * (u ** (t - i)) * (d ** (i))
S.append(St)
put_payoff = []
if OptionType == 'put':
for i in range(0, t + 1):
pi = max(K - S[i], 0)
put_payoff.append(pi)
elif OptionType == 'call':
for i in range(0, t + 1):
pi = max(S[i] - K, 0)
put_payoff.append(pi)
price = []
for i in range(t+1):
price.append([])
price[0] = put_payoff
for j in range(0, t):
for i in range(0, t - j):
St = (price[j][i] * p + price[j][i+1] * (1 - p)) * math.exp(-r*2/t)
price[j+1].append(St)
return (price[t], S)
```
### Caculate prices of put options in the following steps: 12(1 month), 52(1 week), 252(1 trading day)
``` pythonscript
steps = [12, 52, 252]
for i in range(0, 3):
print(f"Put Price({steps[i]}T steps) = {pricing(steps[i], 'put')[0]}")
print('\n')
```
`Put Price(12T steps) = [6.761718527861203]`
`Put Price(52T steps) = [6.786837673688396]`
`Put Price(252T steps) = [6.763849905842416]`
### The result of binomial tree(steps = 2500)
``` pythonscript
print(pricing(2500, 'put')[0])
```
`[6.760639211934076]
`
## Compare the results of Binomial Tree whith the result of Black-Scholes formula
### Black-Scholes formula
$$ c=S_0N(d_1)-Ke^{-rT}N(d_2)$$
$$ p=Ke^{-rT}N(-d_2)-S_0N(-d_1)$$
$$;d_1=\frac{ln(S_0/K)+(r+\sigma^2/2)T}{\sigma\sqrt{T}}$$
$$ d_2 = \frac{ln(S_0/K)+(r-\sigma^2/2)T}{\sigma\sqrt{T}}=d_1-\sigma\sqrt{T}$$
Using the assumption on the beginig of article, we can calculate the put price by using Black-Sholes Formula.
``` pythonscript
import numpy as np
from scipy.stats import norm
d1 = (np.log(S0/K)+(r+sigma**2/2)*T)/(sigma*math.sqrt(T))
d2 = d1-sigma*math.sqrt(T)
BS_putprice = K * math.exp(-r*T) * norm.cdf(-d2) - S0 * norm.cdf(-d1)
print(f"Put price from BS model = {BS_putprice}")
```
`Put price from BS model = 6.760140373699151`
When the number of steps increase large enough, discrete form becomes closer to continuous form. So the result of binomial tree is very close to the result of Black-Sholes model.
## Terminal stock price(6, 12, 52 steps)
```pythonscript
steps = [6, 12, 52]
for i in steps:
x_axis = []
for k in range(0, i + 2):
x_axis.append(k)
y_axis = pricing(i, 'put')[1]
y_axis.insert(0, 0)
plt.plot(x_axis, y_axis)
plt.ylabel('Stock Price')
plt.show()
print('\n')
```



We can find that the terminal stock price follow lognormal distribution.
## American Option
American options can excercise at any time before the excercise day.
So we Define new functions to measure the price of American funtion.
``` pythonscript
def us_pricing(t, OptionType):
u = udp(t)[0]
d = udp(t)[1]
p = udp(t)[2]
binomial = []
for i in range(t+1):
binomial.append([])
for j in range(0, t+1):
S = []
for i in range(0, j+1):
St = S0 * (d ** (i)) * (u ** (j-i))
S.append(St)
binomial[j] = S
#print(binomial)
put_payoff = []
if OptionType == 'put':
for i in range(0, t+1):
pi = max(K - binomial[t][i], 0)
put_payoff.append(pi)
elif OptionType == 'call':
for i in range(0, t+1):
pi = max(binomial[t][i] - K, 0)
put_payoff.append(pi)
#print(put_payoff)
price = []
for i in range(2*t+1):
price.append([])
price[0] = put_payoff
#print(price)
for j in range(0, t+1):
if OptionType == 'put':
for i in range(0, t-j):
pi = (price[j][i] * p + price[j][i+1] * (1 - p)) / math.exp(r *2/ t)
s = max(K - binomial[t-1-j][i], 0)
price[j+1].append(max(pi, s))
elif OptionType == 'call':
for i in range(0, t-j):
pi = (price[j][i] * p + price[j][i+1] * (1 - p)) / math.exp(r *2/ t)
s = max(binomial[t-1-j][i] - K, 0)
price[j+1].append(max(pi, s))
return price[t][0]
```
Ex. calculate the price of American put whith number of steps = 12, 52, 252
```pythonscript
steps = [12, 52, 252]
for i in range(0, 3):
print(f"Put Price({steps[i]}T steps) = {us_pricing(steps[i], 'put')}")
```