Sharpe ratio, CAPM

2023. 10. 9. 22:10금융 데이터 분석

반응형

주식을 하다보면, 하나의 종목만을 사고 팔고하는 경우가 없고 여러 종목을 선정하고 비중을 조정하는 경우가 많습니다.
이런 여러 종목들을 섞는 것을 포트폴리오를 구성한다고 하는 것이고, 포트폴리오의 성과와 위험을 관리하는 것은 중요 합니다.

이번 포스팅에서는 포트폴리오의 성과를 측정하기 위한 가장 기본적인 숫자들을 다뤄보도록 하겠습니다.

[Sharpe Ratio]

Sharpe Ratio는 포트폴리오 위험성 대비 수익성이 어떠한지를 나타내는 것으로, 값이 클수록 좋습니다. 
Sharpe Ratio가 크다는 것은 포포트폴리오 위험성(표준편차)가 낮고 수익성이 높다는 것입니다. 결국 변동(위험)대비 수익률이 어떠한지를 보는 것입니다.

$R_p$는 포트폴리의 수익률, $R_f$는 무위험 수익률, $\sigma_p$는 포트폴리오 수익률의 표준편차를 나타냅니다.

 

import FinanceDataReader as fdr
import pandas as pd
import numpy as np
import OpenDartReader
import requests
from bs4 import BeautifulSoup
import os
import matplotlib.pyplot as plt
import seaborn as sns
import pandas_datareader.data as pdr


### DATA LOADING 

kakao = fdr.DataReader('035720','2022-10-01', '2023-10-01')
samsung = fdr.DataReader('005930','2022-10-01', '2023-10-01')
naver = fdr.DataReader('035420','2022-10-01', '2023-10-01')


kakao.head(10)
samsung.head(10)
naver.head(10)

df_stock = pd.concat([kakao["Close"],samsung["Close"],naver["Close"]] ,axis = 1)
df_stock.columns = ["kakao", "samsung", "naver"]
returns = df_stock.pct_change().iloc[1:]


### SHARPE RATIO
def sharpe_ratio(return_series, N, rf):
    mean = return_series.mean() * N -rf ## 1년 수익률로 변환
    sigma = return_series.std() * np.sqrt(N) ## 1년 수익률의 표준편차로 변환
    return mean / sigma

N = 255 #255 trading days in a year
rf =0.01 #1% risk free rate (무위험수익률)
sharpes = returns.apply(sharpe_ratio, args=(N,rf,),axis=0)
sharpes.plot.bar()

 

22년 10월 부터 1년동안의 카카오, 삼성전자,네이버 주가의 Sharpe ratio를 보면 삼성전자가 가장 높게 나옵니다. 1년치 주가 흐름을 보면 1년동안 삼성전자는 꾸준히 상승했던 반면에 네이버는 조금 더 변동성이 있는 것으로 보입니다. 카카오는 오히려 가격이 떨어져 Sharpe ratio가 음수로 나오게 되었습니다. 즉 현재의 Sharpe ratio를 보면 삼성전자가 가장 좋은 주식임을 알 수 있습니다. 

[CAPM]

CAPM(Capital Asset Pricing Model)은 포트폴리오의 초과수익과 시장의 위험간의 관계를 분석하는 모델입니다. CAPM은 포트폴리오의 수익이 무위험수익률에 Risk premium을 더한 것과 같다고 가정합니다.

CAPM모델링을 하는 목적은 해당 포트폴리오에서 어느정도의 수익률을 기대할 수 있을지를 측정해보고자 하는 것입니다.

https://www.mlq.ai/capital-asset-pricing-model-python/

 $\beta$는 해당 포트폴리오의 수익률이 시장 지수에 어떻게 반응 하는지를 나타냅니다. $\beta$가 1보다 크다면 시장보다 더 변동성이 크다는 것을 뜻하고 1보다 작다면 시장보다 더 변동성이 적은 주식임을 뜻합니다. 

위의 수식에는 나타나지 않지만 $\alpha$가 해당 수식에 숨어져 있는데, $\alpha$는 위험초과수익률로 시장과 관계없이 얻는 수익률을 나타냅니다.

### DATA LOADING 

kakao = fdr.DataReader('035720','2022-09-01', '2023-09-01')
samsung = fdr.DataReader('005930','2022-09-01', '2023-09-01')
naver = fdr.DataReader('035420','2022-09-01', '2023-09-01')


kakao.head(10)
samsung.head(10)
naver.head(10)

df_stock = pd.concat([kakao["Close"],samsung["Close"],naver["Close"]] ,axis = 1)
df_stock.columns = ["kakao", "samsung", "naver"]
df_stock["portfolio"] = df_stock["kakao"]*1/3+df_stock["samsung"]*1/3+df_stock["naver"]*1/3
returns = df_stock.pct_change().iloc[1:]

kospi = pd.read_csv("C:/Users/user/Desktop/Project/finance_analytics/^KS11.csv")
df_kospi = kospi[["Date", "Close"]]
df_kospi = df_kospi.set_index("Date")
df_kospi["kospi"] = df_kospi["Close"].pct_change()
df_kospi = df_kospi.iloc[1:]


beta, alpha = np.polyfit(df_kospi["kospi"], returns["portfolio"], 1)
print(beta)
print(alpha)

df_kospi["portfolio"] = returns["portfolio"].values

from statsmodels.formula.api import ols

camp = ols('portfolio~ kospi', data = df_kospi).fit()
camp.summary()

CAPM 회귀식 결과

여기서 무위험수익률을 0으로 가정하면 Intercept는 -0.0005로 해당 22년 9월 1일~23년 9월 1일 삼성전자/카카오/네이버를 1:1:1 비중으로 갖는 포트폴리오는 시장과 관계없는 수익률은 -0.5%로 낮음을 알 수 있습니다. 다만 P-value가 유의하지 않고 CAPM에서 장기로 보면 Alpha는 0이라고 보기 때문에 CAPM에서 유의깊게 추정해야 하는 것은 Beta입니다.

해당 포트폴리의 Beta를 보면 1.3291로 시장의 변화보다 더 민감하게 반응함을 볼 수 있습니다. 실제로 카카오나 네이버와 같은 IT서비스기업들의 주간는 경기변동이나 트렌드에 민감하게 움직이고 있는 것으로 보입니다.

 

반응형