Post List

레이블이 Henry's Thought인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Henry's Thought인 게시물을 표시합니다. 모든 게시물 표시

2020년 12월 9일 수요일

인버스(곱버스) ETF 트레이딩으로 수익을 내기 힘든 이유 (feat. 시장미시구조)

 


시장의 하락을 예상할 때 가장 좋은 투자 수단은 선물을 매도하는 것입니다. 그러나 현실적으로 선물 매매에 대한 부담감 때문인지 많은 개미 투자자들이 인버스(-X1) 혹은 곱버스(-X2) ETF를 이용해 하방에 베팅합니다.

그러나 이러한 ETF를 이용해 데일리 트레이딩 하는 것은 호가와 스프레드로 인해 상방 베팅 ETF (X1 혹은 X2) 보다 효율적으로 돈을 벌기 힘듭니다.

각 기초지수와 ETF의 틱데이터를 이용해 비교해보도록 하겠습니다.


2020년 12월 8일 화요일

ETF를 통한 장기투자, 과연 득이기만 할까?


바야흐로 ETF 투자의 시대입니다. 상장된 주식수와 ETF수가 비슷할 정도라고 해도 과언이 아닐 만큼 수많은 ETF가 상장되어 있고, 그 투자 대상 역시 상상을 초월합니다.

덕분에 장기투자, 특히 개인연금 혹은 IRP에서 ETF를 이용한 투자가 유행이고 마치 진리처럼 소개되고 있습니다. 사실 장점은 명확합니다. 기존 펀드에 비해 훨씬 저렴한 수수료, 훨씬 간편한 매수/매도, 훨씬 다양한 형태의 투자대상 등이 있겠죠.

그러나 이런것들이 다 결과론적인 얘기이지 실제 투자의 세계에서, 특히나 처음 투자를 하는 분들에게는 얘기가 조금 다를 듯합니다. 특히나 '실시간 투자 가능' 여부는 장점이 될수도 있지만 오히려 독이 될수도 있습니다. 

펀드를 통해 투자를 할 경우 수익률을 일간 단위로만 확인이 가능합니다. 그러나 ETF의 경우 주식시장에 상장되어 거래가 되는 만큼 계속해서 그 수익률이 바뀝니다. 그만큼 계좌의 실시간 변동성도 커지게 되기 마련입니다.




멋진 예제를 살펴보죠. 많이들 투자하는 올웨더 포트폴리오를 대상으로요.



모두가 원하는 꾸준한 우상향, 매우 멋진 모습을 보입니다. 연평균 수익률 7%에 샤프지수는 1 이상, 투자 결과만 보면 매우 뛰어난 전략입니다.



하락 방어도 우수합니다. 08년도와 코로나 때도 MDD가 15% 내외일 만큼 우수합니다.

그런데 만약 이 포트폴리오를 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는 일간 수익률 기준입니다. 연율화 수익률(Return Annual)은 모두 같으며, 연율화 변동성(Vol Annual)도 거의 비슷하여 연율화 샤프지수도 셋다 거의 비슷합니다. 

그러나 연율화 하지 않은 샤프지수는 극단적으로 차이가 납니다. 수익률의 주기가 짧으면 짧을 수록, 즉 수익률을 자주 확인할 수록(예: 일간) 샤프지수는 급격히 떨어집니다. 이게 바로 투자자들이 실제 투자를 할때 체감으로 느끼는 수익률 일 것입니다.


##         Annual   Monthly     Daily
## [1,] 0.1428571 0.3214286 0.4414029

이번에는 주기별 손실 빈도 입니다. 연간으로 수익률을 확인할 경우 손해를 관찰할 확률이 14%에 불가합니다. 그런데 월간으로 관찰을 하면 그 확률이 32%로 증가하죠. 일간으로 확인할 경우 무려 손실을 관찰할 확률이 44%로 증가합니다. 한마디로 계좌를 들여다 보면 거의 절반 확률로 그날은 손실을 본 것으로 나오는 것이죠.

만약 위에서 처럼 포트폴리오를 ETF로 직접 투자한다면 과연 하루에 한번만 계좌를 볼까요? 아마 하루에도 수십 혹은 수백번도 mts를 켜서 확인할 겁니다. 그럼면 거의 절반 확률로 손실을 기록하고 있는 것을 볼태고요. 그 과정에서 심리적 불안감은 더욱 커질 겁니다.

