コード例 #1
0
        public static async void BackTestAllConsole(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            List <BackTestStrategyResult> results = await BackTestAll(backtestOptions, dataStore);

            Console.WriteLine();
            Console.WriteLine($"\t=============== BACKTESTING REPORT ===============");
            Console.WriteLine();
            ConsoleUtility.WriteColoredLine($"\tNote: Profit is based on trading with 0.1 BTC each trade.", ConsoleColor.Cyan);
            Console.WriteLine();

            // Prints the results for each coin for this strategy.
            if (results.Count > 0)
            {
                Console.WriteLine(results
                                  .OrderByDescending(x => x.SuccessRate)
                                  .ToList()
                                  .ToStringTable(new[] { "Strategy", "# Trades", "# Profitable", "Success Rate", "BTC Profit", "Profit %", "Avg. Duration", "Max. Period" },
                                                 (x) => x.Strategy,
                                                 (x) => x.AmountOfTrades,
                                                 (x) => x.AmountOfProfitableTrades,
                                                 (x) => $"{x.SuccessRate:0.00}%",
                                                 (x) => $"{x.TotalProfit:0.00000000}",
                                                 (x) => $"{x.TotalProfitPercentage:0.00}%",
                                                 (x) => $"{(x.AverageDuration):0.00} hours",
                                                 (x) => $"{x.DataPeriod} days"));
            }
            else
            {
                ConsoleUtility.WriteColoredLine("\tNo backtests results found...", ConsoleColor.Red);
            }
            ConsoleUtility.WriteSeparator();
        }
コード例 #2
0
        public async Task SaveTradeSignals(BacktestOptions backtestOptions, IDataStoreBacktest dataStore, List <TradeSignal> signals)
        {
            if (backtestOptions.EndDate == DateTime.MinValue)
            {
                backtestOptions.EndDate = DateTime.UtcNow;
            }

            await dataStore.SaveBacktestTradeSignalsBulk(signals, backtestOptions);
        }
コード例 #3
0
        public static void GetCacheAgeConsole(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            Console.WriteLine("\tBacktest StartDate: " + Convert.ToDateTime(backtestOptions.StartDate).ToUniversalTime() + " UTC");
            if (backtestOptions.EndDate != DateTime.MinValue)
            {
                Console.WriteLine("\tBacktest EndDate: " + Convert.ToDateTime(backtestOptions.EndDate).ToUniversalTime() + " UTC");
            }
            else
            {
                Console.WriteLine("\tBacktest EndDate: " + DateTime.UtcNow + " UTC");
            }

            Console.WriteLine("");

            int dataCount = 0;

            foreach (var globalSymbol in backtestOptions.Coins)
            {
                backtestOptions.Coin = globalSymbol;

                Candle currentHistoricalDataFirst = dataStore.GetBacktestFirstCandle(backtestOptions).Result;
                Candle currentHistoricalDataLast  = dataStore.GetBacktestLastCandle(backtestOptions).Result;
                if (currentHistoricalDataFirst != null && currentHistoricalDataLast != null)
                {
                    Console.WriteLine("\tAvailable Cache for " + backtestOptions.Exchange + " " + globalSymbol + " Period: " + backtestOptions.CandlePeriod + "min  - from " + currentHistoricalDataFirst.Timestamp.ToUniversalTime() + " until " + currentHistoricalDataLast.Timestamp.ToUniversalTime());
                    dataCount = dataCount + 1;
                }
            }

            if (dataCount == 0)
            {
                Console.WriteLine("\tNo data - Please run 4. Refresh candle data first");
            }

            Console.WriteLine();
        }
コード例 #4
0
        public static async Task <List <BackTestResult> > BackTest(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore, string baseCurrency, bool saveSignals, decimal startingWallet, decimal tradeAmount)
        {
            var runner  = new BackTestRunner();
            var results = await runner.RunSingleStrategy(strategy, backtestOptions, dataStore, baseCurrency, saveSignals, startingWallet, tradeAmount);

            return(results);
        }
コード例 #5
0
        public async Task <List <TradeSignal> > GetSignals(BacktestOptions backtestOptions, IDataStoreBacktest dataStore, string strategy)
        {
            if (backtestOptions.EndDate == DateTime.MinValue)
            {
                backtestOptions.EndDate = DateTime.UtcNow;
            }

            List <TradeSignal> items = await dataStore.GetBacktestSignalsByStrategy(backtestOptions, strategy);

            return(items);
        }
コード例 #6
0
        public async Task <List <Candle> > GetCandles(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            if (backtestOptions.EndDate == DateTime.MinValue)
            {
                backtestOptions.EndDate = DateTime.UtcNow;
            }

            List <Candle> candles = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions);

            return(candles);
        }
コード例 #7
0
        public static async Task <JArray> BackTestShowTradesJson(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            var results = await BackTestShowTrades(strategy, backtestOptions, dataStore);

            JArray jArrayResult = new JArray();

            var trades = new List <BackTestTradeResult>();

            foreach (var result in results)
            {
                trades.AddRange(result.Trades);
            }

            foreach (var trade in trades)
            {
                JObject currentResult = new JObject();
                currentResult["Strategy"]         = strategy.Name;
                currentResult["Market"]           = trade.Market;
                currentResult["OpenRate"]         = trade.OpenRate;
                currentResult["CloseRate"]        = trade.CloseRate;
                currentResult["Profit"]           = trade.Profit;
                currentResult["ProfitPercentage"] = trade.ProfitPercentage;
                currentResult["Duration"]         = trade.Duration;
                currentResult["StartDate"]        = trade.StartDate;
                currentResult["EndDate"]          = trade.EndDate;
                jArrayResult.Add(currentResult);
            }
            return(jArrayResult);
        }
コード例 #8
0
        public static async Task <JArray> GetCacheAge(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            var jArrayResult = new JArray();

            foreach (var globalSymbol in backtestOptions.Coins)
            {
                backtestOptions.Coin = globalSymbol;

                //Candle currentHistoricalDataFirst = await dataStore.GetBacktestFirstCandle(backtestOptions);
                //Candle currentHistoricalDataLast = await dataStore.GetBacktestLastCandle(backtestOptions);

#warning //TODO create a Count method

                var data = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions);

                Candle currentHistoricalDataFirst = data.FirstOrDefault();
                Candle currentHistoricalDataLast  = data.LastOrDefault();

                if (currentHistoricalDataFirst != null && currentHistoricalDataLast != null)
                {
                    var dataFirst            = currentHistoricalDataFirst.Timestamp.ToUniversalTime();
                    var dataLast             = currentHistoricalDataLast.Timestamp.ToUniversalTime();
                    var minutes              = dataLast.Subtract(dataFirst).TotalMinutes;
                    var numOfCandles         = data.Count();
                    var numOfExpectedCandles = minutes / backtestOptions.CandlePeriod;

                    var currentResult = new JObject();
                    currentResult["Exchange"]           = backtestOptions.Exchange.ToString();
                    currentResult["Coin"]               = globalSymbol;
                    currentResult["CandlePeriod"]       = backtestOptions.CandlePeriod;
                    currentResult["FirstCandleDate"]    = dataFirst;
                    currentResult["LastCandleDate"]     = dataLast;
                    currentResult["CandlesNum"]         = numOfCandles;
                    currentResult["ExpectedCandlesNum"] = numOfExpectedCandles;
                    jArrayResult.Add(currentResult);
                }
            }
            return(jArrayResult);
        }
コード例 #9
0
        public static async Task <bool> CheckForCandleData(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            List <string> allDatabases = await dataStore.GetBacktestAllDatabases(backtestOptions);

            if (allDatabases.Count == 0)
            {
                return(false);
            }
            return(true);
        }
コード例 #10
0
        public static async void BackTestConsole(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            List <BackTestResult> results = await BackTest(strategy, backtestOptions, dataStore);

            if (results.Count > 0)
            {
                Console.WriteLine(results
                                  .OrderByDescending(x => x.SuccessRate)
                                  .ToList()
                                  .ToStringTable(new[] { "Market", "# Trades", "# Profitable", "Success Rate", "BTC Profit", "Profit %", "Avg. Duration", "Period" },
                                                 (x) => x.Market,
                                                 (x) => x.AmountOfTrades,
                                                 (x) => x.AmountOfProfitableTrades,
                                                 (x) => $"{x.SuccessRate:0.00}%",
                                                 (x) => $"{x.TotalProfit:0.00000000}",
                                                 (x) => $"{x.TotalProfitPercentage:0.00}%",
                                                 (x) => $"{(x.AverageDuration):0.00} hours",
                                                 (x) => $"{x.DataPeriod} days"));
            }
            else
            {
                ConsoleUtility.WriteColoredLine("\tNo backtests results found...", ConsoleColor.Red);
            }
            ConsoleUtility.WriteSeparator();
        }
コード例 #11
0
        public static async Task <JArray> BackTestJson(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            List <BackTestResult> results = await BackTest(strategy, backtestOptions, dataStore);

            JArray jArrayResult = new JArray();

            if (results.Count > 0)
            {
                foreach (var result in results)
                {
                    JObject currentResult = new JObject();
                    currentResult["Market"]                   = result.Market;
                    currentResult["Strategy"]                 = strategy.Name;
                    currentResult["AmountOfTrades"]           = result.AmountOfTrades;
                    currentResult["AmountOfProfitableTrades"] = result.AmountOfProfitableTrades;
                    currentResult["SuccessRate"]              = result.SuccessRate;
                    currentResult["TotalProfit"]              = result.TotalProfit;
                    currentResult["TotalProfitPercentage"]    = result.TotalProfitPercentage;
                    currentResult["AverageDuration"]          = result.AverageDuration;
                    currentResult["DataPeriod"]               = result.DataPeriod;
                    jArrayResult.Add(currentResult);
                }
            }
            return(jArrayResult);
        }
コード例 #12
0
        public static async Task <JArray> BackTestAllJson(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            List <BackTestStrategyResult> results = await BackTestAll(backtestOptions, dataStore);

            JArray jArrayResult = new JArray();

            foreach (var result in results)
            {
                JObject currentResult = new JObject();
                currentResult["Strategy"]                 = result.Strategy;
                currentResult["AmountOfTrades"]           = result.AmountOfTrades;
                currentResult["AmountOfProfitableTrades"] = result.AmountOfProfitableTrades;
                currentResult["SuccessRate"]              = result.SuccessRate;
                currentResult["TotalProfit"]              = result.TotalProfit;
                currentResult["TotalProfitPercentage"]    = result.TotalProfitPercentage;
                currentResult["AverageDuration"]          = result.AverageDuration;
                currentResult["DataPeriod"]               = result.DataPeriod;
                jArrayResult.Add(currentResult);
            }
            return(jArrayResult);
        }
コード例 #13
0
        public static async Task <List <BackTestStrategyResult> > BackTestAll(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            var runner  = new BackTestRunner();
            var results = new List <BackTestStrategyResult>();

            foreach (var item in GetTradingStrategies())
            {
                var stratResult = new BackTestStrategyResult()
                {
                    Strategy = item.Name
                };
                stratResult.Results.AddRange(await runner.RunSingleStrategy(item, backtestOptions, dataStore));
                results.Add(stratResult);
            }

            return(results);
        }
コード例 #14
0
        public static async void BackTestShowTradesConsole(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            var results = await BackTestShowTrades(strategy, backtestOptions, dataStore);

            Console.WriteLine();
            Console.WriteLine($"\t=============== BACKTESTING REPORT {strategy.Name.ToUpper()} ===============");
            Console.WriteLine();
            ConsoleUtility.WriteColoredLine($"\tNote: Profit is based on trading with 0.1 BTC each trade.", ConsoleColor.Cyan);
            Console.WriteLine();

            // Prints the results for each coin for this strategy.

            if (results.Count > 0)
            {
                var trades = new List <BackTestTradeResult>();

                foreach (var result in results)
                {
                    trades.AddRange(result.Trades);
                }

                Console.WriteLine(trades
                                  .OrderBy(x => x.StartDate)
                                  .ToList()
                                  .ToStringTable(new[] { "Market", "Open", "Close", "BTC Profit", "Profit %", "Duration", "Startdate", "Enddate" },
                                                 (x) => x.Market,
                                                 (x) => $"{x.OpenRate:0.00000000}",
                                                 (x) => $"{x.CloseRate:0.00000000}",
                                                 (x) => $"{x.Profit:0.00000000}",
                                                 (x) => $"{x.ProfitPercentage:0.00}%",
                                                 (x) => $"{(x.Duration):0.00} hours",
                                                 (x) => $"{x.StartDate:dd-MM-yyyy hh:mm}",
                                                 (x) => $"{x.EndDate:dd-MM-yyyy hh:mm}"));
            }
            else
            {
                ConsoleUtility.WriteColoredLine("\tNo backtests results found...", ConsoleColor.Red);
            }
            ConsoleUtility.WriteSeparator();
        }
コード例 #15
0
        public static async Task <JArray> BackTestJson(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore, string baseCurrency, bool saveSignals, decimal startingWallet, decimal tradeAmount)
        {
            var results = await BackTest(strategy, backtestOptions, dataStore, baseCurrency, saveSignals, startingWallet, tradeAmount);

            var jArrayResult = new JArray();

            if (results.Count > 0)
            {
                var resultsSummary = new BackTestStrategyResult();
                resultsSummary.Results          = results;
                resultsSummary.Strategy         = strategy.Name;
                resultsSummary.ConcurrentTrades = results.First().ConcurrentTrades;
                resultsSummary.Wallet           = results.First().Wallet;
                resultsSummary.LowWallet        = results.First().LowWallet;

                var endWallet            = Math.Round(resultsSummary.Wallet, 3);
                var walletRealPercentage = Math.Round(((resultsSummary.Wallet - startingWallet) / startingWallet) * 100, 3);
                var lowWallet            = Math.Round(resultsSummary.LowWallet, 3);

                var currentResult1 = new JObject();
                currentResult1["Strategy"]                 = resultsSummary.Strategy;
                currentResult1["ConcurrentTrades"]         = resultsSummary.ConcurrentTrades;
                currentResult1["Wallet"]                   = endWallet + " " + baseCurrency + " (" + walletRealPercentage + "%)";
                currentResult1["LowWallet"]                = lowWallet;
                currentResult1["AmountOfTrades"]           = resultsSummary.AmountOfTrades;
                currentResult1["AmountOfProfitableTrades"] = resultsSummary.AmountOfProfitableTrades;
                currentResult1["SuccessRate"]              = resultsSummary.SuccessRate;
                currentResult1["TotalProfit"]              = resultsSummary.TotalProfit;
                currentResult1["TotalProfitPercentage"]    = resultsSummary.TotalProfitPercentage;
                currentResult1["AverageDuration"]          = resultsSummary.AverageDuration;
                currentResult1["DataPeriod"]               = resultsSummary.DataPeriod;
                currentResult1["BaseCurrency"]             = baseCurrency;
                jArrayResult.Add(currentResult1);

                foreach (var result in results)
                {
                    var currentResult = new JObject();
                    currentResult["Market"]                   = result.Market;
                    currentResult["Strategy"]                 = strategy.Name;
                    currentResult["AmountOfTrades"]           = result.AmountOfTrades;
                    currentResult["AmountOfProfitableTrades"] = result.AmountOfProfitableTrades;
                    currentResult["SuccessRate"]              = result.SuccessRate;
                    currentResult["TotalProfit"]              = result.TotalProfit;
                    currentResult["TotalProfitPercentage"]    = result.TotalProfitPercentage;
                    currentResult["AverageDuration"]          = result.AverageDuration;
                    currentResult["DataPeriod"]               = result.DataPeriod;

                    jArrayResult.Add(currentResult);
                }
            }

            return(jArrayResult);
        }
コード例 #16
0
        public static async Task FillCandlesGaps(Action <string> callback, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            BaseExchange baseExchangeApi = new BaseExchangeInstance().BaseExchange(backtestOptions.Exchange.ToString());

            foreach (string globalSymbol in backtestOptions.Coins)
            {
                string exchangeSymbol = await baseExchangeApi.GlobalSymbolToExchangeSymbol(globalSymbol);

                backtestOptions.Coin = globalSymbol;

                string currentlyRunningString = backtestOptions.Exchange + "_" + globalSymbol + "_" + backtestOptions.CandlePeriod;
                lock (CurrentlyRunningUpdates)
                {
                    if (CurrentlyRunningUpdates.ContainsKey(currentlyRunningString))
                    {
                        callback($"\tUpdate still in process:  {backtestOptions.Exchange.ToString()} " +
                                 $"with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} " +
                                 $"from {backtestOptions.StartDate} UTC to {DateTime.UtcNow.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                        return;
                    }
                    CurrentlyRunningUpdates[currentlyRunningString] = backtestOptions;
                }

                //current db candles
                var data = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions);

                Candle currentHistoricalDataFirst = data.FirstOrDefault();
                Candle currentHistoricalDataLast  = data.LastOrDefault();

                //there are data
                if (currentHistoricalDataFirst != null && currentHistoricalDataLast != null)
                {
                    var dataFirst            = currentHistoricalDataFirst.Timestamp.ToUniversalTime();
                    var dataLast             = currentHistoricalDataLast.Timestamp.ToUniversalTime();
                    var minutes              = dataLast.Subtract(dataFirst).TotalMinutes;
                    var numOfExpectedCandles = minutes / backtestOptions.CandlePeriod + 1;
                    var numOfCandles         = data.Count();

                    callback($"\t- Check database\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                             $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                             $"\tfrom {dataFirst} \tto {dataLast} UTC " +
                             $"expected:{numOfExpectedCandles}, have:{numOfCandles}");

                    if ((numOfExpectedCandles / numOfCandles) != 1) //found holes/multiple overall
                    {
                        callback($"\tFound overall holes\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                 $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                 $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC " +
                                 $"expected:{numOfExpectedCandles}, have:{numOfCandles}");

                        DateTime startDate = dataFirst;
                        DateTime endDate   = dataLast;

                        //date range inspector
                        while (startDate < endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod)))
                        {
                            backtestOptions.StartDate = startDate;
                            backtestOptions.EndDate   = backtestOptions.StartDate.AddHours(1).RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod));

                            //candles of sub-period
                            var data2 = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions);

                            var minutes2 = backtestOptions.EndDate.Subtract(backtestOptions.StartDate).TotalMinutes;
                            var numOfExpectedCandles2 = (minutes2 / backtestOptions.CandlePeriod) + 1;
                            var numOfCandles2         = data2.Count();

                            callback($"\tCheck period\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                     $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                     $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC " +
                                     $"expected:{numOfExpectedCandles2}, have:{numOfCandles2} ");

                            //normalize dates

                            var expectedCandlesList = new List <DateTime>();
                            for (int i = 0; i < numOfExpectedCandles2; i++)
                            {
                                var t = backtestOptions.StartDate.AddMinutes(i * (int)backtestOptions.CandlePeriod.FromMinutesEquivalent());
                                expectedCandlesList.Add(t);
                            }

                            var newCandlesToAdd = new List <Candle>();
                            foreach (var expectedItem in expectedCandlesList)
                            {
                                Candle newAdd = null;

                                long min = long.MaxValue;
                                foreach (var dbItem in data2)
                                {
                                    var d = Math.Abs(expectedItem.Subtract(dbItem.Timestamp).Ticks);

                                    if (d == 0) //exact date
                                    {
                                        continue;
                                    }

                                    if (d < min)
                                    {
                                        min = d;

                                        var n = dbItem.DeepClone();
                                        n.Timestamp = expectedItem;
                                        newAdd      = n;
                                    }
                                }

                                //if distance is less then period (e.g. 15min)
                                if (newAdd != null && TimeSpan.FromTicks(min).TotalMinutes <= (int)backtestOptions.CandlePeriod.FromMinutesEquivalent() / 2)
                                {
                                    newCandlesToAdd.Add(newAdd);
                                }
                            }

                            if (newCandlesToAdd.Any())
                            {
                                foreach (var dbItem in data2)
                                {
                                    callback($"\t b dbItem: {dbItem.Timestamp} {dbItem.Close}");
                                }

                                await dataStore.DeleteBacktestCandles(backtestOptions);

                                await dataStore.SaveBacktestCandlesBulkCheckExisting(newCandlesToAdd, backtestOptions);

                                data2 = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions);

                                foreach (var dbItem in data2)
                                {
                                    callback($"\t a dbItem: {dbItem.Timestamp} {dbItem.Close}");
                                }
                            }

                            if (numOfCandles2 == 0 || (numOfExpectedCandles2 / numOfCandles2) != 1) //found holes/multiple in period or no candles
                            {
                                if (numOfCandles2 < numOfExpectedCandles2)                          //holes or nothing
                                {
                                    callback($"\tFound holes\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                             $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                             $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC " +
                                             $"expected:{numOfExpectedCandles2}, have:{numOfCandles2} ");
                                    try
                                    {
                                        List <Candle> candlesToAdd = await baseExchangeApi.GetTickerHistory(exchangeSymbol,
                                                                                                            backtestOptions.CandlePeriod.FromMinutesEquivalent(),
                                                                                                            backtestOptions.StartDate,
                                                                                                            backtestOptions.EndDate);

                                        //start tmp log
                                        foreach (var dbItem in data2)
                                        {
                                            callback($"\t dbItem: {dbItem.Timestamp} {dbItem.Close}");
                                        }

                                        for (int i = 0; i < numOfExpectedCandles2; i++)
                                        {
                                            var t = backtestOptions.StartDate.AddMinutes(i * (int)backtestOptions.CandlePeriod.FromMinutesEquivalent());
                                            callback($"\t expenctedItem: {t} ");
                                        }

                                        foreach (var excItem in candlesToAdd)
                                        {
                                            callback($"\t excItem: {excItem.Timestamp} {excItem.Close}");
                                        }
                                        //end tmp log

                                        if (candlesToAdd?.Count < numOfExpectedCandles2)//got less candle that required
                                        {
                                            callback($"\tNot enought data from Exchange\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                                     $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                                     $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC " +
                                                     $"expected:{numOfExpectedCandles2}, have:{numOfCandles2} ");

                                            Candle lastPeriodCandle = null;

                                            //exchange doesn't give data for period
                                            if (candlesToAdd?.Count == 0)
                                            {
                                                if (data2.Count == 0) //no data on db
                                                {
                                                    //precedent period
                                                    var backtestOptions2 = new BacktestOptions
                                                    {
                                                        DataFolder   = backtestOptions.DataFolder,
                                                        Exchange     = backtestOptions.Exchange,
                                                        Coin         = backtestOptions.Coin,
                                                        CandlePeriod = backtestOptions.CandlePeriod,
                                                        EndDate      = backtestOptions.StartDate
                                                    };

                                                    //last candle of precedent period
                                                    var c = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions2);

                                                    lastPeriodCandle = c?.LastOrDefault();

                                                    //insert last candle of precedent period in candles to save
                                                    if (lastPeriodCandle != null)
                                                    {
                                                        var cc = lastPeriodCandle.DeepClone();
                                                        cc.Timestamp = startDate;
                                                        candlesToAdd.Add(cc);
                                                    }
                                                }
                                                else //data on db for period
                                                {
                                                    //understand where is hole
                                                    var innerExpected = expectedCandlesList.DeepClone();
                                                    innerExpected.RemoveAll(i => data2.Select(d => d.Timestamp).Contains(i));

                                                    foreach (var expectedItem in innerExpected)
                                                    {
                                                        bool found = false;
                                                        for (int i = 0; i < data2.Count; i++)
                                                        {
                                                            if (expectedItem == data2[i].Timestamp)
                                                            {
                                                                found = true;
                                                                continue;
                                                            }
                                                        }

                                                        if (!found)
                                                        {
                                                            //find the close to
                                                            Candle newAdd = null;

                                                            long min = long.MaxValue;
                                                            foreach (var dbItem in data2)
                                                            {
                                                                var d = Math.Abs(expectedItem.Subtract(dbItem.Timestamp).Ticks);

                                                                if (d < min)
                                                                {
                                                                    min = d;

                                                                    if (min == 0) //exact date
                                                                    {
                                                                        continue;
                                                                    }

                                                                    var n = dbItem.DeepClone();
                                                                    n.Timestamp = expectedItem;
                                                                    newAdd      = n;
                                                                }
                                                            }

                                                            if (newAdd != null)
                                                            {
                                                                candlesToAdd.Add(newAdd);
                                                            }
                                                        }
                                                    }
                                                }
                                            }

                                            candlesToAdd = candlesToAdd.OrderBy(c => c.Timestamp).ToList();

                                            var newCandlesToAdd2 = new List <Candle>();
                                            //find definitive position
                                            foreach (var excItem in candlesToAdd)
                                            {
                                                Candle newAdd = null;

                                                long min = long.MaxValue;
                                                foreach (var expectedItem in expectedCandlesList)
                                                {
                                                    var d = Math.Abs(expectedItem.Subtract(excItem.Timestamp).Ticks);

                                                    if (d < min)
                                                    {
                                                        min = d;

                                                        var n = excItem.DeepClone();
                                                        n.Timestamp = expectedItem;
                                                        newAdd      = n;
                                                    }
                                                }

                                                newCandlesToAdd2.Add(newAdd);
                                            }

                                            //fill holes
                                            foreach (var expectedItem in expectedCandlesList)
                                            {
                                                Candle newAdd = null;

                                                long min = long.MaxValue;
                                                foreach (var dbItem in data2)
                                                {
                                                    var d = Math.Abs(expectedItem.Subtract(dbItem.Timestamp).Ticks);

                                                    if (d < min)
                                                    {
                                                        min = d;

                                                        if (d == 0) //exact date
                                                        {
                                                            continue;
                                                        }

                                                        var n = dbItem.DeepClone();
                                                        n.Timestamp = expectedItem;
                                                        newAdd      = n;
                                                    }
                                                }

                                                //if distance is less then period (e.g. 15min) and is not exact date
                                                if (min > 0 && TimeSpan.FromTicks(min).TotalMinutes <= (int)backtestOptions.CandlePeriod.FromMinutesEquivalent() / 2)
                                                {
                                                    newCandlesToAdd2.Add(newAdd);
                                                }
                                                else if (TimeSpan.FromTicks(min).TotalMinutes > (int)backtestOptions.CandlePeriod.FromMinutesEquivalent() / 2)//not found equivalence: clone
                                                {
                                                    var cc = candlesToAdd.Last().DeepClone();
                                                    cc.Timestamp = expectedItem;
                                                    newCandlesToAdd2.Add(cc);
                                                }
                                            }



                                            await dataStore.SaveBacktestCandlesBulkCheckExisting(newCandlesToAdd2, backtestOptions);

                                            callback($"\tUpdated cloning\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                                     $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                                     $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC ");

                                            startDate = backtestOptions.EndDate;
                                        }
                                        else //got right num of candles
                                        {
                                            await dataStore.SaveBacktestCandlesBulkCheckExisting(candlesToAdd, backtestOptions);

                                            callback($"\tUpdated from Exchange\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                                     $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                                     $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC ");

                                            startDate = candlesToAdd.Last().Timestamp.ToUniversalTime();
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        callback($"\tError while updating from\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                                 $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                                 $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC ");

                                        startDate = backtestOptions.EndDate;

                                        continue;
                                    }
                                }
                                else if (numOfCandles2 > numOfExpectedCandles2) //multiple
                                {
                                    callback($"\tFound multiple\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                             $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                             $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC " +
                                             $"expected:{numOfExpectedCandles2}, have:{numOfCandles2} ");

                                    foreach (var dbItem in data2)
                                    {
                                        callback($"\t dbItem: {dbItem.Timestamp} {dbItem.Close}");
                                    }

                                    await dataStore.DeleteBacktestCandles(backtestOptions);

                                    var expectedCandlesList2 = new List <DateTime>();

                                    for (int i = 0; i < numOfExpectedCandles2; i++)
                                    {
                                        var t = backtestOptions.StartDate.AddMinutes(i * (int)backtestOptions.CandlePeriod.FromMinutesEquivalent());
                                        expectedCandlesList2.Add(t);
                                    }

                                    List <Candle> candlesToAdd = await baseExchangeApi.GetTickerHistory(exchangeSymbol,
                                                                                                        backtestOptions.CandlePeriod.FromMinutesEquivalent(),
                                                                                                        backtestOptions.StartDate,
                                                                                                        backtestOptions.EndDate);

                                    var newCandlesToAdd2 = new List <Candle>();
                                    foreach (var expectedItem in expectedCandlesList2)
                                    {
                                        Candle newAdd = null;

                                        long min = long.MaxValue;
                                        foreach (var excItem in candlesToAdd)
                                        {
                                            var d = Math.Abs(expectedItem.Subtract(excItem.Timestamp).Ticks);

                                            if (d < min)
                                            {
                                                min = d;

                                                var n = excItem.DeepClone();
                                                n.Timestamp = expectedItem;
                                                newAdd      = n;
                                            }
                                        }

                                        //if distance is less then period (e.g. 15min)
                                        if (newAdd != null && TimeSpan.FromTicks(min).TotalMinutes <= (int)backtestOptions.CandlePeriod.FromMinutesEquivalent() / 2)
                                        {
                                            newCandlesToAdd2.Add(newAdd);
                                        }
                                    }

                                    await dataStore.SaveBacktestCandlesBulkCheckExisting(newCandlesToAdd2, backtestOptions);

                                    var data3 = await dataStore.GetBacktestCandlesBetweenTime(backtestOptions);

                                    foreach (var dbItem in data3)
                                    {
                                        callback($"\t dbItem: {dbItem.Timestamp} {dbItem.Close}");
                                    }

                                    startDate = newCandlesToAdd.Last().Timestamp.ToUniversalTime();
                                }
                            }
                            else
                            {
                                callback($"\tNo update\t: {backtestOptions.Exchange.ToString()} on {globalSymbol} " +
                                         $"with Period {backtestOptions.CandlePeriod.ToString()}min " +
                                         $"\tfrom {backtestOptions.StartDate.ToUniversalTime()} \tto {backtestOptions.EndDate.ToUniversalTime()} UTC ");

                                startDate = backtestOptions.EndDate;
                            }
                        }
                    }
                }

                lock (CurrentlyRunningUpdates)
                {
                    CurrentlyRunningUpdates.Remove(currentlyRunningString);
                }
            }
        }
コード例 #17
0
        public static async Task <List <BackTestResult> > BackTestShowTrades(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            var runner  = new BackTestRunner();
            var results = await runner.RunSingleStrategy(strategy, backtestOptions, dataStore);

            return(results);
        }
コード例 #18
0
        public static async Task RefreshCandleData(Action <string> callback, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            BaseExchange baseExchangeApi = new BaseExchangeInstance().BaseExchange(backtestOptions.Exchange.ToString());

            //var cts = new CancellationTokenSource();
            //var parallelOptions = new ParallelOptions();
            //parallelOptions.CancellationToken = cts.Token;
            //parallelOptions.MaxDegreeOfParallelism = Environment.ProcessorCount;
            //Parallel.ForEach(backtestOptions.Coins, parallelOptions, async globalSymbol =>
            //{
            foreach (string globalSymbol in backtestOptions.Coins)
            {
                string exchangeSymbol = await baseExchangeApi.GlobalSymbolToExchangeSymbol(globalSymbol);

                backtestOptions.Coin = globalSymbol;
                string currentlyRunningString = backtestOptions.Exchange + "_" + globalSymbol + "_" + backtestOptions.CandlePeriod;
                lock (CurrentlyRunningUpdates)
                {
                    if (CurrentlyRunningUpdates.ContainsKey(currentlyRunningString))
                    {
                        callback($"\tUpdate still in process:  {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} from {backtestOptions.StartDate} UTC to {DateTime.UtcNow.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                        return;
                    }
                    CurrentlyRunningUpdates[currentlyRunningString] = backtestOptions;
                }

                DateTime startDate      = Convert.ToDateTime(backtestOptions.StartDate).ToUniversalTime();
                DateTime endDate        = DateTime.UtcNow;
                bool     databaseExists = true;

                // Delete an existing file if this is no update
                if (!backtestOptions.UpdateCandles)
                {
                    dataStore.DeleteBacktestDatabase(backtestOptions).RunSynchronously();
                    callback($"\tRecreate database: {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} {startDate.ToUniversalTime()} to {endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                }
                else
                {
                    //candleCollection.EnsureIndex("Timestamp");
                    Candle databaseLastCandle = await dataStore.GetBacktestLastCandle(backtestOptions);

                    if (databaseLastCandle != null)
                    {
                        startDate = databaseLastCandle.Timestamp.ToUniversalTime();
                        callback($"\tUpdate database: {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} {startDate.ToUniversalTime()} to {endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                    }
                    else
                    {
                        callback($"\tCreate database: {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} {startDate.ToUniversalTime()} to {endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                        databaseExists = false;
                    }
                }

                if (startDate == endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod)))
                {
                    callback($"\tAlready up to date: {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} {startDate.ToUniversalTime()} to {endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                    lock (CurrentlyRunningUpdates)
                    {
                        CurrentlyRunningUpdates.Remove(currentlyRunningString);
                    }
                    return;
                }

                // Get these in batches of 500 because they're limited in the API.
                while (startDate < endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod)))
                {
                    try
                    {
                        //List<Candle> candles = await baseExchangeApi.GetChunkTickerHistory(exchangeSymbol, backtestOptions.CandlePeriod.FromMinutesEquivalent(), startDate, endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod)));
                        List <Candle> candles = await baseExchangeApi.GetTickerHistory(exchangeSymbol,
                                                                                       backtestOptions.CandlePeriod.FromMinutesEquivalent(),
                                                                                       startDate,
                                                                                       endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod)));

                        if (candles.Count == 0 || candles.Last().Timestamp.ToUniversalTime() == startDate)
                        {
                            callback($"\tNo update: {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} {startDate.ToUniversalTime()} to {endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                            break;
                        }
                        startDate = candles.Last().Timestamp.ToUniversalTime();

                        if (!databaseExists)
                        {
                            await dataStore.SaveBacktestCandlesBulk(candles, backtestOptions);

                            databaseExists = true;
                        }
                        else
                        {
                            await dataStore.SaveBacktestCandlesBulkCheckExisting(candles, backtestOptions);
                        }

                        callback($"\tUpdated: {backtestOptions.Exchange.ToString()} with Period {backtestOptions.CandlePeriod.ToString()}min for {globalSymbol} {startDate.ToUniversalTime()} to {endDate.RoundDown(TimeSpan.FromMinutes(backtestOptions.CandlePeriod))} UTC");
                    }
                    catch (Exception e)
                    {
                        callback($"\tError while updating: {backtestOptions.Exchange.ToString()} {globalSymbol}: {e.Message}");
                        break;
                    }
                }
                lock (CurrentlyRunningUpdates)
                {
                    CurrentlyRunningUpdates.Remove(currentlyRunningString);
                }
            }
        }
コード例 #19
0
        public async Task <List <BackTestResult> > RunSingleStrategy(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            var results = new List <BackTestResult>();

            // Go through our coinpairs and backtest them.
            foreach (string globalSymbol in backtestOptions.Coins)
            {
                var candleProvider = new DatabaseCandleProvider();
                backtestOptions.Coin = globalSymbol;

                // This creates a list of buy signals.
                var candles = await candleProvider.GetCandles(backtestOptions, dataStore);

                var backTestResult = new BackTestResult {
                    Market = globalSymbol
                };

                try
                {
                    var trend   = strategy.Prepare(candles);
                    var signals = new List <TradeSignal>();

                    for (int i = 0; i < trend.Count; i++)
                    {
                        if (trend[i] == TradeAdvice.Buy)
                        {
                            var id = Guid.NewGuid();

                            signals.Add(new TradeSignal
                            {
                                Id           = id,
                                MarketName   = globalSymbol,
                                Price        = candles[i].Close,
                                TradeAdvice  = TradeAdvice.Buy,
                                SignalCandle = candles[i],
                                Timestamp    = candles[i].Timestamp,
                                StrategyName = strategy.Name
                            });

                            // Calculate win/lose forwards from buy point
                            for (int j = i; j < trend.Count; j++)
                            {
                                // Sell as soon as the strategy tells us to..
                                if (trend[j] == TradeAdvice.Sell ||
                                    ShouldSell((double)candles[i].Close, (double)candles[j].Close, candles[j].Timestamp) != SellType.None
                                    )
                                {
                                    //if (candles[i].Close == 0 || candles[j].Close == 0)
                                    //    continue;

                                    // We ignore fees for now. Goal of the backtester is to compare strategy efficiency.
                                    var currentProfitPercentage = ((candles[j].Close - candles[i].Close) / candles[i].Close) * 100;
                                    var quantity      = backtestOptions.StakeAmount / candles[i].Close; // We always trade with 0.1 BTC.
                                    var currentProfit = (candles[j].Close - candles[i].Close) * quantity;

                                    backTestResult.Trades.Add(new BackTestTradeResult
                                    {
                                        Market           = globalSymbol,
                                        Quantity         = quantity,
                                        OpenRate         = candles[i].Close,
                                        CloseRate        = candles[j].Close,
                                        ProfitPercentage = currentProfitPercentage,
                                        Profit           = currentProfit,
                                        Duration         = j - i,
                                        StartDate        = candles[i].Timestamp,
                                        EndDate          = candles[j].Timestamp
                                    });

                                    signals.Add(new TradeSignal
                                    {
                                        Id               = Guid.NewGuid(),
                                        ParentId         = id,
                                        MarketName       = globalSymbol,
                                        Price            = candles[j].Close,
                                        TradeAdvice      = TradeAdvice.Sell,
                                        SignalCandle     = candles[j],
                                        Profit           = currentProfit,
                                        PercentageProfit = currentProfitPercentage,
                                        Timestamp        = candles[j].Timestamp,
                                        StrategyName     = strategy.Name
                                    });

                                    if (backtestOptions.OnlyStartNewTradesWhenSold)
                                    {
                                        i = j;
                                    }

                                    break;
                                }
                            }
                        }
                    }

                    await candleProvider.SaveTradeSignals(backtestOptions, dataStore, signals);
                }
                catch (Exception ex)
                {
                    ConsoleUtility.WriteColoredLine($"Error in Strategy: {strategy.Name}", ConsoleColor.Red);
                    ConsoleUtility.WriteColoredLine($"\t{ex.Message}", ConsoleColor.Red);
                }

                results.Add(backTestResult);
            }

            return(results);
        }
コード例 #20
0
        public async Task <List <BackTestResult> > RunSingleStrategy(ITradingStrategy strategy, BacktestOptions backtestOptions, IDataStoreBacktest dataStore, string baseCurrency, bool saveSignals, decimal startingWallet, decimal tradeAmount)
        {
            var results    = new List <BackTestResult>();
            var allSignals = new List <TradeSignal>();

            // Go through our coinpairs and backtest them.
            foreach (string globalSymbol in backtestOptions.Coins)
            {
                var candleProvider = new DatabaseCandleProvider();
                backtestOptions.Coin = globalSymbol;

                // This creates a list of buy signals.
                var candles = await candleProvider.GetCandles(backtestOptions, dataStore);

                if (candles == null || !candles.Any())
                {
                    continue;
                }

                candles = await candles.FillCandleGaps((Period)Enum.Parse(typeof(Period), backtestOptions.CandlePeriod.ToString(), true));

                var backTestResult = new BackTestResult {
                    Market = globalSymbol
                };

                try
                {
                    var trend   = strategy.Prepare(candles);
                    var signals = new List <TradeSignal>();

                    for (int i = 0; i < trend.Count; i++)
                    {
                        if (trend[i] == TradeAdvice.Buy)
                        {
                            var id = Guid.NewGuid();

                            signals.Add(new TradeSignal
                            {
                                Id           = id,
                                MarketName   = globalSymbol,
                                Price        = candles[i].Close,
                                TradeAdvice  = TradeAdvice.Buy,
                                SignalCandle = candles[i],
                                Timestamp    = candles[i].Timestamp,
                                StrategyName = strategy.Name
                            });

                            // Calculate win/lose forwards from buy point
                            for (int j = i; j < trend.Count; j++)
                            {
                                // Sell as soon as the strategy tells us to..
                                if (trend[j] == TradeAdvice.Sell ||
                                    ShouldSell((double)candles[i].Close, (double)candles[j].Close, candles[j].Timestamp) != SellType.None
                                    )
                                {
                                    // We ignore fees for now. Goal of the backtester is to compare strategy efficiency.
                                    var currentProfitPercentage = ((candles[j].Close - candles[i].Close) / candles[i].Close) * 100;
                                    var quantity      = tradeAmount / candles[i].Close;
                                    var currentProfit = (candles[j].Close - candles[i].Close) * quantity;

                                    backTestResult.Trades.Add(new BackTestTradeResult
                                    {
                                        Market           = globalSymbol,
                                        Quantity         = quantity,
                                        OpenRate         = candles[i].Close,
                                        CloseRate        = candles[j].Close,
                                        ProfitPercentage = currentProfitPercentage,
                                        Profit           = currentProfit,
                                        Duration         = j - i,
                                        StartDate        = candles[i].Timestamp,
                                        EndDate          = candles[j].Timestamp
                                    });

                                    signals.Add(new TradeSignal
                                    {
                                        Id               = Guid.NewGuid(),
                                        ParentId         = id,
                                        MarketName       = globalSymbol,
                                        Price            = candles[j].Close,
                                        TradeAdvice      = TradeAdvice.Sell,
                                        SignalCandle     = candles[j],
                                        Profit           = currentProfit,
                                        PercentageProfit = currentProfitPercentage,
                                        Timestamp        = candles[j].Timestamp,
                                        StrategyName     = strategy.Name
                                    });

                                    if (backtestOptions.OnlyStartNewTradesWhenSold)
                                    {
                                        i = j;
                                    }

                                    break;
                                }
                            }
                        }
                    }

                    if (saveSignals)
                    {
                        await candleProvider.SaveTradeSignals(backtestOptions, dataStore, signals);
                    }

                    allSignals.AddRange(signals);
                }
                catch (Exception ex)
                {
                    ConsoleUtility.WriteColoredLine($"Error in Strategy: {strategy.Name}", ConsoleColor.Red);
                    ConsoleUtility.WriteColoredLine($"\t{ex.Message}", ConsoleColor.Red);
                }

                results.Add(backTestResult);
            }

            allSignals = allSignals.OrderBy(t => t != null).ThenBy(t => t.Timestamp).ToList();

            #region wallet trend

            var strategyTrades = new List <BackTestTradeResult>();
            foreach (var marketResult in results)
            {
                strategyTrades.AddRange(marketResult.Trades);
            }
            strategyTrades = strategyTrades.OrderBy(t => t.StartDate).ToList();

            decimal wallet    = startingWallet;
            decimal lowWallet = startingWallet;

            int cct = 0;
            int mct = 0;

            for (int i = 0; i < allSignals.Count(); i++)
            {
                var signal = allSignals[i];

                if (signal.TradeAdvice == TradeAdvice.Buy)
                {
                    cct = cct + 1;

                    if (cct > mct)
                    {
                        mct = cct;
                    }

                    wallet = wallet - tradeAmount;
                }
                else if (signal.TradeAdvice == TradeAdvice.Sell)
                {
                    cct = cct - 1;

                    wallet = wallet + (tradeAmount + signal.PercentageProfit * tradeAmount);

                    if (wallet < lowWallet)
                    {
                        lowWallet = wallet;
                    }
                }
            }

            var ff = results.FirstOrDefault();
            if (ff != null)
            {
                results.FirstOrDefault().ConcurrentTrades = mct;
                results.FirstOrDefault().Wallet           = wallet;
                results.FirstOrDefault().LowWallet        = lowWallet;
            }

            #endregion

            return(results);
        }
コード例 #21
0
        public static async Task <JArray> GetCacheAge(BacktestOptions backtestOptions, IDataStoreBacktest dataStore)
        {
            JArray jArrayResult = new JArray();

            foreach (var globalSymbol in backtestOptions.Coins)
            {
                backtestOptions.Coin = globalSymbol;

                Candle currentHistoricalDataFirst = await dataStore.GetBacktestFirstCandle(backtestOptions);

                Candle currentHistoricalDataLast = await dataStore.GetBacktestLastCandle(backtestOptions);

                if (currentHistoricalDataFirst != null && currentHistoricalDataLast != null)
                {
                    JObject currentResult = new JObject();
                    currentResult["Exchange"]        = backtestOptions.Exchange.ToString();
                    currentResult["Coin"]            = globalSymbol;
                    currentResult["CandlePeriod"]    = backtestOptions.CandlePeriod;
                    currentResult["FirstCandleDate"] = currentHistoricalDataFirst.Timestamp.ToUniversalTime();
                    currentResult["LastCandleDate"]  = currentHistoricalDataLast.Timestamp.ToUniversalTime();
                    jArrayResult.Add(currentResult);
                }
            }
            return(jArrayResult);
        }