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/

    Futures rollover - data feed produced seems to be empty

    General Code/Help
    2
    7
    1147
    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.
    • L
      lampalork last edited by

      Dear All,

      I'm trying to backtest a VIX futures strategy that requires actual futures contract. It is the first time i'm looking at the rollover feature of backtester. My code is fairly simple and inspired from the rollover sample / code I found on this forum. At a high level, I load each indidivudal futures (only 4 contracts in this example) contract from CSV, then i try to "chain" them using cerebro.rollover (with checkvolume). After that, i'm adding the strategy 'TheStrategy' (same as in sample code) to display the daily bars. Unfortunately, nothing gets displayed. it seems that the datafeed generated by cerebro.rollover is empty. I have tried to investigate this issue but i have not found anything (difficult since there is not even an error message). On thing i did is to replace cerebro.rollover by cerebro.chaindata. In this case, it works well, and i see the 4 futures contracts being displayed one after the others. Code used is shown below.

      Any help to resolve/investigate this issue will be extremely welcome!

      Thanks in advance and cheers!
      Lamp'

      data from CBOE website, e.g.
      VX18 - https://markets.cboe.com/us/futures/market_statistics/historical_data/products/csv/VX/2018-12-19

      import datetime
      import time
      import argparse
      import bisect
      import calendar
      import datetime
      import backtrader as bt
      import backtrader.filters as btfilters
      from backtrader.order import Order
      
      class TheStrategy(bt.Strategy):
          def start(self):
              header = ['Len', 'Name', 'RollName', 'Datetime', 'Open',
                                  'High', 'Low', 'Close', 'Volume', 'OpenInterest']
              print(', '.join(header))
      
          def next(self):
              txt = list()
              txt.append('%04d' % len(self.data0))
              txt.append('{}'.format(self.data0._dataname))
              # Internal knowledge ... current expiration in use is in _d
              txt.append('{}'.format(self.data0._d._dataname))
              txt.append('{}'.format(self.data.datetime.date()))
              txt.append('{}'.format(self.data.open[0]))
              txt.append('{}'.format(self.data.high[0]))
              txt.append('{}'.format(self.data.low[0]))
              txt.append('{}'.format(self.data.close[0]))
              txt.append('{}'.format(self.data.volume[0]))
              txt.append('{}'.format(self.data.openinterest[0]))
              print(', '.join(txt))
      
      def get_data_feed(data_filename):
          data = bt.feeds.GenericCSVData(
              dataname=data_filename,
              headers=True,
              dtformat=('%Y-%m-%d'),
              datetime=0,
              open=3,
              high=4,
              low=5,
              close=6,
              volume=8,
              openinterest=10,
              timeframe=bt.TimeFrame.Days,
              compression=1
          )
      
          return data
      
      def checkvolume(d0, d1):
          return d0.volume[0] < d1.volume[0]  # Switch if volume from d0 < d1
      
      month_codes = ['U18', 'V18', 'X18', 'Z18']
      ffeeds = [get_data_feed('./CFE_{0}_VX.csv'.format(x)) for x in month_codes]
      
      month_codes = ['U18', 'V18', 'X18', 'Z18']
      ffeeds = [get_data_feed('./CFE_{0}_VX.csv'.format(x)) for x in month_codes]
      cerebro = bt.Cerebro()
      rollkwargs = dict()
      rollkwargs['checkcondition'] = checkvolume
      cerebro.rolloverdata(name='FESX', *ffeeds, **rollkwargs)
      #cerebro.chaindata(name='FESX', *ffeeds)
      cerebro.addstrategy(TheStrategy)
      cerebro.run()
      
      
      1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        Documentation - Docs - Rolling over Futures

          - checkcondition (default: None)
        
            Note: This will only be called if checkdate has returned True
        

        You have not specified a checkdate, which means that your checkcondition is not being called. In any case that should not be the problem, because it will simply be ignored.

        @lampalork said in Futures rollover - data feed produced seems to be empty:

                open=3,
                high=4,
                low=5,
                close=6,
        

        Those indices are offset by +1. You want 2, 3, 4, 5.

        @lampalork said in Futures rollover - data feed produced seems to be empty:

        class TheStrategy(bt.Strategy):
            def start(self):
                header = ['Len', 'Name', 'RollName', 'Datetime', 'Open',
                                    'High', 'Low', 'Close', 'Volume', 'OpenInterest']
                print(', '.join(header))
        

        You say it seems to be empty, but we don't even know if you are seeing the header printed.

        I would

        • Load one of those single data feeds and see if it loads and is displayed
        • Add 2 of them manually to cerebro.rollover and see what happens.
        1 Reply Last reply Reply Quote 0
        • L
          lampalork last edited by

          Hi Backtrader,

          Thanks for getting back.

          1. i have fixed the field indices but obviously this was not the issue
          2. when i load one feed straight (i.e. using cerebro.adddata(ffeeds[0]) instead of rollover), i can see the header and the data being displayed
          3. When i load one feed or multiple feeds using rolloverdata (e.g. cerebro.rolloverdata(ffeeds[0], name='MyRoll', **rollkwargs) or cerebro.rolloverdata(ffeeds[0],ffeeds[1], name='MyRoll', **rollkwargs)), i can see the header but not the header
          4. When i load the data with chaindata (e.g. cerebro.chaindata(name='MyRoll', *ffeeds)), i can see the header and all the data (i.e. the data of the four futures one after the other)

          Hope this clarifies the issue i'm facing. In case it is relevant, i'm running backtrader version 1.9.66.122

          Thanks and regards
          Lamp'

          1 Reply Last reply Reply Quote 0
          • L
            lampalork last edited by lampalork

            Dear backtrader,

            Any idea how I could investigate this further ?
            thanks in advance

            Regards
            Lamp'

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

              Not really. The sample which is in the repository works.

              My suggestion is that you use that sample with as little modifications as possible, i.e.: change only

              ffeeds = [bt.stores. ...]
              

              and use

              ffeeds = [getdata(x) for x in fcodes]
              

              Where getdata is the one in where you fetch the data using GenericCSV

              @lampalork said in Futures rollover - data feed produced seems to be empty:

              month_codes = ['U18', 'V18', 'X18', 'Z18']
              ffeeds = [get_data_feed('./CFE_{0}_VX.csv'.format(x)) for x in month_codes]
              
              month_codes = ['U18', 'V18', 'X18', 'Z18']
              ffeeds = [get_data_feed('./CFE_{0}_VX.csv'.format(x)) for x in month_codes]
              

              In any case you may also want to remove those duplicates

              1 Reply Last reply Reply Quote 0
              • L
                lampalork last edited by

                Still sort of stuck on this. I replicated the examples, and it is still not working. Is there a way I can run the example without changes, where do I get the VChart data used in rollover.py; I could not find them on GitHub. Do u need to subscribe to visual chart to be able to download the data and run this example? Thanks

                1 Reply Last reply Reply Quote 0
                • L
                  lampalork last edited by

                  Hello all, i finally made some progress on this. at first sight, it seems that upgrading backtrader from version backtrader-1.9.66.122 to backtrader-1.9.70.122 has fixed my issue. this is strange since this feature was added a while back to bt; but anyway, i thought i would post this here in case it can help someone else! happy sunday!

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