결국 장기투자를 위해 선택한 ETF의 변동성 때문에 장기투자를 하지 못하는 아이러니가 생길수도 있습니다.




멀리서 호수를 바라보면 고요하지만, 가까이서 표면을 관찰하면 끊임없는 움직임이 발생하고 있습니다. 주식시장도 마찬가지 입니다. 결과론적으로 수익률을 바라보는 것과, 그 수익률이 완성되기 까지의 움직임을 견디는 것에는 전혀 다른 차이가 있습니다.


본인만의 철저한 투자관과 이를 지킬 인내심이 있다면 분명 장기투자에 ETF를 이용하는 것은 매우 좋은 선택입니다. 그러나 그게 아닌 초보 투자자라면, 차라리 펀드를 통해 투자를 시작해보는게 좋지 않을까 생각합니다.


2020년 3월 23일 월요일

파도가 심할때는 잠시 쉬어갑시다


투자는 무엇일까요? 어떤 면에서 저는 수익률이라는 보물을 찾아 먼 바다를 항해하는 것이 아닌가 합니다. 재무제표라는 나침반과, 바람이라는 주가 모멘텀, 배라는 기업을 가지고요.

바다의 바람이 평소와 같으면 항해도 평소와 같이 하면 됩니다. 믿을 만한 나침반(재무제표)을 가지고 바람(모멘텀)을 타고 앞으로 나아가기만 하면 되죠. 배가 튼튼할 수록 더 좋겠죠.

그러나 안개가 가득끼고 폭풍우가 몰아치면 아무리 좋은 나침반도, 배도 쓸모가 없습니다. 어설프게 자연에 맞서려다가는 침몰하는게 눈에 뻔합니다. 이럴때는 무리해서 배를 끌고나가기 보다 바람이 잦아들때까지 배를 정박하고 기다리는게 좋지 않을까요? 어짜피 그 보물은 누가 먼저 가져간다고 내 것이 사라지는 것도 아니니까요. 살아야 보물도 찾죠.

2020년 3월 14일 토요일

유동성 소용돌이: 하락은 어떻게 하락을 부추기는가?



여러분이 생각하는 것 보다 시장은 복잡한 형태의 함수로 이루어져 있습니다. 각종 파생상품, 레버리지, 대차거래, 신용매매 등이 여기에 해당합니다.

헤지펀드의 경우 100% 매수 포지션을 위해 자기돈 100%를 내는 경우는 거의 없습니다. 자기돈의 50%로 주식을 매수하면 나머지 50%는 프라임 브로커에서 이 주식들을 담보로 제공해준 자금을 통해 매수하면 됩니다. 이것이 흔히 알고있는 '레버리지' 이죠. 개인들의 신용미수 역시 이와 동일하다고 보면 됩니다.

정상적인 시장에서 이러한 메커니즘은 아무 문제가 없겠죠. 그러나 시장이 급락하고 공포에 휩싸여, 모두가 탈출하고 싶어할 때는 얘기가 다릅니다.




먼저 시장에 엄청난 쇼크가 발생한다고 생각합시다. 먼저 쇼크로 인한 손실때문에 트레이더는 포지션을 줄여야 합니다. 그러나 더 큰 문제는 프라임브로커와의 자금 조달 관계입니다. 위험을 느낀 프라임 브로커들이 더욱 많은 담보를 요구하거나, 혹은 부도위험, 손실관리 등 각종 위험관리를 위해 더이상 자금제공을 하지 않기도 합니다.

결국 트레이더는 애초에 매도해야했던 금액에 더해 더 큰 매도를 해야하며, 이는 엄청난 매도 압력을 만들어냅니다. 그 결과 동일한 포지션을 가진 모든 트레이더는 더 큰 손해를 보게 됩니다.


시장의 매도 압력이 커지면 어떻게 될까요? 이러한 주문 불균형으로 인해 시장 변동은 더 커지고 유동성은 말라붙게 됩니다. 일반적인 상황에서 이런 트레이더들이 유동성 공급자였는데, 이제 그들은 매도만을 위해 달려가고 있으니까요.

