본문 바로가기
금융공학

2Star WorstPerform 풋옵션 가격: 시뮬레이션

by hustler78 2023. 1. 15.
728x90
반응형

 

 

 

이번 글은 

 

2023.01.13 - [금융공학] - 여러 개의 기초자산을 가지는 파생상품 가격결정식

 

여러개의 기초자산을 가지는 파생상품 가격결정식

이번 글에서는 여러 개의 지수/주식을 기초자산으로 하는 파생상품의 가격 결정식을 소개할까 합니다. 하나의 기초자산을 가지는 파생상품 결정식은 다음의 글에서 다룬 바 있습니다. 2022.08.02 -

sine-qua-none.tistory.com

에서 다룬 이론을 바탕으로, 

 

2개의 기초자산을 가지는 금융상품의 가격

 

을 계산해 보도록 하겠습니다. 

상품 예시는 아래와 같습니다.

 

 

2Star WorstPerform Put Option

 

기초자산

 

워스트포퍼머는 글 자산의 퍼포먼스(performance)와 워스트포퍼머(worst performer)

 

자산의 퍼포먼스(performance)와 워스트포퍼머(worst performer)

이번 글에서는 지수나 주식 같은 자산의 퍼포먼스(performance)가 무엇인지를 정의해보고, 이를 이용하여 두 개 이상 자산의 워스트 포퍼머(worst performer)의 개념이 무엇인지 알아보겠습니다. 예를

sine-qua-none.tistory.com

 

에서 다룬바 있습니다. 두 개의 기초자산 프로세스 $S_1(t), S_2(t)$가 있을 때, 이를 각각 $t=0$일 때의 기준가로 나눈 프로세스 

$$ \frac{S_1(t)}{S_1(0)}~~,~~ \frac{S_2(t)}{S_2(0)} $$

을 퍼포먼스라고 부르고, 각 시점 $t$에서 위 두 값중 작은 값, 즉,

$$ wp(t): = \min\left( \frac{S_1(t)}{S_1(0)}, \frac{S_2(t)}{S_2(0)} \right)$$

워스트 포퍼머(worst performer)라 불렀습니다.

 

이 워스프포퍼머 $wp(t)$ 를 기초자산으로 하는 풋옵션이 바로 우리가 가격을 구하고자 하는 상품입니다.

 

 

풋옵션의 만기 페이오프

위에서 기초자산이 정해졌습니다. 풋옵션의 만기를 $T$, 행사가를 $K$라 할 때, 해당 풋옵션의 만기 페이오프는

$$ \max \left( K- wp(T), 0 \right)$$

 

입니다. 

 

 

 

가격결정식

 

지난 글에서 다룬 기댓값 표현을 가지고 가격을 계산해 보도록 하겠습니다. 두 퍼포먼스를 $X_t, Y_t$라 하고 위 풋옵션의 시점 $t$에서의 가치를 $f(t,X_t,Y_t)$라 할 때, 저번 글(여러 개의 기초자산을 가지는 파생상품 가격결정식

)에 의하면

 

$$ f(t,X_t,Y_t ) =e^{-r(T-t)} \mathbb{E}(f(T,X_T,Y_T)|\mathcal{F}_t)\tag{1}$$

 

라 하였습니다. 여기서 $f(T,X_T,Y_T)$는 만기 시점의 payoff로서

 

$$ f(T,X_T,Y_T) = \max\left(  K -\min\left(X_T, Y_T)\right),0 \right)$$

이겠죠. 일견 복잡해 보이지만, 중간에 $\min(,)$는 워스프 퍼포머를 뜻하는 것입니다.

 

식(1)에서 $t=0$을 대입하면 바로 현재가치가 나오게 됩니다. 시점 $t=0$에서의 퍼포먼스의 가치를 $x_0, y_0$라 하면

$$f(0,x_0, y_0)  = e^{-r(T-t)} \mathbb{E}\left[\max\left(  K -\min\left(X_T, Y_T)\right),0 \right)\right]$$

 

※ 참고

$x_0, y_0$ 값이 무조건 1 아니냐 생각할 수도 있습니다. 왜냐면 퍼포먼스의 정의상 기준가로 나눴기 때문에 퍼포먼스의 스파트는 1에서 시작하는게 맞기 때문이죠.

하지만
1) 상품의 가격을 시작시점이 아닌 임의의 시점에서 계산할 필요, 
2) 상품 시작시점의 가격을 기준가로 보지 않는 상품에 대한 대응 


등으로 아무 값이나 가능하도록 $x_0, y_0$라 표기하는 것입니다.

 

 

가격 결정방법

식 (1)을 풀어 closed form을 구할 수 있을까요? 딱 봐도 쉽진 않을 듯합니다. 그럼 우선 MonteCarlo 시뮬레이션 방법으로 구해보도록 하겠습니다.

 

구하는 과정은 다음과 같습니다.

 

1. $X_T, Y_T$를 아주 많이 생성한다.
  $X_T, Y_T$는 정규분포를 따르는 확률 변수이고, 서로 상관관계가 있습니다. 
  이 점에 주의하여 생성합니다.
 
