파생상품&금융공학

파생상품 가치평가 방법론 #6 Monte Carlo Simulation (1) Path-dependent option의 가치평가

seungbeomdo 2024. 1. 31. 22:00

 

이 시리즈는 파생상품 이론 분야에서 가장 유명한 교재인 Hull(2021)의 "Options, Futures and Other Derivatives (11th)"을 요약한 것일 뿐이다. 아래는 책 구매 링크

 

Options, Futures, and Other Derivatives

ISBN-13: 9780136939917 Options, Futures, and Other Derivatives Published 2021

www.pearson.com

 

이전 편 링크: 파생상품 가치평가 방법론 #5 Binomial Tree (2) Backwardation method

 

파생상품 가치평가 방법론 #5 Binomial Tree (2) Backwardation method

이 시리즈는 파생상품 이론 분야에서 가장 유명한 교재인 Hull(2021)의 "Options, Futures and Other Derivatives (11th)"을 요약한 것일 뿐이다. 아래는 책 구매 링크 Options, Futures, and Other Derivatives ISBN-13: 978013693

seungbeomdo.tistory.com


 

1. 몬테카를로 시뮬레이션

 

이름이 몬테카를로~ 여서 복잡해보이지만 사실 이름만 어려워보일 뿐이다. 몬테카를로 시뮬레이션은 시뮬레이션을 통해 확률과정을 분석하는 방법론을 말한다. 금융공학에서만 쓰이는 방법론은 아니고 확률과정이 필요한 다양한 분야에서 쓰인다.

 

주가의 확률과정이 기하적 브라운 운동(GBM)을 따른다고 가정하자. 그러면 

$$dS_{t} = \mu(S_{t}, t) d_{t} + \sigma(S_{t}, t) dB_{t}$$

 

여기서 $$dB_{t}$$는 브라운 운동의 증가분을 말한다. 블랙-숄즈-머튼 모형에서는 drift term과 volatility term을 다음과 같은 비교적 간단한 함수로 쓴다.

$$\mu(S_{t}, t) = \mu S_{t}$$

$$\sigma(S_{t}, t) = \sigma S_{t}$$

 

주가가 위와 같은 확률과정을 따른다고 명시할 때, 물론 콜옵션의 해석적 해가 존재하지만, 그냥 시뮬레이션을 돌려서 해를 구할 수도 있다. 위험중립적 가치평가법을 사용한다면, drift rate이 무위험이자율과 동일하다고 가정한 상태에서 충분히 많은 수의 시뮬레이션 path들을 생성한 후, 각 path의 만기에서 콜옵션의 수익을 계산한다. 그리고 무위험이자율을 사용해 각 path에서의 수익을 현재가치로 할인한 후, 평균을 취한다.

 

실제로 해보면 아래와 같다.

S0 = 100 #초기 주가
K = 100 #행사가격
r0 = 0.05 #무위험 이자율
T = 1 #만기 (연 기준)
dt = 1/365 #time step의 길이
mu = r0 #drift rate
s = 0.20 #volatility rate
J = 50 #시뮬레이션 path의 개수

I = int(T/dt) #각 시뮬레이션의 time step 개수
paths = np.zeros([I, J])
paths[0, :] = S0

for i in np.arange(I-1):
  dS = mu * paths[i, :] * dt + s * paths[i, :] * np.random.randn(J) * np.sqrt(dt)
  paths[i+1, :] = paths[i, :] + dS

fig, ax = plt.subplots()
ax.plot(paths)
ax.ticklabel_format(useOffset=False)
plt.show()

 

 

하나의 라인 그래프가 하나의 시뮬레이션 path에 해당한다. 그럼 각 path의 만기에서 콜옵션의 수익이 있을 것이고, 그 값들을 모두 무위험이자율로 할인한 후 평균을 내면 된다.

 

시뮬레이션 개수를 늘림에 따라, 추정된 콜옵션 가격은 블랙-숄즈-머튼 모델의 해석적 해로 수렴한다.

 

 


 

2. 경로의존형 옵션의 가격 추정

 

유로피안 옵션의 경우에는 그냥 BSM 모형의 해를 사용하면 될 것이다. 하지만 몇몇 이색 옵션들의 경우에는 해석적 해가 존재하지 않아서 수치적 방법론을 사용해야 한다. 그 중 몬테카를로 시뮬레이션을 사용하는 것이 유리한 대표적인 경우가 경로의존형 옵션이다.

 

경로의존형 옵션이란, 기초자산 가격의 경로에 의해 수익이 결정되는 옵션이다. 유로피안 옵션은 만기 가격만이 중요하지만, 아시안 옵션, 룩백 옵션, 배리어 옵션 등등은 만기 이전 가격의 움직임도 중요하다.

 

