파인스크립트 기본반
분류 공개스크립트

VAA 전략 백테스트

페이지 정보

본문



//@version=4
study("Vigilant Asset Allocation", "VAA")

// * * * 입력 * * * //
// 사용할 공수 자산 입력
offenseSym1 = input("AMEX:SPY", "공격 자산1 (미국 주식)", input.symbol)
offenseSym2 = input("AMEX:EFA", "공격 자산2 (선진국 주식)", input.symbol)
offenseSym3 = input("AMEX:EEM", "공격 자산3 (신흥국 주식)", input.symbol)
offenseSym4 = input("AMEX:AGG", "공격 자산4 (미국 총 채권)", input.symbol)
defenseSym1 = input("AMEX:LQD", "수비 자산1 (미국 회사채)", input.symbol)
defenseSym2 = input("NASDAQ:IEF", "수비 자산2 (미국 중기채)", input.symbol)
defenseSym3 = input("NASDAQ:SHY", "수비 자산3 (미국 단기채)", input.symbol)

// 월별 거래 비용
cost        = input(0.0, "편도 거래 비용(%)", input.float)

// 백테스트 기간 설정
startYear   = input(1,      "시작 년")
startMonth  = input(1,      "시작 월")
startDay    = input(1,      "시작 일")
endYear     = input(9999,   "종료 년")
endMonth    = input(12,     "종료 월")
endDay      = input(31,     "종료 일")
startPeriod = timestamp(startYear, startMonth, startDay, 0, 0)
endPeriod   = timestamp(endYear, endMonth, endDay, 0, 0)
testPeriod  = time >= startPeriod and time <= endPeriod

// 함수 정의 시작
// 종가 가져오기
getClose(sym) => security(sym, timeframe.period, close, barmerge.gaps_off, barmerge.lookahead_on)

// 수익률 계산
getYield(src, m) => (src/src[m]-1)*100

// 모멘텀 스코어 계산
getScore(src) => 12 * getYield(src, 1) + 4 * getYield(src, 3) + 2 * getYield(src, 6) + 1 * getYield(src, 12)
// 함수 정의 끝

// * * * 연산 * * * //
// 공격적인 자산 종가
spy = getClose(offenseSym1)
efa = getClose(offenseSym2)
eem = getClose(offenseSym3)
agg = getClose(offenseSym4)

// 수비적인 자산 종가
lqd = getClose(defenseSym1)
ief = getClose(defenseSym2)
shy = getClose(defenseSym3)


// 공격적인 자산의 모멘텀 스코어
scoreSPY = getScore(spy)
scoreEFA = getScore(efa)
scoreEEM = getScore(eem)
scoreAGG = getScore(agg)

// 수비적인 자산의 모멘텀 스코어
scoreLQD = getScore(lqd)
scoreIEF = getScore(ief)
scoreSHY = getScore(shy)

// 모든 종목의 모멘텀 스코어가 존재하는가?
isValue = not(na(scoreSPY[1]) or na(scoreEFA[1]) or na(scoreEEM[1]) or na(scoreAGG[1]) or na(scoreLQD[1]) or na(scoreIEF[1]) or na(scoreSHY[1]))

// 공격 모드 판별
offenseCondition = not(min(scoreSPY, scoreEFA, scoreEEM, scoreAGG) < 0)

// 공격형 자산 중 최고 모멘텀 스코어
scoreOffense = max(scoreSPY, scoreEFA, scoreEEM, scoreAGG)

// 수비형 자산 중 최고 모멘텀 스코어
scoreDefense = max(scoreLQD, scoreIEF, scoreSHY)

// 공수 자산의 최근 한달간의 수익률(누적 수익률을 구하기 위함)
yieldSPY = getYield(spy, 1)
yieldEFA = getYield(efa, 1)
yieldEEM = getYield(eem, 1)
yieldAGG = getYield(agg, 1)
yieldLQD = getYield(lqd, 1)
yieldIEF = getYield(ief, 1)
yieldSHY = getYield(shy, 1)

