이번에는 역시 김철호님이 본인 사이트에 올려주신 무료 LAA 백테스트 스크립트를 가지고 LAA 백테스트를 진행할 것이다.
김철호닷컴
kimchulho.com
필요하신 분들은 여기서 참고하시면 될 것 같습니다!
//@version=4
study("Lethargic Asset Allocation", "LAA")
symMaket = input("AMEX:SPY", "시장 판단 종목", input.symbol)
// 수익률 계산할 종목 입력
symStock = input("AMEX:SPY", "주식 종목", input.symbol)
symBond = input("NASDAQ:TLT", "채권 종목", input.symbol)
symGold = input("AMEX:GLD", "금 종목", input.symbol)
rateStock = input(1.0, "주식 비중")
rateBond = input(1.0, "채권 비중")
rateGold = input(1.0, "금 비중")
rateCash = input(1.0, "현금 비중")
rateSum = rateStock + rateBond + rateGold + rateCash
// 함수 정의
// 종가 가져오기
getClose(sym) => security(sym, timeframe.period, close, barmerge.gaps_off, barmerge.lookahead_on)
// 자산 종가
market = getClose(symMaket)
etfStock = getClose(symStock)
etfBond = getClose(symBond)
etfGold = getClose(symGold)
unrate = getClose("FRED:UNRATE")
// 호경기냐 불경기냐? 실업률 < 12개월 실업률 이동평균이면 호경기
isBoom = unrate < sma(unrate, 12)
// 상승장이냐 하락장이냐? 주가 > 12개월 이동평균이면 상승장
isBull = market > sma(market, 12)
// 호경기 또는 상승장이면 현금은 주식에, 아니면 채권에
laaAsset = (isBoom[1] or isBull[1]) ? etfStock : etfBond
prevLaaAsset = (isBoom[1] or isBull[1]) ? etfStock[1] : etfBond[1]
// 백테스트 기간 설정
startYear = input(1, "시작 년")
startMonth = input(1, "시작 월")
startDay = input(1, "시작 일")
startPeriod = timestamp(startYear, startMonth, startDay, 0, 0)
endYear = input(9999, "종료 년")
endMonth = input(12, "종료 월")
endDay = input(31, "종료 일")
endPeriod = timestamp(endYear, endMonth, endDay, 0, 0)
testPeriod = time >= startPeriod and time <= endPeriod and etfStock > 0 and etfBond > 0 and etfGold > 0
capital = 100.0
cptStock = capital * (rateStock / rateSum)
cptBond = capital * (rateBond / rateSum)
cptGold = capital * (rateGold / rateSum)
cptCash = capital * (rateCash / rateSum)
if(testPeriod)
capital := nz(cptStock[1], capital/4) + nz(cptBond[1], capital/4) + nz(cptGold[1], capital/4) + nz(cptCash[1], capital/4)
cptStock := capital * (rateStock / rateSum) * nz(etfStock/etfStock[1], 1)
cptBond := capital * (rateBond / rateSum) * nz(etfBond/etfBond[1], 1)
cptGold := capital * (rateGold / rateSum) * nz(etfGold/etfGold[1], 1)
cptCash := capital * (rateCash / rateSum) * nz(laaAsset/prevLaaAsset, 1)
// 누적 수익률
accRange = (cptStock + cptBond + cptGold + cptCash) - 100
// 백테스트 기간에만 봉 갯수 세기
var barCount = 0
barCount := barCount + (testPeriod ? 1 : 0)
// 연 복리 계산
cagr = testPeriod ? (pow(1+accRange/100, 1/((barCount)/12))-1)*100 : 0
// 최고 수익률 계산
var maxAccRange = 0.0
maxAccRange := max(maxAccRange, accRange)
// 손실폭 계산
var drawdown = 0.0
drawdown := (((1+accRange/100)/(1+maxAccRange/100)) - 1) * 100
// 최대 손실폭 계산
var mdd = 0.0
mdd := min(mdd, drawdown)
// 결과 출력
plot(testPeriod ? accRange : na, "수익률(%)", color.purple) // 누적 수익률
plot(testPeriod ? cagr : na, "연 복리(%)", color.green)
plot(testPeriod ? drawdown : na, "손실폭(%)", color.red)
plot(testPeriod ? mdd : na, "최대 손실폭(%)", color.orange)
plot(testPeriod ? (laaAsset/prevLaaAsset-1)*100 : na, "월별 수익률(%)", color.navy, style=plot.style_columns) // 월별 수익률
plot(testPeriod ? isBoom ? 1:0 : na, "호경기", color.blue, style=plot.style_stepline)
plot(testPeriod ? isBull ? 1:0 : na, "상승장", color.red, style=plot.style_stepline)
bgcolor(testPeriod and (isBoom[1] or isBull[1]) ? color.purple : na, 90)
//plot(cptStock, "주식", color.red)
//plot(cptBond, "채권", color.green)
//plot(cptGold, "금", color.orange)
//plot(cptCash, "현금", color.blue)
먼저 비율을 전체로 조정하여 아래 표시처럼 봉의 기준이 1달이 되게끔 설정해 주고 나서 결과를 살펴보면 다음과 같다.
결과 2004년 10부터 LAA에 투자했으면 약 220%의 수익을 달성할 수 있었고, mdd는 최근에 갱신되어 15% 정도로 나온다.
수정할 점은 원래는 정적자산과 동적자산으로 구분해서 동적자산만 채권과 주식으로 옮겨야 하지만 코드를 보면 리밸런싱을 달마다 진행하는 것을 확인할 수 있다.
밑에 코드를 보면 봉이 한달 주기로 계산 되므로 12개월 마다 한 번씩 전체 자산을 리밸런싱해주고, 그렇지 않으면 정적자산은 1년동안 손익만 계산해주고, 밑에 cptCash, 즉 유동자산에 해당하는 부분은 경제 상황에 맞게 채권과 현금을 오가면서 투자해야 한다. 유동자산 계산이 제대로 되고 있는지 확신이 들지 않으므로 관련해서 좀 더 수정해야 할 것 같다.
//리밸런싱
count = 0
if (testPeriod and count == 0)
capital := nz(cptStock[1], capital/4) + nz(cptBond[1], capital/4) + nz(cptGold[1], capital/4) + nz(cptCash[1], capital/4)
cptStock := capital * (rateStock / rateSum) * nz(etfStock/etfStock[1], 1)
cptBond := capital * (rateBond / rateSum) * nz(etfBond/etfBond[1], 1)
cptGold := capital * (rateGold / rateSum) * nz(etfGold/etfGold[1], 1)
cptCash := capital * (rateCash / rateSum) * nz(laaAsset/prevLaaAsset, 1)
count := count + 1
else if (testPeriod and count < 12)
cptStock := nz(cptStock[1], capital/4) * nz(etfStock/etfStock[1], 1)
cptBond := nz(cptBond[1], capital/4) * nz(etfBond/etfBond[1], 1)
cptGold := nz(cptGold[1], capital/4) * nz(etfGold/etfGold[1], 1)
cptCash := nz(cptCash[1], capital/4) * nz(laaAsset/prevLaaAsset, 1)
count := count + 1
if (count == 12)
count := 0
plot(testPeriod ? (laaAsset/prevLaaAsset-1)*100 : na, "월별 수익률(%)", color.navy, style=plot.style_columns) // 월별 수익률
plot(testPeriod ? ((cptStock + cptBond + cptGold + cptCash)/(cptStock[1] + cptBond[1] + cptGold[1] + cptCash[1])-1)*100 : na, "월별 자산수익률(%)", color.red, style=plot.style_columns)
추가로 월별 수익률에 대한 코드도 유동자산에 대해서만 작성되어 있어서 모두 더해서 계산하는 쪽으로 수정했다. (밑의 빨간 막대 그래프)
'백테스트 실전' 카테고리의 다른 글
46. VAA 백테스트 (Feat. 트레이딩 뷰) (0) | 2022.09.08 |
---|