I'm looking to backtest a strategy using futures options strangles but it has been a long time since I coded anything using Lean. When trying to examine the option chain for options that are within the delta range I am looking for, I can't get it to stop complaining that there is no data in OptionsChain. I presume I'm initializing something incorrectly but I can't quite figure out what. Any help would be appreciated….
namespace QuantConnect.Algorithm.CSharp
{
public class FuturesStranglesTrader : QCAlgorithm
{
DateTime startDate = new(month: 1, day: 1, year: 2022);
//TODO: make deltas optimization variables, for now, just way out of the money
decimal deltaMin = 2; //absolute value
decimal deltaMax = 3; //absolute value
decimal startingCash = 100000;
BrokerageName brokerageName = BrokerageName.Default;
string symbol = Futures.Metals.Gold;
Resolution resolution = Resolution.Hour;
//Intentionally a single DTE
TimeSpan minDTE = TimeSpan.FromDays(7);
TimeSpan maxDTE = TimeSpan.FromDays(7);
Future future;
public override void Initialize()
{
SetBenchmark("QQQ");
SetStartDate(startDate);
SetCash(startingCash);
SetBrokerageModel(brokerageName, AccountType.Margin);
// Chart - Master Container for the Chart:
var stockPlot = new Chart("Trade Plot");
// On the Trade Plotter Chart we want 3 series: trades and price:
var buyOrders = new Series("Buy", SeriesType.Scatter, 0);
var sellOrders = new Series("Sell", SeriesType.Scatter, 0);
var assetPrice = new Series("Price", SeriesType.Line, 0);
// future =
// AddFuture
// (
// symbol,
// Resolution.Hour, //TODO: switch to minute or tick when things generally working
// dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
// dataMappingMode: DataMappingMode.OpenInterest,
// contractDepthOffset: 0
// );
future = AddFuture(symbol);
//TODO: SHOULDN'T need to set filter anymore due to new continuous contract mode
//https://www.quantconnect.com/forum/discussion/12644/continuous-futures-support/p1
future.SetFilter(0, 90); //TODO: What's the minimum I need to get 7 DTE options working?
AddFutureOption(future.Symbol, FuturesOptionsSelector);
SetWarmup(TimeSpan.FromDays(8), resolution); //TODO: do I need a warmup if I'm not using any indicators?
}
//TODO: Can filter to abs(delta) be applied here to speedup test?
//Filter down to options that have a specific DTE
private OptionFilterUniverse FuturesOptionsSelector(OptionFilterUniverse filter) =>
filter.IncludeWeeklys().Expiration(minDTE, maxDTE);
public override void OnData(Slice data)
{
if (!IsReady(data))
return;
Plot("Price Plot", "Price", data.Bars[future.Symbol].Price);
foreach (var changedEvent in data.SymbolChangedEvents.Values)
Log($"Underlying futures contract changed: {changedEvent.OldSymbol} -> {changedEvent.NewSymbol}"); //log futures contract rollovers
//TODO: check for options assignments and close position if assigned
if (!Portfolio.Invested)
EnterPosition(data);
else
ExitPosition(data);
}
private bool IsReady(Slice data) =>
data.HasData && !IsWarmingUp;
private void EnterPosition(Slice data)
{
if (Portfolio.Invested)
return; //Only allow one position at a time
if (!data.OptionChains.Any() && !data.FutureChains.Any())
return; //don't have anything to work with
//Select the calls and puts that are within the delta range
//TODO: THIS LINE ALWAYS FAILS THE BACKTEST AND BREAKPOINT ON IT DOESN'T WORK
var availableContracts = data.OptionChains[future.Symbol].Where(contract => Math.Abs(contract.Greeks.Delta) >= deltaMin && Math.Abs(contract.Greeks.Delta) < deltaMax);
//TODO: make sure I have these +/- deltas right for identifying contract type or use a different method
//TODO: Preferrable to order available contracts by volume and/or open interest?
var availablePuts = availableContracts.Where(contract => contract.Greeks.Delta < 0).OrderByDescending(contract => Math.Abs(contract.Greeks.Delta));
var availableCalls = availableContracts.Where(contract => contract.Greeks.Delta > 0).OrderByDescending(contract => Math.Abs(contract.Greeks.Delta));
var callLeg = availableCalls.FirstOrDefault();
var putLeg = availablePuts.FirstOrDefault();
if (callLeg is not null && putLeg is not null)
{
var optionStrategy = OptionStrategies.Strangle(future.Symbol, callLeg.Strike, putLeg.Strike, putLeg.Expiry);
var order = Sell(optionStrategy, 1); //TODO: how to set as a limit order? How do I do max size with a specified margin buffer?
Debug($"Sold strangle: {order}");
}
}
private void ExitPosition(Slice data)
{
//For now, just letting it expire. I suspect a sell will only trigger every other week because we effectively look to open on the day one is expiring
}
}
}
Derek Melchin
Hi Tb,
The issue occurs because the algorithm above indexes the Option chain with the continuous Future contract Symbol instead of the canonical Future Option Symbol. For a working example, see Navigate Option Chains.
Best,
Derek Melchin
Want to invest in QuantConnect as we build the Linux of quant finance? Checkout our Wefunder campaign to join the revolution.
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.
Tb
The c# example from that page doesn't quite compile but I was able to use it to get past that specific problem. Now I have a problem with the greeks not being populated. I think I need to execute the code from the linked helped page BUT the PriceModel property apparently no longer exists and no other property appears to be IOptionPriceModel so I'm not sure what to assign CrankNicolsonFD to in order to populate the greeks.Â
Â
Derek Melchin
Hi Tb,
Thanks, we just fixed the code snippet examples in the docs.
We need to use
and add
to the imports.Â
We updated the docs for the first code snippet. We'll add the import statement to the default imports.
Best,
Derek Melchin
Want to invest in QuantConnect as we build the Linux of quant finance? Checkout our Wefunder campaign to join the revolution.
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.
Tb
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!