public override void Initialize() { SetStartDate(2021, 1, 4); SetEndDate(2021, 1, 31); _spx = AddIndex("SPX", Resolution.Minute).Symbol; // Select an index option expiring ITM, and adds it to the algorithm. _spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time) .Where(x => x.ID.StrikePrice <= 3200m && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1) .OrderByDescending(x => x.ID.StrikePrice) .Take(1) .Single(), Resolution.Minute); _spxOption.PriceModel = OptionPriceModels.BjerksundStensland(); _expectedOptionContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Call, 3200m, new DateTime(2021, 1, 15)); if (_spxOption.Symbol != _expectedOptionContract) { throw new Exception($"Contract {_expectedOptionContract} was not found in the chain"); } }
public override void OnData(Slice data) { if (!Portfolio[_equitySymbol].Invested) { MarketOrder(_equitySymbol, 100); } if (!(Securities.ContainsKey(_optionContract) && Portfolio[_optionContract].Invested)) { var contracts = OptionChainProvider.GetOptionContractList(_equitySymbol, data.Time); var underlyingPrice = Securities[_equitySymbol].Price; // filter the out-of-money call options from the contract list which expire in 10 to 30 days from now on var otmCalls = (from symbol in contracts where symbol.ID.OptionRight == OptionRight.Call where symbol.ID.StrikePrice - underlyingPrice > 0 where ((symbol.ID.Date - data.Time).TotalDays < 30 && (symbol.ID.Date - data.Time).TotalDays > 10) select symbol); if (otmCalls.Count() != 0) { _optionContract = otmCalls.OrderBy(x => x.ID.Date) .ThenBy(x => (x.ID.StrikePrice - underlyingPrice)) .FirstOrDefault(); if (_contractsAdded.Add(_optionContract)) { // use AddOptionContract() to subscribe the data for specified contract AddOptionContract(_optionContract, Resolution.Minute); } } else { _optionContract = string.Empty; } } if (Securities.ContainsKey(_optionContract) && !Portfolio[_optionContract].Invested) { MarketOrder(_optionContract, -1); } }
public override void OnData(Slice data) { // Compare our previous slice time to this slice // Because of issues with Delisting data we have to let Auxiliary data pass through GH #5207 if (Time.Ticks - _lastSliceTime.Ticks < 1000 && data.Values.Any(x => x.DataType != MarketDataType.Auxiliary)) { throw new Exception($"Emitted two slices within 1000 ticks of each other."); } // Store our slice time _lastSliceTime = Time; var underlyingPrice = Securities[_symbol].Price; var contractSymbol = OptionChainProvider.GetOptionContractList(_symbol, Time) .Where(x => x.ID.StrikePrice - underlyingPrice > 0) .OrderBy(x => x.ID.Date) .FirstOrDefault(); if (contractSymbol != null) { _optionSymbol = AddOptionContract(contractSymbol).Symbol; } }
public override void OnData(Slice data) { if (_option == null) { var option = OptionChainProvider.GetOptionContractList(_twx, Time) .OrderBy(symbol => symbol.ID.Symbol) .FirstOrDefault(optionContract => optionContract.ID.Date == _expiration && optionContract.ID.OptionRight == OptionRight.Call && optionContract.ID.OptionStyle == OptionStyle.American); if (option != null) { _option = AddOptionContract(option).Symbol; } } if (_option != null && Securities[_option].Price != 0 && !_traded) { _traded = true; Buy(_option, 1); foreach (var symbol in new [] { _option, _option.Underlying }) { var config = SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(symbol).ToList(); if (!config.Any()) { throw new Exception($"Was expecting configurations for {symbol}"); } if (config.Any(dataConfig => dataConfig.DataNormalizationMode != DataNormalizationMode.Raw)) { throw new Exception($"Was expecting DataNormalizationMode.Raw configurations for {symbol}"); } } } if (Time.Date > _expiration) { if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_option).Any()) { throw new Exception($"Unexpected configurations for {_option} after it has been delisted"); } if (Securities[_twx].Invested) { if (!SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_twx).Any()) { throw new Exception($"Was expecting configurations for {_twx}"); } // first we liquidate the option exercised position Liquidate(_twx); } } else if (Time.Date > _expiration && !Securities[_twx].Invested) { if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(_twx).Any()) { throw new Exception($"Unexpected configurations for {_twx} after it has been liquidated"); } } }
/// <summary> /// Gets <see cref="OptionHistory"/> object for a given symbol, date and resolution /// </summary> /// <param name="symbol">The symbol to retrieve historical option data for</param> /// <param name="start">The history request start time</param> /// <param name="end">The history request end time. Defaults to 1 day if null</param> /// <param name="resolution">The resolution to request</param> /// <returns>A <see cref="OptionHistory"/> object that contains historical option data.</returns> public OptionHistory GetOptionHistory(Symbol symbol, DateTime start, DateTime?end = null, Resolution?resolution = null) { if (!end.HasValue || end.Value == start) { end = start.AddDays(1); } // Load a canonical option Symbol if the user provides us with an underlying Symbol if (!symbol.SecurityType.IsOption()) { var option = AddOption(symbol, resolution, symbol.ID.Market); // Allow 20 strikes from the money for futures. No expiry filter is applied // so that any future contract provided will have data returned. if (symbol.SecurityType == SecurityType.Future && symbol.IsCanonical()) { throw new ArgumentException("The Future Symbol provided is a canonical Symbol (i.e. a Symbol representing all Futures), which is not supported at this time. " + "If you are using the Symbol accessible from `AddFuture(...)`, use the Symbol from `AddFutureContract(...)` instead. " + "You can use `qb.FutureOptionChainProvider(canonicalFuture, datetime)` to get a list of futures contracts for a given date, and add them to your algorithm with `AddFutureContract(symbol, Resolution)`."); } if (symbol.SecurityType == SecurityType.Future && !symbol.IsCanonical()) { option.SetFilter(universe => universe.Strikes(-10, +10)); } symbol = option.Symbol; } IEnumerable <Symbol> symbols; if (symbol.IsCanonical()) { // canonical symbol, lets find the contracts var option = Securities[symbol] as Option; var resolutionToUseForUnderlying = resolution ?? SubscriptionManager.SubscriptionDataConfigService .GetSubscriptionDataConfigs(symbol) .GetHighestResolution(); if (!Securities.ContainsKey(symbol.Underlying)) { if (symbol.Underlying.SecurityType == SecurityType.Equity) { // only add underlying if not present AddEquity(symbol.Underlying.Value, resolutionToUseForUnderlying); } if (symbol.Underlying.SecurityType == SecurityType.Future && symbol.Underlying.IsCanonical()) { AddFuture(symbol.Underlying.ID.Symbol, resolutionToUseForUnderlying); } else if (symbol.Underlying.SecurityType == SecurityType.Future) { AddFutureContract(symbol.Underlying, resolutionToUseForUnderlying); } } var allSymbols = new List <Symbol>(); for (var date = start; date < end; date = date.AddDays(1)) { if (option.Exchange.DateIsOpen(date)) { allSymbols.AddRange(OptionChainProvider.GetOptionContractList(symbol.Underlying, date)); } } var optionFilterUniverse = new OptionFilterUniverse(); var distinctSymbols = allSymbols.Distinct(); symbols = base.History(symbol.Underlying, start, end.Value, resolution) .SelectMany(x => { // the option chain symbols wont change so we can set 'exchangeDateChange' to false always optionFilterUniverse.Refresh(distinctSymbols, x, exchangeDateChange: false); return(option.ContractFilter.Filter(optionFilterUniverse)); }) .Distinct().Concat(new[] { symbol.Underlying }); } else { // the symbol is a contract symbols = new List <Symbol> { symbol }; } return(new OptionHistory(History(symbols, start, end.Value, resolution))); }
public void OnData(TradeBars data) { if (IsMarketOpen(iSymbol) == false) { return; } if (IsNewBar(TimeSpan.FromHours(1)) == false) { return; } var price = Securities[iSymbol].Price; // If options were exercised and we were assigned to buy shares, sell them immediately if (Portfolio[iSymbol].Invested) { MarketOrder(iSymbol, -100); } if (Portfolio.Invested == false) { var contracts = OptionChainProvider.GetOptionContractList(iSymbol, Time); // Choose all contracts within a month and strike price $1 to $5 from current underlying price var atmPuts = from c in contracts where c.ID.OptionRight == OptionRight.Put where price - c.ID.StrikePrice < 3 && price - c.ID.StrikePrice > 1 where (c.ID.Date - Time).TotalDays < 45 && (c.ID.Date - Time).TotalDays > 0 select c; // Choose all contracts within a month and strike price $1 to $5 from current underlying price var otmPuts = from c in contracts where c.ID.OptionRight == OptionRight.Put where price - c.ID.StrikePrice < 7 && price - c.ID.StrikePrice > 5 where (c.ID.Date - Time).TotalDays < 45 && (c.ID.Date - Time).TotalDays > 0 select c; // Take ATM options with the MIN expiration date and MAX distance from underlying price var contractAtmPut = atmPuts .OrderBy(o => o.ID.Date) .ThenBy(o => price - o.ID.StrikePrice) .FirstOrDefault(); // Take OTM options with the MIN expiration date and MAX distance from underlying price var contractOtmPut = otmPuts .OrderBy(o => o.ID.Date) .ThenBy(o => price - o.ID.StrikePrice) .FirstOrDefault(); // If we found such options - open trade if (contractAtmPut != null && contractOtmPut != null) { AddOptionContract(contractAtmPut, Resolution.Minute); AddOptionContract(contractOtmPut, Resolution.Minute); MarketOrder(contractAtmPut, -1); MarketOrder(contractOtmPut, 1); } } }