For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See:

Futures handling with strategy

  • Hi,
    I was planning to use backtrader for futures testing. I looked at the previous blogs and posts, I see that there is a discussion on how to "stitch" together futures of later expiration's to come up with a single series. However, as the blog also mentions it, it is quite difficult to come up with a single stitching strategy that is best under all scenarios. In fact, part of the strategy I plan to investigate is to find the best way to jump from one future to the next, using the strategy method of backtrader.
    However, I have difficulty doing it in backtrader, as backtrader seems to only work on a singlecontinuous series.

    Is it possible to work with futures of a commodity with different expirations in backtrader. And have the data of these futures available to backtrader strategy, so that the strategy can decide when to sell a current future and buy the next future.

    Thank you


  • administrators

    cerebro.rolloverdata, Docs - Rolling over Futures can be used to move across futures' expiry dates controlling the conditions.

    cerebro.chaindata Docs - Cerebro can be also used but will look into no condition, ie: delivering from one future until expired and then delivering from the next (which may not be ideal for daily timeframes because futures usually close midday and part of the action of that day would therefore be missed)

    Both assume (naively) that the data feeds passed to them are already in order and nowhere else in the system. The latter being what would prevent buying from different targets.

    An approach you may consider:

    • Add each of your futures as a separate data feed.
    • Start with an index target of: index=0
    • When buying you can buy from self.datas[index] (current future) or self.datas[index + 1] (next future)
      • Take into account tht self.datas[index + 1] will not be producing values for a while, so you need to check that len(self.datas[index + 1]) > 0 before doing anything with it.
    • Some time x before the expiry you decide to focus on the next future as the main and then you do: index += 1

    The platform will keep on running even if the expired futures no longer deliver data. The non-expired futures will keep on moving forward.

    In any case your strategy will need a hack. The platform will not call your next until all elements have delivered its minimum amount of data (which for a data feed is 1). Due to the different starting dates of the futures, only when the last of them has delivered the 1st bar, you will have your next called. This could be achieved by overriding _getminperstatus(self)

    • Which will return a negative value as soon as next can be called.

    Probably worth a post sometime soon.

  • Thank you very much for your detailed answer.
    I look forward to details of how _getminperstatus(self) can be used to trick the system to move forward on dates even though future expiring futures's data has not starting rolling yet.

    I have two more questions:

    • Is there a function that returns when a future is expiring? Calculating expiry dates of futures can be pretty tricky.
    • Is there a limit to number of data feeds? Can I have 1000s of data feeds?

    Thank you


  • Suggest to support notify_rollover just like notify_timer,
    in notify_rollover event,add new data delete old data.

  • administrators

    @Humbleguy said in Futures handling with strategy:

    Is there a function that returns when a future is expiring? Calculating expiry dates of futures can be pretty tricky.

    With rollover (or directly with the feed RollOver) you can pass a callable with the argument checkdate. You control when the future is rolled over. The platform knows nothing about expiry dates. That's where you can find it out.

    Docs - Rolling over Futures

    Is there a limit to number of data feeds? Can I have 1000s of data feeds?

    And 10000, there is no limit beyond those imposed by the reality: RAM, Processing Power and the slow by nature Python.

  • @backtrader
    as I learned the RollOver approach just joins together number of price series based on certain rules in checkdate or checkcondition. These price series will be joined as is, so final series will have gaps at the rollover points.

    Could you please advice the approach to create so called continous futures series in bt, where old prices are shifted in order to delete these gaps?

  • administrators

    An approach to create a continuous futures stream inside the platform wouldn't be a good approach. This is the sequence of steps

    1. The platform goes over data part 1
    2. Indicators are calculated
    3. next is evaluated
    4. Rollover takes place and the gap to the new future is seen which allows calculating the modified prices of part 1
    5. Go over data part 1
    6. Re-calculate indicators por data part 1
    7. next MUST not be called (add an exception)
    8. Now go over data part 2
    9. Indicators are calculated
    10. next is evaluated
    11. Rollover takes place and the gap to the new future is seen which allows calculating the modified prices of part 1 and 2
    12. Go over data part 1 and data part 2
    13. Re-calculate indicators por data part 1 data part 2
    14. next MUST not be called (add an exception)
    15. Now go over data part 2

    As you see, such an approach keeps re-going over data parts already seen and recalculating the indicators multiple times.

    The only practical approach is to precalculate the continuous stream outside of the platform and then do a single pass over the data.

  • Thanks @backtrader

    I was thinking to use a separate bt run without indicators and without buy/sell logic just to generate and save continuous futures data. Probably I can run through all datas once and get gap values at each rollover date, save them, and then apply it to the non-adjusted prices as indicator in the actual strategy

    Another question. I planned to use back/forward adjustment (shift prices on the size of the gap). Such approach may bring negative prices into the data series. Will bt be able to process them?

  • administrators

    @ab_trader In theory yes, because there was a use case with spreads (which oscillate around 0). The problem there was that some of Python tests for existence would fail because the price was zero. It was dealt with a long time ago.

Log in to reply

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.