LINQ aggregate and group by periods of time

后端 未结 8 2068
醉酒成梦
醉酒成梦 2020-11-28 06:28

I\'m trying to understand how LINQ can be used to group data by intervals of time; and then ideally aggregate each group.

Finding numerous examples with explicit dat

8条回答
  •  萌比男神i
    2020-11-28 07:16

    I know this doesn't directly answer the question, but I was googling around looking for a very similar solution to aggregate candle data for stocks / crypto currencies from a smaller minute period to a higher minute period (5, 10, 15, 30). You can't simply go back from the current minute taking X at a time, as the timestamps for the aggregated periods won't be consistent. You also have to watch out that there's enough data at the start and end of the list to populate a full candlestick of the larger period. Given that, the solution I came up with was as follows. (It assumes that the candles for the smaller period, as indicated by rawPeriod, are sorted by ascending Timestamp.)

    public class Candle
    {
        public long Id { get; set; }
        public Period Period { get; set; }
        public DateTime Timestamp { get; set; }
        public double High { get; set; }
        public double Low { get; set; }
        public double Open { get; set; }
        public double Close { get; set; }
        public double BuyVolume { get; set; }
        public double SellVolume { get; set; }
    }
    
    public enum Period
    {
        Minute = 1,
        FiveMinutes = 5,
        QuarterOfAnHour = 15,
        HalfAnHour = 30
    }
    
        private List AggregateCandlesIntoRequestedTimePeriod(Period rawPeriod, Period requestedPeriod, List candles)
        {
            if (rawPeriod != requestedPeriod)
            {
                int rawPeriodDivisor = (int) requestedPeriod;
                candles = candles
                            .GroupBy(g => new { TimeBoundary = new DateTime(g.Timestamp.Year, g.Timestamp.Month, g.Timestamp.Day, g.Timestamp.Hour, (g.Timestamp.Minute / rawPeriodDivisor) * rawPeriodDivisor , 0) })
                            .Where(g => g.Count() == rawPeriodDivisor )
                            .Select(s => new Candle
                            {
                                Period = requestedPeriod,
                                Timestamp = s.Key.TimeBoundary,
                                High = s.Max(z => z.High),
                                Low = s.Min(z => z.Low),
                                Open = s.First().Open,
                                Close = s.Last().Close,
                                BuyVolume = s.Sum(z => z.BuyVolume),
                                SellVolume = s.Sum(z => z.SellVolume),
                            })
                            .OrderBy(o => o.Timestamp)
                            .ToList();
            }
    
            return candles;
        }
    

提交回复
热议问题