배리어 옵션의 가격을 추정해보자. 배리어 옵션은 유로피안 옵션과 유사하지만 한 가지 조건이 더 붙어있다. 만기 이전에, 사전에 정한 가격 범위에 도달하거나 도달하지 못할 경우 옵션 가치가 무효해지는 조건이다. 

 

예를 들어서 녹아웃 배리어 콜옵션이란, 기본적으로 유로피안 콜옵션인데, 기초자산의 가격이 만기 이전에 너무 높아지거나 너무 낮아지면 콜옵션이 소멸한다. 즉 가치가 0이 된다. 반대로 녹인 배리어 콜옵션이란, 만기 이전에 배리어 조건을 만족해야만 콜옵션이 유효해진다.

 

배리어가 120이고, 행사가격이 100인 녹아웃 콜옵션이라고 하자. 그럼 기본적으로 콜옵션이니까 주가가 100 이상이어야 수익을 얻을 수가 있다. 그런데 주가가 너무 높아져서 120을 넘어버리는 상황이 발생하면? 그 순간 콜옵션은 무효해진다. 그러니까 주가가 높아야 하되, 너무 높으면 안 되는 제약이 있는 콜옵션이다.

 

가격을 구해보자. 

 

S0 = 100 #초기 주가
K = 100 #행사가격
H = 130 #녹아웃 배리어
r0 = 0.05 #무위험 이자율
T = 1 #만기 (연 기준)
dt = 1/365 #time step의 길이
mu = r0 #drift rate
s = 0.20 #volatility rate
J = 50 #시뮬레이션 path의 개수

I = int(T/dt) #각 시뮬레이션의 time step 개수
paths = np.zeros([I, J])
paths[0, :] = S0

for i in np.arange(I-1):
  dS = mu * paths[i, :] * dt + s * paths[i, :] * np.random.randn(J) * np.sqrt(dt)
  paths[i+1, :] = paths[i, :] + dS

fig, ax = plt.subplots()
ax.plot(paths)
ax.axhline(H, color = 'black', linestyle = ':', label = 'knock-out barrier')
ax.legend()
ax.ticklabel_format(useOffset=False)
plt.show()

 

 

배리어를 130으로 잡았는데, 보다시피 몇몇 경로에서는 배리어가 터치되었으므로, 콜옵션 가치가 0이 된다. 시뮬레이션 path의 수를 늘릴 때 어떤 가격 수준으로 수렴하고 있는 것이 보인다. 사실 배리어 옵션도 GBM 가정 하에서 가격의 해가 존재하기는 한다.

S0 = 100 #초기 주가
K = 100
H = 130
r = 0.05 #무위험 이자율
T = 1 #만기 (연 기준)
dt = 1/365 #time step의 길이
mu = r #drift rate
s = 0.20 #volatility rate


I = int(T/dt) #각 시뮬레이션의 time step 개수
J_min = 50
J_max = 2000 #시뮬레이션 path의 최대 개수
dj = 25

Barrier_call = []
for j in np.arange(J_min, J_max+1, dj):

  paths = np.zeros([I, j])
  paths[0, :] = S0

  for i in np.arange(I-1):
    dS = mu * paths[i, :] * dt + s * paths[i, :] * np.random.randn(j) * np.sqrt(dt)
    paths[i+1, :] = paths[i, :] + dS

  max_path = paths.max(axis = 0)
  S_T = paths[-1]


  touch = [0 if x >= H else 1 for x in max_path]
  Barrier_call.append(np.mean(np.maximum(S_T - K, 0)*np.exp(-r*T)*np.array(touch)))

plt.figure(figsize = (10,4))
plt.plot(np.arange(J_min, J_max+1, dj), Barrier_call, label = 'Simulation price')
plt.legend()
plt.xlabel('# of Simulation path')
plt.show()

 

 

몇 가지 실험도 해보자. 만약 녹아웃 배리어 콜옵션의 배리어가 높아지면 가격은 어떻게 바뀔까? 배리어가 높아지면 녹아웃이 발생할 확률이 줄어드니까, 롱포지셔너에게 유리하다. 따라서 가격은 높아진다. 만약 배리어가 매우 높아지면, 실질적으로 유로피안 옵션과 동일한 옵션이 된다. 아래 그래프를 보면, 배리어가 높아짐에 따라 배리어 옵션의 가격이 유로피안 옵션의 가격으로 수렴한다.

 

 

변동성이 증가하면 어떨까? 일반적으로 변동성이 증가하면 기초자산 가격이 행사가격을 넘을 확률이 높아지므로, 옵션의 가격은 높아진다. 

 

 

그런데 위 그래프를 보면, 변동성이 작은 구간에서는, 변동성이 높아질 때 녹아웃 배리어 옵션 가격이 증가한다. 하지만 변동성이 일정 수준을 넘으면, 변동성이 증가할 때 옵션 가격이 하락한다. 변동성이 증가할 경우 옵션이 행사될 확률이 높아지지만, 배리어를 터치할 확률도 높아지기 때문이다.