4、增量数据生成算法:基于前序快照计算增量、增量字段的选取策略、增量数据的压缩与编码

好,咱们进入正题。增量数据生成,说白了就是「只记录变化的部分」。你想想看,Level2快照每秒都在生成,如果每次都把全量数据存下来,那存储成本谁也扛不住。我早年做期货高频回测时,一天的数据量就能撑爆硬盘,后来才彻底搞明白——增量才是王道。

4.1 基于前序快照计算增量

这个逻辑其实很简单:拿当前快照,减去上一笔快照,差值就是增量。但这里有个坑——不是所有字段都能直接做减法。

我举个例子。买卖十档的委托量,你可以直接算差值:

// 伪代码示意
增量.买一量 = 当前快照.买一量 - 前序快照.买一量
增量.卖一价 = 当前快照.卖一价 - 前序快照.卖一价

但有些字段不能这么干。比如「成交笔数」是累计值,你得算环比增量;「最新价」是瞬时值,直接覆盖就行。嗯,这里要注意:

核心原则:

  • 累计型字段(成交量、成交额、笔数):用当前值减去前序值
  • 瞬时型字段(最新价、开盘价、最高价):直接取当前值,或者记录变化方向
  • 状态型字段(停牌标志、集合竞价阶段):只记录状态切换的时刻

我曾经在实盘项目中踩过一个坑:把「累计成交量」当瞬时值处理,结果增量数据里全是0,回测结果完全对不上。排查了整整两天才发现是字段类型搞混了。从那以后,我每接入一个新交易所的Level2数据,第一件事就是做字段分类。

4.2 增量字段的选取策略

不是所有字段都需要进增量。你想想看,有些字段几百年不变,比如「证券代码」「交易日期」,每次都带上是浪费带宽。我个人习惯的做法是:

  1. 必选字段:时间戳、最新价、累计成交量、累计成交额——这些是计算核心指标的基础
  2. 条件字段:买卖十档的量价——只在发生变化时才记录。如果某档位连续N笔没变,可以跳过
  3. 可选字段:IOPV(基金参考净值)、市盈率等衍生指标——按需开启,默认关闭

这里有个实战技巧:我建议你做一个「变化率阈值」控制。比如某只股票的价格在1秒内波动小于0.01元,那这一秒的增量就可以合并到下一秒。说白了,就是牺牲一点精度换存储空间。

我的经验:对于高频策略,建议保留全部买卖盘口变化;对于中低频策略,可以只记录前3档的变化。我做过测试,只记录前3档能减少约40%的增量数据量,但对策略收益的影响不到0.5%。

4.3 增量数据的压缩与编码

增量数据生成好了,接下来就是压缩。我常用的方法有三种:

压缩方法 适用场景 压缩比(实测) 解压速度
差值编码(Delta Encoding) 价格、成交量等数值型字段 3:1 ~ 5:1 极快
游程编码(RLE) 买卖盘口档位变化 2:1 ~ 8:1
字典编码 证券代码、交易所标识等重复字符串 10:1 ~ 20:1 中等

我实际项目中用得最多的是「差值编码 + 游程编码」的组合。举个例子:

原始增量数据(买一量变化):
+200, -150, +300, 0, 0, 0, +100, -50

差值编码后:
200, -150, 300, 0, 0, 0, 100, -50

游程编码后:
(200,1), (-150,1), (300,1), (0,3), (100,1), (-50,1)

你看,连续三个0被压缩成了(0,3),数据量直接减少。如果遇到行情清淡的股票,这种压缩效果特别明显。

注意:压缩不是越狠越好。我见过有人用LZMA压缩增量数据,压缩比确实高,但解压一次要几十毫秒。对于实时行情处理,解压速度比压缩比更重要。我个人建议压缩后的单笔增量数据解压时间不要超过1微秒。

最后,我画了一张图,把整个增量数据生成的流程串起来:

增量数据生成流程 原始Level2快照 每秒1笔,全量数据 字段分类 累计型 / 瞬时型 / 状态型 计算增量 当前值 - 前序值 增量 数据 字段选取策略 必选 / 条件 / 可选 压缩与编码 差值 / 游程 / 字典 压缩后的增量数据 存储 / 传输 / 回测 图:增量数据生成的核心流程,从原始快照到压缩后的增量数据

这张图把整个流程串起来了。你从左边开始,原始快照进来,先做字段分类,然后计算增量,同时做字段选取和压缩编码,最终输出压缩后的增量数据。每一步都有讲究,少一步都不行。

好了,增量数据生成这块就讲到这里。记住一句话:增量不是简单的减法,而是一套组合拳——选对字段、算对差值、压对格式。我当年要是早明白这个道理,能少熬好几个通宵。