본문 바로가기
금융공학

변동성 변화에 따른 콜옵션 가격 변화 팩터 분석하기

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

 

 

 

이 글에서는, 바로 전 글( 변동성이 커지면 콜옵션 값어치가 올라간다!?)

 

변동성이 커지면 콜옵션 값어치가 올라간다!?

이 글은 2023.05.31 - [금융공학] - Vega! 변동성에 대한 콜옵션 가격 민감도 Vega! 변동성에 대한 콜옵션 가격 민감도 이 글은 2023.05.26 - [금융공학] - 콜옵션의 움직임을 낱낱이 파헤쳐보자: 민감도 팩

sine-qua-none.tistory.com

에 이어서 변동성 변화에 따른 콜옵션 가격 변화가 어떤 요인으로 이루어져 있는지를 알아보겠습니다.

 

콜옵션을 계산하는 시점 $t$와 그 시점에서의 기초자산 $S$가 동일하고 변동성만 바뀌는 상황을 가정해 보겠습니다.

변동성은 $\sigma$에서 $\sigma+\Delta \sigma$로 바뀌었다고 하죠.

 

 

 

변동성 변화에 따른 콜옵션 가격 변화 근사식은?

변동성 변화에 따른 콜 가격변화 역시 테일러 전개를 이용합니다.

콜옵션 가격이 변동성 $\sigma$에 대한 함수임을 강조하기 위해

$$c(t,S;\sigma)$$

라 해보죠.  세미콜론(;)은 $\sigma$가 $t$나 $S$와는 성질이 조금 다른 파라미터임을 강조하기 위해서입니다. 시점과 기초자산 가격이 그대로 있을 때, 변동성의 변화

$\sigma \rightarrow \sigma+\Delta\sigma$에 대해 다음의 테일러 전개가 성립합니다.

$$ c(t,S;\sigma+\Delta \sigma)-c(t,S;\sigma) = \frac{\partial c}{\partial \sigma} \Delta \sigma +\frac12 \frac{\partial^2 c}{\partial \sigma^2} (\Delta \sigma)^2+\frac16 \frac{\partial^3 c}{\partial \sigma^3} (\Delta \sigma)^3 +\cdots \tag{1}$$

 

항의 개수가 늘어날수록 근사치는 정교해지게 되겠죠. 실제로 1,2,3차 근사식을 써보면

 

1차 근사

$$ c(t,S;\sigma+\Delta \sigma)-c(t,S;\sigma) \approx \frac{\partial c}{\partial \sigma} \Delta \sigma \tag{2}$$

 

2차 근사

$$ c(t,S;\sigma+\Delta \sigma)-c(t,S;\sigma)\approx \frac{\partial c}{\partial \sigma} \Delta \sigma +\frac12 \frac{\partial^2 c}{\partial \sigma^2} (\Delta \sigma)^2\tag{3}$$ 

 

3차 근사

$$ c(t,S;\sigma+\Delta \sigma)-c(t,S;\sigma) \approx \frac{\partial c}{\partial \sigma} \Delta \sigma +\frac12 \frac{\partial^2 c}{\partial \sigma^2} (\Delta \sigma)^2+\frac16 \frac{\partial^3 c}{\partial \sigma^3} (\Delta \sigma)^3\tag{4}$$

 

입니다. 여기서 편미분 값들은 모두 시점 $t$, 기초자산 $S$ 그리고 변동성 $\sigma$인 상황에서 구해진 값입니다. 또 각각의 1,2,3차 편미분 값들은 아래의 공식을 이용해 구할 수 있습니다.

 

구분 정의 수식
1차 도함수
(Vega)
$$\mathcal{V}= \frac{\partial c}{\partial \sigma}$$ $$Ke^{-r\tau} \phi(d_2) \sqrt{\tau}= Se^{-r\tau}\phi(d_1) \sqrt{\tau}$$
2차 도함수
(Volga)
$$\frac{\partial^2 c}{\partial \sigma^2}$$ $$  {\rm{(Vega)}} \frac{d_1d_2}{\sigma} $$
3차도함수
(Ultima)
$$\frac{\partial^3 c}{\partial \sigma^3}$$ $$ -\frac{1}{\sigma} {\rm{Vega}}\cdot \left( d_1d_2(1-d_1d_2) + d_1^2+d_2^2 \right)$$

 

 

그럼 식(2), (3),(4)의 근사식이 맞는지 python code를 통해 알아볼까요?

 

 

 

 

Python Code : 콜옵션 가격 변화에 변동성이 미치는 요인 분석

 

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

