파인스크립트 기본반
분류 예제

영구 포트폴리오 수익 곡선

페이지 정보

본문

해리 브라운이 제시한 영구 포트폴리오의 수익 곡선을 구현해봤습니다.

트레이딩뷰는 2종목 이상 동시에 매매하지 못하기 때문에 전략이 아닌 지표 형태로 수익 곡선으로 나타내봤습니다.


영구 포트폴리오는 주식, 채권, 금, 현금에 각각 25%씩 투자하는 포트폴리오입니다.

리벨런싱은 1년에 한번 정도 하면 되겠죠.


예를 들어 100만원을 25만원씩 쪼개서 연초에 주식, 채권, 금, 현금에 투자합니다.

그리고, 1년 후 모든 자산을 팔고 다시 그 돈을 4등분하여 주식, 채권, 금, 현금에 재투자합니다.

실제로는 모든 자산을 팔기보다는 금액만 맞춰서, 돈을 많이 번 자산의 일부를 정리해서 돈을 적게 번 자산쪽으로 이동시키면 되겠죠.


수수료는 고려하지 않았고, 테스트 기간이 짧기 때문에 참고 삼아 보시면 되겠습니다.


주식은 VTI, 채권은 TLT, 금은 GLD를 사용했으며, 현금은 년 1%의 이자를 준다고 가정했습니다.


fb3b7c2cba60abb7ed2d69d73bf14dba_1589572909_36.png
1년 봉에서 봐야 1년 마다 리벨런싱하는 결과가 나옵니다.

(월봉으로 보면 월마다 리벨런싱하는 결과입니다. 월봉은 이자를 0.001 정도로 조정해야합니다.)


초기 자본은 100으로 시작합니다.

약 15년간의 결과인데, 우상향하는 결과가 나왔습니다.


자산 배분 전략은 그 비율에 따라 여러가지 조합이 가능합니다.

영구 포트폴리오외에 주식, 채권 6:4 비율과 올웨더 포트폴리오, 주식, 채권, 금 동일 비중의 결과도 비교해봤습니다.


fb3b7c2cba60abb7ed2d69d73bf14dba_1589572909_19.png 

주식, 채권, 금을 1:1:1로 투자한 결과가 가장 높은 수익을 기록했습니다.

그 다음이 올웨더 포트폴리오(실제와는 약간 다릅니다.)네요.

주식, 채권 6:4 전략이 그 다음을 이었습니다.

영구 포트폴리오는 현금이 들어가있기 때문에 전체적인 수익률은 가장 낮았습니다.


* 기준으로 사용한 VTI, TLT, GLD 중에 GLD가 시작하는 날짜가 가장 최근이라 차트를 GLD로 놓고 적용해야합니다.


...중략 (로그인 하셔야 볼 수 있습니다.)...


관련자료

김철호님의 댓글의 댓글

capital은 나의 자산이고, 초기에 100으로 설정됩니다.
1번을 둔 이유는, 각 자산의 직전 월의 수익률이 반영된 후 증감한 자산을 더해서 다시 각 자산의 투자 비중으로 나눠야하기 때문입니다.
1번을 뒤로 뺀다면 capital은 항상 100으로 시작하여, 제대로된 결과가 나오지 않습니다.

capital은 하나의 값입니다. 나의 자산이죠. 나눠져서 다른 기능을 하지 않습니다.

(첫번째 봉)
(0번) 처음 봉에서는 자본금(capital)이 100이고, 주식 계좌에 넣은 돈(cptStock), 채권 계좌에 넣은 돈(cptBond), 금 계좌에 넣은 돈(cptGold), 현금(cptCash)이 각각 25가 될겁니다.
(1번) 첫번째 봉에서는 1번 스크립트의 필요성을 생각하지 못할 수 있습니다. 그래서 2번 스크립트가 우선적으로 구현될겁니다.
(2번) 각 자산에는 25의 자본금이 있고, 25의 자본금으로 얻어지는 수익이 있을 것입니다.
수익은 전월대비 당월의 종가로 계산가능한데, 첫번째 봉에서는 전월이 없으므로 계산이 불가합니다.
따라서 nz(etfStock/etfStock[1], 1)이런식으로 쓸 수 있는데, nz()함수는 첫번째 인자가 유효한 값이 아니라면 0을 출력해주는데, 이 경우에는 1이 출력되어야 자산의 증감이 없으므로 nz()함수에 두번째 인자까지 준것입니다.
nz()함수에 인자를 2개 주면, 첫번째 인자가 유효한 값이 아니라면 두번째 인자를 출력합니다.
여튼, 첫번째 봉에서는 계산해줄 것이 없습니다.

