Clickhouse 下采样到 OHLC 时间条间隔

clickhouse downsample into OHLC time bar intervals

对于 table 例如包含一个日期,价格时间序列,每个价格例如毫秒,如何将其下采样为具有时间间隔的开高低收(ohlc)行组,例如分钟?

在 ClickHouse 中,您使用数组解决了此类问题。让我们假设 table 如下所示:

CREATE TABLE security (
  timestamp DateTime,
  id UInt32,
  value Float32
)
ENGINE=MergeTree
PARTITION BY toYYYYMM(timestamp)
ORDER BY (id, timestamp)

您可以使用如下查询将采样间隔缩减为一分钟:

SELECT 
  id, minute, max(value) AS high, min(value) AS low, avg(value) AS avg,
  arrayElement(arraySort((x,y)->y, 
    groupArray(value), groupArray(timestamp)), 1) AS first,
  arrayElement(arraySort((x,y)->y, 
    groupArray(value), groupArray(timestamp)), -1) AS last
FROM security
GROUP BY id, toStartOfMinute(timestamp) AS minute
ORDER BY minute

诀窍是使用数组函数。以下是解码调用的方法:

  1. groupArray 将组内的列数据收集到数组中。
  2. arraySort 使用时间戳顺序对值进行排序。我们使用 lambda 函数提供时间戳数组作为第一个值数组的排序键。
  3. arrayElement 允许我们分别选择第一个和最后一个元素。

为了保持示例简单,我使用 DateTime 作为时间戳,它仅以 1 秒的间隔进行采样。您可以使用 UInt64 列来获得您想要的任何精度。我在查询中添加了一个平均值以帮助检查结果。

虽然数组选项可以工作,但这里最简单的选项是使用按时间间隔分组与 minmaxargMinargMax 聚合的组合职能。

SELECT 
  id,
  minute,
  max(value) AS high,
  min(value) AS low,
  avg(value) AS avg,
  argMin(value, timestamp) AS first,
  argMax(value, timestamp) AS last
FROM security
GROUP BY id, toStartOfMinute(timestamp) AS minute
ORDER BY minute