public void CalculateDealVolumeInDepoCurrency()
        {
            const int volume = 10000;
            var deal = new MarketOrder
            {
                Symbol = "USDRUB",
                Volume = volume,
                Side = 1,
                PriceEnter = 1.3290f,
                TimeEnter = DateTime.Now.AddMinutes(-60 * 24 * 3),
                State = PositionState.Opened,
                ExpertComment = "",
                MasterOrder = 10001
            };
            var dicQuote = new Dictionary<string, List<QuoteData>>();
            var quoteArc = new QuoteArchive(dicQuote);

            curveCalculator.CalculateDealVolumeInDepoCurrency(deal, new QuoteData(1.3820f, 1.3822f, DateTime.Now), "USD", quoteArc, DateTime.Now);
            Assert.AreEqual(0, deal.VolumeInDepoCurrency, "При разных валютах депозита и сделки и не инициализированом словаре котировок, метод не вернул правильное значение");

            curveCalculator.CalculateDealVolumeInDepoCurrency(deal, new QuoteData(1.3820f, 1.3822f, DateTime.Now), "RUB", quoteArc, DateTime.Now);
            Assert.AreEqual(volume * (1.3822f + 1.3820f) / 2, deal.VolumeInDepoCurrency,
                "При одинаковых валютах депозита и сделки метод не вернул правильное значение");

            foreach (var smb in DalSpot.Instance.GetTickerNames())
                dicQuote.Add(smb, dailyQuoteStorage.GetQuotes(smb).Select(q => new QuoteData(q.b, q.b, q.a)).ToList());
            quoteArc = new QuoteArchive(dicQuote);

            curveCalculator.CalculateDealVolumeInDepoCurrency(deal, new QuoteData(1.3820f, 1.3822f, DateTime.Now), "RUB", quoteArc, dicQuote["USDRUB"].First().time);
            Assert.AreEqual(volume * (1.3822f + 1.3820f) / 2, deal.VolumeInDepoCurrency,
                "При инициализированных всех данных и метод не вернул правильное значение");
        }
        /// <summary>
        /// Расчитать объем сделки в валюте депозита
        /// </summary>
        public void CalculateDealVolumeInDepoCurrency(MarketOrder deal, QuoteData dealQuote, string depoCurrency, QuoteArchive arc, DateTime date)
        {
            var volumeInCounter = deal.Volume * dealQuote.GetPrice(QuoteType.NonSpecified);

            // перевести из контрвалюты в валюту депо
            bool inverse, pairsAreEqual;
            var smb = DalSpot.Instance.FindSymbol(deal.Symbol, false, depoCurrency, out inverse, out pairsAreEqual);
            if (pairsAreEqual)
            {
                deal.VolumeInDepoCurrency = volumeInCounter;
                return;
            }

            if (string.IsNullOrEmpty(smb)) return;
            var quoteCtDepo = arc.GetQuoteOnDateSeq(smb, date);
            if (quoteCtDepo == null) return;
            var priceCtDepo = quoteCtDepo.GetPrice(QuoteType.NonSpecified);
            if (priceCtDepo == 0) return;

            deal.VolumeInDepoCurrency = inverse ? volumeInCounter / priceCtDepo : volumeInCounter * priceCtDepo;
        }
        public void CalculateEquityCurve()
        {
            var deals = new List<MarketOrder>();

            var dealsOpen = TestDataGenerator.GetOpenPosition().Select(LinqToEntity.DecorateOrder).ToList();
            var dealsClose = TestDataGenerator.GetClosePosition().Select(LinqToEntity.DecorateOrder).ToList();

            deals.AddRange(dealsOpen);
            deals.AddRange(dealsClose);

            var transfers = TestDataGenerator.GetBalanceChange().Select(LinqToEntity.DecorateBalanceChange).ToList();
            var firstDealOpenedTime = deals.Min(d => d.TimeEnter);
            transfers.Insert(0, new BalanceChange
                {
                    AccountID = deals[0].AccountID,
                    ValueDate = firstDealOpenedTime.AddHours(-1),
                    CurrencyToDepoRate = 1,
                    ChangeType = BalanceChangeType.Deposit,
                    Amount = 500000
                });

            var dicQuote = new Dictionary<string, List<QuoteData>>();

            foreach (var smb in DalSpot.Instance.GetTickerNames())
                dicQuote.Add(smb, dailyQuoteStorage.GetQuotes(smb).Select(q => new QuoteData(q.b, q.b, q.a)).ToList());

            var quoteArc = new QuoteArchive(dicQuote);
            var res = curveCalculator.CalculateEquityCurve(deals, DepoCurrency, quoteArc, transfers);

            // сверить точку кривой доходности
            CheckEquityCurvePoint(res, transfers, dealsOpen, dealsClose, quoteArc, dicQuote, 0);
            CheckEquityCurvePoint(res, transfers, dealsOpen, dealsClose, quoteArc, dicQuote, 10);
            CheckEquityCurvePoint(res, transfers, dealsOpen, dealsClose, quoteArc, dicQuote, 40);
        }
        /// <summary>
        /// Рассчитать точку кривой доходности "вручную" и сверить её с рассчитанной в классе "CalculateEquityCurve"
        /// </summary>
        private void CheckEquityCurvePoint(AccountPerformanceRaw res, 
            List<BalanceChange> transfers, List<MarketOrder> dealsOpen, List<MarketOrder> dealsClose,
            QuoteArchive quoteArc, Dictionary<string, List<QuoteData>> dicQuote, int index)
        {
            var calculationTime = res.equity[index].time;

            var depoChangesOnDate = transfers.Where(t => t.ValueDate <= calculationTime).Sum(t => t.SignedAmountDepo);
            var dealsStilOpened = dealsOpen.Where(d => d.State == PositionState.Opened && d.TimeEnter <= calculationTime).ToList();
            var allDeals = dealsClose.Where(d => d.TimeEnter < calculationTime && d.TimeExit > calculationTime).ToList();
            allDeals.AddRange(dealsStilOpened);

            allDeals.ForEach(d =>
                {
                    d.State = PositionState.Opened;
                    d.PriceExit = null;
                });
            // получить котировки на момент
            quoteArc.ToBegin();
            var thatTimeQuotes = dicQuote.Keys.ToDictionary(ticker => ticker,
                                                            ticker => quoteArc.GetQuoteOnDateSeq(ticker, calculationTime));

            var sumDealsProfit = DalSpot.Instance.CalculateOpenedPositionsCurrentResult(allDeals, thatTimeQuotes, DepoCurrency);
            var equity = (float) depoChangesOnDate + sumDealsProfit;
            var delta = Math.Abs(res.equity[index].equity - equity);
            Assert.Less(delta, 0.1f, "CalculateEquityCurve - погрешность расчета средств на момент должна быть в пределах 10C");

            var dealByTicker = allDeals.GroupBy(x => x.Symbol).ToDictionary(d => d.Key, d => d.ToList());
            var exposure = dealByTicker.Sum(d =>
                {
                    var totalVolume = Math.Abs(d.Value.Sum(order => order.Side*order.Volume));

                    if (totalVolume == 0) return 0;
                    string errorStr;
                    var exp = DalSpot.Instance.ConvertToTargetCurrency(d.Key, true, DepoCurrency, totalVolume, thatTimeQuotes, out errorStr);
                    return exp ?? 0;
                });

            var leverage = (float) exposure/equity;
            var resultedLeverage = res.leverage.First(l => l.time == calculationTime).equity;
            delta = Math.Abs(resultedLeverage - leverage);
            Assert.Less(delta, 0.05f, "CalculateEquityCurve - погрешность расчета плеча на момент должна быть в пределах 0.05");
        }
        public void CalculateProfitInDepoCurx()
        {
            const int volume = 10000;
            var deal = new MarketOrder
            {
                Symbol = "USDRUB",
                Volume = volume,
                Side = 1,
                PriceEnter = 1.3290f,
                TimeEnter = DateTime.Now.AddMinutes(-60 * 24 * 3),
                State = PositionState.Opened,
                ExpertComment = "",
                MasterOrder = 10001
            };

            var dicQuote = new Dictionary<string, List<QuoteData>>();
            var quoteArc = new QuoteArchive(dicQuote);

            const float profit = 1000f;
            var volumeUsd = curveCalculator.CalculateProfitInDepoCurx(true, profit, deal.Symbol, "USD", quoteArc, DateTime.Now);
            Assert.AreEqual(profit, volumeUsd, "При совпадении валюты депозита и сделки, метод не вернул правильное значение прибыли по сделке");

            var volumeRub = curveCalculator.CalculateProfitInDepoCurx(true, profit, deal.Symbol + "f", "RUB", quoteArc, DateTime.Now);
            Assert.AreEqual(0, volumeRub, "При отсутствии тикеров валют, метод не вернул правильное значение прибыли по сделке");
            TradeSharpDictionary.Initialize(MoqTradeSharpDictionary.Mock); // возвращаем обратно реализацию метода GetTickers

            var volumeNoQuote = curveCalculator.CalculateProfitInDepoCurx(false, profit, deal.Symbol, "RUB", quoteArc, DateTime.Now);
            Assert.AreEqual(profit, volumeNoQuote, "При отсутствии котировок, метод не вернул правильное значение прибыли по сделке");

            foreach (var smb in DalSpot.Instance.GetTickerNames())
                dicQuote.Add(smb, dailyQuoteStorage.GetQuotes(smb).Select(q => new QuoteData(q.b, q.b, q.a)).ToList());
            var volumeQuote = curveCalculator.CalculateProfitInDepoCurx(true, profit, deal.Symbol, "RUB", new QuoteArchive(dicQuote), dicQuote["USDRUB"].First().time);

            //TODO значение "32369.2012" не расчитывалось в ручную, а просто скопировано, что бы тест не валился (это нужно исправить)
            Assert.AreEqual(32369.2012f, volumeQuote, "Метод рассчитал значение прибыли по сделке не правильно");
        }
