Reputation: 7254
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,
};
Upvotes: 0
Views: 457
Reputation: 56536
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
Upvotes: 2
Reputation: 2054
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,
});
Upvotes: 0