(두번째 봉)
(0번) 첫번째 봉과 같습니다. 처음 봉에서는 자본금(capital)이 100이고, 주식 계좌에 넣은 돈(cptStock), 채권 계좌에 넣은 돈(cptBond), 금 계좌에 넣은 돈(cptGold), 현금(cptCash)이 각각 25가 됩니다.
(1번) 각 자산의 증감한 액수를 여기에서 더해서 현재 총 자산을 capital에 넣어준것입니다.
(2번) 총 자산을 리벨런싱하고, 전월 대비 당월 수익률을 곱해줍니다.

세번째 봉이후 부터는 두번째봉과 같습니다.
글로 설명하려니 어렵네요.

요약하자면
(0번) 초기 자본금 세팅
(1번) 월별 각 자산의 증감을 합한 현재 자본금
(2번) 리벨런싱
입니다.
각 자산 액수를 합한 후 리벨런싱을 하는 것이 맞기 때문에 1번이 2번 앞에 와야합니다.

김철호님의 댓글의 댓글

var로 변수를 선언하면 스크립트에서 딱 한번만 만들어진다고 보시면 됩니다.
라벨을 var로 선언하면 딱 하나의 라벨만 만들어지는 것이죠.
var을 없애고 실행해보시면 여러개의 라벨이 만들어질겁니다. 각 봉마다 만들어지기 때문이죠.
하지만, var로 선언하면 딱 한번만 만들어지기 때문에 첫번째 봉에서만 라벨이 생깁니다.
그런데, 저는 가장 마지막 봉에 라벨이 생기기 원하므로, 이 첫번째 봉에 생긴 라벨의 위치를 변경하는 방법을 써야합니다.
label.set_y()함수로 라벨의 y위치를, label.set_xloc()함수로 라벨의 x위치를 바꿔준것입니다.

(1) 라벨의 위치는 := 이걸로는 바꿀 수 없기 때문에 (2) 함수들로 바꿔준 것입니다.

1)
var labelStock = label.new(bar_index, cptStock, "Stock", style = label.style_none, textcolor = color.red)
// 라벨이 첫번째 봉에서만 보입니다.

2)
var labelStock = label.new(bar_index, cptStock, "Stock", style = label.style_none, textcolor = color.red)
label.set_y(labelStock, cptStock)
label.set_xloc(labelStock, time, xloc.bar_time)
// 라벨이 첫번째 봉에서만 보입니다만, 강제로 위치를 바꿔 마지막 봉에 나타나도록 했습니다.

2)
labelStock = label.new(bar_index, cptStock, "Stock", style = label.style_none, textcolor = color.red)
// 라벨이 모든 봉에서 보입니다만, 라벨은 약 50개 내외로 출력되므로 봉이 그것보다 많다면 뒷쪽에만 나타날것입니다.

구름타고슝님의 댓글의 댓글