악순환은 다시 돌아옵니다. 변동성이 높아지고 유동성이 하락함에  따라 위험을 느낌 프라임브로커는 또다시 증거금을 올리고, 트레이더가 포지션을 정리하도록 만듭니다. 트레이더역시 손실로 인해 포지션을 추가로 줄여야 하며, 투자자나 경영자들이 돈을 뺴가기도 합니다. 이런 악순환은 계속 반복됩니다. 이러한 일련의 과정을 유동성 소용돌이 라고 합니다.



이 상황은 언제 멈출까요? 바로 디레버리징이 끝날때 입니다. 모든 복잡한 함수가 정리되면 가격은 바닥에 도달합니다. 그 후 일부 트레이더는 다시 레버리지를 사용하여 매수를 하기 시작하면 가격은 내재가치를 향해 반등하기 시작합니다. 이 내재가치는 기존 보다 하락한 지점에서 평형을 이루게 됩니다.

물론 그 반등이 몇일만에 끝날지, 아니면 몇달이나 걸릴지는 아무도 모르지겠지만요... (논문에서는 알수 있다고 하니 우리모두 공부합시다!)



참고문헌: Pedersen, Lasse Heje. When everyone runs for the exit. No. w15297. National Bureau of Economic Research, 2009.

2019년 4월 25일 목요일

ETF는 과연 폭락의 '촉매'가 될 것인가?




최근 몇년새 패시브 투자로의 자금유입은 놀랄만큼 증가하는 추세이며, 그 중심에는 ETF가 있습니다. 그러나 이러한 ETF로의 지나친 쏠림이 다음 금융위기의 주범이 될 가능성이 높다는 경고 또한 계속 나오고 있습니다.


최근 시장을 보면 이러한 경고들이 기우가 아니다는 것을 느낄 수 있습니다. 현물시장 - 선물시장 - ETF시장을 동시에 관찰하면, 어떻게 시장의 변동성이 확대되고, 이 변동성이 잠재적 위험이 될 수 있다는 것을 느낄 수 있습니다.




코스피200과 코스닥150 시장의 시가총액 비교입니다. 코스피200 시장이 코스닥150 시장 대비 10배 가량 큽니다. (19-4-24 기준 코스피200 1,200조 vs 코스닥150 123조, 유동비 미적용)







각 시장의 연결선물 거래대금의 비교입니다. 코스피 선물 시장이 코스닥 선물 시장 대비 압도적으로 사이즈가 큰 마켓입니다. 그나마 2018년 이후로는 코스닥 선물 시장 역시 거래대금이 늘긴 했지만, 여전히 코스피 선물 시장이 코스닥 대비 30배 정도 시장의 Depth가 큽니다. (19-4-24 기준 코스피200 17조 vs 코스닥150 5천억)






그러나 우리가 어떤 민족입니까? 가즈아의 민족 입니다. 코스피200과 코스닥150 지수의 30일 이동 표준편차(연율화)를 비교해보면, 코스닥의 변동성이 코스피 변동성 대비 훨씬 높습니다. 이런 화끈한 변동성 만큼 개인투자자들이 좋아할 만한 소재는 없죠






이번엔 각 지수를 추종하는 레버리지 ETF의 시가총액 비교입니다. 2018년부터 코스닥 레버리지 ETF가 무서운 속도로 증가하는 것이 보입니다. (당시 모 은행의 신탁에서 해당 ETF를 조 단위로 팔았던 기억이 나실겁니다.)

그 결과 코스피200 레버리지 ETF와 코스닥150 레버리지 ETF의 시가총액 차이가 2배 밖에 나지 않는 기현상이 벌어지게 되었습니다. 기초지수는 시장 차이가 10배 이상 나는데, 이를 추종하는 (레버리지) ETF의 시장 차이는 겨우 2배인.. 코스닥 레버리지 ETF가 비이상적으로 커지게 되는 현상이 발생하게 된 것입니다.



사실 단순히 1X ETF의 사이즈가 커지는 것은 그리 큰 문제가 안됩니다. 그러나 레버리지 ETF가 커진다는 점, 그것도 시장의 depth가 얕은 코스닥 ETF가 커진다는 점은 잠재적으로 큰 문제가 될 수도 있습니다.






코스닥 레버리지 ETF의 PDF를 확인해보면, 구성종목 중 절반정도를 코스닥 선물로 보유하고 있으며, 이를 이용해 beta를 2로 맞추고 있습니다. 당연히 현물로는 레버리지 이펙트를 일으킬 수 없으니 선물을 이용해 포지션을 맞춰야 겠죠.

