hola, necesito modificar este codigo para que se pueda especificar el numero de anyos de lookback para el calculo de la estacionalidad, lo cual conlleva que para cada anyo se debera calcular la estacionalidad teniendo en cuenta solamente los x anyos previos y no todos los anyos ioncluidos los posteriores como se esta haciendo ahora incurroendo en lookahead bias.     public enum EnumSeasonalityModel
    {
        Additive,
        Multiplicative
    };
    public enum EnumSeasonalityCalculationMethod
    {
        Mean,
        Median
    };

    public interface ISeasonalityCalculator
    {
        SeasonalityResult CalculateSeasonality(IReadOnlyList<DateTime> dates, IReadOnlyList<double> prices);
        double[] GenerateSeasonalitySeries(IReadOnlyList<DateTime> dates, double[] seasonalIndices);
    }

    public record SeasonalityResult(double[] SeasonalIndices);

    public record DataPoint(DateTime Date, double Price);

    public class AdvancedSeasonalityCalculator : ISeasonalityCalculator
    {
        private readonly EnumSeasonalityModel _model;
        private readonly ISeasonalityMethodStrategy _calculationMethod;
        private readonly IDataFiller _dataFiller;

        public AdvancedSeasonalityCalculator(
            EnumSeasonalityModel model,
            ISeasonalityMethodStrategy calculationMethod,
            IDataFiller dataFiller)
        {
            _model = model;
            _calculationMethod = calculationMethod ?? throw new ArgumentNullException(nameof(calculationMethod));
            _dataFiller = dataFiller ?? throw new ArgumentNullException(nameof(dataFiller));
        }

        public SeasonalityResult CalculateSeasonality(IReadOnlyList<DateTime> dates, IReadOnlyList<double> prices)
        {
            ValidateInput(dates, prices);

            var sortedData = CreateSortedData(dates, prices);
            var dataByYear = GroupDataByYear(sortedData);

            ValidateYearlyData(dataByYear);

            var (historicalData, analyzedData) = SplitData(dataByYear);
            var seasonalIndices = CalculateSeasonalIndices(historicalData);

            return new SeasonalityResult(seasonalIndices);
        }

        private void ValidateInput(IReadOnlyList<DateTime> dates, IReadOnlyList<double> prices)
        {
            if (dates == null) throw new ArgumentNullException(nameof(dates));
            if (prices == null) throw new ArgumentNullException(nameof(prices));
            if (dates.Count != prices.Count) throw new ArgumentException("Lists must have same length");
            if (dates.Count < 365 * 2) throw new ArgumentException("Insufficient data points");
        }

        private List<DataPoint> CreateSortedData(IReadOnlyList<DateTime> dates, IReadOnlyList<double> prices)
        {
            return dates.Zip(prices, (date, price) => new DataPoint(date, price))
                       .OrderBy(dp => dp.Date)
                       .ToList();
        }

        private IReadOnlyList<IGrouping<int, DataPoint>> GroupDataByYear(List<DataPoint> sortedData)
        {
            return sortedData.GroupBy(dp => dp.Date.Year)
                            .OrderBy(g => g.Key)
                            .ToList();
        }

        private void ValidateYearlyData(IReadOnlyList<IGrouping<int, DataPoint>> dataByYear)
        {
            if (dataByYear.Count < 2)
                throw new ArgumentException("At least two full years of data required");
        }

        private (List<DataPoint> historical, List<DataPoint> analyzed) SplitData(
                IReadOnlyList<IGrouping<int, DataPoint>> dataByYear)
        {
            var historical = dataByYear.Take(dataByYear.Count - 1)
                                     .SelectMany(g => g)
                                     .ToList();
            var analyzed = dataByYear.Last()
                                    .ToList();
            return (historical, analyzed);
        }

        private double[] CalculateSeasonalIndices(List<DataPoint> historicalData)
        {
            var filledData = _dataFiller.FillMissingDays(historicalData);
            var dayOfYearGroups = GroupByDayOfYear(filledData);
            var indices = CalculateIndicesForEachDay(dayOfYearGroups);

            return NormalizeIndices(indices);
        }

        private Dictionary<int, List<double>> GroupByDayOfYear(List<DataPoint> data)
        {
            var groups = new Dictionary<int, List<double>>();

            foreach (var point in data)
            {
                int day = point.Date.DayOfYear;
                if (DateTime.IsLeapYear(point.Date.Year) && day == 60)
                    continue;

                if (!groups.ContainsKey(day))
                    groups[day] = new List<double>();

                groups[day].Add(point.Price);
            }

            return groups;
        }

        private double[] CalculateIndicesForEachDay(Dictionary<int, List<double>> dayGroups)
        {
            int maxDay = dayGroups.Keys.Max();
            var indices = new double[maxDay + 1];

            for (int day = 1; day <= maxDay; day++)
            {
                indices[day] = dayGroups.TryGetValue(day, out var values) && values.Count > 0
                    ? _calculationMethod.Calculate(values)
                    : InterpolateIndex(day, indices);
            }

            return indices;
        }

        private double[] NormalizeIndices(double[] indices)
        {
            if (_model != EnumSeasonalityModel.Multiplicative)
                return indices;

            double average = indices.Where(x => x > 0).Average();
            return indices.Select(x => x > 0 ? x / average : x).ToArray();
        }

        private double InterpolateIndex(int day, double[] indices)
        {
            var (prevDay, nextDay) = FindNearestValidDays(day, indices);

            return CalculateInterpolatedValue(prevDay, nextDay, indices);
        }

        private (int prev, int next) FindNearestValidDays(int day, double[] indices)
        {
            int prevDay = day - 1;
            int nextDay = day + 1;

            while (prevDay >= 1 && indices[prevDay] == 0) prevDay--;
            while (nextDay < indices.Length && indices[nextDay] == 0) nextDay++;

            return (prevDay, nextDay);
        }

        private double CalculateInterpolatedValue(int prevDay, int nextDay, double[] indices)
        {
            if (prevDay >= 1 && nextDay < indices.Length)
                return (indices[prevDay] + indices[nextDay]) / 2.0;

            if (prevDay >= 1)
                return indices[prevDay];

            if (nextDay < indices.Length)
                return indices[nextDay];

            return _model == EnumSeasonalityModel.Multiplicative ? 1.0 : 0.0;
        }

        public double[] GenerateSeasonalitySeries(IReadOnlyList<DateTime> dates, double[] seasonalIndices)
        {
            if (dates == null)
                throw new ArgumentNullException(nameof(dates));
            if (seasonalIndices == null)
                throw new ArgumentNullException(nameof(seasonalIndices));

            return dates.Select(date =>
            {
                int day = AdjustDayForLeapYear(date);

                if (day >= seasonalIndices.Length)
                    throw new InvalidOperationException($"Day {day} exceeds seasonal indices range");

                return seasonalIndices[day];
            }).ToArray();
        }

        private int AdjustDayForLeapYear(DateTime date)
        {
            int day = date.DayOfYear;
            return DateTime.IsLeapYear(date.Year) && day == 60 ? 59 : day;
        }
    }

    // Interfaces y clases de apoyo
    public interface ISeasonalityMethodStrategy
    {
        double Calculate(IEnumerable<double> values);
    }

    public class MeanStrategy : ISeasonalityMethodStrategy
    {
        public double Calculate(IEnumerable<double> values)
            => values.Average();
    }

    public class MedianStrategy : ISeasonalityMethodStrategy
    {
        public double Calculate(IEnumerable<double> values)
        {
            var sortedValues = values.OrderBy(x => x).ToList();
            int mid = sortedValues.Count / 2;
            return sortedValues.Count % 2 == 0
                ? (sortedValues[mid - 1] + sortedValues[mid]) / 2
                : sortedValues[mid];
        }
    }

    public interface IDataFiller
    {
        List<DataPoint> FillMissingDays(List<DataPoint> data);
    };

    public class LinearDataFiller : IDataFiller
    {
        public List<DataPoint> FillMissingDays(List<DataPoint> data)
        {
            if (!data.Any()) return new List<DataPoint>();

            var filledData = new List<DataPoint>();
            var firstDate = data.Min(d => d.Date);
            var lastDate = data.Max(d => d.Date);
            var currentDate = firstDate;
            var dataIndex = 0;
            double? lastKnownPrice = null;

            while (currentDate <= lastDate)
            {
                if (dataIndex < data.Count && data[dataIndex].Date == currentDate)
                {
                    filledData.Add(data[dataIndex]);
                    lastKnownPrice = data[dataIndex].Price;
                    dataIndex++;
                }
                else if (lastKnownPrice.HasValue)
                {
                    filledData.Add(new DataPoint(currentDate, lastKnownPrice.Value));
                }

                currentDate = currentDate.AddDays(1);
            }

            return filledData;
        }
    };

    // Factory para crear la calculadora
    public class SeasonalityCalculatorFactory
    {
        public static ISeasonalityCalculator Create(EnumSeasonalityModel model, EnumSeasonalityCalculationMethod method)
        {
            ISeasonalityMethodStrategy strategy = method switch
            {
                EnumSeasonalityCalculationMethod.Mean => new MeanStrategy(),
                EnumSeasonalityCalculationMethod.Median => new MedianStrategy(),
                _ => throw new ArgumentException("Invalid calculation method")
            };

            return new AdvancedSeasonalityCalculator(model, strategy, new LinearDataFiller());
        }
    };