using KLHZ.Trader.Core.Contracts.Messaging.Dtos; using KLHZ.Trader.Core.Contracts.Messaging.Interfaces; using KLHZ.Trader.Core.DataLayer; using KLHZ.Trader.Core.DataLayer.Entities.Orders; using KLHZ.Trader.Service.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace KLHZ.Trader.Service.Controllers { [ApiController] [Route("[controller]/[action]")] public class PlayController : ControllerBase { private readonly IDataBus _dataBus; private readonly IDbContextFactory _dbContextFactory; public PlayController(IDataBus dataBus, IDbContextFactory dbContextFactory) { _dbContextFactory = dbContextFactory; _dataBus = dataBus; } [HttpGet] public async Task Run(double? shift = null) { try { var figi1 = "FUTIMOEXF000"; //var figi1 = "BBG004730N88"; var figi2 = "BBG004730N88"; //var figi2 = "FUTIMOEXF000"; var time1 = DateTime.UtcNow.AddDays(-shift ?? -7).Date; //var time1 = new DateTime(2025, 9, 24, 11, 00, 0, DateTimeKind.Utc); //var time2 = DateTime.UtcNow.AddMinutes(18); using var context1 = await _dbContextFactory.CreateDbContextAsync(); context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; while (time1 < DateTime.UtcNow) { var data = new List(); var data2 = new List(); var time2 = time1.AddHours(1); var orderbooks = await context1.OrderbookItems .Where(oi => (oi.Figi == figi1 || oi.Figi == figi2) && oi.Time >= time1 && oi.Time < time2) .OrderBy(c => c.Time) .ToArrayAsync(); var prices = await context1.PriceChanges .Where(c => (c.Figi == figi1 || c.Figi == figi2) && c.Time >= time1 && c.Time < time2) .OrderBy(c => c.Time) .Select(c => new NewPriceMessage() { Figi = c.Figi, Ticker = c.Ticker, Time = c.Time, Price = c.Price, IsHistoricalData = true, Direction = c.Direction, Count = c.Count, }) .ToArrayAsync(); var lookupImoexf = orderbooks.Where(o => o.Figi == "FUTIMOEXF000").ToLookup(o => o.Time); var lookupSber = orderbooks.Where(o => o.Figi == "BBG004730N88").ToLookup(o => o.Time); foreach (var item in lookupImoexf) { var asks = item .Where(i => i.ItemType == Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.Ask) .OrderBy(o => o.Price) .ToList(); var bids = item .Where(i => i.ItemType == Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.Bid) .OrderByDescending(o => o.Price) .ToList(); var forRemove = new List(); if (asks.Count > 4 || bids.Count > 4) { } foreach (var bid in bids) { var bids2 = bids.Where(b => b.Price == bid.Price).ToList(); var summCount = bids2.Sum(b => b.Count); var b = bids2.First(); b.Count = summCount; bids2.Remove(b); forRemove.AddRange(bids2); } foreach (var ask in asks) { var asks2 = asks.Where(b => b.Price == ask.Price).ToList(); var summCount = asks2.Sum(b => b.Count); var b = asks2.First(); b.Count = summCount; asks2.Remove(b); forRemove.AddRange(asks2); } asks.RemoveAll(a => forRemove.Contains(a)); bids.RemoveAll(a => forRemove.Contains(a)); var orderbook = new NewOrderbookMessage() { Figi = "FUTIMOEXF000", Ticker = "IMOEXF", Asks = asks.ToArray(), Bids = bids.ToArray(), AsksCount = asks.Sum(a => a.Count), BidsCount = bids.Sum(a => a.Count), Time = item.Key }; var wrapper = new TimeSeriesData() { Figi = orderbook.Figi, Orderbook = orderbook, Time = item.Key, }; data.Add(wrapper); } foreach (var item in lookupSber) { var asks = item .Where(i => i.ItemType == Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.Ask) .OrderBy(o => o.Price) .ToList(); var bids = item .Where(i => i.ItemType == Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.Bid) .OrderByDescending(o => o.Price) .ToList(); var forRemove = new List(); if (asks.Count > 4 || bids.Count > 4) { } foreach (var bid in bids) { var bids2 = bids.Where(b => b.Price == bid.Price).ToList(); var summCount = bids2.Sum(b => b.Count); var b = bids2.First(); b.Count = summCount; bids2.Remove(b); forRemove.AddRange(bids2); } foreach (var ask in asks) { var asks2 = asks.Where(b => b.Price == ask.Price).ToList(); var summCount = asks2.Sum(b => b.Count); var b = asks2.First(); b.Count = summCount; asks2.Remove(b); forRemove.AddRange(asks2); } asks.RemoveAll(a => forRemove.Contains(a)); bids.RemoveAll(a => forRemove.Contains(a)); var orderbook = new NewOrderbookMessage() { Figi = "BBG004730N88", Ticker = "SBER", Asks = asks.ToArray(), Bids = bids.ToArray(), AsksCount = asks.Sum(a => a.Count), BidsCount = bids.Sum(a => a.Count), Time = item.Key }; var wrapper = new TimeSeriesData() { Figi = orderbook.Figi, Orderbook = orderbook, Time = item.Key, }; data.Add(wrapper); } time1 = time2; foreach (var price in prices) { var wrapper = new TimeSeriesData() { Figi = price.Figi, NewPrice = price, Time = price.Time, }; data.Add(wrapper); } data = data.OrderBy(d => d.Time).ToList(); for (int i = 0; i < data.Count; i++) { if (data[i].NewPrice != null && i > 0) { for (int i1 = i - 1; i1 >= 0; i1--) { var ob = data[i1].Orderbook; if (data[i1].Figi == data[i].Figi && ob != null) { var d = new TimeSeriesData() { Figi = ob.Figi, Orderbook = ob, Time = data[i].Time, NewPrice = data[i].NewPrice, }; data2.Add(d); break; } } } else { var ob = data[i].Orderbook; if (ob != null) { var d = new TimeSeriesData() { Figi = ob.Figi, Orderbook = ob, Time = ob.Time, }; data2.Add(d); } } } foreach (var mess in data2) { if (mess.Orderbook != null) { await _dataBus.Broadcast(mess.Orderbook); } if (mess.NewPrice != null) { //await _traderDataProvider.AddData(mess.NewPrice, TimeSpan.FromHours(6)); await _dataBus.Broadcast(mess.NewPrice); } } data.Clear(); data2.Clear(); } } catch (Exception ex) { } } } }