Пример #6
0
        public bool Calculate(AccountEfficiency ef)
        {
            if (ef == null)
                throw new ArgumentException("EfficiencyCalculator.Calculate - input ptr is NULL");
            if (ef.Statistics.Account == 0)
                throw new ArgumentException("EfficiencyCalculator.Calculate - input_ptr.AccountId is 0");

            // получить сделки
            var deals = DealStorage.Instance.GetDeals(ef.Statistics.Account);
            ef.openedDeals = new List<MarketOrder>();
            ef.closedDeals = new List<MarketOrder>();

            foreach (var deal in deals)
                if (deal.IsOpened)
                    ef.openedDeals.Add(deal);
                else
                    ef.closedDeals.Add(deal);

            if (deals.Count == 0)
            {
                Logger.Info("AccountEfficiency.Calculate - нет сделок");
                return false;
            }

            ef.Statistics.DealsCount = deals.Count;
            ef.DealsStillOpened = ef.openedDeals.Count;

            // транзакции
            ef.listTransaction = BalanceStorage.Instance.GetBalanceChanges(ef.Statistics.Account);
            if (ef.listTransaction == null || ef.listTransaction.Count == 0)
            {
                Logger.Info("AccountEfficiency.Calculate - нет транзакций");
                return false;
            }

            Logger.Info("AccountEfficiency.Calculate(" + ef.Statistics.Account + ")");

            // время отсчета - время первого заведения средств
            var startDate = ef.listTransaction.Min(t => t.ValueDate);

            // получить список используемых котировок
            var symbolsUsed = ef.closedDeals.Select(d => d.Symbol).Union(ef.openedDeals.Select(o => o.Symbol)).Distinct().ToList();
            // ... в т.ч., котировок для перевода базовой валюты в валюту депо (плечо)
            // и перевода контрвалюты в валюту депо (профит)
            var symbolsMore = new List<string>();
            foreach (var smb in symbolsUsed)
            {
                bool inverse, eq;
                var smbBase = DalSpot.Instance.FindSymbol(smb, true, ef.Statistics.DepoCurrency, out inverse, out eq);
                if (!string.IsNullOrEmpty(smbBase)) symbolsMore.Add(smbBase);
                var smbCounter = DalSpot.Instance.FindSymbol(smb, false, ef.Statistics.DepoCurrency, out inverse, out eq);
                if (!string.IsNullOrEmpty(smbCounter)) symbolsMore.Add(smbCounter);
            }
            symbolsUsed.AddRange(symbolsMore);
            symbolsUsed = symbolsUsed.Distinct().ToList();

            // котировки
            var dicQuote = new Dictionary<string, List<QuoteData>>();
            foreach (var smb in symbolsUsed)
            {
                dicQuote.Add(smb,
                    dailyQuoteStorage.GetQuotes(smb).Select(q => new QuoteData(q.b, q.b, q.a)).ToList());
            }
            //TickerStorage.Instance.GetQuotes(symbolsUsed.ToDictionary(s => s, s => (DateTime?)null));
            if (dicQuote == null || dicQuote.Count == 0)
            {
                Logger.Info("AccountEfficiency.Calculate - нет котировок");
                return false;
            }

            if (ef.openedDeals.Count > 0)
            {
                foreach (var t in ef.openedDeals)
                {
                    List<QuoteData> dicQuoteValue;
                    if (!dicQuote.TryGetValue(t.Symbol, out dicQuoteValue))
                        Logger.Error(String.Format("Symbol {0} was not found in dicQuote", t.Symbol));
                    else
                        if (dicQuoteValue.Count == 0)
                            Logger.Error(String.Format("No quote data for symbol {0}", t.Symbol));
                        else
                            t.PriceExit = dicQuoteValue.Last().GetPrice(t.Side == 1
                                ? QuoteType.Bid : QuoteType.Ask);
                }
            }

            var quoteArc = new QuoteArchive(dicQuote);
            AccountPerformanceRaw performance;
            try
            {
                performance = equityCurveCalculator.CalculateEquityCurve(deals, ef.Statistics.DepoCurrency, quoteArc, ef.listTransaction);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в EfficiencyCalculator.CalculateEquityCurve()", ex);
                return false;
            }

            ef.Statistics.TotalTradedInDepoCurrency = performance.totalTradedVolume;
            var lstEquity = performance.equity;
            if (lstEquity == null) return false;
            ef.listLeverage = performance.leverage;

            // исключить пустые значения с начала отсчета
            ef.listEquity = new List<EquityOnTime>();
            var startCopy = false;
            foreach (var eq in lstEquity)
            {
                if (eq.equity > 0) startCopy = true;
                if (startCopy) ef.listEquity.Add(eq);
            }

            if (ef.listEquity.Count == 0) return false;
            ef.StartDate = startDate;
            ef.InitialBalance = ef.listEquity[0].equity;

            // рассчитать коэффициенты доходности
            CalculateProfitCoeffs(ef);
            CalculateRiskCoeffs(ef);

            // актуальные котировки
            ef.currentQuotes = quoteArc.GetCurrentQuotes();

            ef.Statistics.Chart = ef.listProfit1000 == null ||
                                         ef.listProfit1000.Count == 0
                                             ? new byte[MiniChartPacker.profitChartPointCount]
                                             : MiniChartPacker.PackChartInArray(ef.listProfit1000);

            // дней торгует
            var startDayOpen = DateTime.Now;
            if (ef.openedDeals.Count > 0)
                startDayOpen = ef.openedDeals.Max(d => d.TimeEnter);
            if (ef.closedDeals.Count > 0)
            {
                var dateClosed = ef.closedDeals.Min(d => d.TimeEnter);
                if (dateClosed < startDayOpen)
                    startDayOpen = dateClosed;
            }
            ef.Statistics.DaysTraded = (int)Math.Round((DateTime.Now - startDayOpen).TotalDays);

            // сумма профитных сделок (результат) к сумме убыточных сделок
            var sumProf = ef.closedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0) +
                ef.openedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0);
            var sumLoss = ef.closedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0) +
                ef.openedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0);
            ef.Statistics.AvgWeightedDealProfitToLoss = sumLoss == 0 && sumProf == 0
                                                           ? 0
                                                           : 100 * sumProf / (sumProf + sumLoss);
            var dateFirst = DateTime.Now.Date.AddMonths(-3);
            ef.Statistics.WithdrawalLastMonths = (float)ef.listTransaction.Sum(t =>
                                                                               (t.ChangeType ==
                                                                                BalanceChangeType.Withdrawal &&
                                                                                t.ValueDate >= dateFirst)
                                                                                   ? t.AmountDepo : 0);
            // профит в ПП
            ef.Statistics.SumProfitPoints = ef.closedDeals.Sum(d => d.ResultPoints);

            return true;
        }
        public AccountPerformanceRaw CalculateEquityCurve(List<MarketOrder> deals, string depoCurrency, QuoteArchive quoteArc,
            List<BalanceChange> transactions, DateTime timeStart, DateTime timeEnd)
        {
            Logger.InfoFormat("CalculateEquityCurve(closedDeals:{0}, quotes:{1}, transactions:{2})",
                              deals.Count, quoteArc.dicQuote.Count, transactions.Count);

            var performance = new AccountPerformanceRaw();
            if (transactions.Count == 0) return performance;
            // скопировать списки сделок и транзакций, т.к. они будут модифицированы
            var dueDeals = deals.ToList();
            var dueTransactions = transactions.ToList();

            // посчитать результат
            decimal balance = 0;

            var lstEq = performance.equity;
            var lstLev = performance.leverage;

            // сформировать список дат - момент входа в рынок, конец дня
            // флаг (второй параметр) - означает конец дня
            var dateList = new List<Cortege2<DateTime, bool>>();
            for (var date = timeStart.Date; date <= timeEnd; date = date.AddDays(1))
            {
                var nextDate = date.AddDays(1);
                // сделки за день
                for (var i = 0; i < dueDeals.Count; i++)
                {
                    if (dueDeals[i].TimeEnter > nextDate) continue;
                    dateList.Add(new Cortege2<DateTime, bool>(dueDeals[i].TimeEnter, false));
                    dueDeals.RemoveAt(i);
                    i--;
                }

                // конец дня
                dateList.Add(new Cortege2<DateTime, bool>(date, true));
            }
            dateList = dateList.OrderBy(d => d.a).ToList();
            dueDeals = deals.ToList();

            foreach (var datePart in dateList)
            {
                var date = datePart.a;
                var isEndOfDay = datePart.b;

                if (DaysOff.Instance.IsDayOff(date)) continue;
                // добавить сумму транзакции
                for (var i = 0; i < dueTransactions.Count; i++)
                {
                    var trans = dueTransactions[i];
                    if (date < trans.ValueDate) continue;
                    balance += trans.SignedAmountDepo;
                    dueTransactions.RemoveAt(i);
                    i--;
                }
                if (balance == 0) continue;

                // посчитать результат по открытым сделкам
                // и суммировать плечи по открытым сделкам
                var openResult = 0f;
                for (var i = 0; i < dueDeals.Count; i++)
                {
                    var deal = dueDeals[i];
                    // удалить закрытую сделку
                    if (deal.TimeExit.HasValue && deal.TimeExit.Value < date)
                    {
                        // учесть объем сделки второй раз - на закрытии
                        performance.totalTradedVolume += (long)Math.Round(deal.VolumeInDepoCurrency);
                        dueDeals.RemoveAt(i);
                        i--;
                        continue;
                    }

                    if (date < deal.TimeEnter || date > deal.TimeExit) continue;
                    // получить текущую котиру
                    if (!quoteArc.dicQuote.ContainsKey(deal.Symbol)) continue;
                    var quote = quoteArc.GetQuoteOnDateSeq(deal.Symbol, date);
                    if (quote == null) continue;

                    if (deal.VolumeInDepoCurrency == 0)
                    {
                        CalculateDealVolumeInDepoCurrency(deal, quote, depoCurrency, quoteArc, date);
                        performance.totalTradedVolume += (long)Math.Round(deal.VolumeInDepoCurrency);
                    }

                    // текущая прибыль по сделке
                    var dealProfit = deal.CalculateProfit(quote);
                    // перевести в валюту депо
                    dealProfit = CalculateProfitInDepoCurx(false, dealProfit, deal.Symbol, depoCurrency, quoteArc, date);
                    openResult += dealProfit;
                }

                // посчитать плечо по сделкам
                var dealByTicker = dueDeals.Where(d => d.TimeEnter < date).GroupBy(x => x.Symbol).ToDictionary(d => d.Key, d => d.ToList());
                var sumVolumeDepo = dealByTicker.Sum(d =>
                    {
                        var totalVolume = Math.Abs(d.Value.Sum(order => order.Side*order.Volume));
                        if (totalVolume == 0) return 0;
                        return CalculateProfitInDepoCurx(true, totalVolume, d.Key, depoCurrency, quoteArc, date);
                    });

                var equity = balance + (decimal)openResult;
                var leverage = equity == 0 ? 0 : (decimal)sumVolumeDepo / equity;

                // добавить точки в кривые
                if (isEndOfDay)
                    lstEq.Add(new EquityOnTime((float)equity, date));
                lstLev.Add(new EquityOnTime((float)leverage, date));
            }

            var dateNow = DateTime.Now;
            // открытым сделкам посчитать текущую прибыль / убыток
            foreach (var deal in dueDeals)
            {
                var quote = quoteArc.GetLastQuote(deal.Symbol, dateNow);
                if (quote == null) continue;

                // условно - цена выхода
                deal.PriceExit = deal.Side > 0 ? quote.bid : quote.ask;
                var dealProfit = deal.CalculateProfit(quote);
                // перевести в валюту депо
                dealProfit = CalculateProfitInDepoCurx(false, dealProfit, deal.Symbol, depoCurrency, quoteArc, dateNow);
                deal.ResultDepo = dealProfit;
            }

            return performance;
        }
 public AccountPerformanceRaw CalculateEquityCurve(List<MarketOrder> deals, string depoCurrency, QuoteArchive quoteArc, List<BalanceChange> transactions)
 {
     var timeStart = transactions.Min(t => t.ValueDate);
     return CalculateEquityCurve(deals, depoCurrency, quoteArc, transactions, timeStart, DateTime.Now);
 }
        /// <summary>
        /// Пересчитать указанный профит по сделке в профит в валюте депозита
        /// </summary>
        public float CalculateProfitInDepoCurx(bool useBase, float profit, string dealTicker, string depoCurrency, QuoteArchive arc, DateTime date)
        {
            bool inverse, pairsAreEqual;
            var smb = DalSpot.Instance.FindSymbol(dealTicker, useBase, depoCurrency, out inverse, out pairsAreEqual);
            if (pairsAreEqual) return profit;

            if (string.IsNullOrEmpty(smb)) return 0;
            // найти котиру по символу
            var quote = arc.GetQuoteOnDateSeq(smb, date);
            if (quote == null) return 0;
            return inverse
                       ? profit / quote.GetPrice(QuoteType.Middle)
                       : profit * quote.GetPrice(QuoteType.Middle);
        }