2. 만기페이오프를 구한다.
  만기페이오프는 $\max(K-W(T),0)~,~ W(T) =\min(X_T , Y_T)$ 로 주어집니다. 1에서 구한 $X_T,Y_T$의 최솟값인 $W(T)$를 
  구한 뒤 페이오프를 계산하면 됩니다.
 
3. 만기페이오프를 평균한다.
  2번에서 구한 페이오프의 기댓값을 구하기 위해 샘플을 평균합니다.
 
4. 마지막으로 할인팩터를 곱한다.
  3에서 구한 평균에 할인팩터 $e^{-rT}$를 곱하여 현재가치로 할인합니다.

 

 

Python Code

 

○ 워스트포퍼머에 대한 로직은 워스트포퍼머의 분포라는 글에서 다룬 코드랑 아주 유사합니다. 그 글과 비교하여 보시기 바랍니다.

 

○ Underlying과 Market이라는 클래스를 이용하여 코딩하는 방법은 ELS 가격졀정방법 글에서 소개한 바 있습니다. 링크의 글을 참고하시기 바랍니다.

 

 

아래는 해당 코드입니다. Call, Put Closed form은 2star put과 가격비교를 위해 또 한 번 작성합니다.

코드의 간략한 설명은 주석을 참고하시기 바랍니다.

 

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

N = norm.cdf

# call option closed formula
def CallOptionBS(S, K, T, r, q, sigma):
    if T == 0:
        return np.max(S - K, 0)
    else:
        d1 = (np.log(S / K) + (r - q + sigma ** 2 / 2) * T) / (sigma * np.sqrt(T))
        d2 = d1 - sigma * np.sqrt(T)
        return S * np.exp(-q * T) * N(d1) - K * np.exp(-r * T) * N(d2)

# put option closed formula
def PutOptionBS(S, K, T, r, q, sigma):
    if T == 0:
        return np.max(K - S, 0)
    else:
        d1 = (np.log(S / K) + (r - q + sigma ** 2 / 2) * T) / (sigma * np.sqrt(T))
        d2 = d1 - sigma * np.sqrt(T)
        return -S * np.exp(-q * T) * N(-d1) + K * np.exp(-r * T) * N(-d2)

# Market class : 시장의 무위험이자율과 기초자산간 상관계수
class Market:
    def __init__(self, rfr, correlation):
        self._rfr = rfr
        self._correl = correlation

# Underlying class: 기초자산의 기준가, 현재가, 변동성, 연속배당률
class Underlying: 
    def __init__(self, refprice, spotvalue, volatility, dividend):
        self._volatility = volatility
        self._dividend = dividend
        self._spot = spotvalue
        self._refprice = refprice


def TwoStarPut_MC(objUnderlyings: Underlying, objMarket: Market, strike, maturity,
                  n_iteration):
    nUnderlying = 2    # 기초자산 개수
    spot = []          # spot list : size 2
    refprice = []      # 기준가 list : size 2
    vol = []           # 변동성 list : size 2
    div = []           # 연속배당률 list : size 2
    drift = []         # drift :(r-q-1/2 vol^2)T
    diffusion = []     # diffusion list : vol*sqrt(T)
    rfr = objMarket._rfr
    corr = objMarket._correl

	# 위에서 정의한 list 완성
    for i in range(nUnderlying):
        spot.append(objUnderlyings[i]._spot)
        refprice.append(objUnderlyings[i]._refprice)
        vol.append(objUnderlyings[i]._volatility)
        div.append(objUnderlyings[i]._dividend)
        drift.append((rfr - div[i] - 0.5 * vol[i] ** 2) * maturity)
        diffusion.append((vol[i] * np.sqrt(maturity)))
	
    # numpy array의 broadcast 연산을 위해 list -> array형으로 변환
    spot = np.array(spot)
    refprice = np.array(refprice)
    vol = np.array(vol)
    div = np.array(div)
    drift = np.array(drift)
    diffusion = np.array(diffusion)

	# column이 2개이고 열이 simulation  횟수개인 정규분포 난수 배열 생성
    norm_rand = np.random.normal(size=(n_iteration, 2))
    norm_rand_correlated = norm_rand
    
    # 촐레스키 분해를 이용하여 서로 상관계수가 있는 두 난수로 변환(두 난수씩 simulation횟수 개)
    norm_rand_correlated[:, 1] = corr * norm_rand[:, 0] + np.sqrt(1 - corr ** 2) * norm_rand[:, 1]

    # 만기 종가 생성 (각 행당 만기종가 2개씩(열) 얻음)
    mat_price = spot / refprice * np.exp(drift + diffusion * norm_rand_correlated)
    
    # axis=1 방향, 즉 각 행당 두 종가중 작은 값 선택(worst performer)
    worst_perf = np.min(mat_price, axis=1)
    
    # put option 페이오프 산출을 위해 numpy.maximum  값으로 배열화
    payoff = np.maximum(strike - worst_perf, 0)
    payoff_mean = payoff.mean()        # payoff들의 평균
    dfactor = np.exp(-rfr * maturity)   # discount factor
    return dfactor * payoff_mean       # discount factor * E(payoff) 반환


