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 基于市场深度的建模方法

实际建模时,我建议分三步走:

  1. 获取L2快照数据——买一到买十、卖一到卖十的挂单量
  2. 计算累计深度曲线——从最优价开始,累计挂单量
  3. 拟合线性关系——用最小二乘法求出深度斜率

我的小技巧:不要只用最优价位的深度。我习惯用前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 知识体系总览

下面这张图,是我做冲击成本建模时的核心逻辑框架。你照着这个思路走,基本不会跑偏:

冲击成本建模:线性模型知识体系 L2快照数据 买一~买十 / 卖一~卖十 订单流数据 逐笔成交 / 订单簿变化 交易参数 订单量 / 交易频率 线性冲击模型构建 累计深度曲线 → 深度斜率拟合 → 冲击成本公式 I = S/2 + (Q / D_slope) × 0.5 订单拆分优化 控制单笔冲击 回测滑点模拟 评估策略可行性 实时交易控制 调整下单速度 降低交易成本 → 提升策略收益

4.7 小结与建议

线性冲击模型,说白了就是「用一把尺子量市场深度」。它简单、直观、容易实现。但你要记住:

  • 小单用线性,大单要修正
  • 深度会变,要实时更新
  • 冲击会恢复,别只看瞬时

我个人习惯在实盘前,先用历史数据跑一遍冲击模型,看看参数是否稳定。如果深度斜率一天内波动超过30%,那就要考虑用更复杂的模型了——比如后面会讲到的「非线性冲击模型」和「时间衰减模型」。

最后送你一句话:冲击成本建模不是越复杂越好。我见过很多团队用深度学习预测冲击,结果还不如线性模型稳定。先跑通线性模型,再考虑升级——这是最稳妥的路径。


公众号:蓝海资料掘金营,微信deep3321