Question

I have an IEnumerable<Bar>, where Bar contains among other data a DateTime type variable TimeStamp.

I have the following code,

var convertedBars = from myData in bars
                    group myData by (int) myData.TimeStamp.TimeOfDay.TotalMinutes / 60 into barData
                    select new Bar(){
                        TimeStamp = barData.FirstOrDefault().TimeStamp,
                        Open = barData.FirstOrDefault().Open,
                        Low = barData.Min(bd => bd.Low),
                        High = barData.Max(bd => bd.High),
                        Close = barData.LastOrDefault().Close,
                    };

which returns an IEnumerable<Bar> where bars are grouped into 60 minute bars. This works fine as long as the original bars collection contains bars of only one and the same day timestamp. If the source collection contains multiple days then all bars are grouped into a maximum of 24 hourly buckets.

How can I adjust the code so that the collection is first grouped by Date and then grouped by TotalMinutes /60 (such as above) in order to end up with 60 minute buckets separately for each date?

EDIT

I generalized the query somewhat, could someone comment whether that is the correct approach or am I missing something obvious?

var requestedTimeSpan = TimeSpan.FromHours(1); //1 hour
long numberTicks = requestedTimeSpan.Ticks;
var convertedBars = from myData in bars
                    group myData by myData.TimeStamp.Ticks / numberTicks  into barData
                    select new Bar()
                    {
                        TimeStamp = new DateTime(barData.Key * numberTicks),
                        Open = barData.First().Open,
                        Low = barData.Min(bd => bd.Low),
                        High = barData.Max(bd => bd.High),
                        Close = barData.Last().Close,
                    };
Was it helpful?

Solution

Try this, using an anonymous type for the grouping:

group myData by new { myData.TimeStamp.Date,
       Hour = (int) myData.TimeStamp.TimeOfDay.TotalMinutes / 60 } into barData

OTHER TIPS

Try something like:

var convertedBars =
        bars.GroupBy(b => b.TimeStamp.Date).Select(g => g.GroupBy(b2 => (int)(b2.TimeStamp.TimeOfDay.TotalMinutes / 60))).Select(gb => new Bar()
        {                
            TimeStamp = gb.FirstOrDefault().FirstOrDefault().TimeStamp,
            Open = gb.FirstOrDefault().FirstOrDefault().Open,
            Low = gb.SelectMany(bd => bd).Min(ibd => ibd.Low),
            High = gb.SelectMany(bd => bd).Max(ibd => ibd.High),
            Close = gb.LastOrDefault().LastOrDefault().Close,
        });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top