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
Fatih
-
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) orself.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 thatlen(self.datas[index + 1]) > 0
before doing anything with it.
- Take into account tht
- 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 is1
). Due to the different starting dates of the futures, only when the last of them has delivered the1st
bar, you will have yournext
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
Fatih
-
Suggest to support notify_rollover just like notify_timer,
in notify_rollover event,add new data delete old data. -
@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 feedRollOver
) you can pass a callable with the argumentcheckdate
. You control when the future is rolled over. The platform knows nothing about expiry dates. That's where you can find it out.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 theRollOver
approach just joins together number of price series based on certain rules incheckdate
orcheckcondition
. 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 inbt
, where old prices are shifted in order to delete these gaps? -
An approach to create a continuous futures stream inside the platform wouldn't be a good approach. This is the sequence of steps
- The platform goes over data part 1
- Indicators are calculated
next
is evaluated- Rollover takes place and the gap to the new future is seen which allows calculating the modified prices of part 1
- Go over data part 1
- Re-calculate indicators por data part 1
next
MUST not be called (add an exception)- Now go over data part 2
- Indicators are calculated
next
is evaluated- Rollover takes place and the gap to the new future is seen which allows calculating the modified prices of part 1 and 2
- Go over data part 1 and data part 2
- Re-calculate indicators por data part 1 data part 2
next
MUST not be called (add an exception)- 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 strategyAnother 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? -
@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.