Example #1
0
        /// <summary>
        /// Gets the FOP's underlying Future. The underlying Future's contract month might not match
        /// the contract month of the Future Option when providing CBOT or COMEX based FOPs contracts to this method.
        /// </summary>
        /// <param name="futureOptionTicker">Future option ticker</param>
        /// <param name="market">Market of the Future Option</param>
        /// <param name="futureOptionExpiration">Expiration date of the future option</param>
        /// <param name="date">Date to search the future chain provider with. Optional, but required for CBOT based contracts</param>
        /// <returns>Symbol if there is an underlying for the FOP, null if there's no underlying found for the Future Option</returns>
        public static Symbol GetUnderlyingFutureFromFutureOption(string futureOptionTicker, string market, DateTime futureOptionExpiration, DateTime?date = null)
        {
            var futureTicker    = FuturesOptionsSymbolMappings.MapFromOption(futureOptionTicker);
            var canonicalFuture = Symbol.Create(futureTicker, SecurityType.Future, market);
            // Get the contract month of the FOP to use when searching for the underlying.
            // If the FOP and Future share the same contract month, this is reused as the future's
            // contract month so that we can resolve the Future's expiry.
            var contractMonth = GetFutureContractMonthNoRulesApplied(canonicalFuture, futureOptionExpiration);

            if (_underlyingFuturesOptionsRules.ContainsKey(futureTicker))
            {
                // The provided ticker follows some sort of rule. Let's figure out the underlying's contract month.
                var newFutureContractMonth = _underlyingFuturesOptionsRules[futureTicker](contractMonth, date);
                if (newFutureContractMonth == null)
                {
                    // This will only happen when we search the Futures chain for a given contract and no
                    // closest match could be made, i.e. there are no futures in the chain that come after the FOP's
                    // contract month.
                    return(null);
                }

                contractMonth = newFutureContractMonth.Value;
            }

            var futureExpiry = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture)(contractMonth);

            return(Symbol.CreateFuture(futureTicker, market, futureExpiry));
        }
Example #2
0
        /// <summary>
        /// Gets the entry for the specified market/symbol/security-type
        /// </summary>
        /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param>
        /// <param name="symbol">The particular symbol being traded</param>
        /// <param name="securityType">The security type of the symbol</param>
        /// <returns>The entry matching the specified market/symbol/security-type</returns>
        public virtual Entry GetEntry(string market, string symbol, SecurityType securityType)
        {
            Entry entry;

            // Fall back on the Futures MHDB entry if the FOP lookup failed.
            // Some FOPs have the same symbol properties as their futures counterparts.
            // So, to save ourselves some space, we can fall back on the existing entries
            // so that we don't duplicate the information.
            if (!TryGetEntry(market, symbol, securityType, out entry) &&
                !(securityType == SecurityType.FutureOption && TryGetEntry(market, FuturesOptionsSymbolMappings.MapFromOption(symbol), SecurityType.Future, out entry)))
            {
                var key  = new SecurityDatabaseKey(market, symbol, securityType);
                var keys = string.Join(", ", _entries.Keys);
                Log.Error($"MarketHoursDatabase.GetExchangeHours(): Unable to locate exchange hours for {key}.Available keys: {keys}");

                if (securityType == SecurityType.Future && market == Market.USA)
                {
                    var exception =
                        "Future.Usa market type is no longer supported as we mapped each ticker to its actual exchange. " +
                        "Please find your specific market in the symbol-properties database.";
                    if (SymbolPropertiesDatabase.FromDataFolder().TryGetMarket(symbol, SecurityType.Future, out market))
                    {
                        // let's suggest a market
                        exception += $" Suggested market based on the provided ticker 'Market.{market.ToUpperInvariant()}'.";
                    }

                    throw new ArgumentException(exception);
                }
                // there was nothing that really matched exactly
                throw new ArgumentException($"Unable to locate exchange hours for {key}");
            }

            return(entry);
        }
Example #3
0
 /// <summary>
 /// Tries to get the entry for the specified market/symbol/security-type
 /// </summary>
 /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param>
 /// <param name="symbol">The particular symbol being traded</param>
 /// <param name="securityType">The security type of the symbol</param>
 /// <param name="entry">The entry found if any</param>
 /// <returns>True if the entry was present, else false</returns>
 public bool TryGetEntry(string market, string symbol, SecurityType securityType, out Entry entry)
 {
     return(_entries.TryGetValue(new SecurityDatabaseKey(market, symbol, securityType), out entry)
            // now check with null symbol key
            || _entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out entry)
            // if FOP check for future
            || securityType == SecurityType.FutureOption && TryGetEntry(market,
                                                                        FuturesOptionsSymbolMappings.MapFromOption(symbol), SecurityType.Future, out entry)
            // if custom data type check for type specific entry
            || (securityType == SecurityType.Base && symbol.TryGetCustomDataType(out var customType) &&
                _entries.TryGetValue(new SecurityDatabaseKey(market, $"TYPE.{customType}", securityType), out entry)));
 }
