/// <summary> /// Calculates a buy signal based on several technical analysis indicators. /// </summary> /// <param name="market">The market we're going to check against.</param> /// <returns></returns> private async Task <TradeSignal> GetStrategySignal(string market) { try { _logger.LogInformation("Checking market {Market}...", market); var minimumDate = _strategy.GetMinimumDateTime(); var candleDate = _strategy.GetCurrentCandleDateTime(); var candles = await _api.GetTickerHistory(market, _strategy.IdealPeriod, minimumDate); // We eliminate all candles that aren't needed for the dataset incl. the last one (if it's the current running candle). candles = candles.Where(x => x.Timestamp >= minimumDate && x.Timestamp < candleDate).ToList(); // Not enough candles to perform what we need to do. if (candles.Count < _strategy.MinimumAmountOfCandles) { _logger.LogWarning("Not enough candle data for {Market}...", market); return(new TradeSignal { TradeAdvice = TradeAdvice.Hold, MarketName = market }); } // Get the date for the last candle. var signalDate = candles[candles.Count - 1].Timestamp; // This is an outdated candle... if (signalDate < _strategy.GetSignalDate()) { _logger.LogInformation("Outdated candle for {Market}...", market); return(null); } // This calculates an advice for the next timestamp. var advice = _strategy.Forecast(candles); return(new TradeSignal { TradeAdvice = advice, MarketName = market, SignalCandle = _strategy.GetSignalCandle(candles) }); } catch (Exception ex) { // Couldn't get a buy signal for this market, no problem. Let's skip it. _logger.LogError(ex, "Couldn't get buy signal for {Market}...", market); return(null); } }
/// <summary> /// Calculates a buy signal based on several technical analysis indicators. /// </summary> /// <param name="market">The market we're going to check against.</param> /// <param name="strategy"></param> /// <returns></returns> private async Task <TradeSignal> GetStrategySignal(string market, ITradingStrategy strategy) { //Global.Logger.Information($"Starting GetStrategySignal {market}"); //var watch1 = System.Diagnostics.Stopwatch.StartNew(); var minimumDate = strategy.GetMinimumDateTime(); var candleDate = strategy.GetCurrentCandleDateTime(); DateTime?endDate = null; if (Global.Configuration.ExchangeOptions.FirstOrDefault().IsSimulation) { //in simulation the date comes from external candleDate = Global.Configuration.ExchangeOptions.FirstOrDefault().SimulationCurrentDate; //TODO: improve to other timeframe minimumDate = candleDate.AddMinutes(-(30 * strategy.MinimumAmountOfCandles)); endDate = candleDate; } var candles = await Global.ExchangeApi.GetTickerHistory(market, strategy.IdealPeriod, minimumDate, endDate); var desiredLastCandleTime = candleDate.AddMinutes(-(strategy.IdealPeriod.ToMinutesEquivalent())); //Global.Logger.Information("Checking signal for market {Market} lastCandleTime {a} - desiredLastCandleTime {b}", market, candles.Last().Timestamp, desiredLastCandleTime); if (!candles.Any()) { return(null); } int k = 1; //on simulation, if we dont have candles we have to re-check our DB data.. while (candles.Last().Timestamp < desiredLastCandleTime && k < 20 && !Global.Configuration.ExchangeOptions.FirstOrDefault().IsSimulation) { k++; Thread.Sleep(1000 * k); candles = await Global.ExchangeApi.GetTickerHistory(market, strategy.IdealPeriod, minimumDate, endDate); Global.Logger.Information("R Checking signal for market {Market} lastCandleTime {a} - desiredLastCandleTime {b}", market, candles.Last().Timestamp, desiredLastCandleTime); } //Global.Logger.Information("Checking signal for market {Market} lastCandleTime: {last} , close: {close}", market, candles.Last().Timestamp, candles.Last().Close); if (!candles.Any()) { return(null); } // We eliminate all candles that aren't needed for the dataset incl. the last one (if it's the current running candle). candles = candles.Where(x => x.Timestamp >= minimumDate && x.Timestamp < candleDate).ToList(); // Not enough candles to perform what we need to do. if (candles.Count < strategy.MinimumAmountOfCandles) { //Global.Logger.Warning("Not enough candle data for {Market}...", market); return(new TradeSignal { TradeAdvice = TradeAdvice.Hold, MarketName = market }); } // Get the date for the last candle. var signalDate = candles[candles.Count - 1].Timestamp; var strategySignalDate = strategy.GetSignalDate(); if (Global.Configuration.ExchangeOptions.FirstOrDefault().IsSimulation) { //TODO: improve to other timeframe strategySignalDate = candleDate.AddMinutes(-30); } // This is an outdated candle... if (signalDate < strategySignalDate) { Global.Logger.Information("Outdated candle for {Market}...", market); return(null); } // This calculates an advice for the next timestamp. var advice = strategy.Forecast(candles); //watch1.Stop(); //Global.Logger.Warning($"Ended FindBuyOpportunities in #{watch1.Elapsed.TotalSeconds} seconds"); return(new TradeSignal { TradeAdvice = advice, MarketName = market, SignalCandle = strategy.GetSignalCandle(candles) }); }