private async void Broker_StreamingEventReceived(object sender, StreamingEventReceivedEventArgs e) { Debug.WriteLine(JsonConvert.SerializeObject(e.Response)); switch (e.Response) { case CandleResponse cr: { _lastEventReceived = DateTime.Now; var candle = cr.Payload; var stock = _tradingVM.Stocks.FirstOrDefault(s => s.Figi == candle.Figi); if (stock != null) { stock.IsNotifying = false; if (candle.Interval == CandleInterval.Day) { stock.TodayOpen = candle.Open; stock.TodayDate = candle.Time; stock.LastUpdate = DateTime.Now; stock.Price = candle.Close; if (stock.TodayOpen > 0) { stock.DayChange = (stock.Price - stock.TodayOpen) / stock.TodayOpen; } stock.DayVolume = candle.Volume; Interlocked.Increment(ref _refreshPendingCount); // отписываемся от дневного апдейта и подписываемся на 5минутную свечу QueueBrokerAction(b => b.SendStreamingRequestAsync( UnsubscribeCandle(stock.Figi, CandleInterval.Day)), $"Отписка от часовой свечи {stock.Ticker} ({stock.Figi})"); QueueBrokerAction(b => b.SendStreamingRequestAsync( SubscribeCandle(stock.Figi, CandleInterval.Minute)), $"Подписка на минутную свечу {stock.Ticker} ({stock.Figi})"); } #region 5min code //else if (candle.Interval == CandleInterval.FiveMinutes) //{ // if (candle.Time.Date > stock.TodayDate) // { // QueueBrokerAction(b => b.SendStreamingRequestAsync( // UnsubscribeCandle(stock.Figi, CandleInterval.FiveMinutes)), // $"Отписка от 5-ти минутной свечи {stock.Ticker} ({stock.Figi})"); // QueueBrokerAction(b => b.SendStreamingRequestAsync( // SubscribeCandle(stock.Figi, CandleInterval.Day)), // $"Подписка на дневную свечу {stock.Ticker} ({stock.Figi})"); // break; // } // var change = (candle.Close - candle.Open) / candle.Open; // stock.Price = candle.Close; // stock.LastUpdate = DateTime.Now; // if (stock.TodayOpen > 0) // stock.DayChange = (stock.Price - stock.TodayOpen) / stock.TodayOpen; // if (stock.DayChange > (decimal)0.05 // && (stock.LastAboveThreshholdDate == null // || stock.LastAboveThreshholdDate.Value.Date < stock.LastUpdate.Date)) // { // stock.LastAboveThreshholdDate = stock.LastUpdate; // var infoReq = StreamingRequest.SubscribeInstrumentInfo(stock.Figi); // QueueBrokerAction(b => b.SendStreamingRequestAsync(infoReq), // $"Подписка на статус инструмента {stock.Ticker} ({stock.Figi})"); // //if (stock.MonthVolume == 0) // //await GetMonthStats(stock); // //_telegram.PostMessage(stock.GetChangeInfoText()); // //_telegram.PostMessage($"Цена {stock.Ticker} изменилась на {stock.DayChange:P2} с начала дня. Объем (5 минут): {candle.Volume}" + // // $"\r\nЦена на начало дня: {stock.TodayOpenF}, Текущая: {stock.PriceF}"); // _uiContext.Post(obj => { // _tradingVM.Messages.Add(new MessageViewModel // { // Ticker = stock.Ticker, // Date = DateTime.Now, // Change = stock.DayChange, // Volume = candle.Volume, // Text = $"Цена {stock.Ticker} изменилась на {stock.DayChange:P2} с начала дня." // }); // }, null); // Interlocked.Increment(ref _refreshPendingCount); // } // if ((change > (decimal)0.05 || change < (decimal)-0.05) && (stock.LastAboveThreshholdCandleTime == null // || stock.LastAboveThreshholdCandleTime < candle.Time)) // { // stock.LastAboveThreshholdCandleTime = candle.Time; // if (stock.MonthVolume == 0) // await GetMonthStats(stock); // _telegram.PostMessage(stock.GetFiveMinChangeInfoText()); // //_telegram.PostMessage($"Цена {stock.Ticker} изменилась на {change:P2} за 5 минут. Объем за 5 минут: {candle.Volume}" + // // $"\r\nКурс на начало дня: {stock.TodayOpenF}, Текущий: {stock.PriceF}, Изменение за день: {stock.DayChangeF}"); // _uiContext.Post(obj => { // _tradingVM.Messages.Add(new MessageViewModel // { // Ticker = stock.Ticker, // Date = DateTime.Now, // Change = change, // Volume = candle.Volume, // Text = $"Цена {stock.Ticker} изменилась на {change:P2} за 5 минут." // }); // }, null); // Interlocked.Increment(ref _refreshPendingCount); // } // QueueBrokerAction(b => b.SendStreamingRequestAsync( // UnsubscribeCandle(stock.Figi, CandleInterval.FiveMinutes)), // $"Отписка от 5-ти минутной свечи {stock.Ticker} ({stock.Figi})"); // QueueBrokerAction(b => b.SendStreamingRequestAsync( // SubscribeCandle(stock.Figi, CandleInterval.Minute)), // $"Подписка на минутную свечу {stock.Ticker} ({stock.Figi})"); //} #endregion else if (candle.Interval == CandleInterval.Minute) { if (candle.Time.Date > stock.TodayDate) { QueueBrokerAction(b => b.SendStreamingRequestAsync( UnsubscribeCandle(stock.Figi, CandleInterval.Minute)), $"Отписка от минутной свечи {stock.Ticker} ({stock.Figi})"); QueueBrokerAction(b => b.SendStreamingRequestAsync( SubscribeCandle(stock.Figi, CandleInterval.Day)), $"Подписка на дневную свечу {stock.Ticker} ({stock.Figi})"); break; } stock.Price = candle.Close; if (stock.TodayOpen > 0) { stock.DayChange = (stock.Price - stock.TodayOpen) / stock.TodayOpen; } stock.LastUpdate = DateTime.Now; stock.LogCandle(candle); if (TradeBot != null) { await TradeBot.Check(stock); } if (stock.DayChange > DayChangeTrigger && (stock.LastAboveThreshholdDate == null || stock.LastAboveThreshholdDate.Value.Date < stock.LastUpdate.Date)) { stock.LastAboveThreshholdDate = stock.LastUpdate; var infoReq = StreamingRequest.SubscribeInstrumentInfo(stock.Figi); QueueBrokerAction(b => b.SendStreamingRequestAsync(infoReq), $"Подписка на статус инструмента {stock.Ticker} ({stock.Figi})"); if (IsTelegramEnabled) { _telegram.PostMessage(stock.GetDayChangeInfoText(), stock.Ticker); } BackgroundInvoke(() => { _tradingVM.Messages.Add(new MessageViewModel { Ticker = stock.Ticker, Date = DateTime.Now, Change = stock.DayChange, Volume = candle.Volume, Text = $"Цена {stock.Ticker} изменилась на {stock.DayChange:P2} с начала дня." }); }); Interlocked.Increment(ref _refreshPendingCount); } var change = stock.GetLast10MinChange(TenMinChangeTrigger); if (Math.Abs(change.change) > TenMinChangeTrigger && stock.DayChange > TenMinChangeTrigger && (stock.LastAboveThreshholdCandleTime == null || stock.LastAboveThreshholdCandleTime < candle.Time.AddMinutes(-change.minutes))) { stock.LastAboveThreshholdCandleTime = candle.Time; try { await GetMonthStats(stock); } catch (Exception ex) { await ResetConnection("Ошибка при получении статистики за месяц: " + ex.Message); } if (IsTelegramEnabled) { _telegram.PostMessage(stock.GetMinutesChangeInfoText(change.change, change.minutes, change.candles), stock.Ticker); } _uiContext.Post(obj => { _tradingVM.Messages.Add(new MessageViewModel { Ticker = stock.Ticker, Date = DateTime.Now, Change = change.change, Volume = candle.Volume, Text = $"Цена {stock.Ticker} изменилась на {change.change:P2} за {change.minutes} мин." }); }, null); if (TradeBot != null && change.change > TenMinChangeTrigger && stock.DayChange < 0.2m && change.candles.Sum(c => c.Volume) > 100) { await TradeBot.Buy(stock); } Interlocked.Increment(ref _refreshPendingCount); } } stock.IsNotifying = true; } break; } case OrderbookResponse or: { var stock = _tradingVM.Stocks.FirstOrDefault(s => s.Figi == or.Payload.Figi); if (stock != null && or.Payload.Asks.Count > 0 && or.Payload.Bids.Count > 0) { stock.Price = (or.Payload.Asks[0][0] + or.Payload.Bids[0][0]) / 2; if (stock.TodayOpen > 0) { stock.DayChange = (stock.Price - stock.TodayOpen) / stock.TodayOpen; stock.LastUpdate = or.Time.ToLocalTime(); } } break; } case InstrumentInfoResponse ir: { var info = ir.Payload; var stock = _tradingVM.Stocks.FirstOrDefault(s => s.Figi == info.Figi); if (stock != null) { stock.Status = info.TradeStatus; } break; } } }