Exemplo n.º 1
0
        public ProfitInfo GetTotalReport(ProfitInfo[] profits)
        {
            var total = new ProfitInfo();

            foreach (var profit in profits)
            {
                total.TradesCount      += profit.TradesCount;
                total.BuysCount        += profit.BuysCount;
                total.SellsCount       += profit.SellsCount;
                total.TotalBought      += profit.TotalBought;
                total.TotalSold        += profit.TotalSold;
                total.TotalBoughtQuote += profit.TotalBoughtQuote;
                total.TotalSoldQuote   += profit.TotalSoldQuote;
                total.Pnl              += profit.Pnl;
                total.PnlNoExcess      += profit.PnlNoExcess;
                total.PnlWithFee       += profit.PnlWithFee;
                total.DisplayWithFee    = profit.DisplayWithFee;
                total.QuoteSymbol       = profit.QuoteSymbol;
                total.BaseSymbol        = profit.BaseSymbol;
                total.MaxInventory      = profit.MaxInventory;
                total.MaxInventoryLimit = profit.MaxInventoryLimit;
                total.OrderSize         = profit.OrderSize;
            }

            total.AverageBuyPrice  = total.TotalBoughtQuote / total.TotalBought;
            total.AverageSellPrice = total.TotalSoldQuote / total.TotalSold;

            var formattedTotal = $"{total} with excess";

            total.Report = formattedTotal;
            total.Day    = null;
            total.Month  = null;
            total.Year   = null;
            return(total);
        }
Exemplo n.º 2
0
        public ProfitInfo[] GetReportPerDays(int year, int month)
        {
            var grouped = _trades
                          .Where(x => x.TimestampDate.Month == month)
                          .GroupBy(x => x.TimestampDate.Day);
            var reports = new List <ProfitInfo>();

            ProfitInfo total = null;

            foreach (var group in grouped)
            {
                var trades    = group.ToArray();
                var dayReport = GetReport(trades.ToArray());
                var formatted = $"day:   {group.Key:00}, {dayReport}";
                dayReport.Report = formatted;
                dayReport.Day    = group.Key;
                dayReport.Year   = year;
                dayReport.Month  = month;
                reports.Add(dayReport);

                if (total == null)
                {
                    total             = dayReport.Clone();
                    total.AverageBuy  = 0;
                    total.AverageSell = 0;
                }
                else
                {
                    total.TradesCount += dayReport.TradesCount;
                    total.BuysCount   += dayReport.BuysCount;
                    total.SellsCount  += dayReport.SellsCount;
                    total.TotalBought += dayReport.TotalBought;
                    total.TotalSold   += dayReport.TotalSold;
                    total.Pnl         += dayReport.Pnl;
                    total.PnlNoExcess += dayReport.PnlNoExcess;
                    total.PnlWithFee  += dayReport.PnlWithFee;
                }
            }

            if (total != null)
            {
                var formattedTotal = $"total: __, {total}";
                total.Report = formattedTotal;
                total.Day    = null;
                reports.Add(total);
            }

            return(reports.ToArray());
        }
Exemplo n.º 3
0
        private static void Visualize(BacktestConfig backtest, ProfitComputer computer, IStrategy strategy,
                                      int maxInv, ProfitInfo report, ProfitInfo[] days, ProfitInfo[] months)
        {
            if (computer == null || backtest.Visualize == null || !backtest.Visualize.Value)
            {
                return;
            }

            PrepareWebVisualization(backtest, computer, strategy, maxInv, report, report, days, months);

            var chart        = new ChartVisualizer();
            var filename     = Path.GetFileName(backtest.DirectoryPath);
            var strategyName = strategy.GetType().Name.ToLower();
            var pnl          = report.Pnl;
            var name         = $"{pnl:#.00} {backtest.QuoteSymbol} (max inv: {maxInv}) ";
            var nameWithFee  = $"{report.PnlWithFee:#.00} {backtest.QuoteSymbol} (max inv: {maxInv}) ";

            var dir        = GetPathToReportDir(backtest);
            var pattern    = ExtractFromPattern(backtest);
            var targetFile = Path.Combine(dir, $"{pattern}__{strategyName}__{maxInv}__{pnl:0}");

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            var bars      = computer.Bars;
            var totalBars = bars.Length;

            if (backtest.VisualizeSkipBars.HasValue)
            {
                bars = bars.Skip(backtest.VisualizeSkipBars.Value).ToArray();
            }
            if (backtest.VisualizeLimitBars.HasValue)
            {
                bars = bars.Take(backtest.VisualizeLimitBars.Value).ToArray();
            }

            var minIndex = bars.Min(x => x.Index);
            var maxIndex = bars.Max(x => x.Index);

            var trades = computer.Trades
                         .Where(x => x.BarIndex >= minIndex && x.BarIndex <= maxIndex)
                         .ToArray();

            chart.Plot(name, nameWithFee, targetFile, totalBars, bars, trades, days, months);
        }
