Ejemplo n.º 1
0
        public EntityResponse <OptionChain> GetOptionChain(string underlying)
        {
            EntityResponse <StockQuoteInfo> stockQuote = GetStockQuote(underlying);

            if (!stockQuote.IsSuccess)
            {
                return(EntityResponse <OptionChain> .Error(stockQuote));
            }

            EntityResponse <List <OptionBasicInformation> > optionBasicInformationResponse = _marketDataProvider.GetOptionBasicInformation(underlying);

            if (!optionBasicInformationResponse.IsSuccess)
            {
                return(EntityResponse <OptionChain> .Error(optionBasicInformationResponse));
            }

            double interestRate = _riskFreeRateProvider.GetRiskFreeRate();

            decimal spotPrice = stockQuote.Entity.LastPrice == 0
                ? (stockQuote.Entity.PreviousClose ?? 0)
                : (stockQuote.Entity.LastPrice ?? 0);

            //filtering OptionBasicInformation and get all not expired
            DateTime nowInmarketTimeZone = _marketWorkTimeService.NowInMarketTimeZone.Date;
            List <OptionBasicInformation> optionsBasicInformation = optionBasicInformationResponse.Entity
                                                                    .Where(item => item.ExpireDate.Date >= nowInmarketTimeZone.Date)
                                                                    .ToList();

            List <string> optionNumbers = optionsBasicInformation.Select(item => item.OptionNumber).Distinct().ToList();

            EntityResponse <List <OptionQuotation> > optionQuotesResponse = GetOptionQuotesByOptionNumbers(optionNumbers);

            if (!optionQuotesResponse.IsSuccess)
            {
                return(EntityResponse <OptionChain> .Error(optionQuotesResponse));
            }

            // To filter the optionBasicInformation
            Dictionary <string, OptionQuotation> optionQuotesDict = new Dictionary <string, OptionQuotation>();

            foreach (OptionQuotation itemOptionQuotation in optionQuotesResponse.Entity)
            {
                optionQuotesDict.Add(itemOptionQuotation.OptionNumber, itemOptionQuotation);
            }

            if (!MemoryCache.IsOptionChainCacheExpired(underlying))
            {
                // memory cache working.
                MemoryCache.OptionChainCache[underlying].OptionChains.UpdateQuotation((double)spotPrice, interestRate, optionQuotesResponse.Entity);
                return(MemoryCache.OptionChainCache[underlying].OptionChains);
            }

            // todo: 4 requests here. Big problem with performance

            SecurityInformationCache securityInfo = _marketDataProvider
                                                    .GetAllSecuritiesInformation().FirstOrDefault(s => s.SecurityCode == underlying);

            if (securityInfo == null)
            {
                return(ErrorCode.SZKingdomLibraryNoRecords);
            }

            HashSet <OptionPair> chains = new HashSet <OptionPair>();

            foreach (OptionBasicInformation optionBasicInformation in optionsBasicInformation)
            {
                // Filter the option if the quotation of the specified options cannot be found
                if (!optionQuotesDict.ContainsKey(optionBasicInformation.OptionNumber))
                {
                    continue;
                }

                DateAndNumberOfDaysUntil expiry = _marketWorkTimeService
                                                  .GetNumberOfDaysLeftUntilExpiry(optionBasicInformation.ExpireDate);

                OptionPair pair = new OptionPair
                {
                    Expiry            = expiry,
                    StrikePrice       = (double)optionBasicInformation.StrikePrice,
                    PremiumMultiplier = optionBasicInformation.OptionUnit,
                    SecurityCode      = optionBasicInformation.OptionUnderlyingCode,
                    SecurityName      = optionBasicInformation.OptionUnderlyingName
                };

                if (!chains.Contains(pair))
                {
                    chains.Add(pair);
                }
                else
                {
                    pair = chains.Single(c => c.Equals(pair));
                }

                Option op = new Option(pair, optionBasicInformation.OptionNumber, optionBasicInformation.OptionCode)
                {
                    Name          = optionBasicInformation.OptionName,
                    OptionName    = optionBasicInformation.OptionName,
                    OpenInterest  = optionBasicInformation.UncoveredPositionQuantity,
                    SecurityCode  = optionBasicInformation.OptionUnderlyingCode,
                    PreviousClose = (double)optionBasicInformation.PreviousClosingPrice,
                    Greeks        = new Greeks()
                };
                if (optionBasicInformation.OptionType == OptionType.Call)
                {
                    op.LegType      = LegType.Call;
                    pair.CallOption = op;
                }
                else
                {
                    op.LegType     = LegType.Put;
                    pair.PutOption = op;
                }
            }

            OptionChain chain = new OptionChain(chains, (double)spotPrice, interestRate, optionQuotesResponse.Entity);

            MemoryCache.AddOrUpdateOptionChainCache(underlying, chain);
            return(chain);
        }