/// <summary> /// Converts a SecurityDefinition to a <see cref="Symbol" /> /// </summary> /// <param name="securityDefinition">Security definition</param> /// <param name="tradingDate"> /// The date that the stock was being traded. This is used to resolve /// the ticker that the stock was trading under on this date. /// </param> /// <returns>Symbol if matching Lean Symbol was found on the trading date, null otherwise</returns> private Symbol SecurityDefinitionToSymbol(SecurityDefinition securityDefinition, DateTime tradingDate) { if (securityDefinition == null) { return(null); } var mapFileResolver = _mapFileProvider.Get(AuxiliaryDataKey.Create(securityDefinition.SecurityIdentifier)); // Get the first ticker the symbol traded under, and then lookup the // trading date to get the ticker on the trading date. var mapFile = mapFileResolver .ResolveMapFile(securityDefinition.SecurityIdentifier.Symbol, securityDefinition.SecurityIdentifier.Date); // The mapped ticker will be null if the map file is null or there's // no entry found for the given trading date. var mappedTicker = mapFile?.GetMappedSymbol(tradingDate, null); // If we're null, then try again; get the last entry of the map file and use // it as the Symbol we return to the caller. mappedTicker ??= mapFile? .LastOrDefault()? .MappedSymbol; return(string.IsNullOrWhiteSpace(mappedTicker) ? null : new Symbol(securityDefinition.SecurityIdentifier, mappedTicker)); }
private string GetMappedTicker(Symbol symbol) { var ticker = symbol.ID.Symbol; if (symbol.ID.SecurityType == SecurityType.Equity) { var mapFile = _mapFileProvider.Get(AuxiliaryDataKey.Create(symbol)).ResolveMapFile(symbol); ticker = mapFile.GetMappedSymbol(DateTime.UtcNow, symbol.Value); } return(ticker); }
/// <summary> /// Gets the list of option contracts for a given underlying symbol /// </summary> /// <param name="symbol">The underlying symbol</param> /// <param name="date">The date for which to request the option chain (only used in backtesting)</param> /// <returns>The list of option contracts</returns> public virtual IEnumerable <Symbol> GetOptionContractList(Symbol symbol, DateTime date) { if (!symbol.SecurityType.HasOptions()) { if (symbol.SecurityType.IsOption() && symbol.Underlying != null) { // be user friendly and take the underlying symbol = symbol.Underlying; } else { throw new NotSupportedException($"BacktestingOptionChainProvider.GetOptionContractList(): " + $"{nameof(SecurityType.Equity)}, {nameof(SecurityType.Future)}, or {nameof(SecurityType.Index)} is expected but was {symbol.SecurityType}"); } } // Resolve any mapping before requesting option contract list for equities // Needs to be done in order for the data file key to be accurate Symbol mappedSymbol; if (symbol.RequiresMapping()) { var mapFileResolver = _mapFileProvider.Get(AuxiliaryDataKey.Create(symbol)); var mapFile = mapFileResolver.ResolveMapFile(symbol); var ticker = mapFile.GetMappedSymbol(date, symbol.Value); mappedSymbol = symbol.UpdateMappedSymbol(ticker); } else { mappedSymbol = symbol; } // create a canonical option symbol for the given underlying var canonicalSymbol = Symbol.CreateOption( mappedSymbol, mappedSymbol.ID.Market, mappedSymbol.SecurityType.DefaultOptionStyle(), default(OptionRight), 0, SecurityIdentifier.DefaultDate); return(GetSymbols(canonicalSymbol, date)); }
public MapFileResolver Get(AuxiliaryDataKey auxiliaryDataKey) { return(new TestMapFileResolver()); }
/// <summary> /// Gets the list of option contracts for a given underlying symbol /// </summary> /// <param name="underlyingSymbol">The underlying symbol</param> /// <param name="date">The date for which to request the option chain (only used in backtesting)</param> /// <returns>The list of option contracts</returns> public IEnumerable <Symbol> GetOptionContractList(Symbol underlyingSymbol, DateTime date) { if (!underlyingSymbol.SecurityType.HasOptions()) { throw new NotSupportedException($"BacktestingOptionChainProvider.GetOptionContractList(): SecurityType.Equity, SecurityType.Future, or SecurityType.Index is expected but was {underlyingSymbol.SecurityType}"); } // Resolve any mapping before requesting option contract list for equities // Needs to be done in order for the data file key to be accurate Symbol mappedSymbol; if (underlyingSymbol.RequiresMapping()) { var mapFileResolver = _mapFileProvider.Get(AuxiliaryDataKey.Create(underlyingSymbol)); var mapFile = mapFileResolver.ResolveMapFile(underlyingSymbol); var ticker = mapFile.GetMappedSymbol(date, underlyingSymbol.Value); mappedSymbol = underlyingSymbol.UpdateMappedSymbol(ticker); } else { mappedSymbol = underlyingSymbol; } // build the option contract list from the open interest zip file entry names // create a canonical option symbol for the given underlying var canonicalSymbol = Symbol.CreateOption( mappedSymbol, mappedSymbol.ID.Market, mappedSymbol.SecurityType.DefaultOptionStyle(), default(OptionRight), 0, SecurityIdentifier.DefaultDate); var zipFileName = string.Empty; Stream stream = null; // In order of trust-worthiness of containing the complete option chain, OpenInterest is guaranteed // to have the complete option chain. Quotes come after open-interest // because it's also likely to contain the option chain. Trades may be // missing portions of the option chain, so we resort to it last. foreach (var tickType in new[] { TickType.OpenInterest, TickType.Quote, TickType.Trade }) { // build the zip file name and fetch it with our provider zipFileName = LeanData.GenerateZipFilePath(Globals.DataFolder, canonicalSymbol, date, Resolution.Minute, tickType); stream = _dataProvider.Fetch(zipFileName); if (stream != null) { break; } } if (stream == null) { Log.Trace($"BacktestingOptionChainProvider.GetOptionContractList(): File not found: {zipFileName}"); yield break; } // generate and return the contract symbol for each zip entry var zipEntryNames = Compression.GetZipEntryFileNames(stream); foreach (var zipEntryName in zipEntryNames) { yield return(LeanData.ReadSymbolFromZipEntry(canonicalSymbol, Resolution.Minute, zipEntryName)); } stream.DisposeSafely(); }