시장의 하락을 예상할 때 가장 좋은 투자 수단은 선물을 매도하는 것입니다. 그러나 현실적으로 선물 매매에 대한 부담감 때문인지 많은 개미 투자자들이 인버스(-X1) 혹은 곱버스(-X2) ETF를 이용해 하방에 베팅합니다.
그러나 이러한 ETF를 이용해 데일리 트레이딩 하는 것은 호가와 스프레드로 인해 상방 베팅 ETF (X1 혹은 X2) 보다 효율적으로 돈을 벌기 힘듭니다.
각 기초지수와 ETF의 틱데이터를 이용해 비교해보도록 하겠습니다.
시장의 하락을 예상할 때 가장 좋은 투자 수단은 선물을 매도하는 것입니다. 그러나 현실적으로 선물 매매에 대한 부담감 때문인지 많은 개미 투자자들이 인버스(-X1) 혹은 곱버스(-X2) ETF를 이용해 하방에 베팅합니다.
그러나 이러한 ETF를 이용해 데일리 트레이딩 하는 것은 호가와 스프레드로 인해 상방 베팅 ETF (X1 혹은 X2) 보다 효율적으로 돈을 벌기 힘듭니다.
각 기초지수와 ETF의 틱데이터를 이용해 비교해보도록 하겠습니다.
바야흐로 ETF 투자의 시대입니다. 상장된 주식수와 ETF수가 비슷할 정도라고 해도 과언이 아닐 만큼 수많은 ETF가 상장되어 있고, 그 투자 대상 역시 상상을 초월합니다.
덕분에 장기투자, 특히 개인연금 혹은 IRP에서 ETF를 이용한 투자가 유행이고 마치 진리처럼 소개되고 있습니다. 사실 장점은 명확합니다. 기존 펀드에 비해 훨씬 저렴한 수수료, 훨씬 간편한 매수/매도, 훨씬 다양한 형태의 투자대상 등이 있겠죠.
그러나 이런것들이 다 결과론적인 얘기이지 실제 투자의 세계에서, 특히나 처음 투자를 하는 분들에게는 얘기가 조금 다를 듯합니다. 특히나 '실시간 투자 가능' 여부는 장점이 될수도 있지만 오히려 독이 될수도 있습니다.
펀드를 통해 투자를 할 경우 수익률을 일간 단위로만 확인이 가능합니다. 그러나 ETF의 경우 주식시장에 상장되어 거래가 되는 만큼 계속해서 그 수익률이 바뀝니다. 그만큼 계좌의 실시간 변동성도 커지게 되기 마련입니다.
멋진 예제를 살펴보죠. 많이들 투자하는 올웨더 포트폴리오를 대상으로요.
## Annual Monthly Daily
## Return(Annual) 0.07818458 0.07818458 0.07867070
## Vol(Annual) 0.07239884 0.07379339 0.07469286
## Sharpe(Annual) 1.07991472 1.05950653 1.05325599
## Sharpe 1.11138278 0.30602237 0.06623194
## Annual Monthly Daily
## [1,] 0.1428571 0.3214286 0.4414029
|
AUM
|
2X 노출도 (목표)
|
|
10,000,000,000
|
20,000,000,000
|
선물 노출
|
|
20,000,000,000
|
선물 개당 금액
|
|
80,000,000
|
선물 개수
|
|
250.00
|
1% 상승시
|
||
|
AUM
|
2X 노출도 (목표)
|
|
10,100,000,000
|
20,400,000,000
|
선물 금액
|
|
20,200,000,000
|
선물 개당 금액
|
|
80,800,000
|
차이
|
|
200,000,000
|
추가 매수
|
|
2.5
|
2% 상승시
|
||
|
AUM
|
2X 노출도 (목표)
|
|
10,200,000,000
|
20,800,000,000
|
선물 금액
|
|
20,400,000,000
|
선물 개당 금액
|
|
81,600,000
|
차이
|
|
400,000,000
|
추가 매수
|
|
4.9
|
종목
|
종가
|
주식수
|
유동비
|
|
1
|
삼성전자
|
45,850
|
5,969,782,550
|
0.7879
|
2
|
SK하이닉스
|
75,900
|
728,002,365
|
0.7389
|
3
|
셀트리온
|
200,500
|
125,461,438
|
0.6670
|
4
|
POSCO
|
258,000
|
87,186,835
|
0.8117
|
5
|
신한지주
|
43,300
|
474,199,587
|
0.8978
|
6
|
LG화학
|
382,000
|
70,592,343
|
0.6611
|
7
|
현대차
|
124,500
|
213,668,187
|
0.6577
|
8
|
NAVER
|
128,000
|
164,813,395
|
0.7877
|
9
|
KB금융
|
43,000
|
418,111,537
|
0.8452
|
10
|
현대모비스
|
213,500
|
97,343,863
|
0.6712
|
const = tibble( '종목' = c('삼성전자','SK하이닉스','셀트리온','POSCO','신한지주', 'LG화학','현대차','NAVER','KB금융','현대모비스'), '종가' = c(45850,75900,200500,258000,43300, 382000,124500,128000,43000,213500), '주식수' = c(5969782550,728002365,125461438,87186835,474199587, 70592343,213668187,164813395,418111537,97343863), '유동비' = c(0.7879,0.7389,0.667,0.8117,0.8978, 0.6611,0.6577,0.7877,0.8452,0.6712) ) const = const %>% mutate(cap = 종가 * 주식수 * 유동비, cap.ratio = cap / sum(cap)) const # A tibble: 10 x 6 종목 종가 주식수 유동비 cap cap.ratio 1 삼성전자 45850 5969782550 0.788 2.16e14 0.551 2 SK하이닉스 75900 728002365 0.739 4.08e13 0.104 3 셀트리온 200500 125461438 0.667 1.68e13 0.0429 4 POSCO 258000 87186835 0.812 1.83e13 0.0467 5 신한지주 43300 474199587 0.898 1.84e13 0.0471 6 LG화학 382000 70592343 0.661 1.78e13 0.0456 7 현대차 124500 213668187 0.658 1.75e13 0.0447 8 NAVER 128000 164813395 0.788 1.66e13 0.0425 9 KB금융 43000 418111537 0.845 1.52e13 0.0389 10 현대모비스 213500 97343863 0.671 1.39e13 0.0357
invest = 10000000000 const = const %>% mutate(inv.number = floor(invest * cap.ratio / 종가), inv.money = inv.number * 종가, inv.ratio = inv.money / sum(inv.money)) const # A tibble: 10 x 9 종목 종가 주식수 유동비 cap cap.ratio inv.number inv.money inv.ratio 1 삼성전자 45850 5969782550 0.788 2.16e14 0.551 120282 5514929700 0.552 2 SK하이닉스 75900 728002365 0.739 4.08e13 0.104 13755 1044004500 0.104 3 셀트리온 200500 125461438 0.667 1.68e13 0.0429 2139 428869500 0.0429 4 POSCO 258000 87186835 0.812 1.83e13 0.0467 1809 466722000 0.0467 5 신한지주 43300 474199587 0.898 1.84e13 0.0471 10887 471407100 0.0471 6 LG화학 382000 70592343 0.661 1.78e13 0.0456 1193 455726000 0.0456 7 현대차 124500 213668187 0.658 1.75e13 0.0447 3593 447328500 0.0447 8 NAVER 128000 164813395 0.788 1.66e13 0.0425 3319 424832000 0.0425 9 KB금융 43000 418111537 0.845 1.52e13 0.0389 9037 388591000 0.0389 10 현대모비스 213500 97343863 0.671 1.39e13 0.0357 1670 356545000 0.0357 invest - (const$inv.money %>% sum) [1] 1044700
library(httr) library(rvest) library(readxl) library(dplyr) library(ggplot2) library(tidyr) date = '20190322' pdf_200 = POST(url = 'http://www.kodex.com/excel_pdf.do', query = list( fId = '2ETF01', gijunYMD = date ), write_disk(tf <- tempfile(fileext = '.xls'))) pdf_data = read_excel(tf, skip = 2, col_names = TRUE) pdf_data # A tibble: 202 x 9 번호 종목명 ISIN 종목코드 수량 `비중(%)` `평가금액(원)` `현재가(원)` `등락(원)` 1 1 원화예금 KRD010010001 KRD010010001 28653419 0 28653419 0 0 2 2 삼성전자 KR7005930003 005930 8220 0.268 376887000 46550 700 3 3 SK하이닉스 KR7000660001 000660 977 0.0527 74154300 76100 200 4 4 셀트리온 KR7068270008 068270 172 0.0245 34486000 199500 -1000 5 5 POSCO KR7005490008 005490 120 0.0220 30960000 259000 1000 6 6 신한지주 KR7055550008 055550 710 0.0219 30743000 43250 -50 7 7 LG화학 KR7051910008 051910 80 0.0217 30560000 379500 -2500 8 8 현대차 KR7005380001 005380 245 0.0217 30502500 123500 -1000 9 9 NAVER KR7035420009 035420 221 0.0201 28288000 127000 -1000 10 10 KB금융 KR7105560007 105560 619 0.0189 26617000 42500 -500 # ... with 192 more rows
# Data cleansing pdf_data_mod = pdf_data %>% filter(종목명 != '원화예금') %>% mutate(비중 = `평가금액(원)` / sum(`평가금액(원)`)) %>% select(종목명, 종목코드, 비중) %>% mutate(종목명 = factor(종목명, levels = unique(종목명))) ggplot(pdf_data_mod, aes(x = 종목명, y = 비중)) + geom_point()
# Download Factor data from Company Guide data_factor = list() for (i in pdf_data_mod$종목코드) { # i = '005930' url = paste0('http://comp.fnguide.com/SVO2/ASP/SVD_main.asp?pGB=1&gicode=A',i) down_page = GET(url) %>% read_html fct_mom = down_page %>% html_nodes(xpath = '//*[@id="svdMainGrid1"]/table/tbody/tr[3]/td[1]/span[4]') %>% html_text() %>% as.numeric() if (length(fct_mom) == 0) { fct_mom = NA } fct_pbr = down_page %>% html_nodes(xpath = '//*[@id="corp_group2"]/dl[4]/dd') %>% html_text() %>% as.numeric() fct_per = down_page %>% html_nodes(xpath = '//*[@id="corp_group2"]/dl[1]/dd') %>% html_text() %>% as.numeric() fct_roe = fct_pbr / fct_per fct_data = data.frame(fct_mom, fct_pbr, fct_roe) data_factor[[i]] = fct_data print(i) Sys.sleep(2) } # Bind Data data_factor_bind = bind_rows(data_factor) rownames(data_factor_bind) = pdf_data_mod$종목명 summary(data_factor_bind) fct_mom fct_pbr fct_roe Min. :-63.100 Min. : 0.220 Min. :0.002087 1st Qu.:-23.265 1st Qu.: 0.650 1st Qu.:0.053074 Median :-10.320 Median : 0.945 Median :0.078653 Mean : -9.378 Mean : 1.599 Mean :0.113277 3rd Qu.: 3.248 3rd Qu.: 1.708 3rd Qu.:0.124089 Max. : 49.740 Max. :14.860 Max. :1.250000 NA's :3 NA's :1 NA's :27
# Calculate Factor Strength data_factor_scale = apply(data_factor_bind, 2, rank, na.last = 'keep') %>% scale() %>% data.frame() data_factor_scale$fct_pbr = -data_factor_scale$fct_pbr data_factor_scale %>% gather(key, value) %>% ggplot(aes(x = value, group = key)) + geom_histogram() + facet_grid(key ~ .)
# Bind factor strength # Momentum 40%, Value 40%, Quality 20% data_factor_scale = data_factor_scale %>% mutate(score = 0.4 * fct_mom + 0.4 * fct_pbr + 0.2 * fct_roe, rank = rank(desc(score)), 종목명 = pdf_data_mod$종목명)
# Top 10 top.10 = data_factor_scale %>% filter(rank <= 10) %>% select(종목명) %>% unlist() %>% as.character() data_factor_bind %>% mutate(종목명 = rownames(.)) %>% filter(종목명 %in% top.10) fct_mom fct_pbr fct_roe 종목명 1 8.86 0.83 0.12749616 SK텔레콤 2 8.15 0.51 0.04214876 기아차 3 29.71 0.68 0.12078153 대림산업 4 43.62 0.92 0.16197183 GS건설 5 9.08 0.58 0.05669599 현대백화점 6 2.57 0.88 0.23466667 대우조선해양 7 38.38 0.56 0.06481481 태광산업 8 1.93 0.65 1.25000000 효성 9 15.80 0.77 0.40314136 대덕전자 10 42.81 0.67 0.09795322 세방전지
# Bottom 10 bottom.10 = data_factor_scale %>% filter(rank >= 190) %>% select(종목명) %>% unlist() %>% as.character() data_factor_bind %>% mutate(종목명 = rownames(.)) %>% filter(종목명 %in% bottom.10) fct_mom fct_pbr fct_roe 종목명 1 -15.22 1.39 NA 동아에스티 2 -24.17 0.38 NA 동국제강 3 -49.55 0.27 NA 두산중공업 4 -4.46 3.28 NA JW중외제약 5 -37.08 0.59 NA LG상사 6 14.57 2.38 NA 한세실업 7 -26.89 3.00 NA 일양약품 8 -21.76 1.41 NA LIG넥스원 9 -22.65 0.66 NA LG하우시스 10 NA 0.41 0.002087258 효성중공업 11 2.99 1.03 NA 쌍용차 12 -63.10 0.22 NA 한진중공업
# Change NA to lower number data_factor_scale %>% filter(is.na(score)) %>% head() data_factor_scale = data_factor_scale %>% mutate_at(vars(score), list(~ifelse(is.na(.), min(score, na.rm = TRUE), .)))
top.50 = data_factor_scale %>% filter(rank <= 50) %>% select(종목명) %>% unlist() %>% as.character() # 시총 상위 100종목에서 언더 웨이트 method_first = pdf_data_mod %>% mutate(투자비중 = 비중, 시총랭킹 = rank(desc(비중))) %>% mutate_at(vars(투자비중), list(~ifelse(시총랭킹 <= 100, 투자비중 - 0.0005, 투자비중))) sum(method_first$투자비중) # 상위 50 종목에 오버웨이트 method_first = method_first %>% mutate_at(vars(투자비중), list(~ifelse(종목명 %in% top.50, 투자비중 + 0.0010, 투자비중))) # 둘 간의 비중 비교 method_first %>% select(종목명, 비중, 투자비중) %>% gather(key, value, -종목명) %>% ggplot(aes(x = 종목명)) + geom_point(aes(y = value, color = key))
# 삼성전자 제외 p1 = method_first %>% slice(-1) %>% select(종목명, 비중, 투자비중) %>% gather(key, value, -종목명) %>% ggplot(aes(x = 종목명)) + geom_point(aes(y = value, color = key, shape = key), size = 1) p1
# (2) 전체 종목에 팩터 강도 적용 method_second = data_factor_scale %>% select(score) %>% mutate(cdf = pnorm(score)) %>% bind_cols(pdf_data_mod) method_second = method_second %>% mutate(투자비중 = cdf * 비중, 투자비중 = 투자비중 / sum(투자비중))
method_second %>% slice(-1) %>% select(종목명, 비중, 투자비중) %>% gather(key, value, -종목명) %>% ggplot(aes(x = 종목명)) + geom_point(aes(y = value, color = key, shape = key), size = 1)
method_second = method_second %>% mutate(TE = 투자비중 - 비중) TE.max = 0.005 method_second %>% select(종목명, TE) %>% ggplot(aes(x = 종목명, y = TE)) + geom_point() + geom_hline(aes(yintercept = TE.max)) + geom_hline(aes(yintercept = -TE.max))
while (max(abs(method_second$TE)) > (TE.max + 0.0001)) { method_second = method_second %>% mutate_at(vars(투자비중), list(~ifelse(TE < -TE.max, 비중 - TE.max, 투자비중))) %>% mutate_at(vars(투자비중), list(~ifelse(TE > TE.max, 비중 + TE.max, 투자비중))) %>% mutate(투자비중 = 투자비중 / sum(투자비중), TE = 투자비중 - 비중) } method_second %>% select(종목명, TE) %>% ggplot(aes(x = 종목명, y = TE)) + geom_point() + geom_hline(aes(yintercept = TE.max)) + geom_hline(aes(yintercept = -TE.max))
p2 = method_second %>% slice(-1) %>% select(종목명, 비중, 투자비중) %>% gather(key, value, -종목명) %>% ggplot(aes(x = 종목명)) + geom_point(aes(y = value, color = key, shape = key), size = 1) library(gridExtra) grid.arrange(p1, p2)