using KLHZ.Trader.Core.Contracts.Declisions.Interfaces; using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Intarfaces; namespace KLHZ.Trader.Core.Declisions.Services { public class PriceHistoryCacheUnit : IPriceHistoryCacheUnit { public const int ArrayMaxLength = 500; public string Figi { get; init; } private readonly object _locker = new(); private readonly float[] Prices = new float[ArrayMaxLength]; private readonly DateTime[] Timestamps = new DateTime[ArrayMaxLength]; private int Length = 0; public ValueTask AddData(INewPriceMessage priceChange) { lock (_locker) { Array.Copy(Prices, 1, Prices, 0, Prices.Length - 1); Array.Copy(Timestamps, 1, Timestamps, 0, Timestamps.Length - 1); Prices[Prices.Length - 1] = (float)priceChange.Value; Timestamps[Timestamps.Length - 1] = priceChange.Time; if (Length < ArrayMaxLength) { Length++; } } return ValueTask.CompletedTask; } public ValueTask<(DateTime[] timestamps, float[] prices)> GetData() { var prices = new float[Length]; var timestamps = new DateTime[Length]; lock (_locker) { Array.Copy(Prices, Prices.Length - Length, prices, 0, prices.Length); Array.Copy(Timestamps, Prices.Length - Length, timestamps, 0, timestamps.Length); return ValueTask.FromResult((timestamps, prices)); } } public PriceHistoryCacheUnit(string figi, params INewPriceMessage[] priceChanges) { Figi = figi; if (priceChanges.Length == 0) { return; } var selectedPriceChanges = priceChanges .OrderBy(pc => pc.Time) .Skip(priceChanges.Length - ArrayMaxLength) .ToArray(); var prices = selectedPriceChanges .Select(pc => (float)pc.Value) .ToArray(); var times = selectedPriceChanges .Select(pc => pc.Time) .ToArray(); Array.Copy(prices, 0, Prices, Prices.Length - prices.Length, prices.Length); Array.Copy(times, 0, Timestamps, Timestamps.Length - times.Length, times.Length); Length = times.Length > ArrayMaxLength ? ArrayMaxLength : times.Length; } } }