第1章:冲击成本与订单簿重建

大家好,我是老张。今天咱们聊聊冲击成本和订单簿重建这个话题。

说实话,我刚入行那会儿,对冲击成本的理解特别肤浅。就觉得——我下单量大,价格就会往不利方向跑,这就是冲击成本呗。但后来在实盘中被市场狠狠教育了几次,才明白事情远没那么简单。

1.1 冲击成本到底是什么?

冲击成本,说白了就是你的订单对市场价格造成的影响。你买,价格涨;你卖,价格跌。这个价差,就是冲击成本。

但这里有个关键点:冲击成本不是固定的。它取决于很多因素:

  • 你的订单大小(相对于市场深度)
  • 市场的流动性状况
  • 订单簿的微观结构
  • 你下单的速度和方式

我记得有一次做回测,策略在模拟环境里年化收益30%,实盘一跑直接变成负的。查了半天,问题就出在冲击成本上。模拟环境里我假设每笔交易冲击成本是1个tick,但实际市场里,大单进去直接打穿好几层深度,冲击成本翻了5倍。

核心观点:冲击成本不是线性增长的。当你的订单量超过订单簿第一档深度时,冲击成本会呈指数级上升。

1.2 订单簿重建:为什么需要重建?

订单簿重建,就是把逐笔委托数据还原成完整的订单簿状态。你可能会问:交易所不是实时推送订单簿吗?为什么还要重建?

嗯,这里有个坑。交易所推送的快照数据,更新频率有限。比如深交所的Level-2行情,快照是每3秒推送一次。但在这3秒内,可能发生了成百上千笔委托和成交。如果你只看快照,中间的价格波动和深度变化就全丢了。

我做过一个统计:在快照间隔的3秒内,订单簿的变化量平均在200-500笔。这意味着什么?意味着你看到的订单簿,其实是3秒前的「历史遗迹」。

注意:使用快照数据做高频策略,相当于闭着眼睛开车。你必须重建订单簿,才能看到真实的市场状态。

1.3 事件驱动重建:核心逻辑

订单簿重建有两种方式:

  1. 全量重建:每次收到快照,重新构建整个订单簿
  2. 事件驱动重建:基于逐笔委托事件,增量更新订单簿

我个人更推荐事件驱动重建。为什么?因为效率高。全量重建每次都要处理几千条记录,而事件驱动只需要处理增量变化。

事件驱动重建的核心逻辑是这样的:

# 伪代码示例
class OrderBook:
    def __init__(self):
        self.bids = {}  # 买单,key=价格,value=数量
        self.asks = {}  # 卖单,key=价格,value=数量
    
    def on_order(self, order_event):
        # 处理委托事件
        if order_event.side == 'buy':
            self.bids[order_event.price] = order_event.quantity
        else:
            self.asks[order_event.price] = order_event.quantity
    
    def on_trade(self, trade_event):
        # 处理成交事件
        # 成交意味着订单被部分或全部吃掉
        if trade_event.side == 'buy':
            self.asks[trade_event.price] -= trade_event.quantity
        else:
            self.bids[trade_event.price] -= trade_event.quantity
        
        # 清理空档
        self._clean_empty_levels()
    
    def on_cancel(self, cancel_event):
        # 处理撤单事件
        if cancel_event.side == 'buy':
            del self.bids[cancel_event.price]
        else:
            del self.asks[cancel_event.price]

你看,逻辑其实不复杂。但实际实现时,有几个坑要注意:

  • 时间戳对齐:不同事件的时间戳精度可能不同,需要统一处理
  • 事件顺序:同一时刻发生的事件,处理顺序会影响结果
  • 数据缺失:逐笔数据偶尔会丢包,需要做校验和补偿

小技巧:我习惯在重建时维护一个「校验和」。每处理1000笔事件,就和快照数据做一次对比。如果偏差超过阈值,就触发全量重建。这样既保证了效率,又防止了误差累积。

1.4 逐笔委托数据的应用

重建订单簿只是第一步。真正有价值的是,基于重建后的数据做分析。我常用的几个应用场景:

应用场景 说明 我的经验
冲击成本估算 基于实时深度,估算不同订单量的冲击成本 比固定比例法准确3-5倍
流动性预测 分析订单簿变化趋势,预测未来流动性 对高频策略特别有用
订单流分析 识别大单、算法单、散户单的行为模式 能提前发现机构动向
市场微观结构研究 分析价差、深度、订单到达率等指标 做市商策略的核心输入

举个例子。我曾经用逐笔数据做过一个「大单预警」模型。逻辑很简单:当订单簿的某一侧突然出现大量限价单,且这些单子很快被吃掉,说明有大资金在进场。这时候,冲击成本会急剧上升。我的策略就会暂停交易,等市场稳定后再出手。

1.5 知识体系总览

下面这张图,是我对本章知识体系的总结。你看一眼,就能明白各个概念之间的关系:

冲击成本与订单簿重建知识体系 冲击成本分析 订单簿重建 全量重建(基于快照) 事件驱动重建(基于逐笔) 逐笔委托数据 委托事件(Order) 成交事件(Trade) 撤单事件(Cancel) 应用:冲击成本估算 | 流动性预测 | 订单流分析

这张图把整个知识体系串起来了。你看,冲击成本分析是核心目标,订单簿重建和逐笔委托数据是两大支撑。重建提供了「状态」,逐笔数据提供了「过程」。两者结合,才能准确估算冲击成本。

1.6 避坑指南

最后,分享几个我踩过的坑:

  • 别信快照数据:快照只是「参考」,逐笔数据才是「真相」
  • 注意数据延迟:逐笔数据也有延迟,尤其是跨市场套利时
  • 别忽略撤单:很多策略只关注委托和成交,但撤单同样重要——它反映了市场情绪的变化
  • 做好异常处理:数据偶尔会乱序、重复、缺失,代码要能容错

一句话总结:冲击成本不是算出来的,是「重建」出来的。没有准确的订单簿重建,一切冲击成本分析都是空中楼阁。

好了,这一章就到这里。下一章我们会深入讨论如何用逐笔数据做更精细的冲击成本建模。到时候我会分享一个我实际用过的模型,以及它的代码实现。