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
def european_mc(option_type, S0, K, r, T, sigma, I): #I번은 반복횟수
N = 252 * T
dt = T / N
S = np.zeros(((N+1), I))
S[0] = S0
for t in range(1, N+1):
A = np.random.standard_normal(I) #I개의 난수 생성
S[t] = S[t-1] * np.exp((r - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * A)
payoff = np.zeros(I)
if option_type == 'call':
payoff = np.exp(-r * T) * np.maximum((S[N] - K), 0)
if option_type == 'put':
payoff = np.exp(-r * T) * np.maximum((K - S[N]), 0)
plt.plot(S[:,:50])
V = np.mean(payoff)
return V
S = 100
K = 100
r = 0.02
T = 1
sigma = 0.2
I = 50000
european_mc('call',S, K, r, T, sigma, I)
8.890188221644781

문제1: 만기 전 마지막 일주일 동안의 평균 가격이 만기 기초자산 가격이 되는 American option의 가격을 구해보세요
def american_mc(option_type, S0, K, r, T, sigma, I): #I번은 반복횟수
N = 252 * T
dt = T / N
S = np.zeros(((N+1), I))
S[0] = S0
for t in range(1, N):
A = np.random.standard_normal(I) #I개의 난수 생성
S[t] = S[t-1] * np.exp((r - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * A)
#만기 전 일주일 동안의 평균 가격이 만기 기초자산 가격이 된다.
for i in range(I):
S[N, i] = np.mean(S[-7:-1, i])
payoff = np.zeros(I)
if option_type == 'call':
payoff = np.exp(-r * T) * np.maximum((S[N] - K), 0)
if option_type == 'put':
payoff = np.exp(-r * T) * np.maximum((K - S[N]), 0)
plt.plot(S[:,:50])
V = np.mean(payoff)
return V
print('American option using Monte Carlo: ', american_mc('call', S, K, r, T, sigma, I))
American option using Monte Carlo: 8.846993116124935

Barrier Option
B = 110 #barrier
def barrier_call(S0, K, r, T, sigma, I, B):
#주가의 경로
N = 252 * T
dt = T / N
S = np.zeros(((N+1), I))
S[0] = S0
for t in range(1, N+1):
A = np.random.standard_normal(I) #I개의 난수 생성
S[t] = S[t-1] * np.exp((r - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * A) #주가 설정
Cuo = np.zeros(I) #up-and-out call
Cui = np.zeros(I) #up-and-in call
for i in range(I):
if np.all(S[:, i] < B): #주가경로 전체가 barrier보다 밑에 있게 된다면
Cuo[i] = S[N, i] #Cuo가 유효함, payoff 넣어줌
if np.any(S[:, i] > B): #주가경로중 하나라도 barrier 보다 위에 간다면
Cui[i] = S[N, i] #Cui가 유효함, payoff 넣어줌
#값이 있으면 0이아니고, 유효하지 않아서 값이 없으면 0임
Cuo_payoff = np.exp(-r * T) * np.maximum(Cuo - K, 0)
Cui_payoff = np.exp(-r * T) * np.maximum(Cui - K, 0)
Cuo_value = np.mean(Cuo_payoff)
Cui_value = np.mean(Cui_payoff)
return Cuo_value, Cui_value
Cuo, Cui = barrier_call(S, K, r, T, sigma, I, B)
print(Cuo, Cui)
0.15704465913942903 8.643704858539854
print('BS price: ', BS_formula('call', S, K, r, T, sigma))
print('european_mc: ',european_mc('call', S, K, r, T, sigma, I))