본문 바로가기
금융공학

세타: 기초자산이 죽어있어도 옵션 가격은 변하더라!?

by hustler78 2023. 5. 22.
728x90
반응형

 

 

이 글은 세타: 시간의 흐름이 콜옵션에 미치는 영향

 

세타: 시간의 흐름이 콜옵션에 미치는 영향

이 글은 2023.05.12 - [금융공학] - 콜옵션 가격 변동 헤지 시뮬레이션: 주가가 만기까지 횡보한다면.. 콜옵션 가격 변동 헤지 시뮬레이션: 주가가 만기까지 횡보한다면.. 이번 글은 전 글 (콜옵션 가

sine-qua-none.tistory.com

에서 이어집니다.

 

저번 글에서는 파생상품의 세타라는 개념을 알아봤습니다. 세타는 시점의 변화에 따른 파생상품의 가치 변화를 뜻하며 특히 콜옵션의 세타는 

 

콜옵션의 세타 공식

$$ \Theta =qSe^{-q\tau} \Phi(d_1) - rK e^{-r\tau} \Phi(d_2) - \frac{Ke^{-r\tau}\sigma\phi(d_2)}{2\sqrt{\tau}} \tag{1}$$

또는

$$ \Theta + (r-q)S \Delta +\frac12 \sigma^2 S^2 \Gamma -r c =0 \tag{2}$$

 

이 됩니다(각 기호는 저번 글을 참고해 주세요. $\Delta, \Gamma$ 는 각각 콜옵션의 델타, 감마를 뜻합니다.)

 

이제 재미있는 상황을 하나 가정해 보겠습니다. 

 

 

재미있는 상황: 기초자산이 멈춰버린 경우 콜옵션의 가격 변화는?

 

기초자산이 멈춰서 변하지 않는 경우, 콜옵션의 가격은 어떻게 될까요?  저번 글에서도 소개했던 아래 그림을 보시죠.

 

극단적으로 만기 5년짜리, 3년, 1년, 6M, 1 Day 인 콜옵션의 가격(곡선들)과, 만기 페이오프(제일 아래 검은 꺾은선)를 그려 보면, 만기가 얼마 안남을 수록 검은 꺾은선에 붙어 감을 알 수 있습니다. 즉, 옵션가치는 시간가치와 내재가치로 나누어지는데, 시간가치가 계속 줄어들어 만기에 다다를수록 내재가치만이 남게 되죠.

 

그러면 콜옵션의 가격이 내재가치에 붙어가는 속도는 어떻게 될까요? 

 

기초자산의 변화가 없다고 합시다. 즉, 기초자산 초기값 $S_0=100$에서 만기 때까지 그대로 변화가 없다고 해보죠. 테일러 전개에 따르면,  임의의 시점 $t$와 기초자산의 가격 $S$에 대해

 

시점 $t$에 따른 콜옵션 가격 $c$의 테일러 전개

시간의 작은 변화량 $\Delta t$에 대해,

$$ c(t+\Delta t, S) -c(t, S) \approx \frac {\partial c}{\partial t} c(t, S) \cdot ((t+\Delta t) - t) = \Theta \cdot \Delta t \tag {3}$$

입니다. 물론 $c$는 $S$에 대한 함수이기도 하지만, 우리는 지금 $S$가 움직이지 않는 상황을 얘기하고 있죠.

식(3)을 1일 간격의 time grid로 쪼개어 써 볼까요? 현재시점 $t=0$에서 만기시점 $T$까지를 

$$ 0=t_0<t_1<\cdots <t_{N-1}<t_N=T$$

로 균등분할 했다고 해봅시다. $\Delta t$는 time grid의 간격이라 해보죠. 그렇다면 식(3)은 모든 $i=0,1,\cdots, N-1$에 대해

 

$$ c(t_{i+1},S) - c(t_i S) = \Theta_i \cdot \Delta t$$
입니다. 여기서 $\Theta_i$는 시점 $t_i$, 기초자산 $S$일 때 세타값입니다.

 

만일 시간 가격 $\Delta t$가 하루를 뜻하는 $\Delta t = \frac{1}{250}$ 이라 한다면, 식 (3)은 아래와 같이 해석이 됩니다.

 

 

내일의 콜옵션 가격 $\approx$ 오늘 콜옵션 가격 + 오늘 콜옵션 세타 × $\frac{1}{250}$ !!

 

즉, 기초자산이 안 변한다고 가정했을 때,  그럼에도 불구하고 콜옵션 가격 변화는  매일매일 일어나는데, 그 변화량은 세타에 비례한다는 것이죠.

 

그럼 실제적으로 만기까지 시점이 경과하면서,

Black Scholes Formula을 통한 콜옵션 가격의 변화가, 세타에 의한 변화와 잘 맞아떨어지는지 코딩을 통해 계산해 보겠습니다.

 

 

 

Python Code

 

아래 코드에서는 다음의 두 콜옵션 가격을 비교해 볼 참입니다.

 

time grid $0=t_0<t_1<\cdots <t_{N-1}<t_N$에 대해, 고정된 $S=100$에 대해서

 

1. $c(t_i, S)$를 Black Scholes Formula (Closed form)으로 직접 구하기

 

2. $c(t_i,S) \approx c(t_{i-1},S) + \Theta_{i-1} \Delta t$ 공식을 이용하여, $C(t_{i-1},S)$와 $\Theta_{i-1}$을 통해 얻은 $c(t_i, S)가 1의 값과 유사한지 살펴보기

 

코드를 보시죠.

 

 

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

# calculate call option value and greeks
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    # 식(1)처럼 closed form으로 구하기
        theta2 =0   # 식(2)처럼 delta, gamma를 이용하여 구하기
    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)                                  # 식(1) theta
        theta2 = -(r - q) * S * delta - 0.5 * sigma ** 2 * S ** 2 * gamma + r * val  # 식(2) theta
    return val, delta, gamma, speed, theta, theta2

