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/

    Simple strategy using IB live data

    General Code/Help
    3
    3
    100
    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.
    • M
      mlbt2020 last edited by

      Hi
      I have done backtesting strategies using R quantstrat and now looking to use Python for execution.
      I am new to backtrader. After looking at some examples I was able to use getdata from IB and separately I was able to backtest a simple strategy using a different CSV data. Now I would like to combine those 2 things together for my first milestone using backtrader.

      However I am getting error:
      AttributeError: 'IBBroker' object has no attribute 'setcash'

      Not sure what is wrong and I would really appreciate your help!

      The code is here:

      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      
      import datetime  # For datetime objects
      import backtrader as bt
      
      class TestStrategy(bt.Strategy):
          params = (
              ('maperiod', 15),
          )
      
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              # dt = dt or self.datas[0].datetime.date(0)
              # print('%s, %s' % (dt.isoformat(), txt))
      
              txt = []
              txt.append("{}".format(self.data._name))
              txt.append("{}".format(len(self)))
              txt.append('{}'.format(
                  self.data.datetime.datetime(0).isoformat())
              )
              txt.append("{:.2f}".format(self.data.open[0]))
              txt.append("{:.2f}".format(self.data.high[0]))
              txt.append("{:.2f}".format(self.data.low[0]))
              txt.append("{:.2f}".format(self.data.close[0]))
              txt.append("{:.2f}".format(self.data.volume[0]))
              print(", ".join(txt))
      
          data_live = False
      
          def notify_data(self, data, status, *args, **kwargs):
              print('*' * 5, 'DATA NOTIF:', data._getstatusname(status),
                    *args)
              if status == data.LIVE:
                  self.data_live = True
      
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              self.dataclose = self.datas[0].close
      
              # To keep track of pending orders and buy price/commission
              self.order = None
              self.buyprice = None
              self.buycomm = None
      
              # Add a MovingAverageSimple indicator
              self.sma = bt.indicators.SimpleMovingAverage(
                  self.datas[0], period=self.params.maperiod)
      
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted]:
                  # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                  return
      
              # Check if an order has been completed
              # Attention: broker could reject order if not enough cash
              if order.status in [order.Completed]:
                  if order.isbuy():
                      self.log(
                          'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm))
      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  else:  # Sell
                      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                               (order.executed.price,
                                order.executed.value,
                                order.executed.comm))
      
                  self.bar_executed = len(self)
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')
      
              # Write down: no pending order
              self.order = None
      
          def notify_trade(self, trade):
              if not trade.isclosed:
                  return
      
              self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                       (trade.pnl, trade.pnlcomm))
      
          def next(self):
              # Simply log the closing price of the series from the reference
              self.log('Close, %.2f' % self.dataclose[0])
      
              # Check if an order is pending ... if yes, we cannot send a 2nd one
              if self.order:
                  return
      
              # Check if we are in the market
              if not self.position:
      
                  # Not yet ... we MIGHT BUY if ...
                  if self.sma[0] < 2700:
      
                      # BUY, BUY, BUY!!! (with all possible default parameters)
                      self.log('BUY CREATE, %.2f' % self.dataclose[0])
      
                      # Keep track of the created order to avoid a 2nd order
                      self.order = self.buy()
      
              else:
      
                  if self.sma[0] > 2900:
                      # SELL, SELL, SELL!!! (with all possible default parameters)
                      self.log('SELL CREATE, %.2f' % self.dataclose[0])
      
                      # Keep track of the created order to avoid a 2nd order
                      self.order = self.sell()
      
      if __name__ == '__main__':
          # Create a cerebro entity
          cerebro = bt.Cerebro()
      
          store = bt.stores.IBStore(host="127.0.0.1", port=7496, clientId=1)
          cerebro.broker = store.getbroker()
      
          stockkwargs = dict(
              timeframe=bt.TimeFrame.Minutes,
              rtbar=False,  # use RealTime 5 seconds bars
              historical=True,  # only historical download
              qcheck=0.5,  # timeout in seconds (float) to check for events
              fromdate=datetime.datetime(2020, 4, 20),  # get data from..
              # todate=datetime.datetime(2020, 4, 21),  # get data from..
              latethrough=False,  # let late samples through
              tradename=None  # use a different asset as order target
          )
          data = store.getdata(dataname='ES-202006-GLOBEX', **stockkwargs)
      
          cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=60)
      
          # Add a strategy
          cerebro.addstrategy(TestStrategy)
      
          # Add the Data Feed to Cerebro
          cerebro.adddata(data)
      
          # Set our desired cash start
          cerebro.broker.setcash(1000.0)
      
          # Add a FixedSize sizer according to the stake
          cerebro.addsizer(bt.sizers.FixedSize, stake=10)
      
          # Set the commission
          cerebro.broker.setcommission(commission=0.0)
      
          # Print out the starting conditions
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
          # Run over everything
          cerebro.run()
      
          # Print out the final result
          print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
          # Plot the result
          cerebro.plot()
      
      1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        @mlbt2020 said in Simple strategy using IB live data:

        cerebro.broker.setcash(1000.0)

        Seems you can't just set cash for the real broker account from the bt script. Probably you need to move some cash to the real broker account from bank account before trading.

        1 Reply Last reply Reply Quote 0
        • Jeffrey C F Wong
          Jeffrey C F Wong last edited by

          @mlbt2020 I am new to backtrader as well and is trying to learn from all these IB related posts. I am trying to plot your shared code and it seems like it is able to pull data from IB, but it is not able to execute any trades for backtesting. Have you experienced this same issue?

          Figure_0.png

          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(); }); }