이번 글은 미래주가의 분포를 활용하여 콜옵션 델타 구하기
미래주가의 분포를 활용하여 콜옵션 델타 구하기
이번 글에서는 GBM 모델로 생성된 주가의 누적분포함수, 확률밀도함수 GBM 모델로 생성된 주가의 누적분포함수, 확률밀도함수 이번 글에서는 시점 t에서 주식의 가격이 St인 상황에서 St가 GB
sine-qua-none.tistory.com
에서 이어집니다. 위 글에서는 콜옵션의 델타(delta)를 미래주가의 분포를 이용하여 구하는 이론을 알아보았습니다.
그렇다면 감마(gamma)는 어떨까요?
먼저 지난 글에서 다루었던 내용을 간략하게 복습해 보겠습니다.
복습
글 GBM 모델로 생성된 주가의 누적분포함수, 확률밀도함수
GBM 모델로 생성된 주가의 누적분포함수, 확률밀도함수
이번 글에서는 시점 t에서 주식의 가격이 St인 상황에서 St가 GBM(Geometric Brownian Motion)을 따를 때, 특정 만기 시점 T에 생성된 ST 의 누적분포함수(cumulative distribution function) 과 확률밀도함
sine-qua-none.tistory.com
에서 다룬 내용에서
기초자산 St가 GBM 모델
dSt/St=(r−q)dt+σdWt
(r는 무위험 이자율, q는 연속배당률, σ는 변동성(volatility), 그리고 Wt는 위너프로세스)
을 따를 때, 만기 시점의 주가 ST의 확률밀도함수와 누적분포함수는
ST의 | 수식 |
누적분포함수 F(x) | F(x)=Φ(d(x)) 여기서 Φ(⋅)는 표준정규분포의 누적분포함수이고 d(x)=ln(x/S)−(r−q−12σ2)Tσ√T |
확률밀도함수 g(x) | g(x)=1xσ√Tϕ(d(x)), 여기서 ϕ(⋅)는 표준정규분포의 확률밀도함수 |
와 같다고 했습니다.
이제 이 사실을 바탕으로 콜옵션의 감마를 구해보겠습니다.
콜옵션의 감마
만기 T이고 행사가 K인 유로피안 콜옵션의 가격 c는
c(S)=e−rTE(max
입니다(현재시점 t=0에서의 옵션 가격으로 간주하여, c를 S에 대한 1 변수 함수로 표현하였습니다.)
위의 복습 파트에서, S_T의 확률밀도 함수를 g(\cdot)라 하였으므로 식(1)은
\begin{align} c(S) & = e^{-rT} \int_0^\infty \max(x-K,0) g(x)dx\\ & = \int_0^\infty e^{-rT}\max(x-K,0) g(x) \tag{2}dx \end{align}
변수 x는 S_T를 의미하고 x의 범위가 (0,\infty)이므로 적분 구간은 (0,\infty)가 됩니다.
감마는 파생상품의 가격을 기초자산으로 두 번 미분한 것이므로
\frac{\partial^2 C}{\partial S^2}
이죠. 이 값을 식(1)을 이용해 무작정 구해보도록 하죠.
\begin{align} \frac{\partial^2 c}{\partial S^2} & = \frac{\partial^2}{\partial S^2} \int_0^\infty e^{-rT}\max(x-K,0) g(x) dx\\ & = \int_0^\infty \frac{\partial^2}{\partial S^2} \left( e^{-rT}\max(x-K,0) g(x) \right)dx\\ & = \int_0^\infty e^{-rT}\max(x-K,0) \frac{\partial^2 g(x)}{\partial S^2} dx\\ & = \int_0^\infty e^{-rT}\max(x-K,0) \frac{\partial^2 g(x)}{\partial S^2} \frac{1}{g(x)} \cdot g(x) dx\\ & = \mathbb{E} \left(e^{-rT}\max(x-K,0) \frac{\partial^2 g(x)}{\partial S^2} \frac{1}{g(x)}\right)\tag{3} \end{align}
이제 식(3)의 마지막 등식의 \mathbb{E}(\cdot)에 있는 수식
\frac{\partial^2 g(x)}{\partial S^2} \frac{1}{g(x)}
을 보기 좋게 정리할 일만 남았습니다.
몇가지 소소한 계산을 미리 해놓자면,
d(x) = \frac{\ln(x/S)-(r-q-\frac12\sigma^2)T}{\sigma\sqrt{T}} 이므로
\frac{\partial d}{\partial S} =- \frac1{S\sigma\sqrt{T}} ~,~\frac{\partial^2 d}{\partial S^2} = \frac1{S^2\sigma\sqrt{T}} \tag{4} 가 성립합니다.
또한 표준정규분포 확률밀도 함수 \phi는
\phi'(x) =-x\phi(x)\tag{5} 이고
\phi''(x) =\frac{d}{dx}\phi'(x) = -\phi(x) -x\phi'(x) = -\phi(x) +x^2\phi(x)=(x^2-1)\phi(x)\tag{6}
를 만족합니다.
g(x) =\frac{\phi(d(x))}{x\sigma\sqrt{T}} 이므로
\begin{align} \frac{\partial^2 g(x)}{\partial S^2} \frac{1}{g(x)} & = \frac{1}{x\sigma\sqrt{T}} \frac{\partial^2 \phi(d(x))}{\partial S^2} \cdot \frac{x\sigma\sqrt{T}}{\phi(d(x))}\\ & = \frac{\partial}{\partial S} \left(\phi'(d(x)) \frac{\partial d(x) }{\partial S} \right) \cdot \frac{1}{\phi(d(x))} \\ & = \frac{1}{\phi(d(x))} \left( \phi''(d(x)) \Big(\frac{\partial d(x)}{\partial S}\Big)^2 + \phi'(d(x)) \frac{\partial^2 d(x) )}{\partial S^2} \right) \\ & =\frac{1}{\phi(d(x))} \left( \phi''(d(x)) \frac{1}{S^2\sigma^2 T} +\frac{1}{S^2\sigma\sqrt{T}}\phi'(d(x)) \right)~~ \because {\rm {by~ (4)}} \\ & = \frac{1}{\phi(d(x))} \left( \frac{(d^2(x)-1)\phi(d(x))}{S^2\sigma^2 T} - \frac{d(x)\phi(d(x))}{S^2\sigma\sqrt{T}} \right)~~ \because {\rm {by~ (5),(6)}}\\ & = \frac{d(x)^2-d(x)\sigma\sqrt{T} -1}{S^2\sigma^2 T}\tag{7} \end{align}
입니다. 따라서 식(3)과 식(7)에 의해
\frac{\partial^2 c}{\partial S^2} = \mathbb{E} \left(e^{-rT}\max(x-K,0) \frac{d(x)^2+d(x)\sigma\sqrt{T} -1}{S^2\sigma^2 T} \right) \tag{8}
를 만족합니다. 이러한 방법을 likelihood 방법(우도비 방법)이라고 부릅니다.
식(8)은 다음과 같이 이용하면 됩니다.
○ 식(8)의 x는 만기종가를 뜻합니다. 즉, 어떤 표준정규분포를 따르는 난수 z에 대해
x= S \exp\left((r-q-\frac12\sigma^2)T +\sigma\sqrt{T}z\right)
로 생성할 수 있습니다.
○ d(x) 를 계산해보면,
d(x) = \frac{\ln(x/S)-(r-q-\frac12\sigma^2)T}{\sigma\sqrt{T}} =z
이죠. 따라서,
d(x)는 표준정규분포 난수, x는 이 난수를 통해 만들어지는 GBM 만기 종가
라고 이해하면 될 것 같습니다. 이제 코딩을 통해 이 내용을 확인해보도록 하겠습니다.
Python Code
예전 글에서 구현해 놓았던 Closed form formula 관련 코드를 그대로 가져다 쓰겠습니다(관련 코드는 이런 글 등에서 찾아볼 수 있습니다.) 또는 바로 전 글 (미래주가의 분포를 활용하여 콜옵션 델타 구하기)의 코드 부분을 보셔도 됩니다.
또한 아래 코드는 바로 전 글의 코드와 너무나 흡사합니다. 밑의 코드의 estimator 변수만 식(7)의 공식으로 바꿔 주면 됩니다.
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
import pandas as pd
# 아래는 call option delta의 수학 공식
def CallOptionBS(S, K, T, r, q, sigma):
Ncdf = norm.cdf
npdf = norm.pdf
if T == 0:
val = np.maximum(S - K, 0)
delta = 1 if S >= K else 0
gamma = 0
speed = 0
theta = 0
vega = 0
volga = 0
ultima = 0
else:
d1 = (np.log(S / K) + (r - q + sigma ** 2 / 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
val = S * np.exp(-q * T) * Ncdf(d1) - K * np.exp(-r * T) * Ncdf(d2)
delta = np.exp(-q * T) * Ncdf(d1)
gamma = np.exp(-q * T) * npdf(d1) / (S * sigma * np.sqrt(T))
speed = -np.exp(-q * T) * npdf(d1) / (S ** 2 * sigma * np.sqrt(T)) * (1 + d1 / (sigma * np.sqrt(T)))
theta = -np.exp(-q * T) * S * npdf(d1) * sigma / (2 * np.sqrt(T)) - r * K * np.exp(-r * T) * Ncdf(
d2) + q * S * np.exp(-q * T) * Ncdf(d1)
# theta2 = -(r - q) * S * delta - 0.5 * sigma ** 2 * S ** 2 * gamma + r * val
# theta +(r-q)S *delta + 0.5*sigma^2*S^2 *gamma -rf =0
vega = S * np.exp(-q * T) * npdf(d1) * np.sqrt(T) # vega
volga = vega * d1 * d2 / sigma # volga
ultima = -vega / sigma ** 2 * (d1 * d2 * (1 - d1 * d2) + d1 ** 2 + d2 ** 2) # ultima
# return index
# 0. value
# 1. delta
# 2. gamma
# 3. speed
# 4. theta
# 5. vega
# 6. volga
# 7. ultima
return val, delta, gamma, speed, theta, vega, volga, ultima
def call_option_gamma_likelihood(spot, strike, maturity, rfr, div, vol):
np.random.seed(0)
n_iter = 100000
drift = rfr - div - 0.5 * vol ** 2
diffusion = vol * np.sqrt(maturity)
rand_vec = np.random.normal(size=n_iter)
smat_vec = spot * np.exp(drift + diffusion * rand_vec)
# 식(7)을 이용하여 estimator를 구성한다.
estimator = np.exp(-rfr * maturity)* \
np.maximum(smat_vec - strike, 0) * \
(rand_vec**2 -rand_vec*vol*np.sqrt(maturity)-1) / (spot**2 * vol**2 * maturity)
call_gamma = estimator.mean()
return call_gamma
def theoretical_vs_likelihood_call_gamma():
strike = 100
rfr = 0.02
div = 0.01
maturity = 1
vol = 0.2
s_vec = np.arange(10, 150, 1)
theoretical_gamma = [CallOptionBS(s, strike, maturity, rfr, div, vol)[2] for s in s_vec]
likelihood_gamma = [call_option_gamma_likelihood(s, strike, maturity, rfr, div, vol) for s in s_vec]
max_diff = abs(np.array(theoretical_gamma) - np.array(likelihood_gamma)).max()
print('maximum error is {:.6f}'.format(max_diff)) # 너무 차이가 작아 소수6째자리까지 표시
plt.plot(s_vec, theoretical_gamma, label='theoretical gamma')
plt.plot(s_vec, likelihood_gamma, label='likelihood gamma')
plt.legend()
plt.show()
if __name__ == '__main__':
theoretical_vs_likelihood_call_gamma()
실행시키면 다음과 같습니다.
maximum error is 0.000380
너무 오차가 작아 code에 오차 수준을 소수 여섯째 자리까지 표기하는 걸로 바꿨을 지경입니다.
현재주가에 따른 이론적 감마와 위 이론의 감마를 그래프로 비교해 볼까요?

거의 완전히 일치하는 모양새를 볼 수 있습니다.
감마를 시뮬레이션법으로 구했는데도 불구하고 엄청 정확하네요.
유한차분법으로 구한 감마보다 낫다!
전의 글 몬테카를로 시뮬레이션과 그릭의 안정성 #2 : 시드 고정
몬테카를로 시뮬레이션과 그릭의 안정성 #2 : 시드 고정
이번 글은 2023.07.07 - [금융공학] - 몬테카를로 시뮬레이션과 그릭의 안정성 #1 몬테카를로 시뮬레이션과 그릭의 안정성 #1 이번 글은 2023.06.23 - [금융공학] - 그릭을 수치 해석적인 방법으로 해결하
sine-qua-none.tistory.com
에서는 MC방법과 유한차분방법을 통해 그릭을 구하는 방법을 설명했었습니다. 시드를 고정시키고 세 값
c(t,S+\Delta S), c(t,S), c(t,S-\Delta S)
을 구한 뒤
\frac{c(t,S+\Delta S) - 2c(t,S) +c(t,S-\Delta S)}{\Delta S^2}
로 감마를 구할 수 있다 했습니다. 이 결과는 아래와 같이 나왔었고, 밑에 줄 왼쪽 그림이 감마를 표시한 그래프입니다.

아무래도 세 개의 값을 각각 구해 차분법으로 구하니, 정확성도 떨어지고, 세 개의 값을 구하는데서 많은 시간이 소요됩니다.
하지만 식(7)의 결과 그래프를 보십시오. 엄청 아름답지 않나요? 값도 안정적이면서 계산시간도 짧은 아주 좋은 방법임을 알 수 있습니다.
다음 글에서는 베가(Vega, 변동성에 대한 민감도)도 유사한 방법으로 어떻게 구할 수 있는지 알아보겠습니다.
'금융공학' 카테고리의 다른 글
클리켓 옵션 #1 클리켓 옵션이 뭐야? (0) | 2024.04.16 |
---|---|
미래 주가 분포를 활용하여 콜옵션 베가 구하기 (7) | 2023.09.12 |
미래주가의 분포를 활용하여 콜옵션 델타 구하기 (0) | 2023.08.21 |
GBM모델로 생성된 미래 주가는 어떻게 분포할까? 변동성이 커지면 분포는? (0) | 2023.08.11 |
GBM 모델로 생성된 주가의 누적분포함수, 확률밀도함수 (0) | 2023.08.08 |
댓글