// 투자 종목별 색상
colorScore = offenseCondition
 ? ((scoreOffense == scoreSPY) ? color.red : 
 (scoreOffense == scoreEFA) ? color.orange :
 (scoreOffense == scoreEEM) ? color.yellow :
 (scoreOffense == scoreAGG) ? color.green : na)
 : ((scoreDefense == scoreLQD) ? color.blue :
 (scoreDefense == scoreIEF) ? color.navy :
 (scoreDefense == scoreSHY) ? color.purple : na)

// 월말 투자 종목
nextInvestment = offenseCondition
 ? ((scoreOffense == scoreSPY) ? "미국" : 
 (scoreOffense == scoreEFA) ? "선진국" :
 (scoreOffense == scoreEEM) ? "신흥국" :
 (scoreOffense == scoreAGG) ? "미 총채권" : "")
 : ((scoreDefense == scoreLQD) ? "미 회사채" :
 (scoreDefense == scoreIEF) ? "미 중기채" :
 (scoreDefense == scoreSHY) ? "미 단기채" : "")
 
// 전월과 보유 종목이 같으면 거래 비용 없음
realCost = cost + (nextInvestment[1] == nextInvestment ? 0 : cost) + (nextInvestment[1] == nextInvestment[2] ? - cost : 0)

// 공수 전환으로 인해 선택된 자산의 월별 수익률
monthYield = (offenseCondition[1]
 ? ((scoreOffense[1] == scoreSPY[1]) ? yieldSPY : 
 (scoreOffense[1] == scoreEFA[1]) ? yieldEFA :
 (scoreOffense[1] == scoreEEM[1]) ? yieldEEM :
 (scoreOffense[1] == scoreAGG[1]) ? yieldAGG : 0)
 : ((scoreDefense[1] == scoreLQD[1]) ? yieldLQD :
 (scoreDefense[1] == scoreIEF[1]) ? yieldIEF :
 (scoreDefense[1] == scoreSHY[1]) ? yieldSHY : 0)) - realCost
 
// 월별 수익률 누적 결과
var yield = 0.0
yield := testPeriod ? (((1+yield/100) * (1+monthYield/100)) - 1) * 100 : 0.0

// 백테스트 기간에만 봉 갯수 세기
var barCount = 0
barCount := barCount + (testPeriod ? 1 : 0)

// 연 복리 계산
cagr = (pow(1+yield/100, 1/((barCount)/12))-1)*100

// 최고 수익률 계산
var maxYield = 0.0
maxYield := max(maxYield, yield)

// 손실폭 계산
var drawdown = 0.0
drawdown := (((1+yield/100)/(1+maxYield/100)) - 1) * 100

// 최대 손실폭 계산
var mdd = 0.0
mdd := min(mdd, drawdown)

// * * * 출력 * * * //
// 1. 공격 자산의 모멘텀 스코어
plot(scoreSPY, "미국", color.red, 1, plot.style_stepline)
plot(scoreEFA, "선진국", color.orange, 1, plot.style_stepline) 
plot(scoreEEM, "신흥국", color.yellow, 1, plot.style_stepline) 
plot(scoreAGG, "미 총채권", color.green, 1, plot.style_stepline)   

// 2. 수비 자산의 모멘텀 스코어
plot(scoreLQD, "미 회사채", color.blue, 1, plot.style_stepline)
plot(scoreIEF, "미 중기채", color.navy, 1, plot.style_stepline)
plot(scoreSHY, "미 단기채", color.purple, 1, plot.style_stepline)

// 3. 월별 수익률 & 월말 투자 종목
plot(testPeriod and isValue ? monthYield : na, "월별 수익률(%)", colorScore[1], 1, plot.style_columns)
var labelNext = label.new(bar_index, 0, style = label.style_label_upper_left)
label.set_xy(labelNext, bar_index, 0)
label.set_color(labelNext, colorScore)
label.set_text(labelNext, tostring(month) + "월말 투자 종목 : " + nextInvestment)

// 4. 수익률
plot(testPeriod and isValue ? yield : na, "수익률(%)", color.purple)

// 5. 연 복리
plot(testPeriod and isValue ? cagr : na, "연 복리(%)", color.green)

// 6. 손실폭과 최대 손실폭
plot(testPeriod and isValue ? drawdown : na, "손실폭(%)", color.red)
plot(testPeriod and isValue ? mdd : na, "최대 손실폭(%)", color.orange)

관련자료

전체 25건 / 1페이지

+ 최근글


+ 새댓글


통계