예제 #1
0
 private AdvisorRanking GetStartAdvisorRanking(DomainObjects.Advisor.Advisor advisor, DateTime referenceDate, int totalAdvisors)
 {
     return(advisor == null || !advisor.Enabled ? null : new AdvisorRanking()
     {
         Id = advisor.Id,
         Email = advisor.Email,
         Password = advisor.Password,
         CreationDate = advisor.CreationDate,
         ConfirmationCode = advisor.ConfirmationCode,
         ConfirmationDate = advisor.ConfirmationDate,
         ReferralCode = advisor.ReferralCode,
         ReferralStatus = advisor.ReferralStatus,
         BonusToReferred = advisor.BonusToReferred,
         ReferredId = advisor.ReferredId,
         AllowNotifications = advisor.AllowNotifications,
         DiscountProvided = advisor.DiscountProvided,
         IsAdvisor = true,
         Name = advisor.Name,
         Description = advisor.Description,
         UrlGuid = advisor.UrlGuid,
         BecameAdvisorDate = advisor.BecameAdvisorDate,
         Enabled = advisor.Enabled,
         UpdateDate = referenceDate,
         Rating = 2.5,
         Ranking = totalAdvisors + 1,
         TotalAdvisors = totalAdvisors + 1,
         AdvisorProfit = new List <AdvisorProfit>()
         {
             AdvisorProfitBusiness.GetBaseUsdAdvisorProfit(advisor.Id, referenceDate)
         }
     });
 }
예제 #2
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));
        }
예제 #3
0
        public async Task <LoginResponse> CreateAsync(string email, string password, string name, string description, string referralCode,
                                                      bool changePicture, Stream pictureStream, string pictureExtension)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new BusinessException("Name must be filled.");
            }
            if (name.Length > 50)
            {
                throw new BusinessException("Name cannot have more than 50 characters.");
            }
            if (!string.IsNullOrWhiteSpace(description) && description.Length > 160)
            {
                throw new BusinessException("Short description cannot have more than 160 characters.");
            }

            byte[] picture = null;
            if (changePicture && pictureStream != null)
            {
                picture = AdvisorBusiness.GetPictureBytes(pictureStream, pictureExtension);
            }

            User user       = null;
            var  updateUser = false;

            if (LoggedEmail != null)
            {
                if (!string.IsNullOrWhiteSpace(email) && email != LoggedEmail)
                {
                    throw new BusinessException("Invalid email.");
                }
                if (!string.IsNullOrWhiteSpace(password))
                {
                    throw new BusinessException("Invalid password.");
                }

                user = UserBusiness.GetForLoginByEmail(LoggedEmail);
                if (UserBusiness.IsValidAdvisor(user))
                {
                    throw new BusinessException("User already registered.");
                }

                if (!user.ReferredId.HasValue)
                {
                    var referredUser = UserBusiness.GetReferredUser(referralCode);
                    if (referredUser != null)
                    {
                        updateUser           = true;
                        user.ReferralStatus  = ReferralStatusType.InProgress.Value;
                        user.ReferredId      = referredUser.Id;
                        user.BonusToReferred = UserBusiness.GetBonusToReferredUser(referredUser);
                    }
                }
                else if (!string.IsNullOrEmpty(referralCode))
                {
                    throw new BusinessException("User already has a referral code defined.");
                }
            }
            else
            {
                user = UserBusiness.GetValidUserToRegister(email, password, referralCode);
            }

            var  advisorsCount = AdvisorRankingBusiness.ListAdvisorsFullData().Count;
            Guid urlGuid       = Guid.NewGuid();
            var  creationDate  = Data.GetDateTimeNow();

            using (var transaction = TransactionalDapperCommand)
            {
                if (LoggedEmail == null)
                {
                    transaction.Insert(user);
                }
                else if (updateUser)
                {
                    transaction.Update(user);
                }

                var advisor = new DomainObjects.Advisor.Advisor()
                {
                    Id                = user.Id,
                    Name              = name,
                    Description       = description,
                    BecameAdvisorDate = creationDate,
                    Enabled           = true,
                    UrlGuid           = urlGuid
                };

                transaction.Insert(advisor);

                var virtualDolar = new Order()
                {
                    AssetId           = AssetUSDId,
                    CreationDate      = creationDate,
                    Price             = 1,
                    Quantity          = VirtualMoney,
                    RemainingQuantity = VirtualMoney,
                    Status            = OrderStatusType.Executed.Value,
                    StatusDate        = creationDate,
                    Type       = OrderType.Buy.Value,
                    UserId     = user.Id,
                    ActionType = OrderActionType.Automated.Value,
                    Fee        = 0
                };
                transaction.Insert(virtualDolar);

                var rating  = 2.5;
                var ranking = advisorsCount + 1;
                transaction.Insert(new AdvisorRanking()
                {
                    Id         = user.Id,
                    UpdateDate = creationDate,
                    Rating     = rating,
                    Ranking    = ranking
                });
                transaction.Insert(new AdvisorRankingHistory()
                {
                    UserId        = user.Id,
                    ReferenceDate = creationDate,
                    Rating        = rating,
                    Ranking       = ranking
                });
                var baseProfit = AdvisorProfitBusiness.GetBaseUsdAdvisorProfit(user.Id, creationDate);
                transaction.Insert(baseProfit);
                transaction.Insert(new AdvisorProfitHistory()
                {
                    AssetId                = baseProfit.AssetId,
                    OrderCount             = baseProfit.OrderCount,
                    ReferenceDate          = baseProfit.UpdateDate,
                    Status                 = baseProfit.Status,
                    SuccessCount           = baseProfit.SuccessCount,
                    SummedProfitDollar     = baseProfit.SummedProfitDollar,
                    SummedProfitPercentage = baseProfit.SummedProfitPercentage,
                    SummedTradeMinutes     = baseProfit.SummedTradeMinutes,
                    TotalDollar            = baseProfit.TotalDollar,
                    TotalQuantity          = baseProfit.TotalQuantity,
                    Type     = baseProfit.Type,
                    UserId   = baseProfit.UserId,
                    TotalFee = baseProfit.TotalFee
                });

                transaction.Commit();
            }

            await AzureStorageBusiness.UploadUserPictureFromBytesAsync($"{urlGuid}.png", picture ?? AdvisorBusiness.GetNoUploadedImageForAdvisor(user));

            if (LoggedEmail == null || !user.ConfirmationDate.HasValue)
            {
                await UserBusiness.SendEmailConfirmationAsync(user.Email, user.ConfirmationCode);
            }

            UserBusiness.ClearUserCache(user.Email);
            AdvisorRankingBusiness.AppendNewAdvisorToCache(user.Id);

            return(new LoginResponse()
            {
                Id = user.Id,
                Email = user.Email,
                PendingConfirmation = !user.ConfirmationDate.HasValue,
                AdvisorName = name,
                ProfileUrlGuid = urlGuid.ToString(),
                HasInvestment = false,
                IsAdvisor = true,
                RequestedToBeAdvisor = false
            });
        }