For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Backtest multiple tickers at a same time



  • Hi, I'm a beginner using backtrader.

    I have some data feeds (using sqlite from my local laptop), and I wanna backtest multiple tickers at a same time with a same logic.

    My logic is simple. Buy stocks at a close price, Sell stocks at a open price next day.
    I can run this logic when just backtest a stock.
    But I have some trouble when adding tickers (two stocks)

    My code is here.

    class OverNight(bt.Strategy):

    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))
    
    def __init__(self):
        self.inds = {}
        for i, d in enumerate(self.datas):
            self.inds[d] = dict()
    
        self.order = None           # Issued Order (not yet executed)
        self.buyprice = None
        self.buycomm = None
    
    
    def next(self):
        for i, d in enumerate(self.datas):
            dt, dn = self.datetime.date(), d._name
            pos = self.getposition(d).size
    
            if not pos:
                self.buy(data=d, exectype=bt.Order.Close)
            else:
                self.close(data=d)
                self.buy(data=d, exectype=bt.Order.Close
    
    def notify_order(self, order):
        if order.status != order.Completed:
            return
    
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log('매수 완료 | 매수가격: %.2f, 총매매금액: %.2f, 수수료: %.2f' %
                         (order.executed.price, order.executed.value, order.executed.comm))
    
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
    
            elif order.issell():
                self.log('매도 완료 | 매도가격: %.2f, 총매매금액: %.2f, 수수료: %.2f' %
                         (order.executed.price, order.executed.value, order.executed.comm))
                pass
    
            self.bar_executed = len(self)
    
        self.order = None
    
    def notify_trade(self, trade):
        if trade.justopened:
            pass
        if not trade.isclosed:
            self.log('매매 손익 | 총손익: %.2f, 순손익: %.2f, 주식수: %.2f' % (trade.pnl, trade.pnlcomm, trade.size))
            self.log('총자산: %.2f' % self.broker.getvalue())
    

    class maxRiskSizer(bt.Sizer):
    '''
    Returns the number of shares rounded down that can be purchased for the max risk tolerance
    '''
    params = (('risk', 0.03),)

    def __init__(self):
        if self.p.risk > 1 or self.p.risk < 0:
            raise ValueError('The risk parameter is a percentage which must be'
                             'entered as a float. e.g. 0.5')
    
    def _getsizing(self, comminfo, cash, data, isbuy):
        if isbuy == True:
            size = math.floor((self.broker.getvalue() * self.p.risk) / data[0])
            print('현금: %s, 주식수: %s, 주가: %s' % (math.floor(cash), size, data[0]))
        else:
            size = math.floor((self.broker.getvalue() * self.p.risk) / data[0]) * -1
            print('현금: %s, 주식수: %s, 주가: %s' % (math.floor(cash), size, data[0]))
        return size
    

    if name == 'main':
    cerebro = bt.Cerebro()

    # 전략 추가
    cerebro.addstrategy(OverNight)
    
    # Analyzer
    cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")
    cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
    
    # 데이터 입력
    data_path = 'E:/AutoTrading_test/DB/cmp_ohlcv.db'
    sql = "SELECT * FROM '{0}' WHERE day > ""20201001"" ORDER BY day ASC"
    con = sqlite3.connect(data_path)
    code_list = pd.read_sql("SELECT * FROM cmp_master", con)
    
    code_list = list(np.array(code_list['Code'].tolist()))
    code_list = ['A005930', 'A000660']
    for code in code_list:
        data = pd.read_sql(sql.format(code), con, index_col='day', parse_dates=['day'])
        data = bt.feeds.PandasData(dataname=data, name=code)
    
        cerebro.adddata(data)
    
    startcash = 1000000
    cerebro.broker.set_cash(startcash)
    cerebro.broker.setcommission(0.0015)
    cerebro.addsizer(maxRiskSizer, risk=0.7)
    
    strategies = cerebro.run()
    firstStrat = strategies[0]
    
    portvalue = cerebro.broker.getvalue()
    
    print('기초자산: %.2f' % startcash)
    print('기말자산: %.2f' % portvalue)
    
    # print the analyzers
    printTradeAnalysis(firstStrat.analyzers.ta.get_analysis())
    printSQN(firstStrat.analyzers.sqn.get_analysis())
    
    cerebro.plot(style='candlestick')

Log in to reply
 

});