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);
        }
Exemple #4
0
        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;
            }
        }