Example #4
0
        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);
            }
        }
Example #5
0
        /// <summary>
        /// Generic generate method. This method should be used carefully as some parameters are not required and
        /// some parameters mean different things for different security types
        /// </summary>
        private static SecurityIdentifier Generate(DateTime date,
                                                   string symbol,
                                                   SecurityType securityType,
                                                   string market,
                                                   decimal strike                = 0,
                                                   OptionRight optionRight       = 0,
                                                   OptionStyle optionStyle       = 0,
                                                   SecurityIdentifier underlying = null,
                                                   bool forceSymbolToUpper       = true)
        {
            if ((ulong)securityType >= SecurityTypeWidth || securityType < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(securityType), "securityType must be between 0 and 99");
            }
            if ((int)optionRight > 1 || optionRight < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(optionRight), "optionType must be either 0 or 1");
            }

            // normalize input strings
            market = market.ToLowerInvariant();
            symbol = forceSymbolToUpper ? symbol.LazyToUpper() : symbol;

            if (securityType == SecurityType.FutureOption)
            {
                // Futures options tickers might not match, so we need
                // to map the provided future Symbol to the actual future option Symbol.
                symbol = FuturesOptionsSymbolMappings.Map(symbol);
            }

            var marketIdentifier = QuantConnect.Market.Encode(market);

            if (!marketIdentifier.HasValue)
            {
                throw new ArgumentOutOfRangeException(nameof(market), "The specified market wasn't found in the  markets lookup. " +
                                                      $"Requested: {market}. You can add markets by calling QuantConnect.Market.AddMarket(string,ushort)"
                                                      );
            }

            var days       = (ulong)date.ToOADate() * DaysOffset;
            var marketCode = (ulong)marketIdentifier * MarketOffset;

            ulong strikeScale;
            var   strk = NormalizeStrike(strike, out strikeScale) * StrikeOffset;

            strikeScale *= StrikeScaleOffset;
            var style   = (ulong)optionStyle * OptionStyleOffset;
            var putcall = (ulong)optionRight * PutCallOffset;

            var otherData = putcall + days + style + strk + strikeScale + marketCode + (ulong)securityType;

            var result = new SecurityIdentifier(symbol, otherData, underlying ?? Empty);

            // we already have these so lets set them
            switch (securityType)
            {
            case SecurityType.Base:
            case SecurityType.Equity:
            case SecurityType.Future:
                result._date = date;
                break;

            case SecurityType.Option:
            case SecurityType.FutureOption:
                result._date        = date;
                result._strikePrice = strike;
                result._optionRight = optionRight;
                result._optionStyle = optionStyle;
                break;
            }
            return(result);
        }
        /// <summary>
        /// Parses the specified path into a new instance of the <see cref="LeanDataPathComponents"/> class
        /// </summary>
        /// <param name="path">The path to be parsed</param>
        /// <returns>A new instance of the <see cref="LeanDataPathComponents"/> class representing the specified path</returns>
        public static LeanDataPathComponents Parse(string path)
        {
            //"../Data/equity/usa/hour/spy.zip"
            //"../Data/equity/usa/hour/spy/20160218_trade.zip"
            var fileinfo = new FileInfo(path);
            var filename = fileinfo.Name;
            var parts    = path.Split('/', '\\');

            // defines the offsets of the security relative to the end of the path
            const int LowResSecurityTypeOffset  = 4;
            const int HighResSecurityTypeOffset = 5;

            // defines other offsets relative to the beginning of the substring produce by the above offsets
            const int MarketOffset     = 1;
            const int ResolutionOffset = 2;
            const int TickerOffset     = 3;


            if (parts.Length < LowResSecurityTypeOffset)
            {
                throw new FormatException($"Unexpected path format: {path}");
            }

            var          securityTypeOffset = LowResSecurityTypeOffset;
            SecurityType securityType;
            var          rawValue = parts[parts.Length - securityTypeOffset];

            if (!Enum.TryParse(rawValue, true, out securityType))
            {
                securityTypeOffset = HighResSecurityTypeOffset;
                rawValue           = parts[parts.Length - securityTypeOffset];
                if (!Enum.TryParse(rawValue, true, out securityType))
                {
                    throw new FormatException($"Unexpected path format: {path}");
                }
            }

            var    market     = parts[parts.Length - securityTypeOffset + MarketOffset];
            var    resolution = (Resolution)Enum.Parse(typeof(Resolution), parts[parts.Length - securityTypeOffset + ResolutionOffset], true);
            string ticker;

            if (securityTypeOffset == LowResSecurityTypeOffset)
            {
                ticker = Path.GetFileNameWithoutExtension(path);
                if (securityType == SecurityType.Option || securityType == SecurityType.FutureOption)
                {
                    // ticker_trade_american
                    var tickerWithoutStyle = ticker.Substring(0, ticker.LastIndexOfInvariant("_"));
                    ticker = tickerWithoutStyle.Substring(0, tickerWithoutStyle.LastIndexOfInvariant("_"));
                }
                if (securityType == SecurityType.Future)
                {
                    // ticker_trade
                    ticker = ticker.Substring(0, ticker.LastIndexOfInvariant("_"));
                }
                if (securityType == SecurityType.Crypto &&
                    (resolution == Resolution.Daily || resolution == Resolution.Hour))
                {
                    // ticker_trade or ticker_quote
                    ticker = ticker.Substring(0, ticker.LastIndexOfInvariant("_"));
                }
            }
            else
            {
                ticker = parts[parts.Length - securityTypeOffset + TickerOffset];
            }

            var date = securityTypeOffset == LowResSecurityTypeOffset ? DateTime.MinValue : DateTime.ParseExact(filename.Substring(0, filename.IndexOf("_", StringComparison.Ordinal)), DateFormat.EightCharacter, null);

            Symbol symbol;

            if (securityType == SecurityType.Option)
            {
                var withoutExtension = Path.GetFileNameWithoutExtension(filename);
                rawValue = withoutExtension.Substring(withoutExtension.LastIndexOf("_", StringComparison.Ordinal) + 1);
                var style = (OptionStyle)Enum.Parse(typeof(OptionStyle), rawValue, true);
                symbol = Symbol.CreateOption(ticker, market, style, OptionRight.Call | OptionRight.Put, 0, SecurityIdentifier.DefaultDate);
            }
            else if (securityType == SecurityType.FutureOption)
            {
                var withoutExtension = Path.GetFileNameWithoutExtension(filename);
                rawValue = withoutExtension.Substring(withoutExtension.LastIndexOf("_", StringComparison.Ordinal) + 1);
                var style        = (OptionStyle)Enum.Parse(typeof(OptionStyle), rawValue, true);
                var futureSymbol = QuantConnect.Symbol.Create(FuturesOptionsSymbolMappings.MapFromOption(ticker), SecurityType.Future, market);
                symbol = Symbol.CreateOption(futureSymbol, market, style, OptionRight.Call | OptionRight.Put, 0, SecurityIdentifier.DefaultDate);
            }
            else if (securityType == SecurityType.Future)
            {
                symbol = Symbol.CreateFuture(ticker, market, SecurityIdentifier.DefaultDate);
            }
            else
            {
                symbol = Symbol.Create(ticker, securityType, market);
            }

            var tickType = filename.Contains("_quote") ? TickType.Quote : (filename.Contains("_openinterest") ? TickType.OpenInterest : TickType.Trade);

            return(new LeanDataPathComponents(securityType, market, resolution, symbol, filename, date, tickType));
        }
