public void Start() { _logger.Info(GetScheduledEventMessageToLog()); while (!_hasFinished) { foreach (KeyValuePair <Coin, Coin> pair in _coins) { // NO HISTORICAL DATA NEEDED AS WE GET THIS SEPARATLEY IN THE PRELOAD WHEN BOT STARTS try { // set the minutes to :00 DateTime fromDate = new DateTime(DateTime.UtcNow.AddMinutes(-5).Year, DateTime.UtcNow.AddMinutes(-5).Month, DateTime.UtcNow.AddMinutes(-5).Day, DateTime.UtcNow.AddMinutes(-5).Hour, DateTime.UtcNow.AddMinutes(-5).Minute, 0); if (fromDate.Minute % 5 > 0) { int diff = fromDate.Minute % 5; fromDate = new DateTime(fromDate.AddMinutes(-diff).Year, fromDate.AddMinutes(-diff).Month, fromDate.AddMinutes(-diff).Day, fromDate.AddMinutes(-diff).Hour, fromDate.AddMinutes(-diff).Minute, 0); } DateTime toDate = new DateTime(fromDate.AddMinutes(5).Year, fromDate.AddMinutes(5).Month, fromDate.AddMinutes(5).Day, fromDate.AddMinutes(5).Hour, fromDate.AddMinutes(5).Minute, 0); IEnumerable <Candle> candles = _exchangeApi.GetCandles(pair.Key, pair.Value, _candlePeriodInSeconds, fromDate, toDate); if (candles.Any()) { var candleMessage = new CandleMessage { Candles = candles.Skip(candles.Count() - 2), // sometimes the request brings back more records than are needed BaseCoin = pair.Key, Coin = pair.Value }; _messageispatcher.Dispatch(candleMessage); } } catch (Exception e) { _logger.Error(e.Message); _logger.Error(e.StackTrace); } } var nextCandle = new DateTime(DateTime.UtcNow.AddMinutes(5).Year, DateTime.UtcNow.AddMinutes(5).Month, DateTime.UtcNow.AddMinutes(5).Day, DateTime.UtcNow.AddMinutes(5).Hour, DateTime.UtcNow.AddMinutes(5).Minute, 0); if (nextCandle.Minute % 5 > 0) { int diff = nextCandle.Minute % 5; nextCandle = new DateTime(nextCandle.AddMinutes(-diff).Year, nextCandle.AddMinutes(-diff).Month, nextCandle.AddMinutes(-diff).Day, nextCandle.AddMinutes(-diff).Hour, nextCandle.AddMinutes(-diff).Minute, 0); } nextCandle = new DateTime(nextCandle.AddMinutes(1).Year, nextCandle.AddMinutes(1).Month, nextCandle.AddMinutes(1).Day, nextCandle.AddMinutes(1).Hour, nextCandle.AddMinutes(1).Minute, 0); var timeToSleepFor = nextCandle.Subtract(DateTime.UtcNow); //var timeToSleepFor = DateTime.UtcNow.AddMinutes() GetTimeSpanToSleepFor(_schedulerType, _schedulerValueInSeconds); _logger.Info($"Going to sleep until the next run on {nextCandle.ToLocalTime()}"); Thread.Sleep(timeToSleepFor); } }
public async Task <HistoryResponseDto> History(string symbol, Int32 from, Int32 to, string resolution) { _exchangeApi = ExchangeFactory.GetExchangeApi(Enumerations.ExchangesEnum.Gdax, null); IEnumerable <Candle> candles = _exchangeApi.GetCandles(new Coin { Code = "EUR" }, new Coin { Code = "BTC" }, 60 * 60 * 24, UnixTimeStampToDateTime(from), UnixTimeStampToDateTime(to)); candles = candles.OrderBy(x => x.Timestamp); //var asTable = ToDataTable(candles.ToList()); var response = new HistoryResponseDto { TimeStamps = candles.Select(x => (long)CryptoUtility.UnixTimestampFromDateTimeSeconds(x.Timestamp)).ToArray(), Opens = candles.Select(x => x.OpenPrice).ToArray(), Highs = candles.Select(x => x.HighPrice).ToArray(), Lows = candles.Select(x => x.LowPrice).ToArray(), Closes = candles.Select(x => x.ClosePrice).ToArray(), Volumes = candles.Select(x => Convert.ToDecimal(x.VolumeQuantity)).ToArray(), Status = "ok" }; return(response); //var json = System.IO.File.ReadAllText("D:\\Development\\CryptoBot\\CryptoBot.Api\\Data\\Sample\\history.json"); //var result = JsonConvert.DeserializeObject<HistoryResponseDto>(json); //var fromDates = result.TimeStamps.Where(x => x > from); //var toDates = result.TimeStamps.Where(x => x < to); //if(!fromDates.Any() || !toDates.Any()) // return new HistoryResponseDto{ Status = "no_data"}; //return JsonConvert.DeserializeObject<HistoryResponseDto>(json); }
public async Task BackTestAllBots() { // get user User user = _dbContext .Users .Include(x => x.ApiSettings.Select(y => y.Exchange)) .Include(x => x.MessagingApps) .Include(x => x.MessagingApps.Select(y => y.MessagingAppSettings)) .Single(x => x.UserId == 1); // get watches, get coins, get exchange List <Bot> bots = _dbContext .Bots .Include("User") .Include("User.ApiSettings") .Include("User.ApiSettings.Exchange") .Include("User.MessagingApps") .Include("User.MessagingApps.MessagingAppSettings") .Include("Exchange") .Include("Coin") .Include("BaseCoin") .Include("Positions") .Include("Indicators") .Include("Indicators.RuleSets") .Include("Indicators.RuleSets.Rules") .AsNoTracking() .Where(x => x.User.UserId == user.UserId) .Where(x => x.Active) .ToList(); // get the messaging app if any if (user.MessagingApps.Any(x => x.Active)) { var app = user.MessagingApps.First(x => x.Active); _messagingApp = MessagingAppFactory.GetMessagingApp(app, _logger, _dbContext); } int oneMinute = 60; int fifteenMinute = oneMinute * 15; int thirtyMinute = oneMinute * 30; int sixtyMinute = oneMinute * 60; foreach (Bot bot in bots) { IExchangeApi exchangeApi = ExchangeEngine.ExchangeFactory.GetExchangeApi( (Enumerations.ExchangesEnum)bot.Exchange.ExchangeId, _mapper.Map <ApiSetting, ExchangeSettings>( user.ApiSettings.Single(x => x.Exchange.ExchangeId == bot.Exchange.ExchangeId), new ExchangeSettings())); /* * Note from GDAX... * * The maximum number of data points for a single request is 200 candles. * If your selection of start/end time and granularity will result in more than 200 data points, your request will be rejected. * If you wish to retrieve fine granularity data over a larger time range, you will need to make multiple requests with new start/end ranges. * */ int requiredWeeks = 1; List <Candle> candles = new List <Candle>(); var requiredHours = 36; for (int k = requiredHours; k > 0; k--) { var fromDate = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(60 * k)); fromDate = new DateTime(fromDate.Year, fromDate.Month, fromDate.Day, fromDate.Hour, 0, 0); // the start of the hour var toDate = fromDate.AddHours(1); toDate = new DateTime(toDate.Year, toDate.Month, toDate.Day, toDate.Hour, 0, 0); int candleSize = 60 * 5; // 60 second x ? try { candles.AddRange(exchangeApi.GetCandles(bot.BaseCoin, bot.Coin, candleSize, fromDate, toDate)); } catch (Exception e) { _logger.Error(e); } if (k % 2 == 0) // only three requests allowed per second on GDAX { Thread.Sleep(1000); } } candles = candles.OrderBy(x => x.Timestamp).ToList(); TradeBot tradeBot = new TradeBot(bot, _logger, _dbContext, _mapper, _IndicatorFactoryWrapper, _messagingApp); _messageDispatcher.AddMessageHandler(tradeBot); foreach (Candle candle in candles) { _messageDispatcher.Dispatch(new CandleMessage { Candles = new List <Candle>() { candle }, BaseCoin = bot.BaseCoin, Coin = bot.Coin }); } // close last order in case its open if (bot.CurrentPosition?.Status == Enumerations.PositionStatusEnum.Bought) { Position position = _dbContext.Positions.Single(x => x.PositionId == bot.CurrentPosition.PositionId); position.Status = Enumerations.PositionStatusEnum.Sold; _dbContext.SaveChanges(); } tradeBot.OnStop(); tradeBot = null; } }