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);
}
}
}
}
Derek Melchin
Hi Austin,
To get historical futures contracts during the initialize method, we can use the FutureChainProvider.
self.sp = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Minute) self.sp.SetFilter(0, 90) contracts = self.FutureChainProvider.GetFutureContractList(self.sp.Symbol, self.StartDate)
Note that the date passed to the GetFutureContractList method must be in the past to avoid look-ahead bias.
See the attached backtest for reference.
Best,
Derek Melchin
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Austin
Derek Melchin thanks for the help! Sorry about the late reply, didn't have time to work these past few days.
I notice that `self.FutureChainProvider.GetFutureContractList(self.sp.Symbol, self.StartDate)` returns an `IEnumberable<Symbol>` (I converted to c#), but does not provide a FuturesChain. Using `Symbol`s has limited capabilities, for example I can't see open interest, expiry date etc.. Is there a way to convert the Symbol (or Symbol.Value, which return individual FuturesContract names like ES15H19) into either a `FuturesChain` or a `FuturesContract` object type?
I've checked the futures docs but don't see a way to create a FuturesChain or a FuturesContract either in the Initialize() or from a contract symbol alone. Attacking the problem from a universe selection angle doesn't seem to provide me any additional benefits in my attempt to set the active contract during initialization.
Austin
For what its worth, I've gotten buy-and-hold futures with rollover to mostly work by putting an additional Initialization method in OnData (see `InitializeForFutures(slice);`), similar to how WarmUp would be used if it worked for futures. If you think this is the best available solution and I should stop trying to set my active contract in the Initialize method, just let me know.
Though this code has a separate issue with getting contracts XYZ days away from StartDate, as seen in logging, but that is a different question entirely.
Austin
Just tried using the FuturesChain constuctor, unsucessfully.. Perhaps I'm using the wrong type of `QuantConnect.Symbol` ?
Derek Melchin
Hi Austin,
FuturesChain is a collection of FuturesContract which is a data element, so it's not possible to create them. They are created during the data process. Consequently, they are only available in OnData or CurrentSlice member.
Best,
Derek Melchin
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Austin
Okay, thanks for your response Derek Melchin! Appreciated.
Austin
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!