반응형
중급 강의에서는 기초적인 내용에 대한 설명은 생략하고 작성됩니다.
또한 기초적인 질문에 대해서는 답변을 생략하거나, 링크로 대체함을 알립니다.

이번 강의에서는 젠포트에서 제공해주지 않는 포트폴리오 평가지표를

젠포트 거래로그 파일을 이용해 분석해 보도록 하겠습니다.


1. Value At Risk

Value At Risk(VaR)는 발생가능한 최대손실금액으로서, 금융기관에서 시장위험의 예측 지표로 사용됩니다.

예시로 목표기간 1년, 신뢰수준 95% 수준의 데이터에서 산출된 VaR이 1억으로 산출되었다면,

1년동안 발생할 수 있는 최대 손실금액이 1억보다 적을 확률이 95%라고 해석할 수 있습니다.

 

2. Expected ShortFall

Expected ShortFall(ES)는 VaR에서 최대 손실금액보다 높은 확률에 위치해 있는 리스크값 전체 모음의

평균을 낸 값입니다.

(1)에서 5%안에 속해있는 값의 최고값이 10억이고, VaR이 1억이면 그 사이에 일어나는 손실값의

전체 평균이 Expected ShortFall로 산출이 됩니다.


 

 

 

 

 

 

 

 

 


3. 파이썬으로  분석해보기

먼저 필요한 패키지를 불러오겠습니다.

## 패키지 호출
## Data manipulation
import numpy as np
import pandas as pd

## Graph
import matplotlib
import matplotlib.pyplot as plt

## Tabular data
from tabulate import tabulate
tabulate 패키지는 데이터를 테이블 형식으로
출력해주는 패키지입니다.

일별 수익률 데이터를 불러와서 정제합니다.

## 수익률 파일 호출
## 총자산 및 남은 현금 Columns는 필요성이 느껴지지 않아 Drop하였음.

## 데이터 호출 및 불필요 데이터 삭제
daily_profit = pd.read_csv('Test_CSV/913695/trade_history_daily_913695.csv')
daily_profit = daily_profit.drop(["총자산", "남은 현금"], axis=1)

## 2017년 데이터 추출
daily_2017 = daily_profit[0:243]

## 2018년 Data
daily_2018 = daily_profit[244:487]

## 2019년 Data
daily_2019 = daily_profit[487:733]

## 2017~2019년 Data
daily_Tot = daily_profit[:733]

일별 수익률 데이터는 각 포트폴리오의 [거래내역] - [일별 거래내역]을 CSV파일로 받으면 됩니다.

1.
거래내역 CSV파일을 받아서 DataFrame으로 불러온 뒤, 필요없는 Column들을 삭제시킵니다.

2.
연도별로 데이터를 나눕니다.

2017년 데이터를 먼저 히스토그램으로 확인해 봅시다.

## 2017년의 데이터를 이용해 Histogram Graph 작도
plt.hist(daily_2017["일일수익률"][0:243], bins = 50)
plt.xlabel("reuturns")
plt.ylabel("frequency")
plt.grid(True)

plt.show()
1.
2017년 일일수익률 데이터를 히스토그램으로 변환합니다.
bins를 이용해 몇분할로 나타낼 건지 설정할 수 있습니다.

2.
가로축은 수익률, 세로축은 빈도로 설정합니다.

* 실행 결과

히스토그램 그림이 불러와집니다.


VaR을 산출해 보겠습니다.

## 2017년 데이터를 이용해 VAR을 구해보자.

'''
VaR(Value At Risk)
특정 금융자산 포트폴리오의 손실위험을 측정하기 위해
널리 이용되는 위험 측정수단으로서 
특정 포트폴리오가 일정기간 동안 보여준 변동률을 고려할 때 
향후 발생할 수도 있는 최대손실 가능금액 (Worst Expected Loss)과 확률을 나타낸다.

이 노트북에서는 과거 데이터를 이용하여 VaR을 산출하였다.(역사적 시뮬레이션)
'''