그러나 레버리지의 경우 매일매일 beta를 2로 맞추어야 된다는 점이 있습니다. 단순히 1X ETF의 경우기초지수에 해당하는 현물 바스켓을 보유하면 끝이지만, 2X ETF의 경우 그날의 상승/하락에 따른 효과로 인해 노출도(beta)가 2가 아닌 지속적으로 변하므로, 이를 맞춰주기 위해 매일 트레이딩을 해야 하며, 대부분 선물을 이용합니다.


예를 들어 AUM이 100억짜리인 레버리지 펀드가 있을 경우, 2X를 추종하기 위해 해당 펀드는 200억의 노출을 맞출 것입니다. 이를 위해 선물을 이용한다고 가정하고, 선물이 개당 8천만원일 경우 250개를 매수해야 합니다.

만약 다음날 기초지수가 1% 올랐다면 펀드의 AUM은 101억이 되며, 2배를 추종하기 위해 펀드의 노출 금액은 200억에서 1%의 2배, 즉 2%가 상승한 204억이 되야 합니다. 그러나 추종하는 선물 자체가 1% 상승했으므로 펀드의 노출 금액은 80,000,000 * 1.01 * 250 = 20,200,000,000 (202억)이 되어 목표금액에 2억이 모자라게 됩니다. 따라서 해당 금액만큼 선물을 추가 매수해야 합니다. 매수 혹은 매도해야 하는 선물의 양은 펀드의 AUM이 클수록, 혹은 당일 변동성이 클 수록 늘어나게 됩니다.



 
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


물론 해당 선물시장의 거래대금이 충분히 크다면 ETF의 일간 리밸런싱으로 인한 효과는 시장에 전혀 충격이 되지 않을 겁니다. 그러나 선물시장이 얉다면 얘기는 다르죠







코스피200과 코스닥150 시장의 선물 거래대금과 추종 레버리지 ETF의 시가총액 비교입니다. 코스피 시장의 경우 선물 시장의 규모가 워낙 크므로 비중이 30% 정도에 불과합니다. 일간 리밸런싱으로 인한 물량이 있다 한들 충분히 소화하고도 남을 선물시장이 존재합니다.


그러나 코스닥 시장은 얘기가 완전 다릅니다. 선물시장의 거래대금이 그리 크지 않은 상황에서 레버리지 ETF가 지나치게 커져, 그 비중이 7~8배에 달합니다. 즉 레버리지 ETF의 리밸런싱 자금이 선물 시장에 상당한 충격으로 작용할 수 있을 가능성이, 아니 이미 충격으로 작용하고 있습니다. 만일 해당 ETF의 사이즈가 더욱 커진다면, 혹은 금융위기 급 충격이 온다면 해당 ETF에서 파생되는 물량으로 발생하는 선물 시장의 충격이 있을 수 있으며, 이로 인해 현물 시장에도 영향을 미치는 'wag the dog' 현상이 나올 가능성이 언제나 열려 있습니다.


물론 이러한 시장의 구조, 눈치(?), 지를 수 있는 용기만 있다면 오르든 내리든 달콤한 포도주는 언제나 마실 수 있겠죠. 그게 설령 누군가의 피일지라도...



2019년 3월 24일 일요일

퀀트 매니저는 어떻게 포트폴리오를 구성할까? (인덱스펀드 구성 예시)



아마 여러분이 퀀트 포트폴리오 매니저 업무를 담당한다면, 십중팔구 (인핸스드) 인덱스 펀드 매니지, 즉 패시브펀드 업무를 담당하실 겁니다. 인핸스드 인덱스 펀드의 운용은 그 중심이 되는 기초지수의 추종, 그리고 알파를 내기 위한 여러 방법으로 차익거래, 대차, 배팅 등의 방법을 이용합니다. 


먼저, 인덱스 펀드의 가장 중심이 되는 기초지수의 추종에 대해 살펴보도록 하겠습니다. 가장 많이 사용되는 기초지수는 각 국가의 주가지수이며, 우리나라의 경우 KOSPI 200지수를 대상으로 합니다.

