如何使用LINQ按间隔(OHLC条)对时间序列进行分组

时间:2011-04-28 14:42:25

标签: c# linq group-by

我之前看到过这个问题的变异,但没有明确的答案。

我有一个带有时间戳的对象列表(股票交易数据或'滴答'):

Class Tick
{
  Datetime Timestamp;
  double Price;
}
  1. 我想基于那些按特定间隔分组的值生成另一个列表 为了创建一个OHLC栏(开放,高,低,关闭)。 这些条可以是指定的任何间隔(1分钟,5,10或甚至1小时)。

  2. 我还需要找到一种有效的方法来将新的“滴答”排序到列表中,就像它们一样 可能会以很高的速度到达(每秒3-5个滴答)。

  3. 对此有任何想法,谢谢!

1 个答案:

答案 0 :(得分:1)

  

我想基于另一个列表生成   在那些按分组的值上   一定的间隔,以创造一个   OHLC栏(开盘价,最高价,最低价,收盘价)。   这些条可以是任何间隔   指定(1分钟,5,10或甚至1)   小时)。

很遗憾,您尚未指定:

  1. 条形系列的阶段将是什么。
  2. 酒吧的开始/结束时间是否完全基于“自然时间”(仅取决于固定的时间表而不是其中第一个和最后一个时间戳的时间戳)。
  3. 假设自然时间日内条形,通常将 夹紧到午夜。所以每小时的酒吧将是00:00 - 01:00,01:00 - 02:00等。在这种情况下,酒吧的开始/结束时间可以作为其唯一键。

    那么问题就变成了:勾选的时间戳属于什么样的开始/结束时间?如果我们假设上面假设的所有内容,那么可以使用一些简单的整数数学来轻松解决。然后查询可以是(未经测试,仅算法):

    var bars = from tick in ticks
    
               // Calculate the chronological, natural-time, intra-day index 
               // of the bar associated with a tick.
               let barIndexForDay = tick.Timestamp.TimeOfDay.Ticks / barSizeInTicks
    
               // Calculate the begin-time of the bar associated with a tick.
               // For example, turn 2011/04/28 14:23.45 
               // into 2011/04/28 14:20.00, assuming 5 min bars.
               let barBeginDateTime = tick.Timestamp.Date.AddTicks
                                  (barIndexForDay * barSizeInTicks)
    
               // Produce raw tick-data for each bar by grouping.
               group tick by barBeginDateTime into tickGroup
    
               // Order prices for a group chronologically.
               let orderedPrices = tickGroup.OrderBy(t => t.Timestamp)
                                            .Select(t => t.Price)
    
               select new Bar
               {
                    Open = orderedPrices.First(),
                    Close = orderedPrices.Last(),
                    High = orderedPrices.Max(),
                    Low = orderedPrices.Min(),
                    BeginTime = tickGroup.Key,
                    EndTime = tickGroup.Key.AddTicks(barSizeInTicks)
               };
    

    通常希望按索引/日期时间定位条形图以及按时间顺序枚举系列中的所有条形图。在这种情况下,您可能需要考虑将条形存储在集合中,例如SortedList<DateTime, Bar>(其中键是条的开始或结束时间),这将很好地填充所有这些角色。

      

    我还需要找到一种有效的方法   将新的“滴答”排序到列表中,如   他们可能会以很高的速度到达(3-5   每秒滴答声。)

    这取决于你的意思。

    如果这些价格与实时价格相关(按时间顺序排列),您根本不需要查找 - 只需存储当前的,不完整的“部分”条形图。当新的刻度线到达时,检查其时间戳。如果它仍然是当前“部分”栏的一部分,只需用新信息更新栏(即Close = tick.Price,High = Max(oldHigh,tick.Price)等)。否则,“部分”栏已完成 - 将其推入栏中。请注意,如果您使用“自然时间”条形图,则条形图的末尾也可以通过时间的推移而不是价格事件(例如,小时条形图在小时内完成)。

    编辑:

    否则,您需要进行查找。如上所述,如果你存储在排序列表中的栏中(按开始时间/结束时间键入),那么你只需要计算与之相关的栏开始时间/结束时间。打勾。这应该很容易;我已经给你一个如何在上面的LINQ查询中完成它的示例。

    例如:

    myBars[GetBeginTime(tick.Timestamp)].Update(tick);