4. 数据源识别与采集

集合竞价样本筛选的质量,首先取决于数据源是否选对、采集是否完整。集合竞价阶段(A股为9:15—9:25,其中9:20—9:25不可撤单)产生的信息并不只存在于一个文件里:交易所行情网关推送的是快照,逐笔委托与逐笔成交则通过Level-2通道下发,而券商柜台、第三方数据商又可能提供加工后的竞价统计。若只取快照,你会丢失“谁在什么时刻挂了多少量、又撤了多少”的关键过程;若只取逐笔,又缺少盘口聚合后的价格参照。因此本节的核心任务是:识别三类数据源各自的字段与语义,设计一套可复现的采集方案,并解决频率、时间戳与缺失值三个工程问题。

三类数据源的字段语义与分工

Level-2逐笔委托记录每一笔委托的进入与撤销,典型字段包括证券代码、委托时间(精确到毫秒或十毫秒)、委托序号、买卖方向、委托价格、委托数量、委托类型(限价/市价/本方最优等)。它是还原竞价过程的主力数据:通过按时间排序的委托流,可以计算9:15—9:20的撤单率、9:20前的虚假挂单规模、以及9:20—9:25的净增委托方向。快照按固定频率(常见3秒一笔,部分源为1秒或逐笔快照)给出十档买卖盘、最新价、成交量、成交额与委托总量,适合刻画竞价末端的盘口形态与虚拟撮合价。成交明细在集合竞价阶段通常只有一笔“开盘集合竞价成交”,但它给出了最终成交价与成交量,是校验前两类数据一致性的锚点。

三者的关系可以概括为:逐笔委托是“过程”,快照是“截面”,成交明细是“结果”。样本筛选若要做撤单行为识别,必须以逐笔委托为主表;若要做竞价强度与盘口失衡度,则以快照为主表;成交明细用于回填标签与交叉验证。

集合竞价数据采集链路:源 → 对齐 → 样本表 Level-2 逐笔委托 委托时间 / 序号 / 方向 价格 / 数量 / 委托类型 含撤单记录(9:20前可撤) 作用:还原挂单与撤单过程 快照(3秒/1秒) 十档买卖盘 / 最新价 成交量 / 成交额 / 委托总量 虚拟撮合价与盘口失衡 作用:刻画竞价末端截面 成交明细 开盘集合竞价成交价 成交量 / 成交笔数 时间戳为撮合完成时刻 作用:结果锚点与标签回填 时间戳对齐与频率统一 统一到交易所时钟(毫秒),逐笔按序号去重排序 快照降采样到3秒栅格,成交明细回填至9:25:00 缺失值:前向填充盘口,委托流缺口标记为不可用 竞价样本宽表(每股票每交易日一行) 撤单率 · 9:20前挂单量 · 净增委托 · 盘口失衡度 · 虚拟撮合价偏离 · 开盘成交量 标签:开盘涨幅、竞价异动标记(由成交明细与快照共同生成)

采集方案的关键设计

采集方案要回答四个问题:采什么、采多久、怎么存、怎么校验。以A股为例,采集窗口应覆盖9:15:00—9:25:00,并向前后各留30秒缓冲,避免网关推送抖动导致首尾丢包。存储上建议按“交易日/证券代码”分区,逐笔委托保留原始字段并追加一列recv_ts(本地接收时间),快照保留原始推送时间src_ts。校验环节至少做三件事:逐笔委托的序号连续性检查、快照时间间隔是否稳定在3秒、成交明细的成交量是否等于快照中9:25时刻的累计成交量。

下面是一段采集落库的伪代码示例,重点在于时间戳双列与去重逻辑:

for msg in l2_stream:            # 逐笔委托与快照混合流
    recv_ts = now_ms()
    if msg.type == "order":
        row = {code, src_ts, seq, side, price, qty, otype, recv_ts}
        upsert("l2_order", key=(code, src_ts, seq), row)   # 序号去重
    elif msg.type == "snapshot":
        row = {code, src_ts, bid1..bid10, ask1..ask10, last, vol, recv_ts}
        upsert("snapshot", key=(code, src_ts), row)
    elif msg.type == "trade" and is_open_auction(msg):
        upsert("auction_trade", key=(code, trade_date), row)

频率、时间戳与缺失值三个坑

频率不一致是最常见的问题。逐笔委托是事件驱动、毫秒级不规则间隔,快照是固定3秒栅格,两者不能直接按行拼接。正确做法是先确定分析栅格(例如以3秒为桶),把逐笔委托聚合到每个桶内(桶内委托笔数、买入量、卖出量、撤单量),再与同桶快照左连接。这样得到的宽表既保留过程强度,又具备截面可比性。

时间戳对齐要区分三种时间:交易所撮合时间src_ts、行情网关推送时间、本地接收时间recv_ts。跨源对齐应以src_ts为准,recv_ts仅用于诊断延迟。若某数据商的逐笔时间只精确到十毫秒,而快照精确到毫秒,需统一截断到十毫秒再比较,否则会出现“同一时刻对不上”的假象。另外,9:25:00的成交明细时间戳可能落在9:25:00.000至9:25:00.500之间,回填时应按“小于等于9:25:00.500”匹配,而不是严格相等。

缺失值分两类处理。快照偶发丢包时,若缺口不超过两个栅格,可用前向填充盘口并标记ffill_flag=1;若缺口更长,该股票当日样本应标记为“盘口不完整”,不参与依赖盘口形态的筛选。逐笔委托的缺口更危险:序号不连续意味着中间有委托丢失,此时撤单率会被系统性低估,应直接将该样本的撤单类特征置为缺失,而不是用0填充——用0填充会把“未知”误判为“没有撤单”,这是样本筛选中典型的标签污染。

不要用全表均值或中位数填充逐笔委托缺口。竞价阶段的委托流具有强时序性,均值填充会抹平9:20前后的结构性差异,导致撤单率、净增委托等特征失真。

一份可直接套用的采集检查表

检查项合格标准不达标处理
逐笔委托序号连续性窗口内无跳号撤单类特征置缺失
快照时间间隔稳定为3秒,抖动≤200ms短缺口前向填充并标记
成交明细与快照一致性成交量误差≤1手以成交明细为准并记录偏差
时间戳精度统一全部截断至十毫秒重新对齐后再合并
采集窗口覆盖9:14:30—9:25:30补采或剔除当日样本

完成上述采集与清洗后,每只股票每个交易日会得到一行结构化的竞价样本,字段涵盖撤单率、9:20前挂单量、净增委托、盘口失衡度、虚拟撮合价偏离与开盘成交量,并附带由成交明细生成的开盘涨幅标签。这份宽表就是后续统计检验的输入底座——数据源选得对、时间戳对得齐、缺失值标得清,后面的筛选结论才站得住。