(1) labelCondition=time>timenow-(time_close-time_close[1])*2
    labelName=label.new(x = labelCondition ? timenow-(time_close-time_close[1])*1 : stopP, y = profitrate,
    text = 'SC ['+tostring(profitrate_2)+'%]', color=color.orange, textcolor=color.orange, style = label.style_none,
    xloc = xloc.bar_time, yloc = yloc.price, size = size.normal)

    위는 슈퍼트렌드입니다.  label.new(x, y, text, xloc, yloc, color, style, textcolor, size, textalign, tooltip)
    label.new는 이런 인자들로 구성되는데, x,y 가 의미상  xloc,yloc과 다를바 없다고 생각하고 있었습니다.
    슈퍼트렌드 지표에서도 x,y 에 지정된 것들이 x 축 위치, y축 위치를 나타낸다고 이해했었습니다.
 
  영구포트폴리오에서도 label.new(bar_index, cptStock, ...... )  이것도 x,y 가 xloc, yloc과 같은 의미로 쓰이는것으로
  이해했는데,  별도로 location을 지정해주는게 이해가 잘 안갑니다.

(2) 만약 x,y가 xloc,yloc과 다르다면  label.new 함수 내에서도 인자에 x.loc / y.loc이 있는데, label.set함수를 사용하지
    않고  label.new( ) 괄호안에서 위치를 지정해줄수도 있는건가요?

(3) label.set_x와 label.set_xloc 가 매뉴얼만 보면 거의 똑같은거같은데, 위에서는 다르게 사용하셨는데 이유가
    있을까요?  쓰고보니 (1)과 동일한 질문같습니다.

(4)  http://kimchulho.com/pineclass/23 댓글에도 질문이 하나 있었는데,  시간되실때 답변 부탁드립니다.

김철호님의 댓글의 댓글

(1)
x, y는 실제 값
xloc, yloc은 x, y값의 유형(단위)이라고 보시면 되겠습니다.

xloc에는 xloc.bar_index, xloc.bar_time 이 올 수 있는데,
xloc을 xloc.bar_index, 그러니까 봉의 인덱스 수로 하겠다 하면
x는 0, 1, 2, 3, 4 이런식으로 값을 써줘야하고요.

xloc을 xloc.bar_time으로 지정하면 시간으로 쓰겠다는 의미입니다.
그렇다면 x가 가질 수 있는 값은 유닉스 시간으로써, 1605345038 이러한 값을 써줘야 합니다.

봉의 인덱스 또는 시간 중 어떤 것으로 접근할 것인지에 따라 차이가 있는 것입니다.
* * *

같은 식으로 yloc에는 yloc.price, yloc.abovebar, yloc.belowbar이 올 수 있습니다.
yloc.abovebar와 yloc.belowbar는 각각 봉의 위 아래에 표시를 해주고,
yloc.price를 쓰면 해당 가격에 표시를 할 수 있습니다.

따라서 y값은 yloc을 yloc.price로 해야만 유효한것이 됩니다.
y에는 라벨을 표시하고 싶은 가격을 쓰면 되는 것이지요.
그리고, yloc=yloc.price로 해야 y가격에 해당하는 부분에 라벨이 표시 될 것입니다.

(2)
네, label.new에서도 xloc, yloc을 지정해 줄 수 있으며, 생략할 경우에는 기본값인 xloc.bar_index, yloc.price가 됩니다.

(3)
label.set_x와 label.set_xloc는 같은데, 후자는 x와 xloc을 한번에 바꿀 수 있는 함수입니다.
예를 들어, label.new로 만든 라벨이 기본적으로 봉 인덱스로 x값을 쓰는 경우 xloc은 xloc.bar_index일것입니다.
그런데, 어떤 이유에서든 x를 봉 인덱스가 아니라 봉 시간으로 접근해야할때는
x를 유닉스 시간으로 표현해야하므로 xloc도 xloc.bar_time 형식이 되어야 할것입니다.
그럴때는 xloc도 같이 바꿀 수 있는 label.set_xloc 함수를 써야 할것입니다.

제가 2)에서 쓴  label.set_xloc(labelStock, time, xloc.bar_time) 함수는
가장 마지막 시간에 라벨 표시를 하고 싶다는 생각으로 time을 썼던 것인데, 지금 다시 보니 굳이 그럴 필요 없이
그냥 봉 인덱스로 label.set_x(labelStock, bar_index) 이렇게 써도 되는 부분이었습니다.

(4)
댓글이 없네요.
전체 25건 / 1페이지

+ 최근글


+ 새댓글


통계