Example #7
0
        /// <summary>
        /// Creates a future option Symbol from the provided ticker
        /// </summary>
        /// <param name="ticker">The future option ticker, for example 'ESZ0 P3590'</param>
        /// <param name="strikeScale">Optional the future option strike scale factor</param>
        public static Symbol ParseFutureOptionSymbol(string ticker, int strikeScale = 1)
        {
            var split = ticker.Split(' ');

            if (split.Length != 2)
            {
                return(null);
            }

            var parsed = ParseFutureTicker(split[0]);

            if (parsed == null)
            {
                return(null);
            }
            ticker = parsed.Underlying;

            OptionRight right;

            if (split[1][0] == 'P' || split[1][0] == 'p')
            {
                right = OptionRight.Put;
            }
            else if (split[1][0] == 'C' || split[1][0] == 'c')
            {
                right = OptionRight.Call;
            }
            else
            {
                return(null);
            }
            var strike = split[1].Substring(1);

            if (parsed.ExpirationYearShort < 10)
            {
                parsed.ExpirationYearShort += 20;
            }
            var expirationYearParsed = 2000 + parsed.ExpirationYearShort;

            var expirationDate = new DateTime(expirationYearParsed, parsed.ExpirationMonth, 1);

            var strikePrice  = decimal.Parse(strike, NumberStyles.Any, CultureInfo.InvariantCulture);
            var futureTicker = FuturesOptionsSymbolMappings.MapFromOption(ticker);

            if (!SymbolPropertiesDatabase.FromDataFolder().TryGetMarket(futureTicker, SecurityType.Future, out var market))
            {
                Log.Debug($"SymbolRepresentation.ParseFutureOptionSymbol(): No market found for '{futureTicker}'");
                return(null);
            }

            var canonicalFuture = Symbol.Create(futureTicker, SecurityType.Future, market);
            var futureExpiry    = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalFuture)(expirationDate);
            var future          = Symbol.CreateFuture(futureTicker, market, futureExpiry);

            var futureOptionExpiry = FuturesOptionsExpiryFunctions.GetFutureOptionExpiryFromFutureExpiry(future);

            return(Symbol.CreateOption(future,
                                       market,
                                       OptionStyle.American,
                                       right,
                                       strikePrice / strikeScale,
                                       futureOptionExpiry));
        }