【维克】价差交易实战:配对交易的核心参数设置

0 阅读14分钟

上一篇文章讲了配对交易的核心逻辑——找两只存在协整关系的股票,等价差偏离时入场,赌价差回归赚钱。

听起来很简单。但实际上,很多配对交易者都踩过同一个坑:协整检验通过了,价差看起来也很稳定,但策略上线就是亏钱。

问题出在哪?不在方向判断,不在品种选择,而在参数设置。

入场阈值定多少倍标准差?出场是回到均值还是回到0.5σ?布林带窗口用多长?交易成本怎么算进预期收益?这些问题中的任何一个设置不当,都能把一个理论上完美的配对交易变成实盘中的持续失血。

这篇文章,把配对交易从"知道怎么做"到"真正做对"之间的那段路补齐。我会从价差计算讲起,覆盖布林带化、开平仓阈值设计、持仓周期优化和交易成本核算,每一步都有代码、有参数参考、有实操经验。

Why:为什么参数设置决定了配对交易的成败?

一个真实的失败案例

某量化团队花了两周时间找到一组完美配对——协整p值0.001,半衰期12天,价差图呈现出教科书般的均值回归形态。他们信心满满地设置了经典的2倍标准差入场、0.5倍标准差出场,上线实盘。

两周后,策略亏了4%。

复盘发现三个致命问题:

1. 交易成本吞噬利润:入场阈值2倍标准差,意味着每月只有1-2次交易机会,但每次持仓约15天。按A股配对交易的成本(佣金+滑点+融券利息),交易成本吃掉了40%的毛利润。

2. 标准差窗口选错:他们用了全样本标准差,但价差波动率在最近3个月明显收窄。全样本2倍标准差等效于近期波动的2.5倍——入场信号根本触发不了。

3. 出场太贪心:出场设在0.5σ,但价差的半衰期是12天,0.5σ的出场意味着平均持仓要10天以上。资金效率极低。

这三个问题有一个共同根源:参数不是孤立设置的,它们之间存在紧密的交互关系。 入场阈值决定了交易频率和持仓时间,出场阈值决定了每次收益和持仓时间,交易成本又反过来约束了最低收益要求。改一个参数,其他参数的最优值也跟着变。

参数之间的核心矛盾

配对交易的参数设计,本质上是在三组矛盾之间寻找平衡:

矛盾一:信号频率 vs 每次收益

入场阈值越低(比如1.0σ),信号越多,但每次价差偏离不够大,单次收益薄。入场阈值越高(比如2.5σ),每次收益丰厚,但信号稀少,资金大量时间闲置。

矛盾二:持仓时间 vs 资金效率

出场阈值越接近均值(比如0σ),每次收益最大化,但持仓时间长、资金效率低。出场阈值越宽松(比如1.0σ),快进快出效率高,但放弃了后续回归的利润。

矛盾三:收益空间 vs 交易成本

每次交易的毛收益必须覆盖交易成本。如果入场阈值太低、单次收益太薄,扣掉手续费和滑点就所剩无几。但为了覆盖成本而拉高入场阈值,又会导致信号频率过低。

这三组矛盾没有通用最优解,只有针对具体品种、具体市场环境和你自己资金规模的合适解。下面一层一层展开。

What:价差计算与布林带化的完整框架

第一步:根据协整关系计算理论价差

回顾上一篇的协整回归结果:

Y = α + β × X + ε

理论价差的定义:

Spread = Y - β × X

关键认知:价差不是简单的 Y - X!必须用协整回归的β作为对冲比率。

为什么?因为β代表了两只股票之间的价格弹性。如果β=1.5,意味着X每涨1%,Y倾向于涨1.5%。用 Y - 1.5X 计算出来的价差才是平稳的;用 Y - X 计算出来的价差可能一直在漂移。

举个具体例子。假设工商银行(Y)和建设银行(X)的协整回归得到 β=1.02,α=0.5。那么:

Spread = 工商银行价格 - 1.02 × 建设银行价格 - 0.5

这个价差序列才是我们在其上建立交易逻辑的对象。它反映的是:剔除掉两只股票之间的长期均衡关系后,当前的"异常偏离"有多大。

第二步:计算价差的滚动统计量

价差计算出来后,需要对其做统计量化。核心指标有三个:均值、标准差和Z-score。

// python
import pandas as pd
import numpy as np

