Ejemplo n.º 1
0
        public void SetAdvisorRankingAndProfit()
        {
            var                      advisors            = AdvisorBusiness.ListAllAdvisors().Select(c => c.Id).Distinct().ToList();
            List <Order>             orders              = null;
            List <AssetCurrentValue> assetsCurrentValues = null;
            List <Order>             finishedOrders      = null;
            var                      now = Data.GetDateTimeNow();

            Parallel.Invoke(() => orders = OrderBusiness.ListOrdersForRankingProfitCalculation(advisors),
                            () => assetsCurrentValues = AssetCurrentValueBusiness.ListAllAssets(true),
                            () => finishedOrders      = OrderBusiness.ListOrders(advisors, null, new OrderStatusType[] { OrderStatusType.Finished }));

            var assetsBidValues             = assetsCurrentValues.ToDictionary(c => c.Id, c => c.BidValue);
            var assetsAskValues             = assetsCurrentValues.ToDictionary(c => c.Id, c => c.AskValue);
            var groupedOrders               = orders.GroupBy(c => c.UserId).ToDictionary(c => c.Key, c => c.ToList());
            var advisorRankingAndProfitData = new Dictionary <int, AdvisorRankingAndProfitData>();

            foreach (var advisorOrders in groupedOrders)
            {
                advisorRankingAndProfitData[advisorOrders.Key] = GetAdvisorRankingAndProfitData(now, advisorOrders.Value, assetsBidValues, assetsAskValues);
            }

            var totalCount = advisorRankingAndProfitData.Sum(c => c.Value.OrderCount);

            if (totalCount == 0)
            {
                return;
            }

            var totalWeight        = advisorRankingAndProfitData.Sum(c => c.Value.RankingWeight);
            var generalAvg         = totalWeight != 0 ? advisorRankingAndProfitData.Sum(c => c.Value.RankingWeightedProfit) / totalWeight : 0;
            var weightedStdDivisor = totalWeight * (totalCount - 1) / totalCount;
            var consideredAdvisors = advisorRankingAndProfitData.Where(c => c.Value.RankingWeight != 0 && c.Value.OrderCount > 0);

            double weightedStd = 0;

            if (weightedStdDivisor != 0)
            {
                weightedStd = Math.Sqrt(consideredAdvisors
                                        .Sum(c => (Math.Pow((c.Value.RankingWeightedProfit / c.Value.RankingWeight) - generalAvg, 2) * c.Value.RankingWeight) / weightedStdDivisor));
            }

            var z    = new Dictionary <int, double>();
            var minZ = 0.0;
            var normalizationDivisor = 1.0;

            if (weightedStd != 0)
            {
                z    = consideredAdvisors.ToDictionary(c => c.Key, c => ((c.Value.RankingWeightedProfit / c.Value.RankingWeight) - generalAvg) / (weightedStd / Math.Sqrt(c.Value.OrderCount)));
                minZ = z.Min(c => c.Value);
                normalizationDivisor = z.Max(c => c.Value) - minZ;
            }
            else
            {
                var value = 1.0001;
                z = consideredAdvisors.OrderByDescending(c => c.Value.OrderCount).ToDictionary(c => c.Key, c =>
                {
                    value -= 0.0001;
                    return(value);
                });
            }

            var advisorRating = new Dictionary <int, double>();

            advisors.ForEach(c =>
            {
                if (!z.ContainsKey(c))
                {
                    advisorRating[c] = 2.5;
                }
                else
                {
                    advisorRating[c] = 2.501 + (2.499 * ((z[c] - minZ) / normalizationDivisor));
                }
            });
            var advisorsOrdered = advisorRating.OrderByDescending(c => c.Value).ThenByDescending(c => c.Key);

            var advisorsRanking = new List <AdvisorRanking>();
            var advisorsProfit  = new List <AdvisorProfit>();

            for (int i = 0; i < advisorsOrdered.Count(); ++i)
            {
                var id = advisorsOrdered.ElementAt(i).Key;
                advisorsRanking.Add(new AdvisorRanking()
                {
                    Id         = id,
                    UpdateDate = now,
                    Ranking    = i + 1,
                    Rating     = advisorsOrdered.ElementAt(i).Value
                });

                var usdPosition = AdvisorProfitBusiness.GetBaseUsdAdvisorProfit(id, now);
                if (advisorRankingAndProfitData.ContainsKey(id))
                {
                    var advisorProfit = BuildAdvisorsProfit(id, now, advisorRankingAndProfitData[id].AssetProfitData);
                    if (advisorProfit.Any())
                    {
                        var closedPositions = groupedOrders[id].Where(c => c.OrderStatusType == OrderStatusType.Close);
                        if (closedPositions.Any())
                        {
                            usdPosition.TotalDollar += closedPositions.Sum(c => GetExpectedCloseValue(c) - c.Fee.Value);
                        }

                        var openOrders = groupedOrders[id].Where(c => c.AssetId != AssetUSDId && (c.OrderStatusType == OrderStatusType.Open));
                        if (openOrders.Any())
                        {
                            usdPosition.TotalDollar -= openOrders.Sum(c => c.Price * c.Quantity);
                        }

                        var openPositions = groupedOrders[id].Where(c => c.AssetId != AssetUSDId && (c.OrderStatusType == OrderStatusType.Executed));
                        if (openPositions.Any())
                        {
                            usdPosition.TotalDollar -= openPositions.Sum(c => c.Price * c.Quantity + c.Fee.Value);
                        }

                        var userFinishedOrders = finishedOrders.Where(c => c.UserId == id);
                        if (userFinishedOrders.Any())
                        {
                            usdPosition.TotalDollar -= userFinishedOrders.Sum(c => c.Price * c.Quantity + c.Fee.Value);
                        }

                        usdPosition.TotalQuantity = usdPosition.TotalDollar;
                        advisorsProfit.AddRange(advisorProfit);
                    }
                }
                advisorsProfit.Add(usdPosition);
            }

            Parallel.Invoke(() => Data.SetAdvisorRanking(advisorsRanking),
                            () => AdvisorProfitBusiness.SetAdvisorProfit(advisorsProfit));

            UpdateAdvisorsFullDataCache(Data.ListAdvisorsRankingAndProfit(null, null));
        }