VaR(Value at Risk) 파이썬으로 구현하기 1

HKK·2022년 11월 24일
0

Finance AI

목록 보기
1/5

Value at Risk

싱글 자산 또는 포트폴리오의 극단적 손실을 의미하는 Value at Risk(VaR) 는 financial risk management의 가장 기본적인 metric이다. VaR을 측정하는데는 크게 세가지 방법으로 구분되어지는데 1) 가장 쉬운 방법으로 포트폴리오 수익률은 나열하여 가장 큰 손실을 해당 포트폴리오의 VaR로 선정하는 것이고 2) 두번째 방법은 공분산행렬을 사용하는 것으로 과거의 수익률이 미래에도 유사할 것이라는 것과 포트폴리오의 손실이 정규분포를 따를 것이라는 전제하에 계산하는 방법으로 parametric-VaR이라고 하자 3) 마지막으로 몬테카를로 시뮬레이션을 사용하는 방법으로 과거 수익률을 random하게 sampling하여 수익률에 대한 분포를 만드는 것으로 nonparmametric-VaR이라고 한다.

첫번째 방법은 너무나도 원시적 방법이기 때문에 그 신뢰성이 떨어진다. 하지만 가장 많이 사용되는 방법은 두번째 방법으로, 투자 손실(손익)의 분포가 아래와 같이 표준정규분포를 띄기 때문에 1일 수익률 평균과 분산은 1년 수익률 평균과 분산의 연율화와 동일하다는 가정에서 출발한다.

물론 금융데이터는 절대 표준정규분포를 따르지 않지만 계산의 편의상 이와 같이 가정하겠다. 그렇다면, VaR에서 'Risk'에 해당하는 부분은 어떻게 측정가능할까. 금융데이터에서 risk라 함은 보통 분산을 이야기 한다. 즉, 변동성이 리스크가 되는 것이다. 그리고, 이 risk를 측정하는 기준은 투자자가 정하는 신뢰가능한 수준, confidence interval로 측정한다.


Mathematical Definition

확률변수 𝑿를 자산의 손익일때, 𝛼 ∈ (0,1)인 confidence level (1-𝛼)%에 대하여, VaR𝛼(𝑿)는 𝑌 ≔ -𝑿를 만족하는 𝑌의 (1-𝛼)분위수가 된다.

VaRα(X)=inf{xR:FX(x)>α}=FY1(1α)VaR_{\alpha }(X)=-\inf \left\{{x\in \mathbb{R}:F_X(x)>\alpha }\right\}=F_Y^{-1}(1-\alpha )

이를 좀 더 쉽게 생각하면, 특정 𝑵기간동안, (1-𝛼)%의 신뢰구간에서 VaR을 추정하고자 한다면,

Nday VaR=1day VaR×NN-day\ VaR=1-day\ VaR\times \sqrt{N}

이 된다. 이때, 우리는 리스크가 표준정규 분포를 따른다고 가정했기 때문에 𝑿~𝑵(0,1)이고, 해당 자산의 𝑿를 표준화 하면 𝑿와 𝛼의 𝑧 score로 나타낼 수 있다.

σday=σyear2521day VaR=Zα×σdayNday VaR=1day VaR × N = Zα×σday×N\sigma _{day}=\frac{\sigma _{year}}{\sqrt{252}} \\ 1-day\ VaR=Z_{\alpha }\times \sigma _{day}\\ N-day\ VaR=1-day\ VaR\ \times \ \sqrt{N}\ =\ Z_{\alpha }\times \sigma _{day}\times \sqrt{N}

예를들어, 마이크로소프트의 1년 변동성(표준편차)가 0.32일때, 하루 표준편차는 0.02가 된다. 그리고 99% 신뢰수준에서의 z score가 2.326이라면 10일동안의 자산의 변동성은 2.326 X 0.02 X 101/210^{1/2}이 되고, 손실가능 자산액은 해당 식에 투자금액을 곱해주면 된다.


VaR for Python

그럼 파이썬으로 VaR을 구해보자.
우선, yahoo finance로 데이터를 얻어보겠다.

import pandas as pd
import numpy as np
import yfinance as yf

ms = yf.download('MSFT', start = '2021-01-01', end = '2022-08-16')[['Close']]
ms['log_close'] = np.log(ms['Close'])
ms['change'] = ms['log_close'].pct_change()
ms = ms.dropna()
ms.haed()

이렇게 약 1년 8개월의 데이터에서 표준편차를 구하고, 99% 신뢰수준에서의 마이크로소프트의 1일 VaR을 구하면, 약 0.00035가 된다.

std = ms['change'].std() #표준편차 계산
std_daily = std/np.sqrt(len(ms.index)) #1일 표준편차 계산

from scipy.stats import norm
CL = 0.99
z_score = norm.ppf(CL)

print('1day VaR of Microsoft: ',z_score * std_daily)

그리고 만약, 향후 마이크로소프트에 20일동안 1억원을 투자한다고 했을때의 최대 손실 가능액은 156,755원이다.