## 데이터 정렬
daily_2017.sort_values('일일수익률', inplace = True, ascending = True)

## 상위값 확인
VaR_1_2017 = daily_2017["일일수익률"].quantile(0.99)
VaR_5_2017 = daily_2017["일일수익률"].quantile(0.95)
VaR_10_2017 = daily_2017["일일수익률"].quantile(0.9)
VaR_50_2017 = daily_2017["일일수익률"].quantile(0.5)

## 하위값 확인 
VaR_90_2017 = daily_2017["일일수익률"].quantile(0.1)
VaR_95_2017 = daily_2017["일일수익률"].quantile(0.05)
VaR_99_2017 = daily_2017["일일수익률"].quantile(0.01)

## 테이블로 출력
## VaR%만큼의 수익 or 손실이 발생할 확률은 X%이다.
print(tabulate([["1%", VaR_1_2017], ["5%", VaR_5_2017], ["10%", VaR_10_2017], ["50%", VaR_50_2017]], headers = ["수익상위값_2017", "VaR"]))
print("\n")
print(tabulate([["10%", VaR_90_2017], ["5%", VaR_95_2017], ["1%", VaR_99_2017]], headers = ["손실상위값_2017", "VaR"]))
1.
수익률 데이터를 값이 큰 순(내림차순)으로 정렬합니다.

2.
quantile 함수를 이용해 상위, 하위 XX%값을 산출합니다.
quantile(X) : 하위 X% 값을 반환합니다.

3.
Tabulate 함수를 이용하여 테이블로 반환합니다.
tabulate(Value, Header) : Value(테이블 값)과 Header(Column, 열 이름)을 입력하면 테이블로 반환합니다.

* 실행 결과

수익상위값_2017       VaR
---------------  ------
1%               3.0132
5%               2.03
10%              1.73
50%              0.27


손실상위값_2017        VaR
---------------  -------
10%              -1.062
5%               -1.448
1%               -2.5174

각 상, 하위값에 따른 일일수익률 값이 출력되었습니다.

제 포트폴리오 기준으로 VaR 1%는 -2.5%로 확인되었습니다.


같은 방식으로 2018년, 2019년의 VaR을 산출해 보겠습니다.

## 2018년

## 데이터 정렬
daily_2018.sort_values('일일수익률', inplace = True, ascending = True)

## 상위값 확인
VaR_1_2018 = daily_2018["일일수익률"].quantile(0.99)
VaR_5_2018 = daily_2018["일일수익률"].quantile(0.95)
VaR_10_2018 = daily_2018["일일수익률"].quantile(0.9)
VaR_50_2018 = daily_2018["일일수익률"].quantile(0.5)

## 하위값 확인 
VaR_90_2018 = daily_2018["일일수익률"].quantile(0.1)
VaR_95_2018 = daily_2018["일일수익률"].quantile(0.05)
VaR_99_2018 = daily_2018["일일수익률"].quantile(0.01)

## 테이블로 출력
print(tabulate([["1%", VaR_1_2018], ["5%", VaR_5_2018], ["10%", VaR_10_2018], ["50%", VaR_50_2018]], headers = ["백분위 비율_2018", "VaR"]))
print("\n")
print(tabulate([["90%", VaR_90_2018], ["95%", VaR_95_2018], ["99%", VaR_99_2018]], headers = ["백분위 비율_2018", "VaR"]))

* 실행 결과

백분위 비율_2018       VaR
------------------  ------
1%                  3.7058
5%                  2.098
10%                 1.694
50%                 0.13


백분위 비율_2018        VaR
------------------  -------
90%                 -1.11
95%                 -1.706
99%                 -3.0088

## 2019년

## 데이터 정렬
daily_2019.sort_values('일일수익률', inplace = True, ascending = True)

