[Python] 백트레이더(Backtrader) 로 여러종목 백테스트 하기
프로젝트/[ing]_백테스팅_툴

[Python] 백트레이더(Backtrader) 로 여러종목 백테스트 하기

728x90
반응형

안녕하세요. 

이번엔 백트레이더를 활용해서 여러종목을 백테스트 해보려 합니다. 

여기선 여러 종목을 읽어오고 데이터를 전달하는데 초점을 맞추었습니다. 

 

조건 : '삼성전자, SK하이닉스, 현대자동차를 일간시세 기준 RSI 40 미만 매수, 60초과 매도'

 

전체적인 코드의 흐름은 첫번째 백트레이더 포스트와 동일하니, 참고해주시면 되겠습니다.

 

백트레이더로 여러 종목 데이터를 전달하려면 여러 종목의 데이터프레임 변수가 필요합니다.

 

'삼성전자', 'SK하이닉스', '현대자동차' 3종목을 가져와보겠습니다. 

 

mk = Analyzer.MarketDB()

# 종목명 기입
stocks = ['삼성전자', 'SK하이닉스', '현대자동차']
datalist = []

cerebro = bt.Cerebro()
cerebro.broker.setcash(10000000)

# 여러 종목의 데이터를 받기 위해 반복문 사용
for i in range(0, len(stocks)):
    df = mk.get_daily_price(stocks[i], '2020-07-31') 
    df['date'] = pd.to_datetime(df['date']) 
    df.columns = ['code', 'datetime', 'open', 'high', 'low', 'close', 'diff', 'volume']
    df.drop(['code', 'diff'], axis=1, inplace=True)
    datalist.append(df)
    data = bt.feeds.PandasData(dataname=datalist[i])
    cerebro.adddata(data, name=stocks[i])

먼저 빈 데이터 리스트를 만들고 종목이 여러개인 만큼 for 반복문을 써서 각 종목의 데이터프레임을 불러와 편집한 후, 데이터리스트에 하나씩 추가한 다음 백트레이더에 데이터를 전달해 주는 형태입니다.

 

여러 종목에 대한 데이터를 전달했으니, 백테스팅 전략도 여러 데이터에 대한 것으로 바꿔줘야 합니다.

이 또한 마찬가지로 각 종목에 대한 반복문을 써서 바꿔주도록 합니다.

 

class MyStrategy(bt.Strategy):
    def __init__(self):

        self.rsi = dict()
        for i, d in enumerate(self.datas): # 여러 데이터 반복
            self.rsi[d] = bt.indicators.RSI_SMA(d.close, period=21)
    
    def next(self):
        for i, d in enumerate(self.datas): # 여러 데이터 반복
            pos = self.getposition(d).size # 단일 데이터일 때와 다른 형태
            if not pos: # no market / no orders
                if self.rsi[d] < 40:
                    self.order = self.buy(data=d)
            else:
                if self.rsi[d] > 60:
                    self.order = self.sell(data=d)

 

 

전체 코드는 아래와 같습니다. ([1]을 참고하시면 더욱 좋습니다.)

 

from datetime import datetime, timedelta
import backtrader as bt
from backtrader import cerebro
from pandas.io.formats import style
import Analyzer
import pandas as pd

class MyStrategy(bt.Strategy):
    def __init__(self):

        self.rsi = dict()
        for i, d in enumerate(self.datas):
            self.rsi[d] = bt.indicators.RSI_SMA(d.close, period=21)
    
    def next(self):
        for i, d in enumerate(self.datas):
            pos = self.getposition(d).size
            if not pos: # no market / no orders
                if self.rsi[d] < 40:
                    self.order = self.buy(data=d)
            else:
                if self.rsi[d] > 60:
                    self.order = self.sell(data=d)
    
mk = Analyzer.MarketDB()

stocks = ['삼성전자', 'SK하이닉스', '현대자동차']
datalist = []

cerebro = bt.Cerebro()
cerebro.broker.setcash(10000000)

for i in range(0, len(stocks)):
    df = mk.get_daily_price(stocks[i], '2020-07-31') 
    df['date'] = pd.to_datetime(df['date']) 
    df.columns = ['code', 'datetime', 'open', 'high', 'low', 'close', 'diff', 'volume']
    df.drop(['code', 'diff'], axis=1, inplace=True) 
    datalist.append(df)
    data = bt.feeds.PandasData(dataname=datalist[i]) 
    cerebro.adddata(data, name=stocks[i])

cerebro.addstrategy(MyStrategy)
cerebro.broker.setcommission(commission=0.0014) 
cerebro.addsizer(bt.sizers.SizerFix, stake=30)

cerebro.run() 
cerebro.plot(style='candlestick')

 

마지막으로 이를 실행해보면 아래 차트가 출력됩니다. 위에서부터 삼성전자, SK하이닉스, 현대자동차의 차트입니다.

 

위에서부터 삼성전자, SK하이닉스, 현대자동차의 RSI 40미만 매수, 60초과 매도조건 백테스팅 결과

 

3종목에 대한 백테스팅이 된걸 확인하실 수 있습니다.

종목명이 한글이라 깨진 현상을 확인할 수 있는데요, 이는 추후 포스팅 해보도록 하겠습니다.

 

참고.

[1]. https://backtest-rookies.com/2017/08/22/backtrader-multiple-data-feeds-indicators/

 

Backtrader: Multiple Data Feeds & Indicators - Backtest Rookies

If you have read through the Backtrader: First Script post or seen any of the other code snippets on this site, you will see that most examples work with just one data feed. Similarly, the number of indicators to be used in a strategy is well-defined in

backtest-rookies.com

 

[2]. https://jsp-dev.tistory.com/104

 

Python,Backtrader 다중 데이터 백테스팅 Python sqlite3 to backtrader / Mutliple Data Feeds / Pandas DataFrame to Backtra

그동안 Pandas Dataframe으로 생성하고 to_excel로 엑셀형태로 주가 데이터를 저장해왔습니다. 이번에는 sqlite3에 저장한 주가 데이터를 가져와 여러개의 데이터를 추가한 Backtesting을 다뤄보겠습니다.

jsp-dev.tistory.com

 

728x90
반응형