第七章:跨品种套利:产业链上下游品种关系、比价与价差的协整检验、配对交易策略实现
各位同学,欢迎来到第七章。
前面几章我们聊了期现套利、跨期套利,说白了都是在同一个品种上做文章。但真正的量化交易世界,远不止这么简单。你有没有想过,为什么螺纹钢和铁矿石总是同涨同跌?为什么豆粕和豆油的价格像一对欢喜冤家?
这背后,就是产业链的上下游关系在起作用。
跨品种套利,就是利用这种关系来赚钱。我个人觉得,这是量化交易里最有意思的一块。因为它不再是简单的价差回归,而是需要你真正理解产业逻辑。
7.1 产业链上下游品种关系:谁是谁的“爸爸”
先讲个我自己的经历。几年前我做黑色系套利,一开始只看螺纹钢和热卷。后来发现,真正决定它们价格的,是上游的铁矿石和焦炭。你想想看,没有铁矿石,哪来的螺纹钢?
产业链关系,说白了就是“原料-加工-成品”这条链。
- 上游品种:比如铁矿石、焦炭、原油、大豆。它们是原材料,价格波动往往先于下游。
- 中游品种:比如螺纹钢、热卷、PTA、豆粕。它们是加工后的半成品或成品。
- 下游品种:比如汽车、家电、饲料。这些是终端需求,反过来影响中游。
做跨品种套利,你得先搞清楚谁影响谁。举个例子:
| 产业链 | 上游 | 中游 | 下游 |
|---|---|---|---|
| 黑色系 | 铁矿石、焦炭 | 螺纹钢、热卷 | 房地产、基建 |
| 能化系 | 原油、煤炭 | PTA、甲醇、LLDPE | 纺织、塑料制品 |
| 农产品 | 大豆、玉米 | 豆粕、豆油、淀粉 | 饲料、食品加工 |
嗯,这里要注意:上下游关系不是一成不变的。比如原油暴跌时,PTA可能跟跌,但有时候PTA自身供需紧张,反而会走出独立行情。所以,光看产业链还不够,还得看当下的市场逻辑。
核心观点:跨品种套利的核心,是找到两个品种之间稳定的“比价”或“价差”关系。这个关系一旦被打破,就是机会。
7.2 比价与价差的协整检验:别把“假关系”当真
很多新手一上来,看到两个品种走势很像,就以为可以套利。我告诉你,这是大忌。
为什么?因为很多品种的走势相似,只是受同一个宏观因素影响,比如通胀、利率。它们之间并没有真正的“因果关系”。你强行做配对,结果就是两边都亏。
那怎么判断两个品种之间有没有稳定的关系?
答案是:协整检验。
协整检验,说白了就是看两个时间序列的“差值”是不是平稳的。如果差值平稳,说明它们长期会回归;如果不平稳,说明它们各走各的路,没法套利。
我常用的方法是 Engle-Granger 两步法。步骤很简单:
- 第一步:用 OLS 回归,找出两个品种的长期关系。比如:
Y = α + β * X + ε - 第二步:检验残差 ε 的平稳性。用 ADF 检验,如果 p 值小于 0.05,说明残差平稳,存在协整关系。
来,看一段 Python 代码,这是我实际项目中用过的:
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
# 假设 price_a 和 price_b 是两个品种的价格序列
def cointegration_test(price_a, price_b):
# 第一步:OLS回归
X = sm.add_constant(price_b)
model = sm.OLS(price_a, X).fit()
residuals = model.resid
# 第二步:ADF检验残差
adf_result = adfuller(residuals)
p_value = adf_result[1]
if p_value < 0.05:
print(f"存在协整关系,p值={p_value:.4f}")
return True, model.params
else:
print(f"不存在协整关系,p值={p_value:.4f}")
return False, None
# 使用示例
# is_cointegrated, params = cointegration_test(iron_ore_price, rebar_price)
避坑指南:我曾经犯过一个错误——直接用收盘价做协整检验。结果发现很多品种都“协整”,但实盘一跑就亏。后来才明白,价格序列往往有趋势,需要先取对数或者差分。我现在的习惯是:先用对数价格,再检验。
7.3 配对交易策略实现:从理论到实盘
好,假设你已经找到了两个协整的品种,比如螺纹钢和热卷。接下来怎么做?
配对交易的逻辑其实很简单:
- 当价差偏离均值超过某个阈值(比如 2 倍标准差),就开仓。
- 做多被低估的品种,做空被高估的品种。
- 等价差回归到均值附近,平仓获利。
但这里有个细节:阈值怎么设?
我个人的经验是,不要用固定的阈值。市场在变,波动率在变。我建议用滚动窗口计算标准差,比如过去 20 天的滚动标准差。这样阈值会自适应市场环境。
来看一个完整的策略框架:
import numpy as np
import pandas as pd
class PairTradingStrategy:
def __init__(self, window=20, entry_z=2.0, exit_z=0.5):
self.window = window
self.entry_z = entry_z
self.exit_z = exit_z
def generate_signals(self, price_a, price_b, hedge_ratio):
# 计算价差
spread = price_a - hedge_ratio * price_b
# 滚动均值和标准差
spread_mean = spread.rolling(window=self.window).mean()
spread_std = spread.rolling(window=self.window).std()
# 计算Z-score
z_score = (spread - spread_mean) / spread_std
# 生成信号
signals = pd.DataFrame(index=price_a.index)
signals['z_score'] = z_score
signals['position_a'] = 0 # 对品种A的头寸
signals['position_b'] = 0 # 对品种B的头寸
# 开仓条件
signals.loc[z_score > self.entry_z, 'position_a'] = -1 # 做空A
signals.loc[z_score > self.entry_z, 'position_b'] = 1 # 做多B
signals.loc[z_score < -self.entry_z, 'position_a'] = 1 # 做多A
signals.loc[z_score < -self.entry_z, 'position_b'] = -1 # 做空B
# 平仓条件
signals.loc[abs(z_score) < self.exit_z, ['position_a', 'position_b']] = 0
return signals
# 使用示例
# strategy = PairTradingStrategy(window=20, entry_z=2.0, exit_z=0.5)
# signals = strategy.generate_signals(rebar_price, hot_coil_price, hedge_ratio=1.2)
警告:配对交易不是“稳赚不赔”的。我见过最惨的一次,价差偏离了 5 倍标准差还不回归,结果爆仓。所以,一定要设止损。我个人的习惯是:当价差偏离超过 3 倍标准差时,强制平仓,认错离场。
7.4 知识体系总览
为了让你更直观地理解本章的逻辑,我画了一张图。这张图展示了跨品种套利的完整流程:
这张图你看懂了吗?从产业链分析开始,到协整检验确认关系,再到策略设计、回测优化,最后实盘监控。每一步都环环相扣。我建议你把这个流程记在脑子里,以后做任何跨品种套利,都按这个框架来。
7.5 实战中的几个坑
最后,分享几个我踩过的坑,希望能帮你少走弯路:
- 坑一:只看相关性,不看协整。相关性高不代表能套利,协整才是关键。
- 坑二:忽略交易成本。跨品种套利往往要双边开仓,手续费和滑点加起来很可观。我建议在回测时就把成本算进去。
- 坑三:过度优化参数。我曾经为了追求回测曲线好看,把窗口期调了又调。结果实盘一塌糊涂。记住:简单就是美。
总结一下:跨品种套利不是玄学,它建立在产业链逻辑和统计检验之上。只要你掌握了协整检验和配对交易的框架,就能在这个领域找到属于自己的机会。
好了,这一章就到这里。记住,交易是一场马拉松,不是百米冲刺。稳扎稳打,才能走得更远。