def spread_statistics(spread, lookback=60):
"""
计算价差的滚动统计量

    参数:
- spread: 价差序列
- lookback: 滚动窗口(天数),默认60天

    返回:
- 包含均值、标准差、Z-score和布林带上下轨的DataFrame
"""
mean = spread.rolling(lookback).mean()
std = spread.rolling(lookback).std()

    # Z-score:当前价差偏离均值多少个标准差
z_score = (spread - mean) / std

    # 布林带化:均值 ± N倍标准差构成上下轨
upper_2std = mean + 2 * std
lower_2std = mean - 2 * std
upper_1std = mean + 1 * std
lower_1std = mean - 1 * std

    return pd.DataFrame({
'spread': spread,
'mean': mean,
'std': std,
'z_score': z_score,
'upper_2std': upper_2std,
'lower_2std': lower_2std,
'upper_1std': upper_1std,
'lower_1std': lower_1std
})

逐行解释:

• rolling(lookback).mean():过去N天价差的滚动均值,代表"当前正常水平"

• rolling(lookback).std():过去N天价差的滚动标准差,代表"正常波动范围"

• z_score:标准化偏离度。Z=2意味着当前价差比近期均值高了2个标准差,属于统计上的极端偏离

• 布林带上下轨:把均值和标准差映射回价差的实际数值空间,方便直接在价格图上画线

lookback窗口的选择——一个被低估的关键参数

lookback窗口决定了均值和标准差的"记忆长度"。这个参数的选择对整个策略影响巨大,但很多教程一笔带过。

窗口太短(如20天):

• 均值和标准差对近期噪音太敏感

• 一次偶然的价差偏离就会显著拉高标准差,导致后续阈值过宽

• 布林带"追着价差跑",失去参考价值

窗口太长(如250天):

• 无法及时反映价差波动率的结构性变化

• 如果市场特征已经改变(比如行业格局变化),你还在用半年前的波动率做参考

• 信号滞后严重

推荐方案:

• 基础窗口60天(约3个月),适合大多数A股配对

• 如果配对品种波动率较稳定(如大行对大行),可以放宽到90-120天

• 如果配对品种波动率经常变化(如科技股配对),缩短到40-60天

• 进阶方案:同时用短期窗口(30天)和长期窗口(90天),短期信号用于入场判断,长期窗口用于确认趋势是否改变

布林带化的实战解读

布林带化的本质是把价差的统计特征转化为可视化的交易通道。

在实盘中,你看到的图是这样的:

上轨(均值 + 2σ):  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  极端超涨区
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
上轨(均值 + 1σ):  - - - - - - - - - -  偏强区域
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
均值:               ═══════════════════  均衡水平
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
下轨(均值 - 1σ):  - - - - - - - - - -  偏弱区域
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
下轨(均值 - 2σ):  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  极端超跌区

价差触及上轨(+2σ)→ 做空价差(卖Y买X)

价差触及下轨(-2σ)→ 做多价差(买Y卖X)

价差回到均值附近 → 平仓

这是最基本的框架。但实际参数怎么设,是下面要重点讨论的。

How:开平仓阈值设计与成本优化

入场阈值:不是"2倍标准差"那么简单

大多数教程告诉你"用2倍标准差入场"。但这只是一个起点,不是终点。

不同入场阈值对应的交易特征完全不同:

| 入场阈值 | 信号频率(月) | 每次期望毛收益 | 平均持仓天数 | 适用场景 | | --- | --- | --- | --- | --- | | 1.0σ | 8-12次 | 低(0.3-0.8%) | 3-7天 | 高频、低波动品种、低交易成本 | | 1.5σ | 4-6次 | 中(0.8-1.5%) | 5-12天 | 大多数配对的默认起点 | | 2.0σ | 1-3次 | 高(1.5-3%) | 8-20天 | 低频、高波动品种 | | 2.5σ | 0-1次 | 很高(2-5%) | 15-30天 | 极端事件捕捉、成本敏感型 |

选择的核心约束:期望毛收益必须大于往返交易成本的2倍。这是一个硬约束——如果覆盖不了成本,策略就没有正期望。

举个例子:

• A股配对的往返成本约0.25%(含佣金+滑点+印花税)

• 如果入场1.5σ、出场0.5σ,期望毛收益约为1.0%×价差标准差

• 价差标准差需要 > 0.25%/1.0% = 0.25%,策略才有正期望

• 如果价差日波动率只有0.1%,这个参数组合就不可行

出场阈值:快进快出 vs 吃满回归

