Example #1
0
        public double GetProbabilityByPrice(double price)
        {
            int count = Prices.Count;

            int probabilityIndex = Prices.BinarySearch(price);

            if (probabilityIndex < 0)
            {
                int largerIndex  = ~probabilityIndex;
                int smallerIndex = largerIndex - 1;

                if (largerIndex == count)
                {
                    return(1 - Probabilities[count - 1]);
                }

                // Do linear interpolation
                double largerIdexProbability  = Probabilities[largerIndex];
                double smallerIdexProbability = Probabilities[smallerIndex];

                double resultProbability = MarketMath.DoLinearInterpolation(Prices[smallerIndex], Prices[largerIndex], smallerIdexProbability, largerIdexProbability, price);

                resultProbability = 1 - resultProbability;
                return(resultProbability);
            }

            double stdDevProbability = 1 - Probabilities[probabilityIndex];

            return(stdDevProbability);
        }
        public Prediction GetPrediction(IBasicPredictionCalculationData data, double daysInFuture)
        {
            double     volatility = data.GetVolatility(daysInFuture);
            Prediction prediction = MarketMath.GetSymmetricPrediction(data.LastPrice, volatility, data.InterestRate, daysInFuture);

            return(prediction);
        }
        public Dictionary <DateAndNumberOfDaysUntil, Prediction> MakePredictionsForDates(IBasicPredictionCalculationData data, IEnumerable <DateAndNumberOfDaysUntil> dates)
        {
            Dictionary <DateAndNumberOfDaysUntil, Prediction> predictions = new Dictionary <DateAndNumberOfDaysUntil, Prediction>();

            foreach (DateAndNumberOfDaysUntil date in dates)
            {
                double daysInFuture = date.TotalNumberOfDaysUntilExpiry;
                if (daysInFuture.AlmostEqual(0) || daysInFuture < 0)
                {
                    continue;
                }

                double     volatility = data.GetVolatility(daysInFuture);
                Prediction prediction = MarketMath.GetSymmetricPrediction(data.LastPrice, volatility, data.InterestRate, daysInFuture);
                predictions.Add(date, prediction);
            }

            return(predictions);
        }
Example #4
0
        public EntityResponse <List <OptionQuotation> > GetOptionQuotes(List <string> optionNumbers)
        {
            EntityResponse <List <OptionQuotation> > results = GetOptionQuotesByOptionNumbers(optionNumbers);

            if (!results.IsSuccess)
            {
                return(results);
            }

            foreach (OptionQuotation quote in results.Entity)
            {
                EntityResponse <OptionBasicInformation> basic = GetOptionInformation(quote.OptionNumber);
                if (basic.IsSuccess)
                {
                    quote.SecurityCode = basic.Entity.OptionUnderlyingCode;
                    decimal?stockPrice;
                    double  daysToMaturity = _marketWorkTimeService.GetNumberOfDaysLeftUntilExpiry(basic.Entity.ExpireDate).TotalNumberOfDaysUntilExpiry;

                    if (!MemoryCache.IsStockQuoteInfoCacheExpired(quote.SecurityCode))
                    {
                        stockPrice = MemoryCache.StockQuoteInfoCache[quote.SecurityCode].StockQuoteInfos.LastPrice;
                    }
                    else
                    {
                        var stockQuoteInfo = GetStockQuote(basic.Entity.OptionUnderlyingCode).Entity;
                        stockPrice = stockQuoteInfo.LastPrice;
                        MemoryCache.AddOrUpdateStockQuoteInfoCache(quote.SecurityCode, stockQuoteInfo);
                    }
                    //decimal? stockPrice = GetStockQuote(basic.Entity.OptionUnderlyingCode).Entity.LastPrice;
                    double spotPrice = 0;
                    if (stockPrice != null)
                    {
                        spotPrice = (double)stockPrice;
                    }
                    quote.Greeks = MarketMath.GetGreeks(daysToMaturity, (double)basic.Entity.StrikePrice,
                                                        _riskFreeRateProvider.GetRiskFreeRate(), spotPrice, quote.Ask, quote.Bid, quote.LatestTradedPrice,
                                                        basic.Entity.OptionType == OptionType.Call ? LegType.Call : LegType.Put);
                }
            }

            return(results);
        }