Пример #10
0
        /// <summary>
        /// Основной метод, рассчитыввающий статистику
        /// </summary>
        public Dictionary<int, AccountPerformanceRaw> GetPerformanceStatistic(BackgroundWorker worker)
        {
            var accountPerformance = new Dictionary<int, AccountPerformanceRaw>();
            const int ProgressForQuotes = 50;
            const int ProgressForDeals = 50;

            try
            {
                var dicQuote = new Dictionary<string, List<QuoteData>>();
                var symbolsUsed = DalSpot.Instance.GetTickerNames();
                var progressCounter = 0;
                foreach (var smb in symbolsUsed)
                {
                    if (worker.CancellationPending) return accountPerformance;
                    dicQuote.Add(smb, LoadTickerQuotesFromFile(smb).Select(q => new QuoteData(q.b, q.b, q.a)).ToList());
                    var progress = (++progressCounter)*100/symbolsUsed.Length*ProgressForQuotes/100;
                    worker.ReportProgress(progress);
                }
                var quoteArc = new QuoteArchive(dicQuote);

                AccountDealContainer.SymbolsUsed = symbolsUsed;
                var containers = DealFileNames.Select(x => new AccountDealContainer(x)).ToList();

                progressCounter = 0;
                foreach (var container in containers)
                {
                    if (worker.CancellationPending) return accountPerformance;
                    accountPerformance.Add(container.Id,
                        equityCurveCalculator.CalculateEquityCurve(
                            container.Deals,
                            DepoCurrency,
                            quoteArc,
                            container.Transactions,
                            container.TimeStart,
                            container.TimeEnd)
                        );
                    var progress = ProgressForQuotes + (++progressCounter) * 100 / containers.Count * ProgressForDeals / 100;
                    worker.ReportProgress(progress);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("GetStat()", ex);
            }
            return accountPerformance;
        }