查看全课大纲(第 4 / 59 节)
- 1.量化投资必备基础知识
- 2.趋势型策略及模型原理
- 3.均值回复型策略及模型原理
- 4.配对交易策略及模型原理
- 5.量化策略研发流程与基本技能
- 6.常用的量化平台概述及如何选择
- 7.如何量化一个主观策略思路
- 8.常用技术指标及指标计算过程
- 9.如何编写指标代码
- 10.指标的物理意义
- 11.技术指标的应用技巧
- 12.更多的交易决策
- 13.编写程序去量化一个趋势型技术指标
- 14.编写趋势型技术指标的性能评价
- 15.策略对交易成本和持仓周期的影响
- 16.股票池策略的原理及基本框架
- 17.基于多因子分析的股票池设计与实现
- 18.股票池的性能评估
- 19.使用定制化财务因子构建股票池
- 20.趋势型策略原理及股票池机制的设计
- 21.趋势型择时信号的设计方法与编程实现
- 22.趋势型策略的回测与性能评估
- 23.优化趋势型策略的思路及方法
- 24.量化体系中的风险控制思想
- 25.风险的度量-波动率
- 26.常用的风险控制方法
- 27.实现止盈止损模块以提高策略性能
- 28.策略性能的评估与优化
- 29.探讨波动率与风险的关系
- 30.量化策略中的经典资金管理模型
- 31.用python编程实现资金管理模块
- 32.构建一个完善的量化交易策略
- 33.趋势型量化策略必备的期货知识
- 34.期货量化工具介绍
- 35.商品期货趋势型策略原理
- 36.用TB编写商品期货趋势型策略(上)
- 37.用TB编写商品期货趋势型策略(下)
- 38.分析优化商品期货趋势型策略的方法思路
- 39.期货交易策略的注意事项
- 40.均值回复型策略的原理
- 41.A股市场有没有稳定的均值回复效应?
- 42.编写一个均值回复型股票量化策略
- 43.编写多空组合策略进行策略改进
- 44.在策略中实现头寸管理进行策略优化
- 45.套利策略原理及常见套利类型
- 46.用MC开发一个跨品种套利交易策略(上)
- 47.用MC开发一个跨品种套利交易策略(下)
- 48.统计套利之股票配对交易策略
- 49.实盘中的细节问题:加减仓
- 50.关于高频交易
- 51.如何评价实盘量化策略的性能
- 52.量化系统的工作过程及研发流程
- 53.运气or实力
- 54.量化实盘交易需要满足什么条件
- 55.未来函数的坑
- 56.实盘数据接口异常的自动报警
- 57.交易系统的压力测试
- 58.自动运行的交易策略,什么时候需要人工干预
- 59.预案准备和实盘心理建设
配对交易策略及模型原理
约 23 分钟
小象实战讲义 · 进阶量化交易实战:迭代式的量化策略研发 本讲义仅用于编程与量化方法教学,不构成任何投资建议。
在量化投资的武库中,统计套利(Statistical Arbitrage)与配对交易(Pairs Trading)被称为”现代金融炼金术”。传统单边看多策略不可避免暴露在全市场系统性风险(Market Beta)之中,而配对交易通过在两只有强基本面联系的关联资产间建立多空对冲头寸,剥离大盘波动干扰,专注获取价差回归的纯净 Alpha 收益。本讲系统解析协整检验(Cointegration)、价差 Z-Score 建模与配对交易的全生命周期工程闭环。
💡 核心导读
- 套利的三种境界与核心概念辨析:
- 无风险套利(Pure / Deterministic Arbitrage):如跨期现货一二级市场瞬间无风险差价,比拼纳秒级硬件网络速度,个人与中低频量化基本无参与空间;
- 统计套利(Statistical Arbitrage):基于大样本历史统计规律,在价差出现异常偏离时建立反向头寸,博取高概率均值回归;
- 配对交易(Pairs Trading):统计套利的最经典形式,同时做多被低估资产并做空被高估资产,实现组合的 Beta 中性(Market Neutral)。
- 相关性(Correlation) vs 协整性(Cointegration)的本质区别:
- 醉汉牵狗理论(Drunkard and his Dog):两只资产价格可能看似同步上涨(高相关性),但如果两者之间的距离(价差)越来越大甚至发散,则不存在协整;
- 协整的数学定义:两组非平稳时间序列 与 ,若存在线性组合使得残差序列平稳: 则称 与 具备协整关系,价差 必定具备长期均值回复特性。
- 配对交易标准五步工程流水线:
- 标的池筛选:同行业双寡头(如贵州茅台 vs 五粮液)、商品期货上下游(如螺纹钢 vs 热卷);
- 协整参数标定:采用 OLS 最小二乘法回归估算对冲比率 ;
- 价差标准化处理:计算滑动窗口下的均值 与方差 ,转化为 ;
- 入场与出场判定: 开仓(多弱空强), 平仓获利;
- 协整破裂硬止损: 判定基本面发生永久性突变,果断止损离场。
┌─────────────────────────────────────────────────────────────┐
│ 配对交易市场中性价差套利拓扑图 │
└──────────────────────────────┬──────────────────────────────┘
│
价差 Z-Score ▲
─── +2.0σ 开仓线 ─────────────┼───────────▲ [做空 A / 做多 B (多弱空强)] ──
│ / \
─── 0 均值回归线 ─────────────┼─────────/───\─────────────▲ (价差归零平仓) ─
│ / \ /
─── -2.0σ 开仓线 ─────────────┼───────/───────▼ [做多 A / 做空 B] ──────────
│ /
─── -3.5σ 协整破裂止损线 ─────┴─────/────────────────────────► (时间 t)一、协整关系检验与对冲比例 计算
在量化回测中,配对交易首先需要标定对冲比率。本节实现 Engle-Granger 两步法的第一步——用 OLS 回归估计对冲比率 与价差残差;第二步(对残差做 ADF 平稳性检验、并使用 MacKinnon 协整专用临界值判定协整)将在后续统计检验环节展开:
import numpy as np
import pandas as pd
def calculate_cointegration_hedge_ratio(series_a, series_b):
"""
通过 OLS 线性回归计算配对资产对冲比率 beta 与价差序列
Price_A = beta * Price_B + alpha + e
(教学示例:历史协整关系可能在未来失效,存在配对漂移风险)
"""
# 计算回归系数 beta
cov_ab = np.cov(series_a, series_b)[0][1]
var_b = np.var(series_b, ddof=1)
beta = cov_ab / (var_b + 1e-8)
alpha = np.mean(series_a) - beta * np.mean(series_b)
# 构造价差残差序列
spread = series_a - beta * series_b - alpha
return beta, alpha, spread
# 合成两只具备协整关系的资产价格序列(历史数据,不代表未来)
rng = np.random.default_rng(42)
n = 100
trend = np.cumsum(rng.normal(0.0005, 0.015, n))
spread_series = np.zeros(n)
for t in range(1, n):
spread_series[t] = 0.8 * spread_series[t-1] + rng.normal(0, 0.8)
price_b = 50.0 * np.exp(trend)
price_a = 1.2 * price_b + spread_series + 5.0
beta, alpha, spread = calculate_cointegration_hedge_ratio(price_a, price_b)
print("===== 协整关系与对冲比率计算 =====")
print(f"资产A对资产B的对冲比率 beta: {beta:.4f}")
print(f"回归截距 alpha: {alpha:.4f}")
print(f"价差序列均值: {spread.mean():.4f}, 标准差: {spread.std():.4f}")
print("(注:价差平稳性是配对交易的前提,需持续监控)")===== 协整关系与对冲比率计算 =====
资产A对资产B的对冲比率 beta: 1.2177
回归截距 alpha: 4.0432
价差序列均值: -0.0000, 标准差: 1.1450
(注:价差平稳性是配对交易的前提,需持续监控)二、价差 Z-Score 动态跟踪与交易信号生成
通过对价差序列进行滑动窗口标准化,消除绝对价格尺度的影响,实现跨品种的统一度量:
import numpy as np
import pandas as pd
def generate_pairs_trading_signals(spread_series, window=20, enter_threshold=2.0, exit_threshold=0.2):
"""
计算动态 Z-Score 并输出多空配对开平仓信号
(教学示例:动态阈值与窗口选择影响策略表现,存在参数过拟合风险)
"""
rolling_mean = spread_series.rolling(window=window).mean()
rolling_std = spread_series.rolling(window=window).std()
z_score = (spread_series - rolling_mean) / (rolling_std + 1e-6)
signals = pd.Series(0, index=spread_series.index)
# Z > 2.0: A 相对高估, B 相对低估 -> 做空 A / 做多 B (信号记为 -1)
signals[z_score > enter_threshold] = -1
# Z < -2.0: A 相对低估, B 相对高估 -> 做多 A / 做空 B (信号记为 1)
signals[z_score < -enter_threshold] = 1
# 价差收敛平仓
signals[z_score.abs() < exit_threshold] = 0
return z_score, signals
# 合成一个平稳的价差序列用于信号生成
rng = np.random.default_rng(123)
n = 150
spread = np.cumsum(rng.normal(0, 0.5, n)) # 随机游走,模拟价差
spread_series = pd.Series(spread, index=pd.date_range('2024-01-01', periods=n, freq='D'))
z_score, signals = generate_pairs_trading_signals(spread_series, window=30, enter_threshold=1.5, exit_threshold=0.5)
print("===== 配对交易信号生成示例 =====")
print(f"数据长度: {len(spread_series)}, 滚动窗口: 30")
print(f"Z-Score 统计: 均值={z_score.mean():.3f}, 标准差={z_score.std():.3f}")
print(f"信号分布: 做多A({(signals == 1).sum()}) | 平仓({(signals == 0).sum()}) | 做空A({(signals == -1).sum()})")
print("(注:信号基于历史统计,交易成本与滑点可能侵蚀收益)")===== 配对交易信号生成示例 =====
数据长度: 150, 滚动窗口: 30
Z-Score 统计: 均值=0.727, 标准差=1.096
信号分布: 做多A(5) | 平仓(111) | 做空A(34)
(注:信号基于历史统计,交易成本与滑点可能侵蚀收益)📝 动手练一练
下面我们用 Python 编写一段 股票配对交易多空对冲回测引擎,验证两只关联标的在大盘震荡背景下如何通过中性化对冲锁定价差回归收益:
import numpy as np
import pandas as pd
def run_pairs_trading_simulation():
"""
经典统计套利之股票配对交易 (Pairs Trading) 引擎
- 验证协整价差 (Cointegrated Spread) 与市场中性 (Market Neutral)
- 多弱空强: 当价差 Z > 2.0 时 做空A/做多B; Z < -2.0 时 做多A/做空B
(教学示例:回测使用合成数据,未考虑交易成本、冲击成本与配对关系破裂风险)
"""
rng = np.random.default_rng(42)
dates = pd.date_range("2023-01-01", periods=120, freq="B")
# 模拟两只具备协整关系的关联股票走势
market_trend = np.cumsum(rng.normal(0.0005, 0.015, 120))
spread = np.zeros(120)
for t in range(1, 120):
spread[t] = 0.8 * spread[t-1] + rng.normal(0, 0.8) # 平稳 AR(1) 价差
p_b = 50.0 * np.exp(market_trend)
p_a = 1.2 * p_b + spread + 5.0
df = pd.DataFrame({'price_a': p_a, 'price_b': p_b}, index=dates)
# 通过滚动窗口 OLS 估计对冲比率 beta (只用当前时刻之前数据, 避免前视偏差)
min_window = 60
betas = np.full(len(df), np.nan)
for t in range(min_window, len(df)):
a = df['price_a'].iloc[:t].values
b = df['price_b'].iloc[:t].values
betas[t] = np.cov(a, b)[0][1] / (np.var(b, ddof=1) + 1e-8)
betas[:min_window] = betas[min_window]
df['beta'] = betas
df['spread'] = df['price_a'] - df['beta'] * df['price_b']
df['spread_mean'] = df['spread'].rolling(20).mean()
df['spread_std'] = df['spread'].rolling(20).std()
df['z_score'] = (df['spread'] - df['spread_mean']) / (df['spread_std'] + 1e-6)
# 信号-持仓分离: signal 列 NaN 表示维持原持仓, 显式值触发开平仓动作
df['signal_a'] = np.nan
# Z > 2.0: A 相对高估 -> 做空 A / 做多 B
df.loc[df['z_score'] > 2.0, 'signal_a'] = -1.0
# Z < -2.0: A 相对低估 -> 做多 A / 做空 B
df.loc[df['z_score'] < -2.0, 'signal_a'] = 1.0
# 价差回归中轴: 显式平仓
df.loc[df['z_score'].abs() < 0.2, 'signal_a'] = 0.0
# 持仓 = 信号前向填充 (无信号日维持原仓位), 期初为空仓; B 腿按 beta 对冲
df['pos_a'] = df['signal_a'].ffill().fillna(0.0)
df['pos_b'] = -df['beta'] * df['pos_a']
# 组合日收益率 (市场中性)
# 教学简化: A 腿按 1 股计, B 腿收益按价格比折算到同一金额尺度;
# 注意此处价格比用的是当日 t 的 price_b/price_a, 属逐日重设 B 腿资金权重的记账简化;
# 固定股数(1 股 A、-beta 股 B)口径下, t 日折算比应取建仓时点 t-1 的价格比:
# df['price_b'].shift(1) / df['price_a'].shift(1)
# 严格工程实现应以两腿固定持股损益加权 (pos_a*dP_a + pos_b*dP_b) / t-1 日占用资金
ret_a = df['price_a'].pct_change()
ret_b = df['price_b'].pct_change()
df['pair_ret'] = df['pos_a'].shift(1) * ret_a + df['pos_b'].shift(1) * ret_b * (df['price_b'] / df['price_a'])
cum_ret = (1 + df['pair_ret'].fillna(0)).cumprod()
res = {
"Total_Bars": len(df),
"Cointegration_Beta": f"{df['beta'].iloc[-1]:.2f}",
"Spread_Mean": f"{df['spread'].mean():.2f}",
"Spread_Std": f"{df['spread'].std():.2f}",
"Pairs_Return": f"{(cum_ret.iloc[-1] - 1)*100:.2f}%",
"Market_A_Return": f"{(df['price_a'].iloc[-1]/df['price_a'].iloc[0] - 1)*100:.2f}%",
"Market_B_Return": f"{(df['price_b'].iloc[-1]/df['price_b'].iloc[0] - 1)*100:.2f}%"
}
return res, df
# 运行模拟并打印结果
results, sim_df = run_pairs_trading_simulation()
print("================ 统计套利配对交易 (Pairs Trading) 模拟 ================")
for k, v in results.items():
print(f" - {k:<22}: {v}")
print("----------------------------------------------------------------------")
print("量化精髓: 配对交易通过多空对冲剥离大盘 Beta,锁定价差回归的纯 Alpha!")
print("风险提示: 合成数据回测,未包含交易成本,历史关系可能在未来失效。")
print("======================================================================")运行结果输出:
================ 统计套利配对交易 (Pairs Trading) 模拟 ================
- Total_Bars : 120
- Cointegration_Beta : 1.20
- Spread_Mean : 6.32
- Spread_Std : 2.85
- Pairs_Return : 15.27%
- Market_A_Return : -8.39%
- Market_B_Return : -5.24%
----------------------------------------------------------------------
量化精髓: 配对交易通过多空对冲剥离大盘 Beta,锁定价差回归的纯 Alpha!
风险提示: 合成数据回测,未包含交易成本,历史关系可能在未来失效。
======================================================================📖 结果解读:① OLS 回归估计的对冲比率 ,接近合成数据的真实值 1.20——对冲比率必须从数据回归得到,不能拍脑袋硬编码;② 全周期 A、B 两只标的双双下跌(-8.39% / -5.24%),而多空对冲的配对组合逆势盈利 +15.27%,这就是”剥离大盘 Beta、只赚价差回归 Alpha”的市场中性效果;③ 工程红线:持仓信号必须”信号-持仓分离”(NaN 维持、显式值触发),若写成
position.replace(0, np.nan).ffill(),显式平仓的 0 会被前一持仓回填覆盖,导致永远无法平仓——这是配对交易回测中最隐蔽的 bug 之一。
👉 点击查看解析
本练习围绕配对交易的核心逻辑展开,重点演示通过两只相关资产构建多空组合,并利用价差偏离历史均值后的回归来获取收益。关键结论是配对交易不依赖市场单边方向,而是捕捉相对价差的均值回复机会。
本章小结
- 认清套利本质:通过多空对冲抵消标的的系统性风险(Beta),仅赚取相对强弱价差回归的 Alpha。
- 严防相关性伪套利:必须基于协整检验(Cointegration)而非简单相关性筛选配对标的。
- 设置协整破裂止损:当企业基本面发生不可逆变故导致价差无限发散时,必须通过 强制平仓截断亏损。
📋 行动清单 (Action Checklist)
- 运行本讲配对交易代码,观察在市场不同行情走势下中性化组合净值的平稳性;
- 尝试下载螺纹钢与热轧卷板的真实日线数据,利用 OLS 计算两者的历史协整比例 ;
- 预习下一节,梳理专业量化策略全流程研发环节与必备的工程软硬件技能。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第1章课件:实战量化投资必备基础知识PDF · 4.5MB