import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
#Black Scholes Formula
def BS_formula(option_type, S, K, r, T, sigma):
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if option_type == 'call':
price = S * stats.norm.cdf(d1) - K * np.exp(-r * T) * stats.norm.cdf(d2)
elif option_type == 'put':
price = - S * stats.norm.cdf(-d1) + K * np.exp(-r * T) * stats.norm.cdf(-d2)
return price
#Greeks
def delta(option_type, S, K, r, T, sigma):
d1 = (np.log(S/K) + (r + 0.5 * (sigma ** 2)) * T) / (sigma * np.sqrt(T))
if option_type == 'call':
return stats.norm.cdf(d1)
elif option_type == 'put':
return stats.norm.cdf(d1) - 1
def theta(option_type, S, K, r, T, sigma):
d1 = (np.log(S/K) + (r + 0.5 * (sigma ** 2)) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if option_type == 'call':
theta = (-sigma * S * stats.norm.pdf(d1)) / (2 * np.sqrt(T)) - r * K * np.exp(-r*T) * stats.norm.cdf(d2)
elif option_type == 'put':
theta = (-sigma * S * stats.norm.pdf(d1)) / (2 * np.sqrt(T)) + r * K * np.exp(-r*T) * stats.norm.cdf(-d2)
return theta
def gamma(S,K,r,T,sigma):
d1 = (np.log(S/K) + (r + 0.5 * (sigma ** 2)) * T) / (sigma * np.sqrt(T))
gamma = stats.norm.pdf(d1) / (sigma * S * np.sqrt(T))
return gamma
def vega(S,K,r,T,sigma):
d1 = (np.log(S/K) + (r + 0.5 * (sigma ** 2)) * T) / (sigma * np.sqrt(T))
vega = S * np.sqrt(T) * stats.norm.pdf(d1)
return vega
def rho(option_type, S, K, r, T, sigma):
d1 = (np.log(S/K) + (r + 0.5 * (sigma ** 2)) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if option_type == 'call':
rho = K * T * np.exp(-r * T) * stats.norm.cdf(d2)
elif option_type == 'put':
rho = - K * T * np.exp(-r * T) * stats.norm.cdf(-d2)
return rho
CRR Model European option pricing, 이항 트리 모형
def call_payoff(S,K):
if S > K:
return (S-K)
else:
return 0
def put_payoff(S,K):
if S < K:
return (K-S)
else:
return 0
def CRR_european(option_type, S0, K, r, T, sigma, n):
S = np.zeros((n+1, n+1))
V = np.zeros((n+1, n+1))
dt = 1 / n
a = np.exp(r * dt)
u = np.exp(sigma * np.sqrt(dt))
d = 1 / u
p = (a - d) / (u - d)
S[0,0] = S0 #현재 가격
for i in range(1, n+1):
for j in range(n, 0, -1):
S[j, i] = u * S[j-1, i-1] #i시점에 j는 위로 몇번 올라갔는지
S[0, i] = d * S[0, i-1] #한 번도 안올라감
if option_type == 'call':
for i in range(n+1):
V[i] = call_payoff(S[i,n],K) #맨 마지막 payoff나옴
for i in range(n, 0, -1):
for j in range(0,n):
V[j, i-1] = ((p * V[j+1, i]) + (1-p) * V[j, i]) * np.exp(-r * dt) #(i-1)시점의 노드값 구함
if option_type == 'put':
for i in range(n+1):
V[i] = put_payoff(S[i,n],K) #맨 마지막 payoff나옴
for i in range(n, 0, -1):
for j in range(0,n):
V[j, i-1] = ((p * V[j+1, i]) + (1-p) * V[j, i]) * np.exp(-r * dt) #(i-1)시점의 노드값 구함
P = pd.DataFrame(S)
F = pd.DataFrame(V)
return V[0,0], P, F #V[0,0]: 구하고 싶은 현재 옵션의 가격
S = 100
K = 100
r = 0.05
T = 1
sigma = 0.3
n = 253
V, P, F = CRR_european('call', S, K, r, T, sigma, n)
print('CRR price: ',V)
print('BS price: ', BS_formula('call', S, K, r, T, sigma))
#점점 n의 수를 늘릴수록 Black Scholes에 수렴해 간다.
CRR price: 14.242110925239784 BS price: 14.231254785985819
P

F