기초지수는 일반적으로 시가총액가중평균 방법을 사용합니다. 따라서 지수를 정확히 복제하기 위해서는 지수 내에 있는 각 종목들의 시가총액을비중을 알 필요가 있습니다. 시가총액은 주가 * 상장주식수로 이루어집니다. 그러나 각 기업의 상장된 모든 주식이 (자사주 등의 이유로) 거래가 되는 것은 아니며, 상장된 주식 중 유동적으로 거래되는 비율을 유동비라고 합니다. 따라서 지수를 만들때 시가총액은 주가 * 상장주식수 * 유동비로 계산됩니다.


종목
종가
주식수
유동비
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


위 테이블은 국내 상위 10 종목의 종가, 주식수 및 유동비입니다. 위의 주식들로 구성된 가상의 지수를 추종하기 위해 어떻게 포트폴리오를 구성해야 하는지 살펴보도록 합시다.


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


각 종목의 시가총액을 구한 후, 이를 전체 합으로 나누어 시총비중을 구하였습니다. 이제 특정 펀드의 투자금액이 100억일 경우 각 종목 당 투자금액을 어떻게 할지 살펴보겠습니다.


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


먼저 각 종목당 투자되는 주식수는 총투자금액 * 시총비중 / 종가를 통해 계산되며, 소수점 이하로를 투자를 할 수 없으므로 내림을 해주도록 합니다. 펀드의 투자금액 100억원과 각 종목 별 투자금액을 합한 금액의 차릴 보면 대략 100만원 정도(0.01% 가량)가 남습니다. 이처럼 실제 포트폴리오의 구성에서는 모델 포트폴리오와는 다르게 약간의 현금이 남기 마련입니다.

또한 위 처럼 99.9% 금액을 주식으로 투자하는 경우도 잘 없습니다. 펀드는 매일매일 설정과 해지가 일어납니다. 만일 여러분이 위와 같이 포트폴리오를 구성했는데 내일 5억원의 해지가 발생한다면 어떡할까요? 5억원치에 해당하는 주식을 매도해야 하며, 이때 발생하는 세금은 여러분 펀드에 손해가 되게 됩니다. 따라서 대부분 펀드는 이러한 현금이 필요할 경우를 대비하여 지수의 일부를 선물로 추종하게 됩니다. 

100억원 중 90억원의 금액을 현물(실제 주식)로 추종하고, 나머지 10억원의 금액은 선물을 매수하여 추종하면 간단합니다. KOSPI 200 선물의 한 계약당 명목금액은 지수 * 250,000 이므로 KOSPI 200 지수가 300pt임을 가정하면 한 계약당 명목금액이 7천 5백만원 정도 됩니다. 따라서 나머지 10억원에 해당하는 선물 13개를 매수(7천5백*13 = 9억 7천 5백)하면, 총 100억원의 명목금액이 맞춰지게 됩니다. 선물의 경우 매수를 하더라도 현금이 들어가지 않기 때문에 펀드에는 아직 10억원 가량의 현금이 남게되며, 이를 통해 해지 금액을 지불하고, 해당 금액만큼의 선물을 매도하면 됩니다. (선물의 경우 매매시 세금이 거의 없다고 봐도 무방합니다.)

위와 같이 펀드를 구성할 경우 기초지수의 수익률을 거의 복제가 가능합니다. 그러나 우리는 언제나 지수+알파를 원합니다. 이를 위해 위에서 살펴본 것처럼 차익거래, 대차, 배팅 등의 방법이 이용됩니다.


먼저 차익거래에 대해 살펴봅시다. 파생상품에 대해 공부해보셨으면 알다시피 선물의 가격은 현물 가격(주가 지수)와 무위험 이자율, 배당, 만기에 의해 가격이 결정되게 됩니다. 





그러나 가끔 이러한 이론가격과 실제 선물의 가격이 벌어지게 되는 일이 생기며, 이를 이용하여 현물 바스켓과 선물간의 차익거래, 현물 바스켓과 ETF간의 차익거래, ETF와 선물간의 차익거래 등을 통해 아비트리지 수익을 얻을 수 있는 경우가 존재합니다. 또한 합병 차익거래, 배당 차익거래 등 상당히 낮은 위험으로 수익률을 얻을 수 있는 기회가 종종 나타나기도 합니다. 대부분의 퀀트 매니저들은 이러한 기회를 놓치지 않고 수익을 얻습니다.