if __name__ == '__main__':
    two_assets =[]
    underlying_spot1 = Underlying(refprice=100, spotvalue=100, volatility=0.3, dividend=0)
    underlying_spot2 = Underlying(refprice=100, spotvalue=100, volatility=0.3, dividend=0.0)
    two_assets.append(underlying_spot1)
    two_assets.append(underlying_spot2)

    market =Market(rfr=0.03, correlation=-0.5)

    Worstoff_Put_value = TwoStarPut_MC(two_assets,market,strike=1,maturity=1, n_iteration=10**6)

    put_closed_form = PutOptionBS(1,1,1,0.03,0,0.3)
    print(Worstoff_Put_value)
    print(put_closed_form)

 

위 예제는 두 기초자산이 모든 게 동일하고, 상관계수가 -0.5인 상황을 설정했습니다. 

 

결과를 보실까요?

 

0.18986208918792397
0.10327861752731726


Process finished with exit code 0

 

상관계수가 -0.5인 두 기초자산의 워스트포퍼머를 팔 수 있는 권리 풋옵션 가격이 , 기초자산 하나의 풋옵션 프리미엄보다 약 2배 정도 나옵니다. 왜 가격이 더 비쌀까요?

 

워스트 포퍼머는 두 기초자산 중 작은 애를 택하는 것입니다. 즉 기초자산인 워스트 포퍼머는 어쨌든 그 값이 낮아지게 됩니다. 따라서 정해진 가격(행사가)에 팔 수 있는 권리가 강해지고, 그 권리의 페이오프가 높아지는 것이죠.

 

 

 

 

상관계수에 따른 2star Worst Put 프리미엄은 어떨까?

 

 

그렇다면 다른 상관계수들은 어떨지요? 한번 비교 분석해 보겠습니다. 여러 값의 비교를 위해 난수를 고정하겠습니다.

 

 

우선 위의 함수 TwoStarPut_MC

np.random.seed(0)

 

를 삽입하여 실행했을 때 항상 같은 값이 나오도록 합니다. 그런 다음, 다음의 코드를 실행시켜 봅니다.

 

if __name__ == '__main__':
    two_assets = []
    underlying_spot1 = Underlying(refprice=100, spotvalue=100, volatility=0.3, dividend=0)
    underlying_spot2 = Underlying(refprice=100, spotvalue=100, volatility=0.3, dividend=0.0)
    two_assets.append(underlying_spot1)
    two_assets.append(underlying_spot2)
    
    #correlation을 -1에서 1까지 0.2단위로 증가
    correlation_vec = np.arange(-1, 1 + 0.2, 0.2)
    put_premium_vec = []
    for corr in correlation_vec:
        market = Market(rfr=0.03, correlation=corr)
        Worstoff_Put_value = TwoStarPut_MC(two_assets, market, strike=1, maturity=1, n_iteration=10 ** 6)
        put_premium_vec.append(Worstoff_Put_value)

    plt.plot(correlation_vec, put_premium_vec, marker='o', color='tomato', label='2star worstPut value')
    put_closed_form = PutOptionBS(1, 1, 1, 0.03, 0, 0.3)
    
    # 만기, 행사가, 변동성, 배당 등 다른 조건이 동일한 1star put closed form value를 수평선으로 그림
    plt.hlines(put_closed_form, correlation_vec[0], correlation_vec[-1], colors='blue', label='1star closed form value')
    plt.legend()
    plt.show()
    
    print(put_premium_vec)
    print(put_closed_form)

 

 

결과는 아래와 같습니다.

 

 

[0.20621289132758164, 0.19919919455191165, 0.19309287650655, 0.1865942423569374, 0.17991861568674636, 0.17303244798464795, 0.16505677437742636, 0.15674692133378682, 0.14672728831869936, 0.13386760848139292, 0.10322694899677576]
0.10327861752731726

Process finished with exit code 0

 

상관계수가 -1로 갈수록 (그래프에서 왼쪽방향) put 프리미엄이 상승합니다.  상관계수가 -1로 갈수록 두 기초자산이 반대로 움직이고, 따라서 두 기초자산의 워스트포퍼머는 더 작아지겠죠. 따라서 풋옵션 권리가 더 세지고 페이오프 기댓값이 커지는 것입니다.

 

상관계수가 1로 갈수록 두 기초자산은 동조화됩니다. 따라서 기초자산 1개일 때와 거의 비슷해지게 됩니다. 극단적으로 상관계수가 1인 경우에는 그냥 하나의 자산이라고 보면 되지요.

상관계수가 1로 갈수록 빨간색 그래프가 파란색 그래프(직선)와 붙는 걸 확인 할 수 있습니다.

 

 

어쨌든, 다음의 관찰만 기억하면 좋을 것 같습니다.

 

 

음의 상관관계를 가질수록, 워스트 포퍼머 값은 작아진다.

 

 

 

 

728x90
반응형

댓글