## 상위값 확인
VaR_1_2019 = daily_2019["일일수익률"].quantile(0.99)
VaR_5_2019 = daily_2019["일일수익률"].quantile(0.95)
VaR_10_2019 = daily_2019["일일수익률"].quantile(0.9)
VaR_50_2019 = daily_2019["일일수익률"].quantile(0.5)

## 하위값 확인 
VaR_90_2019 = daily_2019["일일수익률"].quantile(0.1)
VaR_95_2019 = daily_2019["일일수익률"].quantile(0.05)
VaR_99_2019 = daily_2019["일일수익률"].quantile(0.01)

## 테이블로 출력
print(tabulate([["1%", VaR_1_2019], ["5%", VaR_5_2019], ["10%", VaR_10_2019], ["50%", VaR_50_2019]], headers = ["백분위 비율_2019", "VaR"]))
print("\n")
print(tabulate([["90%", VaR_90_2019], ["95%", VaR_95_2019], ["99%", VaR_99_2019]], headers = ["백분위 비율_2019", "VaR"]))

* 실행 결과

백분위 비율_2019       VaR
------------------  ------
1%                  3.431
5%                  2.5275
10%                 1.88
50%                 0.275


백분위 비율_2019        VaR
------------------  -------
90%                 -1.35
95%                 -1.8275
99%                 -2.991


산출된 VaR을 시각화해보겠습니다.

## VaR 분포를 그래프를 이용하여 시각적으로 확인해본다.
percs = list(np.arange(0.0, 10.1, 0.1))

var_2017 = np.percentile(daily_2017["일일수익률"], percs)
var_2018 = np.percentile(daily_2018["일일수익률"], percs)
var_2019 = np.percentile(daily_2019["일일수익률"], percs)
var_Tot = np.percentile(daily_Tot["일일수익률"], percs)

plt.plot(percs, var_2017, 'r', lw=1.5, label='2017')
plt.plot(percs, var_2018, 'g', lw=1.5, label='2018')
plt.plot(percs, var_2019, 'b', lw=1.5, label='2019')
plt.plot(percs, var_Tot, 'Gray', lw=3, label='ToT')

plt.legend(loc=4)
plt.xlabel('100 - confidence level [%]')
plt.ylabel('Value-at-Risk')
plt.grid(True)
plt.ylim(ymax=0.0)

plt.show()
1.
np.percentile 함수를 이용하여 수익률 하위 0% ~ 10%까지 값을 산출합니다. 
np.percentile(value, array) : Array값에 해당되는 백분위값을 value에서 찾아 매핑하여 반환합니다.

* 실행 결과

VaR값의 분포를 시각화한 그래프가 출력되었습니다.

이것을 통해 알 수 있는 제 포트폴리오의 특징은

◎ 2%대에서 급격히 VaR값이 커진다.
◎ 연도가 지나갈수록 VaR값이 커진다. 
◎ 3년합은 중간값정도에 해당되나 극값에서 급격히 커짐. 2019년의 VaR값들에 의해 영향을 받은것으로 추정됨.

이렇게 3가지 특징을 확인해 볼 수 있습니다.
이것을 기반으로 포트폴리오의 손실을 더 줄이거나, 대형 손실이 발생한 일자의 거래로그를 세부적으로 분석하여
포트폴리오 수식을 수정해 볼 수 있겠습니다.

 


Expected ShrotFall을 확인해 보겠습니다.

## 연도별 Expected_ShortFall을 구해보자. (ES : VaR 에 들어가있는 손실값의 평균)

## 1%의 확률로 일어날 수 있는 포트폴리오 손실값 전체의 평균 (VaR 1%)
print(round(daily_2017["일일수익률"][daily_2017["일일수익률"] <= VaR_99_2017].mean(),3))
print(round(daily_2018["일일수익률"][daily_2018["일일수익률"] <= VaR_99_2018].mean(),3))
print(round(daily_2019["일일수익률"][daily_2019["일일수익률"] <= VaR_99_2019].mean(),3))

