4. Tick与K线的关系
在行情系统中,Tick是市场最细粒度的成交记录,而K线是面向人类阅读与策略计算的聚合结果。二者不是简单的“多对一”关系,而是一套带有时间语义、边界规则和状态维护的映射过程。理解这套映射逻辑,是写出正确K线聚合器的前提。
一、核心原理:Tick到K线的四元映射
每一根K线本质上由四个价格和一个量额构成:开盘价、最高价、最低价、收盘价,以及成交量、成交额。Tick到K线的映射,就是把这六个字段按时间窗口进行归并。其核心规则可以概括为:
- 开盘价:窗口内第一笔Tick的成交价(或该窗口第一笔有效成交价)。
- 最高价:窗口内所有Tick成交价的最大值。
- 最低价:窗口内所有Tick成交价的最小值。
- 收盘价:窗口内最后一笔Tick的成交价。
- 成交量/成交额:窗口内所有Tick的成交量/成交额累加。
这里的关键在于“窗口内”三个字。窗口如何定义、如何对齐、边界Tick归属哪根K线,直接决定了聚合结果是否与交易所行情一致。
二、时间窗口对齐:左闭右开是默认契约
绝大多数行情系统采用左闭右开区间,即 [start, end)。例如1分钟K线,10:00:00.000 到 10:00:59.999 的Tick归属10:00这根K线,10:01:00.000 的Tick归属下一根。这样做的原因是避免同一时刻的Tick被重复计入两根K线。
时间窗口对齐还需要处理“窗口起点”问题。常见做法有两种:
- 自然时间对齐:以交易所开盘时间为基准,按固定周期切分,如09:30、09:31……适用于股票、期货等有明确交易时段的品种。
- 滚动对齐:以第一笔Tick时间为起点,向后滚动切分。适用于7×24小时交易的数字货币等品种。
无论哪种对齐方式,聚合器内部都应维护一个“当前窗口”状态:窗口起始时间、当前OHLC、累计量额。每来一笔Tick,先判断其时间戳是否落在当前窗口内;若不在,则先输出当前K线,再开启新窗口。
# 伪代码:窗口归属判断
if tick.timestamp < current_window.end:
update_current_bar(tick)
else:
emit(current_bar)
current_bar = new_bar(tick)
current_window = next_window(tick.timestamp)
三、边界条件处理:最容易被忽略的坑
边界条件是Tick聚合中最容易出错的地方,常见的有以下几类:
| 边界场景 | 问题描述 | 推荐处理 |
|---|---|---|
| 整点Tick | 10:01:00.000 归属10:00还是10:01 | 左闭右开,归属10:01 |
| 无成交窗口 | 某分钟没有任何Tick | 补空K线或跳过,需与下游约定 |
| 乱序Tick | 时间戳回退的迟到数据 | 丢弃或按事件时间重排 |
| 集合竞价 | 开盘前集中撮合产生大量Tick | 单独窗口或并入首根K线 |
| 收盘最后一秒 | 15:00:00.000 是否计入当日最后一根 | 按交易所规则,通常计入 |
四、案例场景:1分钟K线聚合的完整流程
假设我们收到以下Tick序列(时间戳简化表示):
09:30:00.100 价格100.0 量10
09:30:15.200 价格100.5 量20
09:30:59.900 价格99.8 量5
09:31:00.000 价格100.2 量15
09:31:30.500 价格101.0 量30
按左闭右开规则,前三条归属09:30这根K线,后两条归属09:31。聚合结果为:
- 09:30 K线:开100.0,高100.5,低99.8,收99.8,量35。
- 09:31 K线:开100.2,高101.0,低100.2,收101.0,量45。
注意09:30:59.900这笔Tick虽然接近整点,但仍属于09:30窗口;而09:31:00.000这笔恰好落在边界上,按左闭右开归属09:31。如果实现时用了 <= 而不是 <,就会把整点Tick错误地计入上一根K线。
五、误区与复盘
误区一:用收盘时间判断归属。有些实现用Tick的“接收时间”而非“交易所时间”做窗口判断,导致网络延迟时Tick被错误归入下一根K线。正确做法是始终使用交易所时间戳。
误区二:忽略空窗口。若某分钟无成交,下游策略可能期望K线连续。此时需要明确约定:是补一根开高低收等于前收的“平K线”,还是直接跳过。两种做法对均线、波动率计算影响很大。
误区三:边界用闭区间。把 [start, end] 当作窗口,会导致整点Tick同时属于两根K线,成交量被重复计算。这是最隐蔽也最致命的错误。
误区四:不处理乱序。实时流中迟到Tick若直接更新当前窗口,会破坏OHLC的单调性。建议在聚合器前加一层按事件时间排序的缓冲,或明确丢弃超过水位线的迟到数据。
总结来说,Tick到K线的映射并不复杂,但正确性完全取决于时间窗口的对齐方式和边界条件的处理策略。把“左闭右开”作为默认契约,把乱序和空窗口作为一等公民处理,才能让聚合结果与交易所行情保持一致,为后续策略计算提供可靠基础。