private AdvisorRankingAndProfitData GetAdvisorRankingAndProfitData(DateTime now, List <Order> advisorClosedOpenAndRunningOrders, Dictionary <int, double> assetsBidValues,
                                                                           Dictionary <int, double> assetsAskValues)
        {
            var result = new AdvisorRankingAndProfitData();
            var advisorClosedOrders = advisorClosedOpenAndRunningOrders.Where(c => c.OrderStatusType == OrderStatusType.Close);

            foreach (var order in advisorClosedOrders)
            {
                var tradeMinutes = Convert.ToInt32(Math.Round(order.StatusDate.Subtract(order.OpenDate.Value).TotalMinutes, 0));
                SetAdvisorRankingAndProfitData(ref result, order.OrderStatusType, order.OrderType, order.AssetId, order.Profit.Value, order.Quantity, GetExpectedCloseValue(order) - order.Fee.Value, now, order.StatusDate, tradeMinutes, order.TotalTradeFee);
            }

            var advisorOpenOrders = advisorClosedOpenAndRunningOrders.Where(c => c.OrderStatusType == OrderStatusType.Open);

            foreach (var order in advisorOpenOrders)
            {
                SetAdvisorRankingAndProfitData(ref result, order.OrderStatusType, order.OrderType, order.AssetId, 0, order.Quantity, order.Price * order.Quantity, now, order.StatusDate, null, order.Fee);
            }

            var advisorRunningOrders = advisorClosedOpenAndRunningOrders.Where(c => c.OrderStatusType == OrderStatusType.Executed && c.AssetId != AssetUSDId);

            if (advisorRunningOrders.Any())
            {
                var assetsAvgPrice = advisorRunningOrders.GroupBy(c => new { c.AssetId, c.Type }).Select(c => new
                {
                    AssetId       = c.Key.AssetId,
                    OrderType     = OrderType.Get(c.Key.Type),
                    TotalUSD      = c.Sum(s => s.RemainingQuantity * s.Price),
                    TotalQuantity = c.Sum(s => s.RemainingQuantity),
                    TotalFee      = c.Sum(s => s.Fee ?? 0)
                });
                foreach (var avgPrice in assetsAvgPrice)
                {
                    var price              = (avgPrice.TotalUSD / avgPrice.TotalQuantity);
                    var dictionaryPrice    = avgPrice.OrderType == OrderType.Buy ? assetsBidValues : assetsAskValues;
                    var currentValue       = dictionaryPrice.ContainsKey(avgPrice.AssetId) ? dictionaryPrice[avgPrice.AssetId] : price;
                    var expectedCloseValue = OrderBusiness.GetExpectedCloseValue(avgPrice.OrderType, price, currentValue, avgPrice.TotalQuantity);
                    var closedFee          = expectedCloseValue * OrderFee;
                    var totalDollar        = expectedCloseValue - closedFee;
                    var feePercentage      = avgPrice.TotalFee / (price * avgPrice.TotalQuantity + avgPrice.TotalFee);
                    var profit             = OrderBusiness.GetProfitValue(totalDollar, price, avgPrice.TotalQuantity, feePercentage);
                    SetAdvisorRankingAndProfitData(ref result, OrderStatusType.Executed, avgPrice.OrderType, avgPrice.AssetId, profit, avgPrice.TotalQuantity, totalDollar, now, now, null, avgPrice.TotalFee);
                }
            }
            return(result);
        }
        private void SetAdvisorRankingAndProfitData(ref AdvisorRankingAndProfitData advisorRankingAndProfitData, OrderStatusType statusType, OrderType orderType,
                                                    int assetId, double profit, double quantity, double totalUSD, DateTime now, DateTime closeDate, int?tradeMinutes, double?fee)
        {
            var investedDollar = profit != -1 ? (totalUSD / (1 + profit)) : totalUSD;

            if (statusType != OrderStatusType.Open)
            {
                var days   = now.Subtract(closeDate).TotalDays;
                var weight = (days <= 30 ? 1.0 : Math.Max((Math.Log(days) / -2.5100067169575757) + 2.3550550915595987, 0.0)) * investedDollar;
                advisorRankingAndProfitData.RankingWeight         += weight;
                advisorRankingAndProfitData.RankingWeightedProfit += profit * weight;
                if (weight > 0)
                {
                    ++advisorRankingAndProfitData.OrderCount;
                }
            }

            if (!advisorRankingAndProfitData.AssetProfitData.ContainsKey(assetId))
            {
                advisorRankingAndProfitData.AssetProfitData[assetId] = new Dictionary <OrderStatusType, Dictionary <OrderType, AdvisorRankingAndProfitData.ProfitData> >();
            }
            if (!advisorRankingAndProfitData.AssetProfitData[assetId].ContainsKey(statusType))
            {
                advisorRankingAndProfitData.AssetProfitData[assetId][statusType] = new Dictionary <OrderType, AdvisorRankingAndProfitData.ProfitData>();
            }
            if (!advisorRankingAndProfitData.AssetProfitData[assetId][statusType].ContainsKey(orderType))
            {
                advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType] = new AdvisorRankingAndProfitData.ProfitData();
            }

            advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].SummedProfitPercentage += profit;
            advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].TotalDollar            += totalUSD;
            advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].TotalQuantity          += quantity;
            advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].SummedProfitDollar     += totalUSD - investedDollar;
            ++advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].OrderCount;
            if (profit > 0)
            {
                ++advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].SuccessCount;
            }

            if (tradeMinutes.HasValue)
            {
                if (advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].SummedTradeMinutes.HasValue)
                {
                    advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].SummedTradeMinutes += tradeMinutes.Value;
                }
                else
                {
                    advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].SummedTradeMinutes = tradeMinutes.Value;
                }
            }
            if (fee.HasValue)
            {
                if (advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].TotalFee.HasValue)
                {
                    advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].TotalFee += fee.Value;
                }
                else
                {
                    advisorRankingAndProfitData.AssetProfitData[assetId][statusType][orderType].TotalFee = fee.Value;
                }
            }
        }