## 5%의 확률로 일어날 수 있는 포트폴리오 손실값 전체의 평균 (VaR 5%)
print(round(daily_2017["일일수익률"][daily_2017["일일수익률"] <= VaR_95_2017].mean(),3))
print(round(daily_2018["일일수익률"][daily_2018["일일수익률"] <= VaR_95_2018].mean(),3))
print(round(daily_2019["일일수익률"][daily_2019["일일수익률"] <= VaR_95_2019].mean(),3))

## 10%의 확률로 일어날 수 있는 포트폴리오 손실값 전체의 평균 (VaR 10%)
print(round(daily_2017["일일수익률"][daily_2017["일일수익률"] <= VaR_90_2017].mean(),3))
print(round(daily_2018["일일수익률"][daily_2018["일일수익률"] <= VaR_90_2018].mean(),3))
print(round(daily_2019["일일수익률"][daily_2019["일일수익률"] <= VaR_90_2019].mean(),3))
VaR값보다 일일수익률이 적은(하위 XX%) 값들을 측정하여
mean 함수로 평균값을 낸 뒤, round를 이용하여 소숫점 3째자리까지 반올림해줍니다.

* 실행 결과

-3.183
-3.377
-3.84

-2.073
-2.446
-2.541

-1.659
-1.954
-2.072

ES값이 출력되었습니다.


ES값도 시각화하여 확인 해 보겠습니다.

## ES 분포를 그래프를 이용하여 시각적으로 확인해본다.

## ES 구하는 함수
def get_ES(percent_list, profit_df):
    temp = []
    
    for i in percent_list:
        var_temp =  np.percentile(profit_df["일일수익률"], i)
        es_temp = profit_df["일일수익률"][profit_df["일일수익률"] <= var_temp].mean()
        temp.append(es_temp)
        
    return  temp


## ES 산출용 list 산출 
percs = list(np.arange(0.0, 10.1, 0.5))
    
## ES값 산출    
es_2017 = get_ES(percs, daily_2017)
es_2018 = get_ES(percs, daily_2018)
es_2019 = get_ES(percs, daily_2019)
es_Tot = get_ES(percs, daily_Tot)

## 그래프 작도
plt.plot(percs, es_2017, 'r', lw=1.5, label='2017')
plt.plot(percs, es_2018, 'g', lw=1.5, label='2018')
plt.plot(percs, es_2019, 'b', lw=1.5, label='2019')
plt.plot(percs, es_Tot, 'Gray', lw=3, label='Tot')

plt.legend(loc=4)
plt.xlabel('100 - confidence level [%]')
plt.ylabel('Excepted Shortfall')
plt.grid(True)
plt.ylim(ymax=0.0)

plt.show()

## 그래프를 확인해보니 4%대부터 손실이 커진다.
## 연도가 지나갈수록 ES값도 VaR에 비례하여 커진다.
## 3년합은 중간값정도에 해당되나 2%대에서 급격히 커짐. 2019년의 VaR값들에 의해 영향을 받은것으로 추정됨.
get_ES 함수를 이용하여 백분위별 ES값을 산출합니다.
이후 이 값을 기반으로 그래프를 작도합니다. (가로축은 백분위, 세로축은 ES값)

* 실행 결과

Expected ShortFall 분포 그래프가 출력되었습니다.

이것을 통해 알 수 있는 제 포트폴리오의 특징은

◎ 그래프를 확인해보니 4%대부터 손실이 커진다.
◎ 연도가 지나갈수록 ES값도 VaR에 비례하여 커진다.
◎ 3년합은 중간값정도에 해당되나 2%대에서 급격히 커짐. 2019년의 VaR값들에 의해 영향을 받은것으로 추정됨.

이렇게 3가지 특징을 확인해 볼 수 있습니다.

이것을 기반으로 대형 손실이 발생한 일자의 거래로그를 세부적으로 분석하여
포트폴리오 수식을 수정해 볼 수 있겠습니다.
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기