def call_option_theta_simulation():
    s0 = 100
    strike = 90     # otm 상황을 연출, strike을 초기 S0의 90%로 설정
    maturity = 1
    rfr = 0.03
    div = 0
    vol = 0.3

    dt = 1 / 250
    sqrtdt = np.sqrt(dt)
    ntime = int(maturity / dt)
    time_series = np.linspace(0, maturity, ntime + 1)
    ttm_series = np.flip(time_series)

    drift = rfr - div - 0.5 * vol ** 2


    callval = lambda ttm: CallOptionBS(s0,strike,ttm,rfr,div,vol)

    value_vec = [callval(ttm)[0] for ttm in ttm_series]  # 잔존만기에 따른 call value list
    value_vec = np.array(value_vec)                      # list ->array

    value_via_theta = [callval(ttm)[0] + callval(ttm)[4]*dt for ttm in ttm_series[:-1]]
    # 식(3)을 통한 call value 즉, 
    # t0, t1, .., t_{N-1} 일 때 call value 와 call theta를 구하여
    # call value + theta * (1/250)를 하면 
    # 각각 t1, t2, ..., t_N 일 떄의 call value approximation을 만들 수 있다!

    value_via_theta = np.array(value_via_theta)  # (N-1) size array
    
    # BSF를 이용한 실제 call value와 식(3)을 이용한 value_vis_theta 비교하기
    plt.plot(time_series, value_vec, color='gray', linewidth=5, label='call value(BSF)')
    plt.plot(time_series[1:], value_via_theta, linestyle='--', color='black', label='call value(theta estimation')
    plt.legend()
    plt.show()
    
    # 과연 두 가격 벡터가 크게 차이나는 수준은 얼마인가?
    diff = abs(value_vec[1:]-value_via_theta).max()

    print('call option value at t=0 : {:.2f}'.format(value_vec[0]))
    print('approximation error is {:.2f}'.format(diff))

if __name__ == '__main__':
    call_option_theta_simulation()

 

자세한 사항은 주석을 살펴보시기 바랍니다. 이제 

 

1. Black Scholes Formula로 실제로 구한 콜옵션 가격(아래 그림 회색 두꺼운 선)

2. 전일 콜옵션 가격과 세타로 조합한 오늘의 콜옵션 가격 (식 (3))을 비교한 결과(검은 점선)

 

을 살펴보죠.

 

 

 

call option value at t=0 : 18.61
approximation error is 0.00184  # 초기 call value 18.61에 비하면, 오차는 극미한 수준

 

잘 복원되는 것을 볼 수 있습니다. 

 

이처럼 시간이 경과하며 만기까지 갈 때 시점의 변화에 대한 콜옵션 변화는 세타라는 값에 연동하여 움직임을 알 수 있습니다.

 

 

728x90
반응형

댓글