대차는 말그대로 주식을 빌려주는 행위입니다. 인덱스 펀드를 구성하는 종목들은 지수의 구성종목이 바뀌지 않는 이상 거의 바뀔일이 없으므로, 매도를 할 일도 잘 없습니다. 주식을 빌려주어 조금의 수익이라도 더 보태는 것이 좋습니다.

마지막으로는 배팅에 대한 내용입니다. 매니저의 스타일에 따라 배팅을 하는 방법은 제각각이지만, 일반적으로 많이 사용되는 팩터 모형을 이용하여 특정 종목에 비중을 더욱 싣습니다. 이부분에 대해서 자세히 알아보도록 하겠습니다.

먼저 KOSPI 200 지수를 구성하는 종목들의 시총비에 대해 살펴보겠습니다. 실제 업무에서는 기초지수 제공자(KOSPI 200의 경우 한국거래소)가 각 종목들의 비중을 판매하지만, 여러분이 손쉽게 그 비중을 구할 수 있는 방법도 있습니다. 바로 해당 지수를 추종하는 ETF의 PDF를 통해서 말이죠. 




ETF의 경우 보유종목과 비중을 실시간으로 공표해야 하기에 이를 통해 간단히 기초지수의 종목별 비중을 추론할 수 있습니다. 먼저 KODEX 200 ETF의 PDF를 크롤링하여 그 비중을 추출해 보도록 하겠습니다.


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()




삼성전자의 비중이 압도록으로 높습니다. 이제 각 종목들의 팩터를 구해야 합니다. 간단한 예시로 모멘텀에는 12개월 수익률, 밸류에는 PBR, 퀄리티에는 ROE 데이터를 사용하겠습니다. 물론 데이터가이드와 같은 유료 벤더를 통해 해당 데이터를 손쉽게 구할 수 있지만, 크롤링을 통해 온라인에서도 손쉽게 해당 데이터를 구할 수 있습니다.




CompanyGuide의 종목별 정보에서 PBR과 12개월 수익률을 손쉽게 따올 수 있으며, ROE의 경우 상당의 PBR / PER를 통해 계산할 수 있습니다. KOSPI 200에 해당하는 종목들의 종목코드도 이미 보유하고 있기에, for loop를 통하여 해당 팩터 데이터들을 수집해 보도록 하겠습니다.



# 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  


각 종목들의 팩터 데이터가 구해졌다면, 이를 바탕으로 팩터의 강도를 구해보도록 하겠습니다. 먼저 각 팩터별 랭킹을 구한 후, 이를 다시 Z-Score로 치환하도록 하겠습니다. 또한 모멘텀과 ROE는 높을수록 좋으며, PBR은 낮을수록 좋기때문에, 부호의 통일을 위해 PBR의 Z-Score값에 (-)를 곱하도록 합니다.


# 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 ~ .)




각 팩터의 Z-Score가 균등하게 분포되어 있음이 확인됩니다. 이제 이를 바탕으로 멀티팩터의 강도를 계산해야 합니다. AQR의 방법론에 따라 모멘텀 팩터에는 40%의 비중을, 밸류 팩터에는 40%의 비중을, 퀄리티 팩터에는 20%의 비중을 주도록 하겠습니다. 해당 비중은 매니저의 재량에 의해 결정됩니다. 이렇게 결정된 스코어를 내림차순 해준 후 랭킹을 구해주도록 합니다. (스코어가 높을수록 좋은 종목, 스코어가 낮을 수록 나쁜 이므로, 내림차순을 기준으로 랭킹을 구해야 합니다.)

# 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$종목명)


이제 랭킹 상위 10개 종목의 각 팩터값들을 살펴보도록 하겠습니다.


# 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     세방전지

전반적으로 12개월 수익률도 높고, PBR은 낮으며, ROE 또한 높은 모습을 보입니다. 이번에는 반대로 하위 20개 종목의 각 팩터값들을 살펴보도록 하겠습니다.

# 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 한진중공업


12개월 수익률이 없거나, PBR이 음수거나, ROE가 없는 경우 하위 종목으로 구성됨이 보입니다. 이러한 종목들의 경우 score값도 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), .)))


이제 팩터 스코어가 준비되었으므로 기초지수 복제 포트폴리오에 팩터투자를 통해 배팅을 해주면 됩니다. 배팅 비중은 매니저의 재량 혹은 펀드의 규정에 따라 다르며, 여기서는 간단하게 5%를 예를 들어보겠습니다. 먼저 가장 간단한 방법은 200 종목 중 상위 100 종목에서 각 5bp씩 투자비중을 차감하고, 멀티팩터 기준 상위 50 종목에 각 10bp 씩 투자비중을 더해주는 방법입니다. 


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




