Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    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

    General Code/Help
    multiple data
    2
    2
    137
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      cwjeong last edited by

      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')
      1 Reply Last reply Reply Quote 1
      • Wayne Filkins 0
        Wayne Filkins 0 last edited by

        So are you saying you want to run the backtest on multiple stocks? Did you ever figure it out? I may have found something helpful a few weeks back, I will try to find it again.

        1 Reply Last reply Reply Quote 0
        • 1 / 1
        • First post
          Last post
        Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
        $(document).ready(function () { app.coldLoad(); }); }