public AdvisorRanking GetAdvisorFullData(int advisorId) { var advisors = ListAdvisorsFullData(); var advisor = advisors.FirstOrDefault(c => c.Id == advisorId); if (advisor != null) { advisor.IsAdvisor = true; advisor.TotalAdvisors = advisors.Count; return(advisor); } else { var advisorData = Data.ListAdvisorsRankingAndProfit(new int[] { advisorId }, null).FirstOrDefault(); if (advisorData != null) { advisors.Add(advisorData); advisorData.IsAdvisor = true; advisorData.TotalAdvisors = advisors.Count; return(advisorData); } else { var user = AdvisorBusiness.GetAdvisor(advisorId); var now = Data.GetDateTimeNow(); return(GetStartAdvisorRanking(user, now, advisors.Count)); } } }
public void AppendNewAdvisorToCache(int advisorId) { var user = AdvisorBusiness.GetAdvisor(advisorId); var advisors = ListAdvisorsFullData(); advisors.Add(GetStartAdvisorRanking(user, user.BecameAdvisorDate, advisors.Count)); }
public AdvisorDetail Create(string email, int advisorId, string name, string description) { var advisor = AdvisorBusiness.GetWithOwner(advisorId, email); if (advisor == null) { throw new ArgumentException("Invalid advisor."); } var advisorDetail = SetNew(advisor.Id, name, description, true); Data.Insert(advisorDetail); return(advisorDetail); }
public AdvisorDetail Disable(string email, int advisorId) { var advisor = AdvisorBusiness.GetWithOwner(advisorId, email); if (advisor == null) { throw new ArgumentException("Invalid advisor."); } var oldDetail = GetByAdvisor(advisor.Id); var advisorDetail = SetNew(advisor.Id, oldDetail.Name, oldDetail.Description, false); Data.Insert(advisorDetail); return(advisorDetail); }
public void SetAdvisorsMonthlyRanking() { var now = Data.GetDateTimeNow(); var lastMonth = now.AddMonths(-1); var consideredStartDate = new DateTime(lastMonth.Year, lastMonth.Month, 1, 0, 0, 0, DateTimeKind.Utc); var lastMonthRanking = ListAdvisorsMonthlyRanking(lastMonth.Year, lastMonth.Month); if (lastMonthRanking.Count == 0) { var advisorsId = AdvisorBusiness.ListAllAdvisors().Select(c => c.Id).Distinct().ToHashSet(); var monthlyHistory = AdvisorRankingHistoryBusiness.ListAdvisorRankingAndProfitHistory(advisorsId, consideredStartDate, now); if (monthlyHistory.Any()) { var advisorsMonthlyRanking = new List <AdvisorMonthlyRanking>(); var consideredEndDate = new DateTime(now.Year, now.Month, 1, 0, 0, 0, DateTimeKind.Utc); var advisorsHistory = monthlyHistory.GroupBy(c => c.UserId); foreach (var history in advisorsHistory) { var monthlyAdvisorHistory = history.OrderBy(c => c.ReferenceDate); var firstMonthlyHistory = monthlyAdvisorHistory.FirstOrDefault(c => c.ReferenceDate >= consideredStartDate && c.ReferenceDate < consideredEndDate); var lastMonthlyHistory = monthlyAdvisorHistory.FirstOrDefault(c => c.ReferenceDate >= consideredEndDate); if (firstMonthlyHistory == null || lastMonthlyHistory == null) { continue; } var firstEquity = firstMonthlyHistory.AdvisorProfitHistory.Where(c => c.OrderStatusType != OrderStatusType.Close).Sum(c => c.TotalDollar); var lastEquity = lastMonthlyHistory.AdvisorProfitHistory.Where(c => c.OrderStatusType != OrderStatusType.Close).Sum(c => c.TotalDollar); advisorsMonthlyRanking.Add(new AdvisorMonthlyRanking() { CreationDate = now, Year = lastMonth.Year, Month = lastMonth.Month, UserId = history.Key, AverageReturn = lastEquity / firstEquity - 1 }); } advisorsMonthlyRanking = advisorsMonthlyRanking.OrderByDescending(c => c.AverageReturn).ThenByDescending(c => c.UserId).ToList(); for (var i = 0; i < advisorsMonthlyRanking.Count; ++i) { advisorsMonthlyRanking[i].Ranking = i + 1; } Data.SetAdvisorMonthlyRanking(advisorsMonthlyRanking); } } }
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)); }
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 }); }