N = 20
initial_P = 100000000
VaR = z_score * std_daily * initial_P * np.sqrt(N)

print('99%신뢰수준에서 마이크로소프트에 1억 투자시 20일동안 최대손실가능액: ',round(VaR),'원')

그러나, 보통 리스크를 줄이기 위해서는 우리는 다양한 자산들 구성된 포트폴리오를 생성한다. 여러 자산이 있을때는 공분산을 통해 전체 포트폴리오의 표준편차를 계산한다. 이때의 VaR계산은 다음의 단계를 거친다.

  1. 포트폴리오의 각 자산별 수익률을 계산한다.
  2. 각 자산의 분산과 자산간 공분산으로 이루어진 공분산행렬을 계산한다.
  3. 공분산행렬에 자산별 가중치를 내적해 포트폴리오의 표준편차를 계산한다.
  4. 포트폴리오 표준편차를 연율화 하고, 1일 표준편차를 계산한다.

Multi-asset Portfolio VaR for Python

해당 프로세스에서 가장 중요한 것이 공분산행렬인데, 공분산행렬은 변수들간의 공분산(covariance)를 matrix notation으로 표현한 것으로, 아래와 같이 대각원소는 해당 변수들의 분산이고 대각원소를 제외한 나머지는 변수들간의 공분산을 symmetric하게 나타낸 matrix이다. 그리고 이는 파이썬의 cov()라는 함수로 생성할 수 있다.

C(x,y,z)=(varxcovarx,ycovarx,zcovary,xvarycovary,zcovarz,xcovarz,yvarz)C(x,y,z)=\begin{pmatrix}\text{var}_x&covar_{x,y}&covar_{x,z}\\covar_{y,x}&var_y&covar_{y,z}\\covar_{z,x}&covar_{z,y}&var_z\end{pmatrix}

그리고, 여기에 가중치 벡터 𝑾를 내적하면, 포트폴리오의 분산을 얻을 수 있고, 포트폴리오의 분산이 곧 포트폴리오의 표준편차로 계산된다.

σp2=wTCw=(w1 w2 w3)(varxcovarx,ycovarx,zcovary,xvarycovary,zcovarz,xcovarz,yvarz)(w1w2w3)\sigma _p^2=w^TCw=(w_1\ w_2\ w_3)\begin{pmatrix}\text{var}_x&covar_{x,y}&covar_{x,z}\\covar_{y,x}&var_y&covar_{y,z}\\covar_{z,x}&covar_{z,y}&var_z\end{pmatrix}\begin{pmatrix}w_1\\w_2\\w_3\end{pmatrix}

우선, 포트폴리오에 편입할 자산을 애플, 마이크로소프트, 버크셔 해서웨이, 디즈니로 설정하고 각각의 가중치를 24%, 30%, 15% 30%로 한다.

tickers = ['AAPL','MSFT','BRK-B','DIS']
w = np.array([0.24,0.3,0.15,0.3]) #포트폴리오 가중치
df = yf.download(tickers,start='2021-01-01',end = '2022-08-16')[['Close']]
df = np.log(df)
df = df.pct_change()
df = df.dropna()
df.head()

cov = df.cov() #포트폴리오 공분산 계산
std = np.sqrt(w.T.dot(cov).dot(w))
std_daily = std/np.sqrt(len(df.index)) #1일 표준편차 계산
z_score = norm.ppf(0.99)

print('Covariance of Portfolio: ',cov)
print('------------------------------')
print('1day VaR of Portfolio: ',z_score * std_daily)

그리고, 포트폴리오의 공분산행렬과 1일 VaR을 구하면 약 0.0033이다.

single asset portfolio와 동일하게 해당 포트폴리오에 20일동안 1억원을 투자했을때, 최대가능 손실액은 121,583원으로 마이크로소프트에만 투자했을때보다 그 손실액이 적어진 것을 확인할 수 있다.

N = 20
initial_P = 100000000
VaR = z_score * std_daily * initial_P * np.sqrt(N)

print('99%신뢰수준에서 포트폴리오에 1억 투자시 20일동안 VaR: ',round(z_score * std_daily * np.sqrt(N) * 100,3),'%')
print('99%신뢰수준에서 포트폴리오에 1억 투자시 20일동안 최대손실가능액: ',round(VaR),'원')

이처럼, VaR은 과거 데이터를 통해서 미래에 동일한 투자를 한다고 했을때의 예상가능한 손실액을 알 수 있다. 하지만, 금융데이터는 표준정규분포를 따르지 않기 때문에, 해당 VaR은 현실과는 다소 동떨어진 결과가 나온다. 그래서 이를 보완하기 위해 montecarlo simulation으로 분포를 만들어서 계산하는 방법이 있는데 이것은 다음 포스팅에서 설명하도록 하겠다.

Code: https://github.com/hyeokkukim/python-for-finance/blob/main/Value_at_Risk(VaR).ipynb

profile
Dept. of Urban Bigdata Convergence at University of Seoul

0개의 댓글