Backtrader Community

    • 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/

    Filtering out ticks in strategy.next()

    General Code/Help
    2
    9
    2715
    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.
    • RandyT
      RandyT last edited by

      @backtrader
      What is the appropriate way to filter out ticks for instruments that I am not trading off of in strategy.next()?

      I am getting multiple executions on a strategy with two different datasets. Case where the logic of the entries are still true when a signaling (or reference data) tick is coming through strategy.next().

      I've tried something like the following, but that has the effect of turning off all logic processing after that point for any tick.

      if self.data._name == 'BLAH': 
          return
      
      1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        Your scripts show use of resampledata, which implies and therefore data feed is signaled by means of a change in the len of the data feed.

        A potential approach:

        • Create an array during __init__ or start with a 0 for each of the data feeds: for example self.dl = [0] * len(self.datas)
        • Create a temporary equivalent on entry to next with actual lens: dl = [len(d) for d in self.datas]
        • Check which ones have actually changed: dlnew = [x - y for x, y in zip(dl, self.dl)]
        • Get the indices to it: dlidx = [i for i, x in enumerate(dlnew) if x]
        • Keep actual lenghts: self.dl = dl

        Now dlidx contains the indices to the data feeds which have changed. since the last call to next

        1 Reply Last reply Reply Quote 0
        • RandyT
          RandyT last edited by

          @backtrader
          So I have implemented your suggestion and it seems to accomplish the goal. I've added the following bit of code in strategy.next() to return if the current tick is not for the instrument I am using to execute the strategy.

          # looking for ticks on data1 (SPY)
          if self.datas[dlidx[0]]._name != 'SPY':
              return
          

          Was that the intended way to apply this?

          1 Reply Last reply Reply Quote 0
          • RandyT
            RandyT last edited by

            @backtrader any comment on the appropriate use of the conditional above?

            It seems now that I am not letting ticks past this point while live trading, but it works as expected in running a backtest with static data.

            Here again is the conditional I put in place:

                    # looking for ticks on data1 (SPY)
                    if self.datas[dlidx[0]]._name != 'SPY':
                        return
            
            1 Reply Last reply Reply Quote 0
            • B
              backtrader administrators last edited by

              The conditional as written will probably miss things. Rationale:

              • The approach is meant to gather the indices into the datas array for all data feeds whose length has changed

              • That means that the array dlidx[] will have a varying length, from 1 to n (where n is equal to len(self.datas))

              If several data feeds deliver a tick simultaneously and seeing in the code that SPY is data1, dlidx, could contain for example [0, 1]. The test would effectively be doing self.datas[0]._name != 'SPY', which will fail because SPY is data1 (aka self.datas[1])

              You would need to traverse the dlidx array to see if any of the indices points to your SPY data.

              1 Reply Last reply Reply Quote 0
              • RandyT
                RandyT last edited by RandyT

                Maybe I am doing something very wrong as I continue to struggle to solve my use case, which I would expect to be fairly common.

                I have datas 0,1 and 2.

                data0 = daily timeframe of X symbol
                data1 = minute timeframe of Y symbol
                data2 = daily timeframe of Y symbol

                I want to apply trade execution logic in next() to values presented by data0 and execute trades on data1 if the logic conditions are met at the closing bar values for data0. (I'm using data2 to feed the Sizer FWIW)

                if buysignal:
                    self.buy(data1)
                elif sellsignal:
                    self.sell(data1)
                else:
                   "trade entry signals not met"
                

                In order to prevent an entry or exit to be executed before the closing bar for data0 is seen (since data1 ticks are flowing through every minute), I must put some time check in this logic to filter out ticks for data1 seen before the close of data0, or some way to exclude the data feed itself from that logic.

                If relying on the bar time, I still run the risk of sending duplicate orders for the 16:00 bar on data0 and data1.

                So it seems common that we would need to be able to easily filter out ticks we don't want to evaluate logic for trade execution. Unless I am missing the obvious which is possible...

                This goes back to my comments about a need to put certain data in classification "reference" to avoid seeing it in next(). In this example, I would put data1 and data2 in "reference" classification so I know that values seen in next() are those that I care about. Since it is daily timeframe, I know that any bar I see I must evaluate the trade logic and thereby avoid filters for time and dataname.

                Am I missing something?

                1 Reply Last reply Reply Quote 0
                • RandyT
                  RandyT last edited by

                  So this is where I am at at this point to try to accomplish this goal. Is there a cleaner way?

                          # looking for ticks on data1 (SPY)
                          dlist = []
                          for i in iter(dlidx):
                              dlist.append(self.datas[dlidx[i - 1]]._name)
                  
                          if 'SPY' not in dlist:
                              return
                  
                          if self.p.live:
                              mclose = dt.datetime.combine(dt.datetime.today().date(),
                                                           dt.time(16, 0))
                              bartime = self.data.datetime.datetime(tz=EST)
                              print('%s == %s', (bartime, mclose))
                              if bartime != mclose:
                                  return
                  
                  1 Reply Last reply Reply Quote 0
                  • B
                    backtrader administrators last edited by backtrader

                    Iterating over dlidx and then checking dlidx[i - 1] seems odd.

                    dlist = [self.datas[i]._name for i in dlidx]
                    

                    The above could should actually suffice (although it's not shown how dlidx is actually generated)

                    1 Reply Last reply Reply Quote 0
                    • RandyT
                      RandyT last edited by

                      My hack above worked today, so I will take your much more elegant bit of python and replace a few lines. My python foo is still a bit green... Thanks!

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