3. 滑点度量:实现价差、有效价差、Roll模型、协方差法

做市交易里,滑点是个绕不开的话题。说白了,滑点就是你想成交的价格和实际成交价格之间的差距。我刚开始做市的时候,总觉得滑点是个小问题,后来吃过几次亏才明白——滑点控制不好,策略赚的那点钱全给滑点吞了。

今天咱们就聊聊滑点的度量方法。我个人习惯把这四种方法分成两类:一类是直接观测的,比如价差和有效价差;另一类是需要建模推算的,比如Roll模型和协方差法。咱们一个一个来。

核心观点:滑点度量是做市策略的"体检报告"。没有准确的度量,你根本不知道策略到底赚没赚钱。

3.1 价差(Quoted Spread)

价差是最直观的滑点度量。它就是当前市场上最优卖价和最优买价之间的差值。

公式很简单:

Quoted Spread = Ask Price - Bid Price

但在实际项目中,我们通常用相对价差,因为不同价格的股票,绝对价差没法直接比较:

Relative Spread = (Ask - Bid) / Mid Price

其中 Mid Price = (Ask + Bid) / 2

我记得有一次做美股做市,发现某只股票的价差突然从0.01美元跳到了0.05美元。当时我第一反应是市场出问题了,后来一查,原来是财报发布前的正常波动。嗯,这里要注意:价差突然扩大,往往意味着信息事件或者流动性枯竭。

实战技巧:我个人习惯用5分钟窗口计算平均价差。太短了噪声大,太长了反应迟钝。5分钟是个不错的折中。

3.2 有效价差(Effective Spread)

有效价差比报价价差更"真实"。为什么呢?因为报价价差只是挂在那里的价格,实际成交不一定按那个价格走。

有效价差的计算公式:

Effective Spread = 2 * |Trade Price - Mid Price|

这里有个关键点:为什么乘以2?因为实际成交只偏离了中间价的一侧,但我们要把它换算成"全价差"的概念。

举个例子:某股票中间价是100元,你以100.02元买入。那么有效价差就是 2 * |100.02 - 100| = 0.04元。这意味着你实际付出的滑点成本是0.04元,而不是报价价差的0.03元。

我在项目中遇到过这样的情况:报价价差看起来很小,但有效价差却大得惊人。为什么会这样?因为大单成交时,往往会把价格推到报价之外。你想想看,如果你挂100手买单,而最优卖价只有10手,那剩下的90手就得吃更高的价格。

避坑指南:我曾经犯过一个错误——只看报价价差,不看有效价差。结果策略回测表现很好,实盘却一直亏钱。后来才发现,我的订单总是把价格推高了,有效价差比报价价差大了3倍。从那以后,我每次回测都会同时计算这两个指标。

3.3 Roll模型

Roll模型是个很有意思的方法。它不需要看订单簿数据,只需要用成交价格序列就能估算出有效价差。

Roll模型的逻辑是这样的:假设市场是有效的,价格变动主要由两个因素驱动——新信息的到来和买卖价差的反弹。价差反弹会导致价格序列出现负的自相关。

公式:

Spread = 2 * sqrt(-Cov(ΔP_t, ΔP_{t-1}))

其中 ΔP_t 是价格变化量,Cov 是协方差。

注意:如果协方差是正的,那说明Roll模型不适用。这种情况我遇到过几次,通常发生在趋势性很强的市场中。

代码实现:

import numpy as np

def roll_spread(prices):
    """
    使用Roll模型估算有效价差
    prices: 价格序列,numpy array
    """
    # 计算价格变化
    delta_p = np.diff(prices)
    
    # 计算一阶自协方差
    cov = np.cov(delta_p[:-1], delta_p[1:])[0, 1]
    
    # 如果协方差为负,计算价差
    if cov < 0:
        spread = 2 * np.sqrt(-cov)
        return spread
    else:
        # 协方差为正时,Roll模型不适用
        return None

个人经验:Roll模型对数据频率很敏感。我用1分钟数据算出来的结果,和用5分钟数据算出来的,可能差一倍。我个人建议先用高频数据算,然后取中位数,这样比较稳健。

3.4 协方差法

协方差法其实是Roll模型的升级版。它不假设价差是常数,而是允许价差随时间变化。

核心思想:把价格变化分解成两部分——永久性成分(信息冲击)和暂时性成分(价差反弹)。通过分析价格变化的协方差结构,可以分离出这两部分。

具体做法:

1. 计算价格变化的协方差矩阵
2. 对协方差矩阵进行分解
3. 提取价差成分

代码实现:

import numpy as np

def covariance_spread(prices, window=20):
    """
    使用协方差法估算动态价差
    prices: 价格序列
    window: 滚动窗口大小
    """
    spreads = []
    
    for i in range(window, len(prices)):
        # 取窗口内的价格变化
        delta_p = np.diff(prices[i-window:i])
        
        # 计算协方差矩阵
        cov_matrix = np.cov(delta_p)
        
        # 提取价差估计
        # 这里使用简化方法:取协方差矩阵对角线元素的均值
        spread = np.sqrt(np.mean(np.diag(cov_matrix)))
        spreads.append(spread)
    
    return np.array(spreads)

我在项目中用协方差法做过一个有意思的事情:把不同时间尺度的价差估计画在一起,能看出市场的"微观结构"变化。比如,当短期价差和长期价差出现背离时,往往预示着市场即将发生重大变化。

四种方法对比:

方法 数据需求 优点 缺点
报价价差 订单簿数据 简单直观 不能反映实际成交
有效价差 订单簿+成交数据 反映真实成本 需要成交数据
Roll模型 仅成交价格 数据容易获取 假设较强
协方差法 仅成交价格 允许时变价差 计算复杂

3.5 知识体系总览

下面这张图展示了滑点度量的整体框架。我画这张图的时候,特意把四种方法的关系理清楚了:

滑点度量方法体系 滑点度量 直接观测法 模型推断法 报价价差 有效价差 Roll模型 协方差法 需要订单簿数据 简单直观 需要成交数据 反映真实成本 仅需价格序列 假设较强 允许时变价差 计算复杂 选择建议:数据充足用有效价差,数据有限用Roll模型 实盘监控推荐同时使用多种方法交叉验证

这张图把四种方法的关系梳理得很清楚。左边是直接观测法,需要的数据多但结果可靠;右边是模型推断法,数据需求少但假设条件多。我个人建议,如果条件允许,同时用两种方法互相验证。

最后说一句:滑点度量不是目的,控制滑点才是。度量只是第一步,但这一步走不好,后面的控制策略都是空中楼阁。我见过太多人一上来就搞复杂的滑点控制算法,结果连基本的价差都没算清楚。嗯,先把度量做好,再谈控制。


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