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 ActionResult BacktesterResults(string exchange, string coinsToBuy, string baseCurrency, bool saveSignals, decimal startingWallet, decimal tradeAmount, DateTime?from = null, DateTime?to = null, string candleSize = "5", string strategy = "all")
        {
            var strategies = new JObject();

            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)
            };

            if (from.HasValue)
            {
                backtestOptions.StartDate = from.Value;
            }

            if (to.HasValue)
            {
                backtestOptions.EndDate = to.Value;
                backtestOptions.EndDate = backtestOptions.EndDate.AddDays(1).AddMinutes(-1);
            }

            if (tradeAmount == 0m)
            {
                tradeAmount = backtestOptions.StakeAmount;
            }

            if (startingWallet == 0m)
            {
                startingWallet = backtestOptions.StartingWallet;
            }

            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, baseCurrency, saveSignals, startingWallet, tradeAmount);
                for (int i = 0; i < result.Count(); i++)
                {
                    if (i == 0)
                    {
                        await Runtime.GlobalHubBacktest.Clients.All.SendAsync("SendSummary", JsonConvert.SerializeObject(result[i]));
                    }
                    else
                    {
                        await Runtime.GlobalHubBacktest.Clients.All.SendAsync("Send", JsonConvert.SerializeObject(result[i]));
                    }
                }
            });

            return(new JsonResult(strategies));
        }