private async Task HandleInstrument(Context context, MarketInstrument instrument, NotificationRule notificationRule) { // try get candles var timePeriodInHours = notificationRule.TimePeriodInHours; var interval = CandleInterval.FiveMinutes; if (timePeriodInHours >= 12) { interval = CandleInterval.Hour; } var start = DateTime.UtcNow.AddHours(-2.5 * timePeriodInHours); var end = DateTime.UtcNow; var candles = await context.MarketCandlesAsync(instrument.Figi, start, end, interval); if (candles.Candles.Count == 0) { Log.Debug($"No candles for {instrument.Ticker}\t{start:dd.MM.yy HH:mm} - {end:dd.MM.yy HH:mm}"); await Task.Delay(_sleepTime); return; } // handle a candle with maximum timestamp var lastCandle = candles.Candles.OrderByDescending(i => i.Time).First(); // try to find a previuos candle var previousCandleTimestamp = lastCandle.Time.AddHours(-1 * timePeriodInHours); var previousCandles = candles.Candles.Where(i => i.Time <= previousCandleTimestamp).ToList(); var attempNumber = 1; //in case it is the start of the day then try to get the last price from the first previous working day while (previousCandles.Count == 0) { start = previousCandleTimestamp.AddHours(-12 * attempNumber); end = previousCandleTimestamp.AddHours(-12 * (attempNumber - 1)); Log.Debug($"Can not find a previous candle for {instrument.Ticker} for {end:dd.MM.yy HH:mm}"); Log.Debug($"Try to fetch candles for {instrument.Ticker} for {previousCandleTimestamp.AddHours(-12 * attempNumber):dd.MM.yy HH:mm} - {previousCandleTimestamp:dd.MM.yy HH:mm}"); previousCandles = (await context.MarketCandlesAsync(instrument.Figi, start, end, interval)).Candles; attempNumber++; continue; } var firstCandle = previousCandles.OrderByDescending(i => i.Time).First(); if (notificationRule.IsActual(firstCandle.Close, lastCandle.Close)) { await _sendNotification(notificationRule, instrument, firstCandle, lastCandle); } LogTicker(instrument, notificationRule, lastCandle, firstCandle); }
private static void LogTicker(MarketInstrument instrument, NotificationRule notificationRule, CandlePayload lastCandle, CandlePayload firstCandle) { var priceChange = lastCandle.Close - firstCandle.Close; var priceChangeInPercent = 100 * priceChange / firstCandle.Close; var msg = $"${instrument.Ticker} " + $"{notificationRule.TimePeriodInHours}h / {priceChangeInPercent.ToString("F2")} % / {(priceChange >= 0 ? "+" : "")}{priceChange.ToString("F2")} {instrument.Currency} / " + $"{firstCandle.Close} {instrument.Currency} -> {lastCandle.Close} {instrument.Currency} / " + $"{firstCandle.Time:dd.MM.yyyy HH:mm} -> {lastCandle.Time:dd.MM.yyyy HH:mm}"; Log.Write(notificationRule.IsActual(firstCandle.Close, lastCandle.Close) ? Serilog.Events.LogEventLevel.Warning : Serilog.Events.LogEventLevel.Information, msg); }