public async Task <IActionResult> GetStockIndexComparisonForUserHoldings(ulong userId)
        {
            try
            {
                var tickers = IndexTickers.GetAllowedIndexTickers();
                var stockIndexComparison = await _stockIndexComparisonService.GetComparisonWithIndex(userId, tickers);

                return(Ok(stockIndexComparison));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public async Task <TotalValueComparisonToIndex> GetTotalValueComparison(ulong userId,
                                                                                IEnumerable <string> indexTickers,
                                                                                DateTime from,
                                                                                DateTime to)
        {
            var valueComparisons = await _stockIndexComparisonService.GetComparisonWithIndex(userId, indexTickers, from, to);

            var totalValueComparison = new TotalValueComparisonToIndex();

            totalValueComparison.IndexGainOrLossMap            = new Dictionary <string, decimal>();
            totalValueComparison.IndexTotalCurrentPriceMap     = new Dictionary <string, decimal>();
            totalValueComparison.IndexTotalPurchasePriceMap    = new Dictionary <string, decimal>();
            totalValueComparison.IndexTotalReturnPercentageMap = new Dictionary <string, decimal>();
            foreach (var comparison in valueComparisons)
            {
                totalValueComparison.TotalGainOrLoss    += decimal.Round(comparison.TotalPriceDifference, 2, MidpointRounding.AwayFromZero);
                totalValueComparison.TotalCurrentPrice  += decimal.Round(comparison.TotalCurrentPrice, 2, MidpointRounding.AwayFromZero);
                totalValueComparison.TotalPurchasePrice += decimal.Round(comparison.TotalPurchasePrice, 2, MidpointRounding.AwayFromZero);

                foreach (var indexDifference in comparison.IndexesDifference)
                {
                    if (!totalValueComparison.IndexGainOrLossMap.ContainsKey(indexDifference.IndexTicker))
                    {
                        totalValueComparison.IndexGainOrLossMap[indexDifference.IndexTicker]         = decimal.Round(indexDifference.TotalPriceDifference, 2, MidpointRounding.AwayFromZero);
                        totalValueComparison.IndexTotalCurrentPriceMap[indexDifference.IndexTicker]  = decimal.Round(indexDifference.TotalCurrentPrice, 2, MidpointRounding.AwayFromZero);
                        totalValueComparison.IndexTotalPurchasePriceMap[indexDifference.IndexTicker] = decimal.Round(indexDifference.TotalPurchasePrice, 2, MidpointRounding.AwayFromZero);
                    }
                    else
                    {
                        totalValueComparison.IndexGainOrLossMap[indexDifference.IndexTicker]         += decimal.Round(indexDifference.TotalPriceDifference, 2, MidpointRounding.AwayFromZero);
                        totalValueComparison.IndexTotalCurrentPriceMap[indexDifference.IndexTicker]  += decimal.Round(indexDifference.TotalCurrentPrice, 2, MidpointRounding.AwayFromZero);
                        totalValueComparison.IndexTotalPurchasePriceMap[indexDifference.IndexTicker] += decimal.Round(indexDifference.TotalPurchasePrice, 2, MidpointRounding.AwayFromZero);
                    }
                }
            }

            foreach (var indexTicker in totalValueComparison.IndexTotalPurchasePriceMap.Keys)
            {
                if (totalValueComparison.IndexTotalCurrentPriceMap.ContainsKey(indexTicker))
                {
                    totalValueComparison.IndexTotalReturnPercentageMap[indexTicker] = decimal.Round(((totalValueComparison.IndexTotalCurrentPriceMap[indexTicker] - totalValueComparison.IndexTotalPurchasePriceMap[indexTicker]) / totalValueComparison.IndexTotalPurchasePriceMap[indexTicker]) * 100, 2, MidpointRounding.AwayFromZero);
                }
            }

            totalValueComparison.ReturnPercentage = decimal.Round(((totalValueComparison.TotalCurrentPrice - totalValueComparison.TotalPurchasePrice) / totalValueComparison.TotalPurchasePrice) * 100, 2, MidpointRounding.AwayFromZero);

            return(totalValueComparison);
        }
        public async Task <IEnumerable <IndividualStockReturn> > GetIndividualComparisonService(ulong userId)
        {
            var indexTickers = IndexTickers.GetAllowedIndexTickers();
            var comparisons  = await _stockIndexComparisonService.GetComparisonWithIndex(userId, indexTickers);

            var recommendationTask = _compositionAndRecommendationService.GetAnalystRecommendation(comparisons.Select(x => x.Ticker));
            var stockReturn        = new Dictionary <string, IndividualStockReturn>();
            var totalPorfolioValue = 0.0m;
            var totalInvestment    = 0.0m;
            var individualReturns  = new List <IndividualStockReturn>();

            foreach (var comparison in comparisons)
            {
                totalPorfolioValue += comparison.TotalCurrentPrice;
                totalInvestment    += comparison.TotalPurchasePrice;
                if (stockReturn.ContainsKey(comparison.Ticker))
                {
                    var returnDetails = stockReturn[comparison.Ticker];
                    returnDetails.TotalInvestedAmount += comparison.TotalPurchasePrice;
                    returnDetails.TotalCurrentValue   += comparison.TotalCurrentPrice;
                    foreach (var indexValue in comparison.IndexesDifference)
                    {
                        var indexComparison = returnDetails.IndexReturns[indexValue.IndexTicker];
                        indexComparison.TotalCurrentValue += indexValue.TotalCurrentPrice;
                    }
                }
                else
                {
                    var returnDetails = new IndividualStockReturn();
                    returnDetails.Ticker = comparison.Ticker;
                    returnDetails.TotalInvestedAmount = comparison.TotalPurchasePrice;
                    returnDetails.TotalCurrentValue   = comparison.TotalCurrentPrice;
                    var indexReturns = new Dictionary <string, IndexReturn>();
                    foreach (var indexValue in comparison.IndexesDifference)
                    {
                        var indexReturn = new IndexReturn();
                        indexReturn.IndexTicker              = indexValue.IndexTicker;
                        indexReturn.TotalCurrentValue        = indexValue.TotalCurrentPrice;
                        indexReturn.TotalReturnPercentage    = ((indexValue.TotalCurrentPrice - indexValue.TotalPurchasePrice) / indexValue.TotalPurchasePrice * 100).RoundDecimal();
                        indexReturns[indexValue.IndexTicker] = indexReturn;
                    }
                    returnDetails.IndexReturns     = indexReturns;
                    stockReturn[comparison.Ticker] = returnDetails;
                }
            }
            var recommendation = await recommendationTask;

            foreach (var entry in stockReturn.Values)
            {
                entry.TotalReturnPercentage      = Decimal.Round(((entry.TotalCurrentValue - entry.TotalInvestedAmount) / entry.TotalInvestedAmount) * 100, 2);
                entry.PercentageOfPortfolio      = Decimal.Round((entry.TotalCurrentValue / totalPorfolioValue) * 100, 2);
                entry.PercentageOfInvestedAmount = Decimal.Round((entry.TotalInvestedAmount / totalInvestment) * 100, 2);
                var maxIndexGain           = GetBiggestIndexGain(entry.IndexReturns.Values);
                var maxIndexGainPercentage = GetBiggestIndexGainPercentage(maxIndexGain, entry.TotalInvestedAmount);
                entry.DifferenceFromBiggestIndexGain = entry.TotalReturnPercentage - maxIndexGainPercentage;
                if (recommendation.ContainsKey(entry.Ticker))
                {
                    entry.DifferenceFromMedianPriceTargetPercentage = recommendation[entry.Ticker].DifferenceFromMedianPercentage;
                    entry.DifferenceFromFifyTwoWeekHighPercentage   = recommendation[entry.Ticker].DecreaseFromFiftyTwoWeekHighPercentage;
                }
                individualReturns.Add(entry);
            }

            return(individualReturns.OrderByDescending(x => x.DifferenceFromBiggestIndexGain));
        }