/// <summary> /// Converts an InteractiveBrokers symbol to a Lean symbol instance /// </summary> /// <param name="brokerageSymbol">The InteractiveBrokers symbol</param> /// <param name="securityType">The security type</param> /// <param name="market">The market</param> /// <param name="expirationDate">Expiration date of the security(if applicable)</param> /// <param name="strike">The strike of the security (if applicable)</param> /// <param name="optionRight">The option right of the security (if applicable)</param> /// <returns>A new Lean Symbol instance</returns> public Symbol GetLeanSymbol(string brokerageSymbol, SecurityType securityType, string market, DateTime expirationDate = default(DateTime), decimal strike = 0, OptionRight optionRight = 0) { if (string.IsNullOrWhiteSpace(brokerageSymbol)) { throw new ArgumentException("Invalid symbol: " + brokerageSymbol); } if (securityType != SecurityType.Forex && securityType != SecurityType.Equity && securityType != SecurityType.Option && securityType != SecurityType.Future && securityType != SecurityType.FutureOption) { throw new ArgumentException("Invalid security type: " + securityType); } try { switch (securityType) { case SecurityType.Future: return(Symbol.CreateFuture(GetLeanRootSymbol(brokerageSymbol), market, expirationDate)); case SecurityType.Option: return(Symbol.CreateOption(brokerageSymbol, market, OptionStyle.American, optionRight, strike, expirationDate)); case SecurityType.FutureOption: var future = FuturesOptionsUnderlyingMapper.GetUnderlyingFutureFromFutureOption( GetLeanRootSymbol(brokerageSymbol), market, expirationDate, DateTime.Now); if (future == null) { // This is the worst case scenario, because we didn't find a matching futures contract for the FOP. // Note that this only applies to CBOT symbols for now. throw new ArgumentException($"The Future Option with expected underlying of {future} with expiry: {expirationDate:yyyy-MM-dd} has no matching underlying future contract."); } return(Symbol.CreateOption( future, market, OptionStyle.American, optionRight, strike, expirationDate)); case SecurityType.Equity: brokerageSymbol = brokerageSymbol.Replace(" ", "."); break; } return(Symbol.Create(brokerageSymbol, securityType, market)); } catch (Exception) { throw new ArgumentException($"Invalid symbol: {brokerageSymbol}, security type: {securityType}, market: {market}."); } }
public void GetUnderlyingSymbolFromFutureOption(string futureTicker, string market, int year, int month, int day, int fopContractYear, int fopContractMonth, bool nullExpected) { var optionTicker = FuturesOptionsSymbolMappings.Map(futureTicker); var expectedFuture = Symbol.CreateFuture(futureTicker, market, new DateTime(year, month, day)); var canonicalFutureOption = Symbol.CreateOption(expectedFuture, market, default(OptionStyle), default(OptionRight), default(decimal), SecurityIdentifier.DefaultDate); var futureContractMonthDelta = FuturesExpiryUtilityFunctions.GetDeltaBetweenContractMonthAndContractExpiry(futureTicker, expectedFuture.ID.Date); var futureContractMonth = expectedFuture.ID.Date.AddMonths(futureContractMonthDelta); var futuresOptionsExpiration = FuturesOptionsExpiryFunctions.FuturesOptionExpiry(canonicalFutureOption, futureContractMonth); var actualFuture = FuturesOptionsUnderlyingMapper.GetUnderlyingFutureFromFutureOption(optionTicker, market, futuresOptionsExpiration, new DateTime(2021, 1, 1)); if (nullExpected) { // There were no futures that appeared on the or subsequent contract months from the future option. Assert.IsNull(actualFuture); } else { Assert.AreEqual(expectedFuture, actualFuture); } }