본문 바로가기
Python/금융, 주식

backtrader 패키지, 투자 전략 백테스트 하기 (1)

by 춘춘주모 2020. 6. 18.
반응형

 

 

backtrader 패키지는 전략 백테스트와 알고리즘 주식 거래를 위한 패키지입니다.

 다양한 기능을 제공하며, 커뮤니티가 잘 활성화되어있어 필요한 정보를 얻기에도 편한 환경을 제공합니다.(https://www.backtrader.com/)

 

간단한 전략을 구현하면서 어떻게 사용하는지 알아보겠습니다. 

(google Colab 환경) 

1. 필요한 패키지 

!pip install backtrader

import matplotlib
import matplotlib.pyplot as plt
from datetime import datetime
import backtrader as bt

2. 전략 설정 - 10,20일 이동평균선 전략 : 장단기 이동평균선이 교차하는 지점에서 매매하는 전략 

이런 방식이외에도 다른 전략을 사용하거나, 매매 시점을 정의하는 다른 여러 가지 방법이 있습니다. 

class SmaCross1(bt.Strategy): 
    params = dict(
    pfast=10, # period for the fast moving average
    pslow=20 # 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() # 매도

3. 전략 테스트 

실행은 다음과 같은 순서로 진행됩니다.

  1. 엔진 생성
  2. 데이터 불러오기, 기간설정 - 저는 2019년 1년간의 테스트를 위했습니다. 하지만 20일 이동평균선 생성을 위해서는 지난 20일간의 데이터가 필요하기에 2018년 12월 11일부터로 날짜를 설정하였습니다.
  3. 매매 수수료 설정 - 필수는 아닙니다
  4. 전략 적용 
  5. 실행, 결과 확인 
  6. 결과 시각화 
cerebro = bt.Cerebro() # create a "Cerebro" engine instance
# 삼성전자의 '005930.KS' 코드를 적용하여 데이터 획득

data = bt.feeds.YahooFinanceData(dataname='005930.KS',
fromdate=datetime(2018, 12, 11),
todate=datetime(2019, 12, 31))

cerebro.adddata(data)

cerebro.broker.setcash(10000000) # 초기 자본 설정
cerebro.broker.setcommission(commission=0.00015) # 매매 수수료는 0.015% 설정
cerebro.addstrategy(SmaCross2) # 자신만의 매매 전략 추가
cerebro.run() # 백테스팅 시작

#Get final portfolio Value
portvalue = cerebro.broker.getvalue()
pnl = portvalue - 10000000

#Print out the final result
print('Final Portfolio Value: ${}'.format(portvalue))
print('P/L: ${}'.format(pnl))
print((portvalue-10000000)/10000000*100,'%')

#Visualize
cerebro.plot()

실행 결과 대략 30% 수익 

 

코랩 환경에서는 현재 시각화가 잘 되지 않아 다음과 같은 방법으로 시각화 파일을 불러왔습니다. 

figure = cerebro.plot(volume=False, width=25, height=25)[0][0]
figure.savefig('example_sma.png')

코랩의 파일탭에서 새로운 이미지가 생성된 것을 확인할 수 있습니다. 

  • 시각화 이미지에서 PV의 변화, 각 거래에 대한 평가, 매매 시점, 매매 신호를 확인할 수 있습니다.
  • 원래 cerobro.plot()에서 바로 확인되는 이미지는 대화형으로 잘 나오는데 코랩에서는 저는 일단 창에서 바로 시각화하는 방법은 실패했습니다. 원래는 사용자와 상호작용하는 더 친절한 이미지도 제공됩니다. 

cerebro.plot()

 

 

한 번에 여러 종목 수익률 확인해보기 - 리스트와 반복문 사용 

#종목 코드 리스트 
stockcodes = ['005930', '000660', '005380', '015760', '012330', 
              '028260', '005490', '032830', '055550', '017670', 
              '090430', '105560', '051910', '034730', '000270', 
              '033780', '096770', '011170', '051900', '000810', 
              '034220', '018260', '003550', '002790', '010950', 
              '086790', '010130', '066570', '004020', '035250']

#종목코드 형식 추가 
from datetime import datetime
import backtrader as bt
dataname_t = []
for i in range(len(stockcodes)):

    dataname = stockcodes[i]+'.KS'
    print(dataname)
    dataname_t.append(dataname)

#반복문 형식으로 실행하고 결과를 리스트에 저장 
fromdate1=datetime(2018, 12, 11)
todate1=datetime(2019, 12, 31)
pv = []
for i in range(len(dataname_t)):
    cerebro = bt.Cerebro()
    dataname1 = dataname_t[i]
    data = bt.feeds.YahooFinanceData(dataname=dataname1, fromdate=fromdate1, todate=todate1)

    cerebro.adddata(data)

    cerebro.broker.setcash(10000000) # 초기 자본 설정
    cerebro.broker.setcommission(commission=0.00015) # 매매 수수료는 0.015% 설정
    cerebro.addstrategy(SmaCross1) # 자신만의 매매 전략 추가
    cerebro.run() # 백테스팅 시작

    #Get final portfolio Value
    portvalue = cerebro.broker.getvalue()
    pnl = portvalue - 10000000

    #Print out the final result
    print('stock : ',dataname_t[i])
    print('Final Portfolio Value: {}'.format(portvalue))
    pv.append(portvalue)

이런 식으로 한 번에 여러 종목의 백테스트 결과를 확인해 볼 수 있었습니다. 

 

오늘도 감사드립니다. 혹시 질문 있으시거나, 잘 안 되는 부분이 있으시면 댓글란에 의견 부탁드립니다. 아는 한에서 최대한 설명드리도록 하겠습니다. 

 

 

 

반응형

댓글