3. 价差序列构建:计算方法与标准化处理

价差序列,说白了就是两个品种价格之间的“差值轨迹”。

很多人以为价差就是简单的A减B,其实没那么简单。我做了这么多年套利,见过太多人栽在第一步——价差算错了,后面所有分析都是白搭。

3.1 价差的基本计算方法

先讲最基础的。价差计算有三种主流方式:

  1. 直接相减法:Price_A - Price_B
  2. 对数价差法:ln(Price_A) - ln(Price_B)
  3. 比例价差法:Price_A / Price_B

我个人习惯用对数价差。为什么?因为对数变换后,价差序列的统计性质更稳定,方差齐性更好。我在项目中遇到过用直接相减法做螺纹钢和热卷的套利,结果价差序列的方差随着价格水平变化,搞得我回测结果忽上忽下。换成对数价差后,问题就解决了。

核心原则:价差计算方式取决于品种间的协整关系。如果两个品种价格水平相近,直接相减即可;如果价格水平差异大,建议用对数价差。

3.2 标准化处理:让价差变得“可读”

算完价差,你会发现一个问题——不同时间段的价差数值范围不一样。比如2015年螺纹钢和热卷的价差在[-200, 200]之间波动,到了2021年变成了[-500, 500]。这怎么比较?

所以需要标准化。我常用的方法有两种:

方法 公式 适用场景
Z-score标准化 (X - μ) / σ 均值回归策略,最常用
Min-Max标准化 (X - min) / (max - min) 需要固定阈值区间时

嗯,这里要注意:Z-score标准化假设数据服从正态分布。但实际中价差序列往往有厚尾特征。我建议用滚动窗口计算均值和标准差,窗口大小一般取20个交易日或60个交易日。

我的经验:滚动窗口太短(比如5天),标准化后的序列噪声太大;窗口太长(比如120天),对市场变化的反应太迟钝。我个人偏好60天窗口,兼顾稳定性和灵敏度。

3.3 代码实现:从原始数据到标准化价差

光说不练假把式。下面是我常用的Python实现:

import numpy as np
import pandas as pd

def build_spread(price_a, price_b, method='log'):
    """
    构建价差序列
    method: 'log' 对数价差, 'direct' 直接相减, 'ratio' 比例价差
    """
    if method == 'log':
        spread = np.log(price_a) - np.log(price_b)
    elif method == 'direct':
        spread = price_a - price_b
    elif method == 'ratio':
        spread = price_a / price_b
    return spread

def zscore_normalize(spread, window=60):
    """
    滚动Z-score标准化
    """
    mean = spread.rolling(window=window).mean()
    std = spread.rolling(window=window).std()
    zscore = (spread - mean) / std
    return zscore

# 使用示例
price_a = pd.Series([...])  # 品种A价格
price_b = pd.Series([...])  # 品种B价格
raw_spread = build_spread(price_a, price_b, method='log')
norm_spread = zscore_normalize(raw_spread, window=60)

这段代码我用了好几年,基本没出过问题。但有一个坑——滚动窗口的前期数据会变成NaN。我一般会丢弃前60个数据点,或者用回填法填充。

3.4 避坑指南:价差构建中的常见陷阱

我曾经犯过一个低级错误:用不同交易所的收盘时间不一致的数据构建价差。比如上期所的螺纹钢15:00收盘,而大商所的铁矿石15:00收盘但最后三分钟是集合竞价。结果价差序列里出现了大量“伪信号”。

所以,构建价差前一定要做三件事:

  • 时间对齐:确保两个品种的采样时间完全一致
  • 合约匹配:用相同到期月份的合约,或者用主力连续合约
  • 异常值处理:剔除涨跌停、停牌等异常数据点

警告:不要直接用不同交易所的收盘价做价差!不同交易所的收盘机制不同,价差里会混入“时间错配”的噪声。我建议用日内分钟线数据,或者至少用同一时刻的快照数据。

3.5 知识体系图:价差构建全流程

下面这张图总结了价差构建的完整流程,从原始数据到最终可用的标准化价差:

原始价格数据 时间对齐 (同一时刻采样) 价差计算 (直接/对数/比例) 标准化处理 (Z-score/Min-Max) 异常值处理 (剔除/填充/平滑) 标准化价差序列 (可用于策略回测) 图:价差序列构建全流程 关键参数:滚动窗口(20/60/120天)、标准化方法(Z-score/Min-Max)、异常值阈值(±3σ) 常见组合:对数价差 + 60天滚动Z-score + 3σ异常值剔除

3.6 实战中的几个细节

最后聊几个我踩过的坑:

  • 合约换月:主力合约切换时,价差会出现“跳空”。我一般会在换月前后各留3天缓冲期,用加权平均价过渡。
  • 交易成本:价差序列本身不含交易成本。但做策略时一定要把手续费、滑点算进去。我见过有人回测年化30%,加上成本后直接变负。
  • 数据频率:日线数据适合长周期套利,分钟线适合高频。但高频数据的噪声更大,标准化时建议用更短的滚动窗口。

一个小技巧:构建完价差序列后,先画个图看看。如果价差看起来像随机游走,那大概率没有套利机会。如果价差有明显的均值回复特征,恭喜你,找到金矿了。

价差构建是套利策略的基石。这一步做扎实了,后面的风险控制和资金管理才能有的放矢。嗯,今天就先聊到这里。


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