private void CalculateProfitPercent(AccountDayStatistic statistic, string serverName, DateTime date, DateTime endOfDay, IEnumerable <mt4_trades> orders, AccountDayStatistic previousStatistic) { var equity = previousStatistic.CurrentEquity; var balance = previousStatistic.CurrentBalance; var percents = new List <decimal>(); var currentEquity = 0m; var tradesByPeriods = GetTradingByPeriods(orders, date, endOfDay); for (var i = 0; i < tradesByPeriods.Length; i++) { var endPeriod = tradesByPeriods.Count() == 1 || i >= tradesByPeriods.Length - 1 || !tradesByPeriods[i + 1].Any() ? date.AddDays(1).AddSeconds(-1) : tradesByPeriods[i + 1].First().OPEN_TIME; var newBalance = balance; decimal depWithBeforeTrading; GetDayBalanceEquity(tradesByPeriods[i], endPeriod, ref newBalance, out currentEquity, out depWithBeforeTrading, serverName); var profitPercent = Math.Abs(equity + depWithBeforeTrading) < Constants.Tolerance ? 0m : (currentEquity - (equity + depWithBeforeTrading)) / (equity + depWithBeforeTrading) * 100m; percents.Add(profitPercent); balance = newBalance; equity = currentEquity; } statistic.CurrentBalance = balance; statistic.CurrentEquity = currentEquity; statistic.ClosedProfitInPercentsPerDay = (double)percents.Sum(); statistic.ClosedProfitInPercentsTotal = previousStatistic.ClosedProfitInPercentsTotal + statistic.ClosedProfitInPercentsPerDay; statistic.VolatilityPerDay = Math.Abs(statistic.ClosedProfitInPercentsPerDay); statistic.MaxDailyDrowdown = statistic.ClosedProfitInPercentsPerDay < previousStatistic.MaxDailyDrowdown ? statistic.ClosedProfitInPercentsPerDay : previousStatistic.MaxDailyDrowdown; }
private AccountDayStatistic CalculateStatisticForClosedOrders(DateTime date, DateTime endOfDay, MT4AccountInfo accountInfo, IEnumerable <mt4_trades> allOrders, AccountDayStatistic previousStatistic) { var orders = allOrders .Where(order => order.LOGIN == accountInfo.Login && ((order.CLOSE_TIME >= date && order.CLOSE_TIME < endOfDay) || (order.CLOSE_TIME == Constants.BeginEpoch && order.OPEN_TIME < endOfDay) || (order.CLOSE_TIME >= endOfDay && order.OPEN_TIME < endOfDay))) .ToArray(); var res = new AccountDayStatistic(); res.Date = date; res.AccountId = accountInfo.AccountId; res.ClientAccountId = accountInfo.ClientId; res.CurrentBalance = previousStatistic.CurrentBalance + (decimal)orders .Where(trades => trades.CMD == (int)OrderType.BALANCE || trades.CMD == (int)OrderType.CREDIT || trades.CMD == (int)OrderType.BUY || trades.CMD == (int)OrderType.SELL) .Sum(trade => trade.PROFIT + trade.COMMISSION + trade.SWAPS + trade.TAXES); res.BalancePerDay = orders.Where(trades => trades.CMD == (int)OrderType.BALANCE || trades.CMD == (int)OrderType.CREDIT).Sum(trades => trades.PROFIT); var tradingOrders = orders .Where(trades => trades.CMD == (int)OrderType.BUY || trades.CMD == (int)OrderType.SELL) .Select(trades => trades) .ToArray(); var closedOrders = tradingOrders .Where(trades => trades.CLOSE_TIME != Constants.BeginEpoch && trades.CLOSE_TIME < endOfDay) .Select(trades => trades) .ToArray(); var openedOrders = tradingOrders .Where(trades => trades.OPEN_TIME >= date && trades.OPEN_TIME < endOfDay) .Select(trades => trades) .ToArray(); var performance = (double)previousStatistic.RiskTotal; foreach (var openOrder in openedOrders) { var currentBalance = closedOrders.Where(x => x.CLOSE_TIME < openOrder.OPEN_TIME).Sum(x => x.PROFIT + x.TAXES + x.SWAPS + x.COMMISSION) + orders.Where(x => (x.CMD == 5 || x.CMD == 6) && x.CLOSE_TIME < openOrder.OPEN_TIME).Sum(x => x.PROFIT); var orderPerformance = (openOrder.PROFIT + openOrder.SWAPS + openOrder.TAXES + openOrder.COMMISSION) / ((double)previousStatistic.CurrentBalance + currentBalance) + 1; if (Math.Abs(orderPerformance) > 0.01) { performance = (performance + 1) * orderPerformance - 1; } } res.RiskTotal = (decimal)performance; // Closed per day res.ClosedProfitInPointsPerDay = closedOrders .Where(order => order.CMD == (int)OrderType.BUY || order.CMD == (int)OrderType.SELL) .Sum(trade => trade.CMD == (int)OrderType.BUY ? (int)((trade.CLOSE_PRICE - trade.OPEN_PRICE) / cacheService.GetSymbolCoefficient(trade.SYMBOL, trade.DIGITS)) : (int)((trade.OPEN_PRICE - trade.CLOSE_PRICE) / cacheService.GetSymbolCoefficient(trade.SYMBOL, trade.DIGITS))); res.ProfitTradesCountPerDay = closedOrders.Count(order => order.PROFIT + order.COMMISSION + order.SWAPS + order.TAXES > 0.0); res.ClosedLoseTradesCountPerDay = closedOrders.Count(order => order.PROFIT + order.COMMISSION + order.SWAPS + order.TAXES <= 0.0); res.ClosedProfitPerDay = closedOrders.Sum(order => order.PROFIT + order.COMMISSION + order.SWAPS + order.TAXES); //res.ClosedProfitInPercentsPerDay = Math.Abs(previousStatistic.CurrentBalance) < Constants.Tolerance // ? 0.0 // : ((res.ClosedProfitPerDay / (double)previousStatistic.CurrentBalance) * 100.0); // Closed total res.ClosedLoseTradesTotal = previousStatistic.ClosedLoseTradesTotal + res.ClosedLoseTradesCountPerDay; //res.ClosedProfitInPercentsTotal = previousStatistic.ClosedProfitInPercentsTotal + res.ClosedProfitInPercentsPerDay; res.ClosedProfitInPointsTotal = previousStatistic.ClosedProfitInPointsTotal + res.ClosedProfitInPointsPerDay; res.ClosedProfitTotal = previousStatistic.ClosedProfitTotal + res.ClosedProfitPerDay; res.ClosedProfitTradesTotal = previousStatistic.ClosedProfitTradesTotal + res.ProfitTradesCountPerDay; res.OpenedTradesCountPerDay = tradingOrders.Count(trades => trades.OPEN_TIME >= date); res.OpenedTradesCountCurrent = tradingOrders.Count(order => order.CLOSE_TIME == Constants.BeginEpoch); res.OpenedTradesCountTotal = previousStatistic.OpenedTradesCountTotal + res.OpenedTradesCountPerDay; var tradeTimePerDay = closedOrders.Sum(trades => (trades.CLOSE_TIME - trades.OPEN_TIME).TotalMinutes); var closedTradesTotal = previousStatistic.ClosedProfitTradesTotal + previousStatistic.ClosedLoseTradesTotal; res.AvarageTradeTimeInMinutes = Math.Abs(tradeTimePerDay) <= 0.001 ? 0 : tradeTimePerDay / (res.ProfitTradesCountPerDay + res.ClosedLoseTradesCountPerDay); var totalTradeTime = previousStatistic.AvarageTradeTimeInMinutesTotal * (closedTradesTotal) + tradeTimePerDay; res.AvarageTradeTimeInMinutesTotal = Math.Abs(totalTradeTime) <= 0.001 ? 0 : totalTradeTime / (res.ClosedLoseTradesTotal + res.ClosedProfitTradesTotal); res.VolumePerDay = closedOrders.Sum(trades => trades.VOLUME); res.VolumeEfficiencyPerDay = Math.Abs(res.VolumePerDay) < 0.0001 ? 0.0 : res.ClosedProfitPerDay / res.VolumePerDay; res.MaxOpenOrders = res.OpenedTradesCountPerDay > previousStatistic.MaxOpenOrders ? res.OpenedTradesCountPerDay : previousStatistic.MaxOpenOrders; res.TradeAmountTotal = previousStatistic.TradeAmountTotal + orders .Where(trades => (trades.CMD == (int)OrderType.BUY || trades.CMD == (int)OrderType.SELL) && trades.CLOSE_TIME != Constants.BeginEpoch) .Sum(trades => (decimal)trades.VOLUME); return(res); }
public AccountDayStatistic CalculateStatistic(MT4AccountInfo accountInfo, DateTime date, mt4_trades[] orders, AccountDayStatistic lastStatisticModel) { var statistic = CalculateStatisticForClosedOrders(date, date.AddDays(1), accountInfo, orders, lastStatisticModel); CalculateProfitPercent(statistic, accountInfo.ServerName, date, date.AddDays(1).AddSeconds(-1), orders, lastStatisticModel); return(statistic); }
private void AddStatisticAccount(RatingAccount ratingAccount, AccountDayStatistic statistic, AccountRole accType, List <Trader> traders, List <SignalProvider> providers, List <Manager> s) { if (statistic.MaxOpenOrders <= 0) { return; } switch (accType) { case AccountRole.Trading: traders.Add(new Trader { AccountId = ratingAccount.AccountId, Age = ratingAccount.Age, Country = ratingAccount.Country, AccountNickname = ratingAccount.Nickname, Login = ratingAccount.Login, LoseOrders = statistic.ClosedLoseTradesTotal, MaxDailyDrowdown = (float)statistic.MaxDailyDrowdown, Profit = (float)statistic.ClosedProfitInPointsTotal, ProfitLastDay = (float)statistic.ClosedProfitInPointsPerDay, ProfitOrders = statistic.ClosedProfitTradesTotal, Volatility = (float)statistic.VolatilityPerDay, Avatar = ratingAccount.Avatar, Rating = ratingAccount.Rating, ClientNickname = ratingAccount.ClientNickname, Currency = ratingAccount.Currency, Chart = statisticRepository.GetDecimatedChart(ratingAccount.AccountId, Constants.PointsCountInSmallChart, StatisticRepository.StatisticType.ProfitInPointsTotal), AccountsNumber = ratingAccount.AccountsNumber, }); break; case AccountRole.SignalProvider: var subscribers = signalService.GetProviderSubscribers(ratingAccount.AccountId); if (!subscribers.IsSuccess) { throw new Exception(subscribers.Error); } providers.Add(new SignalProvider { AccountId = ratingAccount.AccountId, Age = ratingAccount.Age, Country = ratingAccount.Country, AccountNickname = ratingAccount.Nickname, Login = ratingAccount.Login, Profit = (float)statistic.ClosedProfitInPointsTotal, ProfitLastDay = (float)statistic.ClosedProfitInPointsPerDay, Subscribers = subscribers.Result.Length, LoseOrders = statistic.ClosedLoseTradesTotal, MaxDailyDrowdown = (float)statistic.MaxDailyDrowdown, ProfitOrders = statistic.ClosedProfitTradesTotal, Volatility = (float)statistic.VolatilityPerDay, Avatar = ratingAccount.Avatar, Rating = ratingAccount.Rating, ClientNickname = ratingAccount.ClientNickname, Currency = ratingAccount.Currency, Chart = statisticRepository.GetDecimatedChart(ratingAccount.AccountId, Constants.PointsCountInSmallChart, StatisticRepository.StatisticType.ProfitInPointsTotal), AccountsNumber = ratingAccount.AccountsNumber, }); break; case AccountRole.Master: var investorsCount = Service.GetIvestorsCount(ratingAccount.AccountId); if (!investorsCount.IsSuccess) { throw new Exception(investorsCount.Error); } s.Add(new Manager { AccountId = ratingAccount.AccountId, Age = ratingAccount.Age, Country = ratingAccount.Country, AccountNickname = ratingAccount.Nickname, Login = ratingAccount.Login, Profit = (float)statistic.ClosedProfitInPercentsTotal, ProfitLastDay = (float)statistic.ClosedProfitInPercentsPerDay, Investors = investorsCount.Result, LoseOrders = statistic.ClosedLoseTradesTotal, MaxDailyDrowdown = (float)statistic.MaxDailyDrowdown, ProfitOrders = statistic.ClosedProfitTradesTotal, Volatility = (float)statistic.VolatilityPerDay, Avatar = ratingAccount.Avatar, Rating = ratingAccount.Rating, ClientNickname = ratingAccount.ClientNickname, Currency = ratingAccount.Currency, Chart = statisticRepository.GetDecimatedChart(ratingAccount.AccountId, Constants.PointsCountInSmallChart, StatisticRepository.StatisticType.ProfitInPercentTotal), AccountsNumber = ratingAccount.AccountsNumber, }); break; } }