I'm working on a code template for buy-and-holding a futures contract, and since it's a template I plan on using a bit I'd like to have clean code to build off of. I'd like to have the algorithm buy the front contract upon initialization, and then use scheduling to update the active contract a few days before contract expiry, so that my OnData isn't mucked up with initialization or rollover logic. I'd like to preserve OnData for generating signals etc, and once I have BAH with rollover down, I'd like to extend this to use the QC Framework.

I've come to realize that SetWarmUp() does not work with Futures (source), so I'm trying to do this using the History API. However, I'm running into a bit of a paradox.. I need a slice to get a futures chain, from which I can find a front contract and a symbol. But in Initialize, I need a symbol in order to request a slice from History().

I've gotten this to work by using the first slice provided to the OnData method, but this is initialization code and doesn't belong outside of the Initialize() method. Perhaps I'm misunderstanding the History API. In the attached code, `History(1)` doesn't return any slices.

Any suggestions?

I'm open to python code, if someone has code that reads slices after using AddFutures(...) and History(...) in the Initialize() method

using QuantConnect.Securities.Future; using QuantConnect.Data.Market; namespace QuantConnect.Algorithm.CSharp { public class OptimizedVerticalContainmentField : QCAlgorithm { private Future _esMini; private FuturesContract _activeContract; public override void Initialize() { SetStartDate(2019, 1, 1); SetEndDate(2019, 3, 1); SetCash(100000); _esMini = AddFuture(Futures.Indices.SP500EMini, Resolution.Minute); _esMini.SetFilter(0, 90); var initialHistorySlice = History(1).First(); SetActiveContractAndScheduleRollover(initialHistorySlice); SetHoldings(_activeContract.Symbol, 1); } override public void OnData(Slice slice) { } private void SetActiveContractAndScheduleRollover(Slice slice) { if (slice.FutureChains.Count != 1) { Log($"ERROR - No contracts in var {nameof(slice.FutureChains)}"); return; } var esMiniChain = slice.FutureChains.First(); var recentContracts = esMiniChain.Value.OrderBy(x => x.Expiry - Time.Date).ToList(); if (recentContracts.Count == 0) { Log($"ERROR - No contracts in var {nameof(recentContracts)}"); return; } var frontContract = recentContracts.First(); _activeContract = frontContract; ScheduleRollover(); } private void ScheduleRollover() { var DAYS_BEFORE_EXPIRY_TO_ROLLOVER = 1; Schedule.On(DateRules.On(_activeContract.Expiry.AddDays(-1 * DAYS_BEFORE_EXPIRY_TO_ROLLOVER)), TimeRules.AfterMarketOpen(_activeContract.Symbol), Rollover); } private void Rollover() { if (Portfolio.Invested) { Liquidate(); SetHoldings(_activeContract.Symbol, 1); } } } }

 

Author