시총 상위주의 투자비중이 지수비중보다 조금씩 작으며, 멀티팩터 기준 상위 50 종목의 투자비중이 지수 대비 조금씩 많은 것이 확인됩니다. 팩터 모델이 장기적으로 지수 대비 뛰어난 성과를 보인다면, 이런식으로 구성한 포트폴리오도 장기적으로 지수 대비 초과성과를 기록할 수 있을 겁니다.

그러나 위 방법으로 포트폴리오를 구성할 경우 배팅금액이 전체 포트폴리오의 5% 밖에 되지 않으며, 좀더 팩터모델을 활용하여 적극적으로 포트폴리오를 구성하고자 할 수 있습니다. 이럴 경우 전 종목에 팩터의 강도를 활용하여 비중을 조절하는 방법이 있습니다. 이는 예전에 썼는 글을 참조하시면 좋습니다.


# (2) 전체 종목에 팩터 강도 적용
method_second = data_factor_scale %>%
  select(score) %>%
  mutate(cdf = pnorm(score)) %>%
  bind_cols(pdf_data_mod)

method_second = method_second %>%
  mutate(투자비중 = cdf * 비중,
             투자비중 = 투자비중 / sum(투자비중))

먼저 앞에서 계산된 Z-Score를 바탕으로 pnorm() 함수를 이용하여 각 Z-Score 값들의 CDF 값을 구해준 후, 기초지수의 비중과 CDF 값을 곱해주도록 합니다. 즉 Z-Score가 높은 값들은 CDF 값 역시 높아 기초지수의 비중만큼 투자할 것이며, Z-Score가 낮은 값들은 CDF 값이 낮아, 기초지수 대비 매우 작은 비중을 투자할 것입니다. 이를 다시 투자비중의 합으로 나누어 합계가 1이 되도록 표준화를 해줍니다.


method_second %>%
  slice(-1) %>%
  select(종목명, 비중, 투자비중) %>%
  gather(key, value, -종목명) %>%
  ggplot(aes(x = 종목명)) +
  geom_point(aes(y = value, color = key, shape = key), size = 1)




삼성전자를 제외한 종목들의 기초지수 비중과 투자비중의 차이입니다. 첫번째 방법에 비해 훨씬 둘 간의 차이가 큰 것이 확인되며, 이는 전체 포트폴리오가 팩터에 훨씬 노출된 정도가 크다는 것을 의미합니다.

그러나 인덱스 펀드에는 각 종목별 지수내 비중과 투자 비중간에 지나치게 차이가 벌어지는 것을 방지하는 제약이 대부분 있습니다. 예로써 둘 간의 차이가 50bp 이상이 되지 않도록 생각해 봅시다.


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))



일부 종목의 경우 허용치인 50bp 대비 차이가 더 큰것이 확인됩니다. 이러한 종목의 경우 차이가 50bp 이상 벌어지지 않도록 강제로 변경해주어야 합니다. 즉, 개별종목 투자비중의 상한은 지수내 비중 + 50bp, 하한은 지수내 비중 - 50bp로 바꿔주도록 합니다. 그 후 다시 투자비중의 합이 1이 되도록 표준화를 시행해 줍니다. 해당 작업은 비중의 차이가 50bp 이상 벌어지지 않을 때까지 while() 구문을 사용하여 계산하며, 미세한 비중차이로 인한 무한루프에 빠지는 것을 방지하기 위해 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))




이제 지수내 비중과 투자비중의 최대 차이가 50bp 이내로 좁혀지게 되었습니다. 마지막으로 첫번째 방법과 두번째 방법의 비중 차이를 한번에 시각화 하도록 하겠습니다. (삼성전자 제외)


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)




두번째 방법의 포트폴리오가 훨씬 더 기초지수 대비 액티브하게 배팅이 된 것을 확인할 수 있습니다. 팩터가 장기적으로 아웃퍼폼 한다면 두번째 포트폴리오의 아웃퍼폼 정도도 더욱 크겠지만, 트래킹 에러 또한 커질 수 있다는 점은 주의해야겠죠?