4. 冲击成本建模:基于市场深度的线性冲击模型
冲击成本,说白了就是「你下单时把价格打上去的那部分损失」。我刚开始做高频策略时,总觉得滑点就是冲击成本。后来吃了大亏才发现——滑点是结果,冲击才是原因。
今天我们来聊聊怎么用市场深度数据,给冲击成本建个模。我个人习惯用线性模型,简单、实用、可解释性强。
4.1 什么是冲击成本?
你想想看,当你下了一笔大单,市场会怎么反应?
- 买单会把卖单吃掉,价格往上走
- 卖单会把买单砸穿,价格往下掉
这个「价格被推动的幅度」,就是冲击成本。它跟你的订单大小成正比,跟市场深度成反比。
核心公式(直觉版):
冲击成本 ≈ (你的订单量 / 市场深度) × 价格
嗯,这里要注意:市场深度不是一成不变的。不同价位上的挂单量不同,冲击成本自然也不同。
4.2 线性冲击模型的基本形式
我在项目中遇到过一个问题:用简单比例算冲击成本,总是低估。后来发现,是因为忽略了「深度分布」的影响。
线性冲击模型长这样:
# 线性冲击模型
def linear_impact(order_size, depth_slope, spread_half):
"""
order_size: 订单数量(股/张)
depth_slope: 深度斜率(价格变动1单位,深度变化量)
spread_half: 半价差
"""
# 冲击成本 = 半价差 + (订单量 / 深度斜率) × 价格系数
impact = spread_half + (order_size / depth_slope) * 0.5
return impact
为什么是线性?因为大部分流动性好的市场,在订单量不超过深度10%时,冲击近似线性。超过这个阈值,就变成非线性了——这个我们后面再讲。
4.3 基于市场深度的建模方法
实际建模时,我建议分三步走:
- 获取L2快照数据——买一到买十、卖一到卖十的挂单量
- 计算累计深度曲线——从最优价开始,累计挂单量
- 拟合线性关系——用最小二乘法求出深度斜率
我的小技巧:不要只用最优价位的深度。我习惯用前5档的累计深度,这样能捕捉到「薄冰层」效应——就是表面深度很厚,但第二档就空了的情况。
来看一个完整的建模流程:
import numpy as np
import pandas as pd
def build_depth_curve(bid_prices, bid_sizes, ask_prices, ask_sizes):
"""
构建买卖双方的累计深度曲线
"""
# 买方:从最优买价往下累加
cum_bid = np.cumsum(bid_sizes)
# 卖方:从最优卖价往上累加
cum_ask = np.cumsum(ask_sizes)
return cum_bid, cum_ask
def fit_linear_impact(cum_sizes, price_levels):
"""
用线性回归拟合深度斜率
"""
# 价格偏移量(相对于最优价)
price_offset = price_levels - price_levels[0]
# 拟合:累计深度 = 斜率 × 价格偏移 + 截距
slope, intercept = np.polyfit(price_offset, cum_sizes, 1)
return slope, intercept
# 示例数据
bid_prices = [100.0, 99.9, 99.8, 99.7, 99.6]
bid_sizes = [500, 300, 200, 100, 50]
cum_bid, _ = build_depth_curve(bid_prices, bid_sizes, None, None)
slope, intercept = fit_linear_impact(cum_bid, bid_prices)
print(f"深度斜率: {slope:.2f} 股/分")
print(f"截距: {intercept:.2f} 股")
4.4 线性冲击模型的实战应用
模型建好了,怎么用?我分享三个场景:
| 场景 | 输入 | 输出 | 决策 |
|---|---|---|---|
| 订单拆分 | 目标成交量 | 每笔冲击成本 | 决定单笔大小 |
| 策略回测 | 历史深度 | 模拟滑点 | 评估策略可行性 |
| 实时交易 | 当前快照 | 预估冲击 | 调整下单速度 |
避坑指南:我曾经在回测时直接用当日平均深度来算冲击,结果实盘亏得一塌糊涂。为什么?因为深度在一天内波动很大——开盘和收盘时深度最薄,中午最厚。一定要用「时间对齐」的深度数据。
4.5 线性模型的局限性
说实话,线性模型不是万能的。我总结了三个坑:
- 大单失效——订单量超过深度20%时,冲击会加速上升,变成二次曲线
- 时间衰减——冲击不会永远持续,做市商会补单,价格会部分恢复
- 相关性忽略——多个策略同时交易时,冲击会叠加
那怎么办?我的做法是:在线性模型基础上,加一个「非线性修正项」。比如:
def adjusted_impact(order_size, depth_slope, spread_half, threshold=0.15):
"""
带非线性修正的冲击模型
"""
# 基础线性冲击
linear_part = spread_half + (order_size / depth_slope) * 0.5
# 如果订单量超过阈值,加二次项
if order_size / depth_slope > threshold:
excess = (order_size / depth_slope) - threshold
nonlinear_part = 0.3 * excess ** 2
return linear_part + nonlinear_part
return linear_part
4.6 知识体系总览
下面这张图,是我做冲击成本建模时的核心逻辑框架。你照着这个思路走,基本不会跑偏:
4.7 小结与建议
线性冲击模型,说白了就是「用一把尺子量市场深度」。它简单、直观、容易实现。但你要记住:
- 小单用线性,大单要修正
- 深度会变,要实时更新
- 冲击会恢复,别只看瞬时
我个人习惯在实盘前,先用历史数据跑一遍冲击模型,看看参数是否稳定。如果深度斜率一天内波动超过30%,那就要考虑用更复杂的模型了——比如后面会讲到的「非线性冲击模型」和「时间衰减模型」。
最后送你一句话:冲击成本建模不是越复杂越好。我见过很多团队用深度学习预测冲击,结果还不如线性模型稳定。先跑通线性模型,再考虑升级——这是最稳妥的路径。
公众号:蓝海资料掘金营,微信deep3321