Exemplo n.º 4
0
        public ProfitInfo[] GetReportByMonth()
        {
            var grouped = _trades.GroupBy(x => new { x.TimestampDate.Year, x.TimestampDate.Month });
            var reports = new List <ProfitInfo>();

            ProfitInfo total = null;

            foreach (var group in grouped)
            {
                var trades      = group.ToArray();
                var monthReport = GetReport(trades.ToArray());
                var formatted   = $"month: {group.Key.Month:00}/{group.Key.Year}, {monthReport}";
                monthReport.Report = formatted;
                monthReport.Year   = group.Key.Year;
                monthReport.Month  = group.Key.Month;
                reports.Add(monthReport);

                if (total == null)
                {
                    total             = monthReport.Clone();
                    total.AverageBuy  = 0;
                    total.AverageSell = 0;
                }
                else
                {
                    total.TradesCount += monthReport.TradesCount;
                    total.BuysCount   += monthReport.BuysCount;
                    total.SellsCount  += monthReport.SellsCount;
                    total.TotalBought += monthReport.TotalBought;
                    total.TotalSold   += monthReport.TotalSold;
                    total.Pnl         += monthReport.Pnl;
                    total.PnlNoExcess += monthReport.PnlNoExcess;
                    total.PnlWithFee  += monthReport.PnlWithFee;
                }
            }

            if (total != null)
            {
                var formattedTotal = $"total: __, {total}";
                total.Report = formattedTotal;
                total.Month  = null;
                reports.Add(total);
            }

            return(reports.ToArray());
        }
        public static ProfitInfo ComputeProfitComplex(TradeModel[] executedOrders, double fee)
        {
            double diff = 0;
            var    bids = executedOrders.Where(x => x.Amount > 0).OrderBy(x => x.Timestamp).ToArray();
            var    asks = executedOrders.Where(x => x.Amount < 0).OrderBy(x => x.Timestamp).ToArray();

            var totalBidAmount = bids.Sum(x => Math.Abs(x.Amount));
            var totalAskAmount = asks.Sum(x => Math.Abs(x.Amount));
            var excessAmount   = totalBidAmount - totalAskAmount;

            var totalBidQuote = bids.Sum(x => Math.Abs(x.Amount * x.Price));
            var totalAskQuote = asks.Sum(x => Math.Abs(x.Amount * x.Price));

            var result = new ProfitInfo()
            {
                Pnl              = 0,
                TradesCount      = executedOrders.Length,
                BuysCount        = bids.Length,
                SellsCount       = asks.Length,
                TotalBought      = totalBidAmount,
                TotalSold        = totalAskAmount,
                TotalBoughtQuote = totalBidQuote,
                TotalSoldQuote   = totalAskQuote,
                AverageBuyPrice  = ComputeAveragePrice(bids),
                AverageSellPrice = ComputeAveragePrice(asks),
                WinRate          = ComputeWinRate(executedOrders),
                ExcessAmount     = excessAmount
            };

            if (!bids.Any() || !asks.Any())
            {
                return(result);
            }

            var amountForBid = totalBidAmount;

            foreach (var bidTrade in bids)
            {
                var amount = bidTrade.Amount;
                var price  = bidTrade.Price;
                amountForBid -= amount;
                if (amountForBid >= 0)
                {
                    diff -= ComputeOrderValue(amount, price, fee, true);
                }
                else
                {
                    var amountTmp = amount + amountForBid;
                    diff -= ComputeOrderValue(amountTmp, price, fee, true);
                    break;
                }
            }

            var amountForSell = totalAskAmount;

            foreach (var askTrade in asks)
            {
                var amount = Math.Abs(askTrade.Amount);
                var price  = askTrade.Price;
                amountForSell -= amount;
                if (amountForSell >= 0)
                {
                    diff += ComputeOrderValue(amount, price, fee, false);
                }
                else
                {
                    var amountTmp = amount + amountForSell;
                    diff += ComputeOrderValue(amountTmp, price, fee, false);
                    break;
                }
            }

            double lastTrade;

            if (excessAmount > 0)
            {
                var lastPrice = bids.LastOrDefault()?.Price ?? 0;
                lastTrade = excessAmount * lastPrice;
            }
            else
            {
                var lastPrice = asks.LastOrDefault()?.Price ?? 0;
                lastTrade = excessAmount * lastPrice;
            }

            var totalDiff = diff + lastTrade;

            result.PnlNoExcess = ComputeProfitNoExcess(executedOrders, fee);
            result.Pnl         = totalDiff;
            return(result);
        }
        public ProfitInfo[] GetReportPerDays(int year, int month, ref double maxTotalPnl, ref double minTotalPnl, ref double totalPnl)
        {
            var grouped = _trades
                          .Where(x => x.TimestampDate.Year == year && x.TimestampDate.Month == month)
                          .GroupBy(x => x.TimestampDate.Day)
                          .ToArray();
            var reports = new List <ProfitInfo>();

            ProfitInfo total = null;

            for (int i = 0; i < grouped.Length; i++)
            {
                var group      = grouped[i];
                var last       = group.Last();
                var nextTrades = _trades
                                 .Where(x => x.TimestampDate > last.TimestampDate)
                                 .OrderBy(x => x.TimestampDate)
                                 .ToArray();

                var trades    = group.ToArray();
                var dayReport = GetReport(trades.ToArray(), nextTrades);
                if (dayReport == ProfitInfo.Empty)
                {
                    continue;
                }

                if (total == null)
                {
                    total                  = dayReport.Clone();
                    total.Pnl             += totalPnl;
                    total.AverageBuyPrice  = 0;
                    total.AverageSellPrice = 0;
                }
                else
                {
                    total.TradesCount      += dayReport.TradesCount;
                    total.BuysCount        += dayReport.BuysCount;
                    total.SellsCount       += dayReport.SellsCount;
                    total.TotalBought      += dayReport.TotalBought;
                    total.TotalSold        += dayReport.TotalSold;
                    total.TotalBoughtQuote += dayReport.TotalBoughtQuote;
                    total.TotalSoldQuote   += dayReport.TotalSoldQuote;
                    total.Pnl         += dayReport.Pnl;
                    total.PnlNoExcess += dayReport.PnlNoExcess;
                    total.PnlWithFee  += dayReport.PnlWithFee;
                }

                var previousMaxPnl = maxTotalPnl;
                maxTotalPnl = Math.Max(maxTotalPnl, total.Pnl);

                if (maxTotalPnl > previousMaxPnl)
                {
                    minTotalPnl = maxTotalPnl;
                }

                minTotalPnl = Math.Min(minTotalPnl, total.Pnl);

                var drawdown = (minTotalPnl - maxTotalPnl) / maxTotalPnl;
                if (drawdown < 0)
                {
                    dayReport.MaxDrawdownPercentage = drawdown;
                }

                if (totalPnl <= 0)
                {
                    totalPnl = total.Pnl;
                }
                else
                {
                    dayReport.ProfitPercentage = (total.Pnl - totalPnl) / totalPnl;
                    totalPnl = total.Pnl;
                }

                var formatted = $"day:   {group.Key:00}, {dayReport}";
                dayReport.Report = formatted;
                dayReport.Day    = group.Key;
                dayReport.Year   = year;
                dayReport.Month  = month;
                reports.Add(dayReport);
            }

            //if (total != null)
            //{
            //    var formattedTotal = $"total: __, {total}";
            //    total.Report = formattedTotal;
            //    total.Day = null;
            //    reports.Add(total);
            //}

            return(reports.ToArray());
        }