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/

    Multiple data feeds - different order gives different trades

    General Code/Help
    3
    6
    600
    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.
    • H
      howardhh last edited by

      Hi,

      I have 3 different data feeds but when I change the order of those around, my strategy gives different trades/ results. I have been able to narrow this down to the Startegy Class itself, but am not sure why this is happening.

      Can someone please help? Thanks in advance.

      import backtrader as bt
      from datetime import datetime
      from datetime import timedelta

      class maCross(bt.Strategy):
      '''
      oneplot = Force all datas to plot on the same master.
      '''
      params = (
      ('ema50', 50),
      ('ema200', 200),
      ('cci20', 20),
      ('oneplot', True)
      )

      def __init__(self):
          '''
          Create an dictionary of indicators so that we can dynamically add the
          indicators to the strategy using a loop. This mean the strategy will
          work with any number of data feeds.
          '''
          self.inds = dict()
          for i, d in enumerate(self.datas):
              self.inds[d] = dict()
              self.inds[d]['ema50'] = bt.indicators.ExponentialMovingAverage(
                  d.close, period=self.params.ema50)
              self.inds[d]['ema200'] = bt.indicators.ExponentialMovingAverage(
                  d.close, period=self.params.ema200)
              self.inds[d]['cci20'] = bt.indicators.CommodityChannelIndex(
                  period=self.params.cci20)
              self.inds[d]['crossUp'] = bt.indicators.CrossOver(self.inds[d]['cci20'], -100)  # crossup = 1
              self.inds[d]['EMAcross'] = bt.indicators.CrossOver(self.inds[d]['ema50'], self.inds[d]['ema200'])
              self.inds[d]['crossDown'] = bt.indicators.CrossOver(self.inds[d]['cci20'], 100)  # crossdown = -1
      
              if i > 0:  # Check we are not on the first loop of data feed:
                  if self.p.oneplot == True:
                      d.plotinfo.plotmaster = self.datas[0]
      
      def prenext(self):
          self.next()
      
      def next(self):
          feeds_with_data = [(i, d) for i, d in enumerate(self.datas) if len(d)]
          for i, d in feeds_with_data:
              # calculate risk/ stop price
              risk = 100  # risk = 100 dollars
              stop = 0.05  # stop 5% below close
              stop_price = self.datas[i].close[0] * (1 - stop)
      
              dt, dn = self.datetime.date(), d._name
              pos = self.getposition(d).size
              if not pos:  # no market / no orders
                  if self.inds[d]['ema50'] >= self.inds[d]['ema200']:
                      if self.inds[d]['crossUp'][0] == 1:  # if CCI crosses up -100
                          if self.datas[i].close[0] - stop_price > 0:  # check if risk is acceptable/ valid
                              qty = round(risk / (self.datas[i].close[0] - stop_price), 0)  # get no. of shares to trade
                              eofthisday = self.datas[i].datetime.date()  #get current date
                              expiry = eofthisday + timedelta(days=4) #keep order active for 4 days (over weekend + public hol)
                              self.buy_bracket(data=d, limitprice=10000, price=self.datas[i].close[0],
                                               stopprice=stop_price, exectype=bt.Order.Limit, size=qty, valid=expiry)
                          else:
                              pass
                      else:
                          pass
                  else:
                      pass
      
              else:
                  if self.inds[d]['crossDown'][0] == -1:  # if cci crosses down 100
                      self.close(data=d)
      
      def notify_trade(self, trade):
          dt = self.data.datetime.date()
          if trade.isclosed:
              print('{} {} Closed: PnL Gross {}, Net {}'.format(
                  dt,
                  trade.data._name,
                  round(trade.pnl, 2),
                  round(trade.pnlcomm, 2)))
      

      datalist = [
      ('data_adjusted/CBA.AX.csv', 'CBA.AX'),
      ('data_adjusted/CSL.AX.csv', 'CSL.AX'),
      ('data_adjusted/BSL.AX.csv', 'BSL.AX'),
      ]

      For example when I swap the order of CBA and BSL with each other, the trades taken are different and I get a different end result.

      Thanks again, appreciate any help available.

      A 1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
        
        H 1 Reply Last reply Reply Quote 0
        • H
          howardhh @backtrader last edited by

          @backtrader

          Apologies, I wasn't aware of that. Will definitely use it next time.

          Regarding the data feed order though, where do you think the problem is?

          Thank you.

          1 Reply Last reply Reply Quote 0
          • A
            ab_trader @howardhh last edited by

            @howardhh said in Multiple data feeds - different order gives different trades:

            I have 3 different data feeds but when I change the order of those around, my strategy gives different trades/ results

            This is quite ambiguous statement and figure this out without having the data is quite hard. But as a first guess assuming that the difference means that some trades are not taken - your sizing is connected to the risk and particular stock price. So it might be a cases when you don't have enough cash to buy on new signal. You may want to check if your size calculated by risk meets the rest of the cash.

            • If my answer helped, hit reputation up arrow at lower right corner of the post.
            • Python Debugging With Pdb
            • New to python and bt - check this out
            1 Reply Last reply Reply Quote 1
            • B
              backtrader administrators last edited by

              @ab_trader is probably right on spot.

              Let me complete the answer by asking a question:

              • How much logging do you have in your code to understand what's happening?

                Barely none. You only print the trades, but that can only inform you about things that happen and not about the things which aren't happening or about the order in which things are happening or why things aren't happening at all.

              Logging may seem tedious at first, but it will let you separate the grain from the chaff.

              1 Reply Last reply Reply Quote 1
              • H
                howardhh last edited by

                Thanks for the replies, I'll double check the code and will see what happens.

                1 Reply Last reply Reply Quote 0
                • 1 / 1
                • First post
                  Last post
                Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors