public async Task DeleteBacktestCandles(BacktestOptions backtestOptions) { LiteCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <CandleAdapter>("Candle_" + backtestOptions.CandlePeriod); candleCollection.EnsureIndex("Timestamp"); candleCollection.Delete(Query.Between("Timestamp", backtestOptions.StartDate, backtestOptions.EndDate, true, true)); }
public async Task <ActionResult> GetSignals(string exchange, string coinsToBuy, string strategy, string candleSize = "5") { var strategyName = WebUtility.HtmlDecode(strategy); List <string> coins = new List <string>(); Char delimiter = ','; String[] coinsToBuyArray = coinsToBuy.Split(delimiter); foreach (var coin in coinsToBuyArray) { coins.Add(coin.ToUpper()); } var backtestOptions = new BacktestOptions { DataFolder = Global.DataPath, Exchange = (Exchange)Enum.Parse(typeof(Exchange), exchange, true), Coins = coins, Coin = coinsToBuy, CandlePeriod = Int32.Parse(candleSize) }; var candleProvider = new DatabaseCandleProvider(); var items = await candleProvider.GetSignals(backtestOptions, Global.DataStoreBacktest, strategyName); return(new JsonResult(items)); }
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(); }
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); }
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(); }
public async Task DeleteBacktestDatabase(BacktestOptions backtestOptions) { if (File.Exists(GetDatabase(backtestOptions))) { File.Delete(GetDatabase(backtestOptions)); } }
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); }
public ActionResult BacktesterResults(string exchange, string coinsToBuy, string baseCurrency, string candleSize = "5", string strategy = "all") { JObject strategies = new JObject(); List <string> coins = new List <string>(); if (String.IsNullOrEmpty(coinsToBuy)) { IExchangeAPI api = ExchangeAPI.GetExchangeAPI(exchange.ToLower()); var exchangeCoins = api.GetSymbolsMetadataAsync().Result.Where(m => m.BaseCurrency == baseCurrency); foreach (var coin in exchangeCoins) { coins.Add(api.ExchangeSymbolToGlobalSymbol(coin.MarketName)); } } else { Char delimiter = ','; String[] coinsToBuyArray = coinsToBuy.Split(delimiter); foreach (var coin in coinsToBuyArray) { coins.Add(coin.ToUpper()); } } var backtestOptions = new BacktestOptions { DataFolder = Global.DataPath, Exchange = (Exchange)Enum.Parse(typeof(Exchange), exchange, true), Coins = coins, CandlePeriod = Int32.Parse(candleSize) }; var cts = new CancellationTokenSource(); var parallelOptions = new ParallelOptions { CancellationToken = cts.Token, MaxDegreeOfParallelism = Environment.ProcessorCount }; Parallel.ForEach(BacktestFunctions.GetTradingStrategies(), parallelOptions, async tradingStrategy => { if (strategy != "all") { var base64EncodedBytes = Convert.FromBase64String(strategy); if (tradingStrategy.Name != Encoding.UTF8.GetString(base64EncodedBytes)) { return; } } var result = await BacktestFunctions.BackTestJson(tradingStrategy, backtestOptions, Global.DataStoreBacktest); foreach (var item in result) { await Runtime.GlobalHubBacktest.Clients.All.SendAsync("Send", JsonConvert.SerializeObject(item)); } }); return(new JsonResult(strategies)); }
public async Task SaveBacktestCandlesBulk(List <Candle> candles, BacktestOptions backtestOptions) { var items = Mapping.Mapper.Map <List <CandleAdapter> >(candles); LiteCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <CandleAdapter>("Candle_" + backtestOptions.CandlePeriod); candleCollection.EnsureIndex("Timestamp"); candleCollection.InsertBulk(items); }
public async Task <Candle> GetBacktestLastCandle(BacktestOptions backtestOptions) { IMongoCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(MongoDbBaseName + backtestOptions.CandlePeriod).GetTable <CandleAdapter>(backtestOptions.Exchange + "_" + backtestOptions.Coin); CandleAdapter lastCandle = await candleCollection.Find(_ => true).SortByDescending(e => e.Timestamp).Limit(1).FirstOrDefaultAsync(); var items = Mapping.Mapper.Map <Candle>(lastCandle); return(items); }
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); }
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); }
public async Task <Candle> GetBacktestFirstCandle(BacktestOptions backtestOptions) { LiteCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <CandleAdapter>("Candle_" + backtestOptions.CandlePeriod); candleCollection.EnsureIndex("Timestamp"); CandleAdapter lastCandle = candleCollection.Find(Query.All("Timestamp"), limit: 1).FirstOrDefault(); var items = Mapping.Mapper.Map <Candle>(lastCandle); return(items); }
public async Task <List <TradeSignal> > GetBacktestSignalsByStrategy(BacktestOptions backtestOptions, string strategy) { IMongoCollection <TradeSignalAdapter> itemCollection = DataStoreBacktest.GetInstance("Signals_" + MongoDbBaseName + backtestOptions.CandlePeriod).GetTable <TradeSignalAdapter>(backtestOptions.Exchange + "_" + backtestOptions.Coin); var items = await itemCollection.Find(entry => entry.StrategyName == strategy).ToListAsync(); #warning TODO: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit=> temporarly order by LINQ var result = Mapping.Mapper.Map <List <TradeSignal> >(items).OrderBy(c => c.Timestamp).ToList(); return(result); }
public async Task <List <TradeSignal> > GetBacktestSignalsByStrategy(BacktestOptions backtestOptions, string strategy) { var itemCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <TradeSignalAdapter>("Signals_" + backtestOptions.CandlePeriod); itemCollection.EnsureIndex("StrategyName"); var items = itemCollection.Find(Query.Where("StrategyName", s => s.AsString == strategy), Query.Descending).ToList(); var result = Mapping.Mapper.Map <List <TradeSignal> >(items); return(result); }
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); }
public async Task <List <string> > GetBacktestAllDatabases(BacktestOptions backtestOptions) { List <string> allDatabases = new List <string>(); var dbList = await _client.GetDatabase(MongoDbOptions.MongoDatabaseName).ListCollectionsAsync(); foreach (var item in await dbList.ToListAsync()) { allDatabases.Add(item.ToString()); } return(allDatabases); }
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); }
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); }
public async Task <List <Candle> > GetBacktestCandlesBetweenTime(BacktestOptions backtestOptions) { var results = new List <Candle>(); IMongoCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(MongoDbBaseName + backtestOptions.CandlePeriod).GetTable <CandleAdapter>(backtestOptions.Exchange + "_" + backtestOptions.Coin); List <CandleAdapter> candles = await candleCollection.Find(entry => entry.Timestamp >= backtestOptions.StartDate && entry.Timestamp <= backtestOptions.EndDate).ToListAsync(); #warning TODO: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit=> temporarly order by LINQ results = Mapping.Mapper.Map <List <Candle> >(candles).OrderBy(c => c.Timestamp).ToList(); return(results); }
public async Task SaveBacktestTradeSignalsBulk(List <TradeSignal> signals, BacktestOptions backtestOptions) { var items = Mapping.Mapper.Map <List <TradeSignalAdapter> >(signals); IMongoCollection <TradeSignalAdapter> itemCollection = DataStoreBacktest.GetInstance("Signals_" + MongoDbBaseName + backtestOptions.CandlePeriod).GetTable <TradeSignalAdapter>(backtestOptions.Exchange + "_" + backtestOptions.Coin); foreach (var item in items) { await itemCollection.DeleteManyAsync(i => i.StrategyName == item.StrategyName); } await itemCollection.InsertManyAsync(items); }
public async Task SaveBacktestCandle(Candle candle, BacktestOptions backtestOptions) { var item = Mapping.Mapper.Map <CandleAdapter>(candle); LiteCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <CandleAdapter>("Candle_" + backtestOptions.CandlePeriod); candleCollection.EnsureIndex("Timestamp"); var newCandle = candleCollection.FindOne(x => x.Timestamp == item.Timestamp); if (newCandle == null) { candleCollection.Insert(item); } }
public static string GetDatabase(BacktestOptions backtestOptions) { if (!Directory.Exists(backtestOptions.DataFolder)) { Directory.CreateDirectory(backtestOptions.DataFolder); } if (backtestOptions.Coin == null) { return(backtestOptions.DataFolder.Replace("\\", "/")); } return(backtestOptions.DataFolder.Replace("\\", "/") + "/" + backtestOptions.Exchange + "_" + backtestOptions.Coin + ".db"); }
public async Task <ActionResult> FillCandlesGaps(string exchange, string coinsToBuy, string baseCurrency, DateTime?from = null, DateTime?to = null, string candleSize = "5") { var coins = new List <string>(); if (String.IsNullOrEmpty(coinsToBuy)) { IExchangeAPI api = ExchangeAPI.GetExchangeAPI(exchange); var exchangeCoins = api.GetSymbolsMetadataAsync().Result.Where(m => m.BaseCurrency == baseCurrency); foreach (var coin in exchangeCoins) { coins.Add(api.ExchangeSymbolToGlobalSymbol(coin.MarketName)); } } else { Char delimiter = ','; String[] coinsToBuyArray = coinsToBuy.Split(delimiter); foreach (var coin in coinsToBuyArray) { coins.Add(coin.ToUpper()); } } var backtestOptions = new BacktestOptions { DataFolder = Global.DataPath, Exchange = (Exchange)Enum.Parse(typeof(Exchange), exchange, true), Coins = coins, CandlePeriod = Int32.Parse(candleSize), EndDate = DateTime.Now }; if (from.HasValue) { backtestOptions.StartDate = from.Value; } if (to.HasValue) { backtestOptions.EndDate = to.Value; backtestOptions.EndDate = backtestOptions.EndDate.AddDays(1).AddMinutes(-1); } await DataRefresher.FillCandlesGaps(x => Global.Logger.Information(x), backtestOptions, Global.DataStoreBacktest); var result = new JObject { ["result"] = "success" }; return(new JsonResult(result)); }
public async Task SaveBacktestCandle(Candle candle, BacktestOptions backtestOptions) { var item = Mapping.Mapper.Map <CandleAdapter>(candle); IMongoCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(MongoDbBaseName + backtestOptions.CandlePeriod).GetTable <CandleAdapter>(backtestOptions.Exchange + "_" + backtestOptions.Coin); FindOptions <CandleAdapter> marketCandleFindOptions = new FindOptions <CandleAdapter> { Limit = 1 }; IAsyncCursor <CandleAdapter> checkData = await candleCollection.FindAsync(x => x.Timestamp == item.Timestamp, marketCandleFindOptions); if (await checkData.FirstOrDefaultAsync() == null) { await candleCollection.InsertOneAsync(item); } }
public async Task <string> Refresh(string exchange, string coinsToBuy, string candleSize = "5") { var backtestOptions = new BacktestOptions { DataFolder = Global.DataPath, Exchange = (Exchange)Enum.Parse(typeof(Exchange), exchange, true), Coins = new List <string>(new[] { coinsToBuy }), CandlePeriod = Int32.Parse(candleSize) }; await DataRefresher.RefreshCandleData(x => Global.Logger.Information(x), backtestOptions, Global.DataStoreBacktest); return("Refresh Done"); }
public async Task <List <Candle> > GetBacktestCandlesBetweenTime(BacktestOptions backtestOptions) { try { LiteCollection <CandleAdapter> candleCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <CandleAdapter>("Candle_" + backtestOptions.CandlePeriod); candleCollection.EnsureIndex("Timestamp"); List <CandleAdapter> candles = candleCollection.Find(Query.Between("Timestamp", backtestOptions.StartDate, backtestOptions.EndDate), Query.Ascending).ToList(); var items = Mapping.Mapper.Map <List <Candle> >(candles); return(items); } catch (Exception ex) { Global.Logger.Error(ex.ToString()); throw; } }
public async Task SaveBacktestTradeSignalsBulk(List <TradeSignal> signals, BacktestOptions backtestOptions) { var items = Mapping.Mapper.Map <List <TradeSignalAdapter> >(signals); LiteCollection <TradeSignalAdapter> itemCollection = DataStoreBacktest.GetInstance(GetDatabase(backtestOptions)).GetTable <TradeSignalAdapter>("Signals_" + backtestOptions.CandlePeriod); foreach (var item in items) { itemCollection.Delete(i => i.StrategyName == item.StrategyName); } // TradeSignalAdapter lastCandle = itemCollection.Find(Query.All("Timestamp", Query.Descending), limit: 1).FirstOrDefault(); itemCollection.EnsureIndex("Timestamp"); itemCollection.InsertBulk(items); }
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); }
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); }