Exotic_option.ipynb

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

Untitled

문제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

Untitled

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))