본문 바로가기

시스템 트레이딩/트레이딩 이야기

[주식투자] 20일선돌파(추세추종)는 정말 수익을 안겨줄까요? - 파이썬 백테스트

안녕하세요 이노도리입니다.

 

오늘은 한번 백테스트를 통해 기존에 많이 알려진 전략을 테스트해보려고 합니다. 아마 많은 분들이 주식 공부하다가 들어 보셨을 것 같은데요, 바로 20일선 돌파매매입니다. 보통 5일선이 20일선을 상향 돌파할 때 매수하고 5일선이 20일선을 하향 돌파할 때 매도하는 방법입니다. 많이 알려진 만큼 과연 이 전략의 성능은 얼마나 나올까요? 한번 코스피 200 ETF를 통해 살펴보도록 하겠습니다. 이 전략의 백테스트는 엑셀로 하기에는 조금 까다로운 부분이 있어서 파이썬으로 진행해보도록 하겠습니다. 

 

짠! 코스피 데이터가 있다면 이 코드를 통해 쉽게 테스트가 가능할 것입니다.

 

with open("data/kospi200.csv") as f:
    lines = f.readlines() # 코스피200 파일의 데이터 읽기
    lineLength = len(lines) # 캔들 갯수
    bought = False # 현재 매수했는지 체크하는 변수
    buyPrice = 0
    buyDay = 0
    profits = {} # 수익기록
    fee = 0.001 # 슬리피지 + 수수료
    for i in range(lineLength): # 캔들갯수만큼 루프
        datas = lines[i].split(",")
        # datas[0] = 날짜
        # datas[1] = 시가
        # datas[2] = 고가
        # datas[3] = 저가
        # datas[4] = 종가
        # datas[5] = 거래량

        # 20일 평균을 구하려면 20개 이상의 데이터가 필요합니다.
        if i < 20:
            continue

        # 평균 구하기(더 효율적인 방법이 있지만 여기서는 생략합니다.)
        sum20 = 0
        for j in range(i - 20, i):
            sum20 += float(lines[j].split(",")[4]) # j번째 종가를 float형으로 변환하여 평균을 구합니다.
        average20 = sum20 / 20
        sum5 = 0
        for j in range(i - 5, i):
            sum5 += float(lines[j].split(",")[4]) # j번째 종가를 float형으로 변환하여 평균을 구합니다.
        average5 = sum5 / 5
        
        # 5일선이 20일선 상향돌파하면 종가에 매수
        if average5 > average20 and not bought:
            bought = True
            buyDay = datas[0]
            buyPrice = float(datas[4])

        # 5일선이 20일선 하향돌파하면 종가에 매도, 수익률 기록
        if average5 < average20 and bought:
            bought = False
            sellPrice = float(datas[4])
            profit = sellPrice * (1 - fee) / (buyPrice * (1 + fee))
            profits[buyDay] = []
            profits[buyDay].append(datas[0])
            profits[buyDay].append(profit)


    for buyDay in profits:
        print(buyDay, profits[buyDay][0], profits[buyDay][1]) # 수익률 출력

 

 이 백테스트를 통해 나온 수익률의 누적수익은 어떻게 나올지 한번 볼까요? 

 

 자 단순 20일선 돌파매매의 코스피 200 성적입니다!

 

누적수익 276%  TPI 1.6577 MDD -26% CAGR 약 5% (슬리피지 + fee 0.1%)

어떤가요? 단순 20일선 돌파매매의 TPI가 무려 1.6이 넘는 값이 나왔습니다. 이 값은 정말 높은 값인데요, 단순히 20일선을 넘겼을 때 매매하는 것 만으로 이런 엄청난 성능을 달성할 수 있습니다. 하지만 역시나 이 전략에는 문제가 있습니다. 연평균 수익이 겨우(?) 5%에 불과하다는 건데요. 거기에 코스피 ETF만으로 거래를 진행할 경우 18년 동안 겨우 60여 번의 거래가 있었을 뿐입니다. 백테스트에서 60번의 거래만 있었다는 것은 과최적화에 대한 걱정을 불러일으키게 되는데요, 만약 20일 평균 5일 평균이 아니라 10일 평균 30일 평균으로 바꿨을 때에 경향이 크게 바뀐다면 이 전략은 과최적화된 전략으로 실전에서 사용하기 어렵다고 봐야 합니다. 그럼 한번 볼까요?

 

 어떤가요? 10일 평균을 사용해도 20일 평균을 사용해도 30일 평균을 사용해도 모두 비슷한 경향을 보여줍니다. 이 전략은 과최적화에 대한 걱정은 조금 덜어도 될 것 같습니다. 사실 이러한 매매방법은 매우 오랫동안 검증되어온 방법입니다. 흔히 이러한 기법을 추세추종이라고 하는데 시장의 추세를 타서 시장의 상승을 그대로 누리는 전략이라고 보시면 되겠습니다. (이 매매전략으로 가장 유명한 사람은 제시 리버모어라는 사람인데 정말 드라마틱한 인생을 살다 가신 분입니다.) 이 매매전략을 자신만의 전략으로 가다듬은 많은 트레이더들이 지금 이 순간에도 시장에 추세추종을 적용하고 알파를 얻고 있습니다. 어떤가요? 이 글을 읽는 여러분들도 한번 자신만의 추세추종 전략으로 알파를 만들어 보는 건 어떨까요?

 

마지막으로 제시 리버모어의 명언을 끝으로 포스팅을 마치겠습니다.

“The human side of every person is the greatest enemy of the average investor or speculator”

“Patterns repeat, because human nature hasn’t changed for thousand of years”