出场阈值的选择直接影响两个指标:每次收益和持仓时间。

| 出场阈值 | 每次收益占比 | 持仓时间 | 特点 | | --- | --- | --- | --- | | 0(回到均值) | 100% | 最长 | 收益最大化,但等的时间也最长 | | 0.5σ | 约75% | 中等 | 收益与效率的平衡点 | | 1.0σ | 约50% | 最短 | 快进快出,适合高频 |

实操建议:

大多数情况下,0.5σ是一个好的出场阈值。原因是:

• 从2σ偏离回到0.5σ,已经获得了约75%的潜在收益

• 从0.5σ回到0,剩余的25%收益需要额外的等待时间(根据半衰期,可能还要等一个半衰期)

• 资金效率更重要——把资金释放出来等下一个机会,比死等最后25%更划算

进阶方案:分批出场

• 价差回到0.5σ时平仓50%

• 价差回到均值时平仓剩余50%

• 这样既锁定了一部分利润,又不完全放弃后续回归的收益

持仓周期与半衰期的关系

持仓周期不是你想定多久就定多久,它由价差的半衰期决定。

半衰期的含义:价差偏离均值后,回归到一半所需的天数。如果半衰期是10天,意味着今天价差偏离了2σ,10天后期望偏差缩小到1σ。

持仓周期和半衰期的关系:

| 持仓周期 vs 半衰期 | 效果 | | --- | --- | | < 0.5 × 半衰期 | 太短,价差大概率还没回归,收益不稳定 | | 0.5 ~ 1.5 × 半衰期 | 最优区间,收益/时间比最佳 | | 1.5 ~ 2 × 半衰期 | 边际收益递减,资金效率下降 | | > 2 × 半衰期 | 大概率均值已经漂移,应考虑止损 |

经验法则:

• 最优持仓周期 ≈ 0.5 到 1.5 倍半衰期

• 时间止损位 = 2 倍半衰期。超过这个时间还没回归,不要等了,止损离场

• 如果半衰期超过30天,这个配对可能不适合做短期交易,考虑换一个

交易成本:配对交易的隐形杀手

交易成本是配对交易最大的敌人。原因很简单:配对交易的利润本来就薄——你赚的是价差回归的钱,不是单边趋势的钱。如果成本太高,利润会被吃光。

A股配对交易的成本构成:

| 成本项 | 估计值 | 说明 | | --- | --- | --- | | 佣金 | 0.025%×2 = 0.05% | 买卖双边,按万2.5计算 | | 印花税 | 0.05% | 卖出方单边征收 | | 滑点 | 0.05-0.1% | 取决于流动性,大市值品种更低 | | 融券利息 | 8-10%/年 | 做空端成本,按年化计算 | | 冲击成本 | 0.02-0.05% | 小市值品种更高 |

单次往返总成本约0.2-0.3%(不含融券利息)。加上融券利息(假设年化8%,持仓15天约0.33%),单次完整成本可达0.5%以上。

这意味着什么?

假设入场阈值1.5σ,出场0.5σ,每次期望毛收益为价差标准差的1.0倍。

• 价差日波动率0.3%时:毛收益≈0.3%,净收益≈0.3%-0.5%=-0.2%,亏损

• 价差日波动率0.5%时:毛收益≈0.5%,净收益≈0.5%-0.5%=0%,不赚不亏

• 价差日波动率0.8%时:毛收益≈0.8%,净收益≈0.8%-0.5%=0.3%,盈利

所以:价差日波动率至少要0.5%以上,配对交易才有正期望。 如果你的配对品种价差波动率低于这个水平,要么换品种,要么拉高入场阈值以增加单次收益。

降低交易成本的实操技巧

1. 限价单代替市价单:可以减少一半以上的滑点。配对交易不追求速度,用限价单等成交完全可行

2. 拉长持仓周期:减少换手率是最直接降成本的方式。把出场阈值从0.5σ放宽到1.0σ,换手率能降低30-40%

3. 选择流动性好的品种:日均成交额>5亿的标的,滑点成本显著降低

4. 用ETF替代个股做空:ETF的融券成本通常比个股低2-3个百分点,且券源更稳定

5. 集中交易时段:开盘后30分钟和收盘前30分钟流动性最好,滑点最低

完整的参数优化流程

把以上所有内容串起来,形成一个系统化的参数设置流程:

// python
def optimize_pair_parameters(spread, cost_per_trade=0.003,
entry_range=[1.0, 1.5, 2.0, 2.5],
exit_range=[0.0, 0.5, 1.0],
half_life=None):
"""
配对交易参数优化

    参数:
- spread: 价差序列
- cost_per_trade: 单次往返交易成本
- entry_range: 入场阈值候选列表
- exit_range: 出场阈值候选列表
- half_life: 价差半衰期(天),用于评估持仓效率
"""
results = []

    for entry_z in entry_range:
for exit_z in exit_range:
if exit_z >= entry_z:
continue  # 出场必须比入场更靠近均值

            # 模拟交易(略去具体实现)
trades = simulate_spread_trades(spread, entry_z, exit_z)

            if len(trades) < 5:
continue  # 样本太少,统计不显著

            gross_return = np.mean([t['return'] for t in trades])
avg_holding = np.mean([t['holding_days'] for t in trades])
net_return = gross_return - cost_per_trade

            # 年化收益 = 单次净收益 × 年交易次数
trades_per_year = 252 / avg_holding if avg_holding > 0 else 0
annual_return = net_return * trades_per_year

            # 检查是否覆盖成本
if net_return <= 0:
continue

            results.append({
'entry_z': entry_z,
'exit_z': exit_z,
'n_trades': len(trades),
'gross_return': round(gross_return, 4),
'net_return': round(net_return, 4),
'annual_return': round(annual_return, 4),
'avg_holding_days': round(avg_holding, 1),
'profit_factor': round(gross_return / cost_per_trade, 1)
})

    results.sort(key=lambda r: r['annual_return'], reverse=True)
return results

优化后的验证清单:

1. 成本覆盖检验:最优参数组合的净收益是否为正?profit_factor是否>2?

2. 参数稳定性:把入场阈值±0.3σ,看收益变化是否剧烈。如果entry_z从1.5变到1.8,收益就从正变负,说明参数太脆弱

3. 样本外测试:用前半段数据优化,后半段数据验证。样本外年化收益下降不超过50%才算通过

4. 半衰期匹配:最优持仓周期是否在0.5-1.5倍半衰期范围内?如果不是,可能需要调整lookback窗口

动态参数调整

市场在变,固定参数不可能永远最优。一个实用的动态调整方案:

// python
def adaptive_parameters(spread, short_window=30, long_window=120):
"""
自适应参数调整

    核心思想:波动率放大时放宽阈值(避免频繁入场),
波动率收窄时收紧阈值(捕捉更多机会)
"""
recent_vol = spread.rolling(short_window).std().iloc[-1]
long_term_vol = spread.rolling(long_window).std().iloc[-1]

    vol_ratio = recent_vol / long_term_vol

    if vol_ratio > 1.5:
# 波动率显著放大 → 放宽入场,避免被噪音触发
entry_z = 2.5
exit_z = 0.5
elif vol_ratio > 1.2:
# 波动率偏高 → 适度放宽
entry_z = 2.0
exit_z = 0.5
elif vol_ratio < 0.7:
# 波动率显著收窄 → 收紧入场
entry_z = 1.5
exit_z = 0.0  # 回到均值才出场
else:
# 正常波动
entry_z = 1.8
exit_z = 0.5

    return entry_z, exit_z

这个方案的核心逻辑是:让参数跟着市场状态走,而不是固定不变。波动大的时候保守一点,波动小的时候积极一点。

总结

配对交易的参数设置,本质上是在信号灵敏度、交易成本和持仓时间之间找最优平衡。

回顾今天的核心要点:

1. 价差计算:必须用协整回归的β作为对冲比率,不是简单的Y-X

2. 布林带化:用滚动均值和标准差构建交易通道,lookback窗口60-120天为宜

3. 入场阈值:1.5σ是大多数配对的合理起点,但最终选择必须结合交易成本核算

4. 出场阈值:0.5σ是收益与效率的平衡点,进阶可用分批出场

5. 持仓周期:由半衰期决定,最优区间是0.5-1.5倍半衰期

6. 交易成本:配对交易的隐形杀手,单次往返约0.2-0.5%,价差日波动率必须>0.5%才有正期望

7. 动态调整:参数不是固定不变的,用波动率比率做自适应调整

最后,记住这句话:没有放之四海皆准的"2倍标准差",只有适合你具体品种、具体成本和具体资金规模的参数。 参数优化不是一次性的工作,而是策略生命周期中持续迭代的一部分。