웬디의 기묘한 이야기

글 작성자: WENDYS
반응형

Python backtrader 주식 전략 백테스팅 시뮬레이션

과거의 주식 데이터를 이용하여 내가 작성한 전략 알고리즘이 어느 정도 수익을 낼 수 있는지 테스트를 해볼 수 있는 시뮬레이션을 해보려 합니다. 특정 상황에서의 매수와 매도 등 간단하게 구현을 해도 되지만 python의 backtrader를 이용하여 간단한 백테스팅 시뮬레이션을 진행해보겠습니다. 

 

과거의 데이터를 이용할 때 가장 주의해야할점은 시뮬레이션 결과가 아무리 좋더라도 과거는 과거일 뿐이라는 겁니다. 과거에 성과가 좋았더라도 미래에는 성공한다는 보장이 없기 때문에 과거에 전략을 너무 믿지는 마세요!

 

자, 그럼 가장 먼저 backtrader를 설치해야합니다.

pip install backtrader

zipline이라는 라이브러리도 있지만 해당 라이브러리는 python 3.5까지만을 지원하고 있기 때문에 최신 python을 지원하는 backtrader를 이용하겠습니다. 현재 샘플은 python 3.7 에서 테스트 되었습니다.

 

 

백테스팅 테스트 케이스

가장 간단한 예를 들기 위해 조건은 SMA5 이평선과 SMA30 이평선을 기준으로 크로스가 되었을 때 풀 매수, 풀 매도하는 전략의 백테스팅입니다.

 

아래의 케이스는 2019년 1월 1일 ~ 2019년 12월 31일까지의 삼성전자 주식을 테스팅해본 결과입니다.

수익률은 아래 보이는 것처럼 좋지는 않네요 1,000,000원으로 시작해서 1년 동안 1,084,750으로 마감을 했습니다.

평균가 49,000원 기준으로 55,800원까지 약 17%가량 상승에 대비 8% 수익률이면 그렇게 나쁘지도 않네요

 

 

다른 케이스를 한번 보겠습니다.

늘 저 정도라도 이득을 보면 다행이겠지만.. 같은 조건을 두고 삼성전자의 2017.12.1일부터 ~ 2018년 12월 31일까지의 데이터로 돌렸을 때 계좌가 조금씩 박살 나는 것을 볼 수 있습니다.. (1월 1일부터 SMA30 이동평균을 내기 위해 12월 1일부터 진행)

 

 

 

 

backtrader python code

위의 백테스팅 전략을 python code로 구현하기 위해선 위에서 얘기했던 backtrader를 사용하도록 합니다.

backtrader 내에서 다양한 indicator를 제공하기 때문에 backtrader.ind 내에 SMA, EMA, RSI 등등 다양한 indicator들을 직접 구현하지 않고도 사용할 수 있습니다.

 

buy 함수에서 size를 아무값도 입력하지않으면 1개씩 매수 하게 되기때문에 전략에 따라 변경하시면 됩니다.

cerebro.broker.setcash (default : 10,000원) : 초기 자본금을 임의로 설정할 수 있습니다.

cerebro.broker.setcommision (default : 0.0%) : 매매 수수료를 임의로 설정할 수 있습니다.

cerebro.broker.addstrategy : 자신만의 매매 전략을 추가할 수 있습니다.

from datetime import datetime
import backtrader as bt

class SmaCross(bt.Strategy): # bt.Strategy를 상속한 class로 생성해야 함.
    
    params = dict(
        pfast=5,  # period for the fast moving average
        pslow=30   # period for the slow moving average
    )

    def __init__(self):
        sma1 = bt.ind.SMA(period=self.p.pfast)  # fast moving average
        sma2 = bt.ind.SMA(period=self.p.pslow)  # slow moving average
        self.crossover = bt.ind.CrossOver(sma1, sma2)  # crossover signal

    def next(self):
        if not self.position:  # not in the market
            if self.crossover > 0:  # if fast crosses slow to the upside

                close = self.data.close[0] # 종가 값
                size = int(self.broker.getcash() / close) # 최대 구매 가능 개수

                self.buy(size=size)  # 매수 size = 구매 개수 설정

        elif self.crossover < 0:  # in the market & cross to the downside
            self.close()  # 매도

cerebro = bt.Cerebro()  # create a "Cerebro" engine instance

# 삼성전자의 '005930.KS' 코드를 적용하여 데이터 획득
data = bt.feeds.YahooFinanceData(dataname='005930.KS',
                                 fromdate=datetime(2019, 1, 1),
                                 todate=datetime(2019, 12, 31))

cerebro.adddata(data)
cerebro.broker.setcash(1000000) # 초기 자본 설정
cerebro.broker.setcommission(commission=0.00015)  # 매매 수수료는 0.015% 설정

cerebro.addstrategy(SmaCross) # 자신만의 매매 전략 추가

cerebro.run() # 백테스팅 시작

cerebro.plot() # 그래프로 보여주기

 

코드는 주석을 달아놔서 간단하게 보시면 되며, 국내 코스닥, 코스피의 모든 종목 코드를 가져오는 방법은 지난번에 소개해드린 Pandas를 이용하여 주식 종목 코드 가져오기! 를 참조하면 됩니다.

 

backtrader documents

backtrader의 공식문서는 아래 페이지에서 확인 가능합니다.

 

https://www.backtrader.com/docu/

 

Introduction - Backtrader

Introduction Welcome to the backtrader documentation! The platform has 2 main objectives: Ease of use Go back to 1 Note Loosely based on the Karate (Kid) rules by Mr. Miyagi. The basics of running this platform: Create a Strategy Decide on potential adjust

www.backtrader.com

 

반응형