devtools::install_github("hyunyulhenry/HenryQuant") library(HenryQuant) library(quantmod) library(PerformanceAnalytics) library(FRAPO)
먼저 HenryQuant 패키지를 업데이트 한 후,
각종 패키지들을 다운로드받습니다.
ticker = get_KOR_ticker()
HenryQuant 패키지 내 함수를 이용해
코스피 + 코스닥 전종목 티커를 다운 받습니다.
전 종목의 티커, 종목명, 시가총액(억) 이 다운됩니다.
symbols = paste0(ticker[1:30, 1], ".KS") getSymbols(symbols, src='yahoo') prices = list() for(i in 1:length(symbols)) { prices[[i]] = Ad(get(symbols[[i]])) } prices = do.call(cbind, prices) colnames(prices) = ticker[1:30, 2]
시가총액 대형주 30 종목 주가를 다운받습니다.
6자리 티커에 ".KS" 를 붙여준 뒤
quantmod의 getSymbols 함수를 이용해
야후에서 수정주가를 다운로드 받습니다.
rets = na.omit(Return.calculate(prices)) mkt_cap = ticker[1:30, 3] mkt_cap = mkt_cap / sum(mkt_cap) covmat = cov(rets)
수익률을 구한 후, na 데이터는 삭제해 줍니다.
ticker 변수의 3번째 열에 시가총액이 있으므로,
시가총액비중 또한 쉽게 구할 수 있으며,
covariance matrix도 계산해 줍니다.
1) 최소 분산 포트폴리오 (Min Vol)
wt_minvol(covmat)
min vol 비중을 구해주는 wt_minvol 함수입니다.
단순히 covariance matrix만 입력해주면,
종목 당 비중이 계산됩니다.
단, 0으로 나오는 종목이 꽤 많이 존재하며 (최소비중 0이 기본),
특정 종목에 비중이 많이 쏠리기도 합니다.
(변동성이 낮은 SK 텔레콤에 22% 가량)
wt_minvol(covmat, lb = rep(0.01, ncol(prices)), ub = rep(0.1, ncol(prices)))
최소 비중 제약(lb)을 1%, 최대 비중 제약(ub)을 10%로 줍니다.
비중이 0 이었던 종목이 그래도 1%는 투자를 하고,
최대 비중도 10% 로 막히게 되었습니다.
이런 제약조건 주는 패키지는 기존에도 있었습니다.
하지만, 종목 별로 비중을 다르게 주는 패키지는 기존에 없었죠?
upper_bound = apply(rbind(rep(0.10, 5), mkt_cap * 3), 2, min) plot(upper_bound, ylab ="", xlab = "")
먼저 upper_bound를 위와 같이 설정합니다.
기존 10%와 시총비중 * 3 을 비교하여,
이 중 낮은 값을 선택합니다.
예를 들어, 삼성전자의 시총비중이 30%라 가정하면
min(10%, 30%*3) = 10%, 즉 최대 비중 제약은 10%가 됩니다.
반면 특정종목의 시총비중이 2%라 가정하면
min(10%, 2%*3) = 6%, 즉 최대 비중 제약은 6%가 됩니다.
이는 벤치마크와의 비중을 줄이는 최적화 포트폴리오를 만들기 위함입니다.
실제로 그래프에서 보면
시총비가 큰 종목의 최대비중 제약은 10% 이며,
시총비가 내려갈수록 최대비중 제약은 내려감이 확인됩니다.
wt_minvol(covmat, lb = rep(0.01, ncol(prices)), ub = upper_bound)
최소투자비중은 1%로,
최대투자비중은 upper_bound를 적용한 최적화 포트폴리오 입니다.
(물론 최소투자비중도 종목 마다 다르게 셋팅할 수 있습니다.)
원하는대로 결과가 나왔군요 :D
2) Max Diversification
wt_maxdiv(covmat) wt_maxdiv(covmat, lb = rep(0.01, ncol(prices)), ub = rep(0.1, ncol(prices))) wt_maxdiv(covmat, lb = rep(0.01, ncol(prices)), ub = upper_bound)
최대분산효과를 구하는 wt_maxdiv 함수입니다.
사용법은 wt_minvol과 같습니다.
단순히 covariance matrix만 입력할 경우 하한과 상한 제약은 0과 1,
lb와 ub에 각각의 제약조건을 입력할 수도 있습니다.
3) 시가총액가중, 동일가중
wt_normal(mkt_cap, MaxWeight = 1.00, type = "VW")
시총가중과 동일가중을 구하는 wt_normal 함수입니다.
해당함수는 시가총액, 최대비중, type
총 3가지 변수가 필요합니다.
type을 "VW"로 할 경우 Value Weight, 즉 시총비중
"EW"로 할경우 Equal Weight, 즉 동일비중이 구해집니다.
위의 경우 시가총액 비중대로 나옵니다.
그러나 문제는 국내의 경우
삼성전자의 비중이 지나치게 높다는 것입니다.
따라서, 시가총액 비중대로 하면서
특정 종목의 상한은 제약할 수 있습니다.
(나머지 비중은 다른 종목들에 뿌려지겠죠)
wt_normal(mkt_cap, MaxWeight = 0.10, type = "VW")
MaxWeight에 원하는 비중을 너으면
최대비중이 해당 숫자만큼 제한됩니다.
(스마트베타 책에 썼던 테크닉이죠?)
삼성전자의 비중이 10%로 제한됨이 확인되며,
나머지 비중들이 차액 만큼 배분되서 증가합니다.
wt_normal(mkt_cap, MaxWeight = 0.50, type = "EW")
이번엔 가장 심플한 동일가중입니다.
mkt_cap에 시가총액을 뭘 넣건, MaxWeight에 뭘 넣건
type = "EW" 해주면 그냥 동일가중이 계산됩니다.
4) 리스크 버짓 (리스크 패러티)
mrc(mkt_cap, covmat)
먼저, 30 종목의 risk contribution을 구해봅니다.
삼성전자가 50% 이상을, SK 하이닉스가 9% 이상을,
둘이 합치면 60% 이상의 risk를 가져갑니다.
극혐인 한국 시장입니다.
budget = rep(1/ncol(rets), ncol(rets)) RiskBudget(covmat, budget)
먼저 모든 종목들의 Risk Contribution이 같게 만드는
Risk Parity Portfolio 를 구합니다.
이는 각 종목의 Risk Budget이 1/n로 똑같은 경우입니다.
RiskBudget 함수는 covariance matrix와 원하는 budget 값을 입력하면 됩니다.
최적화된 비중이 계산되어 집니다.
mrc(RiskBudget(covmat, budget), covmat)
구해진 값들의 risk contribution을 확인해 봅니다.
모든 종목이 3.33%로 동일하군요!
budget = mkt_cap
RiskBudget(covmat, budget)
물론 종목마다 Risk Budget을 다르게 입력할 수도 있습니다.
시험 삼아 budget을 시총비로 입력해봅니다.
최적화 값이 잘 나옵니다.
mrc(RiskBudget(covmat, budget), covmat) mkt_cap
시총비를 Budget 으로 한 포트폴리오의 Risk Contribution과
시총비의 비교입니다.
두 값이 동일함이 확인됩니다.
요약
함수명
|
목적
|
입력변수
|
특징
|
wt_minvol
|
MV
|
covmat: 공분산
lb: 최소 비중
ub: 최대 비중
cut_w: 버림 조건
|
lb와 ub 미 입력시 각각 0과 1로 계산
lb와 ub는 종목별로 다르게 적용 가능
|
wt_maxdiv
|
MDP
|
covmat: 공분산
lb: 최소 비중
ub: 최대 비중
cut_w: 버림 조건
|
lb와 ub 미 입력시 각각 0과 1로 계산
lb와 ub는 종목별로 다르게 적용 가능
|
wt_normal
|
VW,
EW
|
MarketCap: 시총 비중
MaxWeight: 최대 비중
type: “VW” or “EW”
|
“VW”의 경우 시총 가중,
“EW”의 경우 동일 가중
|
RiskBudget
|
RB(RP)
|
covmat: 공분산
target: Risk Budget
|
Risk Budget or Risk Parity 가능
|
댓글 없음:
댓글 쓰기