1. 课程导入与数据基础

在逐笔成交与逐笔委托构成的微观结构数据体系中,撤单往往被当作“没有发生的交易”而被忽略。但在真实的撮合市场里,撤单是订单生命周期中信息含量极高的一环:它既可能是做市商在报价被吃掉前的主动收缩,也可能是大单在价格即将穿越时的紧急避险,还可能是算法在队列位置不利时的策略性退出。研究逐笔撤单,本质上是在研究“谁在什么价位、什么时刻、以多大规模放弃了原本愿意成交的意愿”,而这种意愿的撤回,往往先于价格的移动发生。

本课程的核心问题可以归纳为一条主线:撤单行为是否携带对未来成交与价格响应的可预测信息,以及这种信息如何被量化、关联与验证。围绕这条主线,我们需要回答三个层次的问题。第一层是描述层:某只标的在特定时段内的撤单在价格、数量、方向上呈现什么分布,撤单率与成交率如何随时间变化。第二层是关联层:同一订单号从委托到撤单的存活时间、撤单前的盘口状态、撤单与随后成交的方向是否一致,这些关联特征能否区分不同类型的撤单动机。第三层是响应层:撤单事件发生后,未来若干秒或若干笔内的成交强度、买卖压力与价格漂移如何变化,从而判断撤单是“噪声”还是“信号”。

研究目标不是简单地统计撤单数量,而是建立“撤单特征 → 成交响应”的可检验映射。因此整体技术路线遵循:数据清洗与字段对齐 → 订单级生命周期重建 → 撤单特征构造 → 响应变量定义 → 关联分析与模型验证。每一步都必须以订单号为主键,保证委托、撤单、成交三类记录能够被正确缝合。

数据字段解析:从原始记录到订单生命周期

逐笔数据通常以“逐笔委托”和“逐笔成交”两张表呈现,撤单信息一般出现在逐笔成交表中以特定成交类型标识,或在独立的撤单表中给出。无论哪种形式,研究撤单都必须先明确字段语义。以下字段是构建订单生命周期的关键:

字段含义在撤单研究中的作用
订单号交易所为每笔委托分配的唯一标识主键,用于把委托、撤单、成交记录关联为同一订单
撤单时间撤单被撮合系统接受的时刻,精确到毫秒或微秒计算订单存活时间、构造事件时间轴
价格委托价或撤单对应的原委托价判断撤单位于买盘还是卖盘、距盘口多远
数量撤单数量(可能为部分撤单)区分全撤与部撤,衡量撤单规模
方向买或卖判断撤单对买卖压力的影响方向
委托时间原始委托进入系统的时刻与撤单时间相减得到存活时长

需要特别强调两个容易出错的细节。其一是部分撤单:一笔委托可能先成交一部分,剩余部分再被撤回,此时撤单数量小于原始委托数量,若直接用撤单数量当作委托规模会低估订单意图。其二是时间参照系:本文所有时间差均以“撤单时间减委托时间”为正方向,单位为毫秒,若数据源使用交易所本地时钟,需先确认两张表时间戳口径一致,否则存活时间会出现负值或系统性偏移。

下面给出一段示例性的字段对齐与生命周期重建代码,用于说明实际操作方式。示例参数与输出均为教学假设,不代表真实市场数据。

import pandas as pd

# 假设已读入逐笔委托与逐笔成交(含撤单标识)
orders = pd.read_csv("order.csv")      # order_id, order_time, price, qty, side
trades = pd.read_csv("trade.csv")      # order_id, trade_time, trade_type, qty

# 1) 分离撤单记录:trade_type == 'C' 表示撤单
cancels = trades[trades["trade_type"] == "C"].copy()
cancels = cancels.rename(columns={"trade_time": "cancel_time"})

# 2) 以订单号关联委托信息
life = cancels.merge(orders, on="order_id", how="left")

# 3) 计算存活时间(毫秒),并标记全撤/部撤
life["alive_ms"] = (life["cancel_time"] - life["order_time"]).dt.total_seconds() * 1000
life["cancel_ratio"] = life["qty_x"] / life["qty_y"]   # 撤单量 / 原始委托量
life["is_full"] = life["cancel_ratio"] >= 0.999

print(life[["order_id", "alive_ms", "cancel_ratio", "is_full"]].head())

这段代码的关键不在语法,而在于它体现了研究的基本纪律:任何撤单特征都必须回到订单号这一主键上,任何统计都必须先确认撤单是全部撤回还是部分撤回。完成这一步后,我们才拥有了一张“订单级撤单事件表”,后续的价格距离、盘口状态、成交响应都可以在这张表上继续扩展。

逐笔撤单研究:数据基础与技术路线 逐笔委托表 订单号 / 委托时间 价格 / 数量 / 方向 逐笔成交表 订单号 / 成交时间 成交类型 / 数量 撤单记录 撤单时间 / 撤单数量 原委托价 / 方向 订单生命周期重建 以订单号为主键缝合 存活时间 = 撤单 − 委托 撤单比例 = 撤量 / 委托量 全撤 / 部撤标记 撤单特征构造 存活时长 / 距盘口价差 撤单规模 / 方向 / 时段 成交响应变量 未来 N 笔成交强度 买卖压力变化 / 价格漂移 关联分析与验证 分组对比 / 相关性检验 样本外稳健性检查 核心问题:撤单行为是否携带对未来成交与价格响应的可预测信息? 描述层:撤单分布与撤单率 → 关联层:存活时间与盘口状态 → 响应层:成交强度与价格漂移 时间参照约定:存活时间 = 撤单时间 − 委托时间,单位毫秒,正值表示正常生命周期

上图把本节的知识结构压缩为一条可执行的链路:左侧三类原始记录通过订单号汇聚到“订单生命周期重建”,再向右扩展为撤单特征与成交响应变量,最终进入关联分析与验证。图中底部的三层问题对应研究目标,而时间参照约定则提醒我们,所有涉及时间差的特征都必须先统一口径。

研究目标的具体化与首轮观察

把目标落到可操作的层面,本节建议先完成三项基础工作。第一,统计撤单率的时间序列,即每分钟撤单笔数占委托笔数的比例,观察是否存在开盘、收盘或特定事件前后的聚集。第二,按存活时间分桶,例如 0–50ms、50–500ms、0.5–5s、5s 以上,比较不同桶内的撤单比例与方向分布,初步判断哪些撤单更像“瞬时反悔”,哪些更像“长时间挂单后的策略调整”。第三,对每笔撤单计算其价格相对当时最优买价或最优卖价的距离,距离越近的撤单对盘口压力的边际影响越大。