3、Tick数据字段设计:必选字段与可选字段的取舍

好,咱们进入正题。Tick数据长什么样?说白了,就是一笔一笔的切片。每一片里装什么,直接决定了你的系统能做什么、不能做什么。我见过不少团队,一开始图省事只存了价格和成交量,结果做回测时发现盘口数据对不上,整个策略逻辑都得重写。嗯,这里面的坑,我一个个给你拆开讲。

3.1 必选字段:时间戳、价格、成交量、买卖盘口

这四个字段,缺一个,你的Tick数据就是残废的。为什么?我一个个说。

3.1.1 时间戳

时间戳是Tick数据的灵魂。没有精确的时间,你根本没法把不同市场的切片对齐。我个人习惯用纳秒级时间戳,尤其是做高频交易时。为什么?因为交易所的撮合引擎,两个Tick之间可能只差几微秒。你用毫秒级,等于把两个不同的Tick合并成一个,信息就丢了。

重要: 时间戳必须使用交易所原始时间,不要用本地接收时间。我在项目中遇到过,某家券商的行情网关因为时钟同步问题,时间戳偏差了200微秒,导致我们的策略在盘口突变时总是慢半拍。

3.1.2 价格

价格字段,看起来简单,其实坑很多。你得问自己:这个价格是成交价还是最优报价?是限价单的价格还是市价单的?我建议至少存两个价格:最新成交价和最新卖一价。为什么?因为有些策略需要看成交价,有些需要看盘口价,你存一个,后面就得重新算。

精度方面,A股是两位小数,期货是四位,加密货币可能是八位。别想着统一成整数存,我吃过这个亏。统一成整数后,回测时算出来的盈亏总是差几分钱,查了半天才发现是精度丢失。

3.1.3 成交量

成交量字段,注意是「本笔成交量」,不是累计成交量。很多新手会把累计量存进来,结果做回测时发现成交量曲线是单调递增的,根本没法用。我建议存两个:本笔成交量和累计成交量。前者用于计算瞬时流速,后者用于验证数据完整性。

小技巧: 累计成交量可以用来做数据校验。如果前后两个Tick的累计量之差不等于本笔成交量,那说明数据有丢失或重复。我在做数据清洗时,这个校验帮我抓出了不少问题。

3.1.4 买卖盘口

盘口数据,至少存五档。但注意,不是所有交易所都提供五档。有些只给一档,有些给十档。我建议统一存五档,不够的补零。为什么是五档?因为大部分策略只看前五档,再多就是噪音了。

盘口字段包括:买一价、买一量、卖一价、卖一量,一直到买五、卖五。每个字段单独存,不要合并成一个JSON字符串。为什么?因为查询时你要按价格排序,JSON解析太慢了。

3.2 可选字段:逐笔成交与逐笔委托

必选字段是骨架,可选字段是血肉。要不要加,取决于你的应用场景。

3.2.1 逐笔成交

逐笔成交,就是每一笔成交的详细记录。它和Tick的区别是什么?Tick是切片,逐笔是每一笔。如果你做的是高频策略,逐笔成交是必须的。为什么?因为Tick数据是聚合后的,你没法知道这一秒内成交的顺序。而逐笔成交可以告诉你,是先有大单砸盘,还是先有小单托底。

逐笔成交字段包括:成交编号、成交时间、成交价格、成交量、买卖方向。注意,方向字段很重要。有些交易所用B/S表示,有些用1/0。我建议统一成枚举值,方便后续处理。

注意: 逐笔成交数据量非常大。A股一天大约几百万笔,期货可能上千万。如果你全量存储,磁盘很快就爆了。我建议只存活跃合约的逐笔成交,或者只存交易时段的前30分钟和后30分钟。

3.2.2 逐笔委托

逐笔委托,就是每一笔挂单的详细记录。这个数据比逐笔成交还大,因为挂单量是成交量的好几倍。要不要存?我的建议是:如果你做订单簿重建,必须存。如果你只是做策略回测,可以不存。

逐笔委托字段包括:委托编号、委托时间、委托价格、委托量、买卖方向、委托类型(限价/市价)。注意,委托类型字段容易被忽略。限价单和市价单对盘口的影响完全不同,不区分的话,订单簿重建会出错。

3.3 字段类型与精度选择

字段类型选不好,性能差十倍。我直接给结论:

字段 推荐类型 精度 说明
时间戳 int64 纳秒 Unix纳秒时间戳,避免时区问题
价格 int64 小数点后4位 乘以10000后存储,避免浮点误差
成交量 int64 整数 股票按股,期货按手
盘口价格 int64 小数点后4位 同上,统一精度
盘口量 int64 整数 注意单位统一
逐笔成交方向 int8 枚举 0=未知, 1=买, 2=卖
逐笔委托类型 int8 枚举 0=未知, 1=限价, 2=市价
核心原则: 能用整数不用浮点,能用int64不用string。我见过有人用double存价格,结果回测时两个价格明明相等,但浮点比较就是不通过。从那以后,我所有价格都转成整数存。

3.4 知识体系图

下面这张图,把Tick数据字段设计的核心逻辑串起来了。你看一眼,应该就能明白各个字段之间的关系。

Tick数据字段设计知识体系 必选字段 时间戳 int64纳秒,交易所原始时间 价格 int64,乘以10000后存储 成交量 本笔量+累计量,int64 买卖盘口(五档) 买一~买五价/量 卖一~卖五价/量 可选字段 逐笔成交 成交编号、时间、价格、量 买卖方向(枚举int8) 数据量大,建议按需存储 逐笔委托 委托编号、时间、价格、量 买卖方向、委托类型 用于订单簿重建 按需选择 核心原则:整数存储、统一精度、按需取舍

3.5 避坑指南

最后,我把自己踩过的坑总结一下,你遇到了直接绕开:

  • 时间戳时区问题: 我曾经把UTC时间和本地时间混着存,结果回测时发现两个Tick的时间差是负的。从那以后,我统一用Unix纳秒时间戳,不带时区信息。
  • 价格精度不一致: 不同交易所的精度不一样。我建议在入库时统一转成int64,乘以一个公共的精度因子。比如A股乘以100,期货乘以10000,加密货币乘以10^8。
  • 盘口数据缺失: 有些交易所的盘口数据不是每次Tick都推送。我建议在数据清洗时,用前一个Tick的盘口数据填充缺失值,而不是直接丢弃。
  • 逐笔数据重复: 交易所可能会重复推送同一笔成交。我建议用成交编号做去重,不要依赖时间戳。
我的习惯: 每次设计Tick数据字段时,我都会先画一张字段关系图,把必选和可选字段标清楚。然后问自己三个问题:这个字段回测时用不用?实时策略用不用?数据量能不能接受?三个问题都过了,才加进去。

好了,字段设计这块就讲到这里。记住,Tick数据字段不是越多越好,够用就行。你加一个字段,存储成本、传输成本、处理成本都会增加。所以,想清楚再动手。


专注资料整理