Example #5
0
        public void UpdateQuotation(IEnumerable <OptionQuotation> quotations)
        {
            foreach (OptionQuotation optionQuotation in quotations)
            {
                Option option = this[optionQuotation.OptionNumber];
                if (option != null)
                {
                    optionQuotation.SecurityCode = option.SecurityCode;
                    optionQuotation.OptionName   = option.OptionName;
                    optionQuotation.OptionCode   = option.OptionCode;

                    Mapper.Map(optionQuotation, option);
                    option.Name = optionQuotation.OptionName;

                    option.Greeks = MarketMath.GetGreeks(option.RootPair.Expiry.TotalNumberOfDaysUntilExpiry,
                                                         option.RootPair.StrikePrice, RiskFreeRate,
                                                         UnderlyingCurrentPrice, option.Ask, option.Bid, option.LatestTradedPrice, option.LegType);
                }
            }
        }
        private static List <CoveredCall> GetCoveredCallsByLegType(OptionChain data, Dictionary <DateAndNumberOfDaysUntil, Prediction> predictions,       /*EarningsCalendar calendar,*/
                                                                   LegType legType, /*Signal volOfVol,*/ double?minimumPremiumParam, double?minimumReturnParam)
        {
            double minimumPremium = minimumPremiumParam ?? DefaultMinimumPremium;
            double minimumReturn  = minimumReturnParam ?? DefaultMinimumReturn;

            HashSet <DateTime> optimalIsFound = new HashSet <DateTime>();
            List <CoveredCall> coveredCalls   = new List <CoveredCall>();

            foreach (OptionPair optionChain in data)
            {
                Option option = legType == LegType.Call
                                        ? optionChain.CallOption
                                        : optionChain.PutOption;

                double bid                      = option.Bid;
                double currentPremium           = bid;
                DateAndNumberOfDaysUntil expiry = optionChain.Expiry;
                double lastPrice                = data.UnderlyingCurrentPrice;
                double strkePrice               = optionChain.StrikePrice;

                List <OptionPair> chainsWithTheSameExpiry = data.Where(x => x.Expiry == expiry).ToList();

                // todo: optionChain.OptionType
                //bool typeisSuitable = optionChain.OptionType == OptionType.Standard;

                double daysQuantity = expiry.TotalNumberOfDaysUntilExpiry;

                // Ignore expired options
                if (daysQuantity < 0 || daysQuantity.AlmostEqual(0) /*|| !typeisSuitable*/)
                {
                    continue;
                }

                bool strikePriceIsSuitable = legType == LegType.Call
                                        ? optionChain.StrikePrice > lastPrice
                                        : optionChain.StrikePrice < lastPrice;

                if (!strikePriceIsSuitable)
                {
                    // Check if fifth strike is suitable
                    strikePriceIsSuitable = legType == LegType.Call
                                                ? chainsWithTheSameExpiry.Where(x => x.StrikePrice < lastPrice)
                                            .OrderBy(x => lastPrice - x.StrikePrice)
                                            .Take(5).Last().StrikePrice <optionChain.StrikePrice
                                                                         : chainsWithTheSameExpiry.Where(x => x.StrikePrice > lastPrice)
                                                                         .OrderBy(x => x.StrikePrice - lastPrice)
                                                                         .Take(5).Last().StrikePrice> optionChain.StrikePrice;
                }

                if (!strikePriceIsSuitable)
                {
                    continue;
                }

                double intrinsicValue = legType == LegType.Call
                                        ? lastPrice > optionChain.StrikePrice ? lastPrice - optionChain.StrikePrice : 0
                                        : lastPrice < optionChain.StrikePrice ? optionChain.StrikePrice - lastPrice : 0;

                double currentReturn = (Math.Pow(1 + (currentPremium - intrinsicValue) / lastPrice, 365.0 / daysQuantity) - 1) * 100;

                bool firstAboveBelowStdDev = false;

                Prediction   prediction = predictions[optionChain.Expiry];
                StdDevPrices stdDev     = prediction.GetStdDevPrices(1);

                bool deviationIsSuitable = legType == LegType.Call
                                        ? strkePrice > stdDev.UpPrice
                                        : strkePrice < stdDev.DownPrice;
                if (deviationIsSuitable)
                {
                    firstAboveBelowStdDev = legType == LegType.Call
                                                ? chainsWithTheSameExpiry
                                            .Where(x => x.StrikePrice >= stdDev.UpPrice)
                                            .Select(y => y.StrikePrice - stdDev.UpPrice)
                                            .Min()
                                            .AlmostEqual(strkePrice - stdDev.UpPrice)
                                                : chainsWithTheSameExpiry
                                            .Where(x => x.StrikePrice <= stdDev.DownPrice)
                                            .Select(y => stdDev.DownPrice - y.StrikePrice)
                                            .Min()
                                            .AlmostEqual(stdDev.DownPrice - optionChain.StrikePrice);
                }

                double      probability         = prediction.GetProbabilityByPrice(optionChain.StrikePrice) * 100;
                double      probabilityInSigmas = MarketMath.GetSigmaProbabilityByDeviation(probability / 100);
                CoveredCall coveredCall         = new CoveredCall();

                coveredCall.Premium = currentPremium;
                coveredCall.Return  = currentReturn;

                coveredCall.OptionNumber        = option.OptionNumber;
                coveredCall.Probability         = probability;
                coveredCall.ProbabilityInSigmas = probabilityInSigmas;

//				if (volOfVol != null)
//				{
//					coveredCall.VolOfVol = volOfVol.Value;
//				}
                coveredCall.PercentAboveBelowCurrentPrice = Math.Abs((optionChain.StrikePrice - lastPrice)) / lastPrice * 100;

                int numberOfStrikes = legType == LegType.Call
                                        ? chainsWithTheSameExpiry.Where(x => x.StrikePrice >= lastPrice)
                                      .OrderBy(x => x.StrikePrice)
                                      .ToList()
                                      .FindIndex(x => x.StrikePrice.AlmostEqual(optionChain.StrikePrice)) + 1
                                        : chainsWithTheSameExpiry.Where(x => x.StrikePrice <= lastPrice)
                                      .OrderByDescending(x => x.StrikePrice)
                                      .ToList()
                                      .FindIndex(x => x.StrikePrice.AlmostEqual(optionChain.StrikePrice)) + 1;

                coveredCall.NumberOfStrikesBelowAboveCurrentPrice = numberOfStrikes;
                coveredCall.NumberOfSdBelowAboveCurrentPrice      = probabilityInSigmas;

//				coveredCall.HasEarnings = calendar != null && calendar.Date >= DateTime.Now && calendar.Date <= optionChain.Expiry;
//				if (calendar != null)
//				{
//					coveredCall.DaysQuantityBeforeEarnings = (calendar.Date - DateTime.UtcNow).TotalDays;
//				}

                coveredCalls.Add(coveredCall);

                if (bid.AlmostEqual(0.0))
                {
                    coveredCall.RiskTolerance = RiskTolerance.NoBid;
                    continue;
                }

                if (!deviationIsSuitable)
                {
                    if (currentPremium < minimumPremium)
                    {
                        coveredCall.RiskTolerance = RiskTolerance.LowPremium;
                        continue;
                    }

                    coveredCall.RiskTolerance = currentReturn >= minimumReturn
                                                ? RiskTolerance.Aggressive
                                                : RiskTolerance.LowReturn;
                    continue;
                }

                if (currentPremium < minimumPremium)
                {
                    coveredCall.RiskTolerance = RiskTolerance.LowPremium;
                    continue;
                }

                if (currentReturn < minimumReturn)
                {
                    coveredCall.RiskTolerance = RiskTolerance.LowReturn;
                    continue;
                }

                if (!optimalIsFound.Contains(optionChain.Expiry.FutureDate) &&
                    daysQuantity >= 3 &&
                    daysQuantity <= 60
                    //&& (!coveredCall.HasEarnings || daysQuantity < coveredCall.DaysQuantityBeforeEarnings)
                    && firstAboveBelowStdDev)
                {
                    coveredCall.RiskTolerance = RiskTolerance.Optimal;
                    optimalIsFound.Add(optionChain.Expiry.FutureDate);
                }
                else
                {
                    coveredCall.RiskTolerance = RiskTolerance.Conservative;
                }
            }
            return(coveredCalls);
        }