using KLHZ.Trader.Core.Contracts.Declisions.Interfaces; using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Intarfaces; namespace KLHZ.Trader.Core.Math.Declisions.Services { public class PriceHistoryCacheUnit : IPriceHistoryCacheUnit { public const int CacheMaxLength = 500; public string Figi { get; init; } public int Length { get { lock (_locker) { return _length; } } } private readonly object _locker = new(); private readonly float[] Prices = new float[CacheMaxLength]; private readonly DateTime[] Timestamps = new DateTime[CacheMaxLength]; private int _length = 0; public ValueTask AddData(INewPrice 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 < CacheMaxLength) { _length++; } } return ValueTask.CompletedTask; } public ValueTask<(DateTime[] timestamps, float[] prices)> GetData() { lock (_locker) { var prices = new float[_length]; var timestamps = new DateTime[_length]; 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 INewPrice[] priceChanges) { Figi = figi; if (priceChanges.Length == 0) { return; } var selectedPriceChanges = priceChanges .OrderBy(pc => pc.Time) .Skip(priceChanges.Length - CacheMaxLength) .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 > CacheMaxLength ? CacheMaxLength : times.Length; } } }