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,
                            "При инициализированных всех данных и метод не вернул правильное значение");
        }
Esempio n. 2
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);
        }
        /// <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, "Метод рассчитал значение прибыли по сделке не правильно");
        }
        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);
        }
Esempio n. 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);
        }
        /// <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 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);
        }
        /// <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));
        }
        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));
        }