# ----------------------------------------
# call option value/Greeks function
# vega, volga, ultima 추가 (theta2 삭제)
# ----------------------------------------
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 analysis_call_option_vol_risk_factor():
    s0 = 100
    strike = 100
    maturity = 1
    rfr = 0.03
    div = 0
    vol = 0.3   # v0
    
    # 아래 column들을 가지는 dataframe을 만든다.
    # vol_after : 변동 후 volatility
    # dvol = vol_after - v0
    # dc = call_after - call0
    # vega_fac = vega* dvol (1차 근사, 베가 팩터)
    # volga_fac = (1/2) * volga * (dvol)^2  (2차 근사, volga factor)
    # ultima_fac = (1/6) * ultima * (dvol)^3 (3차 근사, ultima factor)
    
    columns = ['vol_after', 'dvol', 'dc', 'vega_fac', 'volga_fac', 'ultima_fac']
    call0 = CallOptionBS(s0, strike, maturity, rfr, div, vol)  # 변경전 call 가치
    val0, vega0, volga0, ultima0 = call0[0], call0[5], call0[6], call0[7] # 필요한 그릭 추출
    
    # 500개의 sample을 생성시켜볼 예정
    num_data = 500
    vol_range = 0.15
    
    # dataframe 판 만듬
    df = pd.DataFrame(data=[], columns=columns)
    
    # 다양한 volatility 생성
    vol_change = np.random.uniform(vol - vol_range, vol + vol_range, num_data)
    
    # volatility 에 따라 변경된 vol
    call_vec = np.array([CallOptionBS(s0, strike, maturity, rfr, div, v)[0] for v in vol_change])
    
    df['vol_after'] = vol_change
    df['dvol'] = vol_change - vol
    df['dc'] = call_vec - val0
    df['vega_fac'] = vega0 * df['dvol']
    df['volga_fac'] = (1 / 2) * volga0 * df['dvol'] ** 2
    df['ultima_fac'] = (1 / 6) * ultima0 * df['dvol'] ** 3

    df['1fac_effect'] = df.dc - df.vega_fac   # 1차 근사 후 error term
    df['2fac_effect'] = df.dc - df.vega_fac - df.volga_fac  #2차 근사 후 error term
    df['3fac_effect'] = df.dc - df.vega_fac - df.volga_fac - df.ultima_fac  # 3차 근사 후 error term

    pd.set_option('display.max_columns', None)  #df의 all column 보이게 출력

    print(df)

    # 500개 sample의 1차, 2차, 3차 근사 error term을 간단히 긁어줌
    # 각 1,2,3차 erorr term의 mean 구함
    df_mean = df[['1fac_effect', '2fac_effect', '3fac_effect']].mean()
    
    print(df_mean)

if __name__ == '__main__':
    analysis_call_option_vol_risk_factor()

 

 

결과를 보시죠.

     vol_after      dvol        dc  vega_fac  volga_fac  ultima_fac  \
0     0.349343  0.049343  1.905557  1.907931  -0.001961   -0.000450   
1     0.260592 -0.039408 -1.524772 -1.523770  -0.001251    0.000229   
2     0.221745 -0.078255 -3.028638 -3.025869  -0.004933    0.001796   
3     0.215647 -0.084353 -3.264640 -3.261667  -0.005732    0.002250   
4     0.223841 -0.076159 -2.947509 -2.944818  -0.004672    0.001656   
..         ...       ...       ...       ...        ...         ...   
495   0.416306  0.116306  4.481344  4.497171  -0.010897   -0.005897   
496   0.185681 -0.114319 -4.423292 -4.420355  -0.010528    0.005600   
497   0.280881 -0.019119 -0.739538 -0.739270  -0.000294    0.000026   
498   0.251358 -0.048642 -1.882240 -1.880814  -0.001906    0.000431   
499   0.359186  0.059186  2.284992  2.288516  -0.002822   -0.000777   

     1fac_effect  2fac_effect  3fac_effect  
0      -0.002374    -0.000413     0.000037  
1      -0.001001     0.000250     0.000020  
2      -0.002770     0.002163     0.000367  
3      -0.002973     0.002759     0.000510  
4      -0.002690     0.001982     0.000326  
..           ...          ...          ...  
495    -0.015827    -0.004930     0.000967  
496    -0.002937     0.007591     0.001991  
497    -0.000267     0.000027     0.000001  
498    -0.001426     0.000480     0.000048  
499    -0.003524    -0.000702     0.000075  

[500 rows x 9 columns]
1fac_effect   -0.005188
2fac_effect    0.000814
3fac_effect    0.000901
dtype: float64

Process finished with exit code 0

 

1차 근사 error > 2차 근사 error > 3차 근사 error

 

 

가 성립하고, 3차 근사까지 하면 call option의 가격 변화를 변도성 변화로 충분히 설명할 수 있다는 것을 알았습니다.

 

 

 

728x90
반응형

댓글