在单边波动剧烈或宽幅震荡的市场里,做多单只股票的风险巨大。这时候,配对交易(Pairs Trading) 这一经典的"市场中性"策略便体现出独特的优势。
配对交易的核心是:寻找两只具有强逻辑关联、价格走势呈现"协整性(Cointegrating)"的股票,在其价差发生异常偏离时买低卖高,等价差收敛后平仓获利。
本篇将结合 Python 数理分析库与 QuantDash 平台的数据接口,带你完整跑通从协整性检验 到交易信号生成的统计套利实战流程。
一、 理论背景与标的选择
我们选择白酒板块中关联度极高的两位龙头:贵州茅台 (600519.SH) 与 五粮液 (000858.SZ) 。
它们属于同一子行业,基本面逻辑高度趋同。虽然各自价格可能非平稳(呈现长期上涨或下跌),但它们的线性组合(价差)在长期上应该是一个均值回归的平稳序列。
核心步骤:
-
获取两只股票的长期历史 K 线。
-
运行 ADF 协整检验(Engle-Granger 两步法)。
-
如果协整通过,计算两者价差(Spread)的 Rolling Z-Score。
-
入场信号:Z-Score 突破 ±2 时做多便宜的一只,同时做空高估的一只。
-
离场信号:Z-Score 回归至 0 附近时平仓。
二、 实战代码:协整检验与配对交易信号
python
import os
import pandas as pd
import numpy as np
import statsmodels.api as sm
from statsmodels.tsa.stattools import coint
from quantdash import QuantDash
# 1. 客户端初始化
QUANTDASH_API_KEY = os.getenv("QUANTDASH_API_KEY", "your_quantdash_api_key_here")
qd = QuantDash(api_key=QUANTDASH_API_KEY)
def fetch_pair_data(sym_a="600519.SH", sym_b="000858.SZ", start="2025-01-01"):
"""
通过 QuantDash 获取配对标的的历史收盘价并对其时间戳
"""
# 统一拉取 A 股前复权日线
df_a = qd.klines.get(symbol=sym_a, period="1d", adjust="qfq", to_dataframe=True)
df_b = qd.klines.get(symbol=sym_b, period="1d", adjust="qfq", to_dataframe=True)
# 转换为 DataFrame 格式并按交易日期合并
df_a = df_a[['trade_date', 'close']].rename(columns={'close': 'close_a'})
df_b = df_b[['trade_date', 'close']].rename(columns={'close': 'close_b'})
merged = pd.merge(df_a, df_b, on='trade_date', how='inner').sort_values('trade_date')
merged.set_index('trade_date', inplace=True)
return merged
def check_cointegration(df):
"""
进行 Granger 协整检验
"""
score, p_value, _ = coint(df['close_a'], df['close_b'])
print(f"协整检验 T-statistic: {score:.4f}, P-value: {p_value:.4f}")
if p_value < 0.05:
print(">> 两只股票在 95% 置信度下【具有明显的协整关系】,适合配对交易。")
return True
else:
print(">> 两只股票不具备统计学上的显著协整关系,强行配对可能面临高风险。")
return False
def generate_signals(df, window=20):
"""
计算动态对冲比例与 Z-Score,生成信号
"""
# 动态回归计算对冲比例 (Beta)
# 此处用简单的滚动价差演示
df['spread'] = df['close_a'] - df['close_b']
# 计算均值和标准差的滚动窗口,防止过拟合
df['mean'] = df['spread'].rolling(window=window).mean()
df['std'] = df['spread'].rolling(window=window).std()
# 计算 Z-Score
df['zscore'] = (df['spread'] - df['mean']) / df['std']
# 清洗前期的 NaN
df.dropna(inplace=True)
# 获取最新的价差状态
latest_date = df.index[-1]
latest_row = df.iloc[-1]
z = latest_row['zscore']
print(f"\n[{latest_date}] 最新价差: {latest_row['spread']:.2f}, 滚动 Z-Score: {z:.2f}")
# 生成交易指引
if z > 2.0:
print("💡 信号:【价差过大】。策略建议:卖出/做空 600519.SH,买入/做多 000858.SZ。")
elif z < -2.0:
print("💡 信号:【价差过小】。策略建议:买入/做多 600519.SH,卖出/做空 000858.SZ。")
elif abs(z) < 0.2:
print("💡 信号:【价差回归正常】。策略建议:双边【平仓离场】。")
else:
print("💡 信号:价差处于常态区间,无交易信号,【保持当前头寸】。")
if __name__ == "__main__":
print("正在通过 QuantDash 提取配对股票历史K线数据...")
df_pair = fetch_pair_data("600519.SH", "000858.SZ")
# 1. 验证是否满足协整
if check_cointegration(df_pair):
# 2. 如果满足,生成实时信号
generate_signals(df_pair, window=20)
三、 落地量化实盘的思考
-
数理准确性源于底层数据质量 :在进行协整检验(ADF)时,哪怕其中一两天的 K 线数据因为缺失或脏数据而产生价格突变,都可能导致回归系数失真、甚至毁掉整条套利模型的统计基础。QuantDash 稳定的机构级行情能够彻底杜绝这个问题[1](https://www.google.com/url?sa=E&q=https%3A%2F%2Fvertexaisearch.cloud.google.com%2Fgrounding-api-redirect%2FAUZIYQGZGDUnwwbZnIL1JbQtPp5cWAgmtvtGHyfkaeTTozq-yCLoVnmt0id8W27ZdeFAwsgTle2DU9ksIMtMlZsUBHW6yrhRZuYGHsTqt6N8sgHGSwJfOOwR2mmX0XuHzfP5ItH3WYjG-1TmnQ%3D%3D "1")。
-
多市场配对的潜力 :除了同一板块的白酒,该框架在 QuantDash 多市场统一 API 的支持下,更可以探索极富想象力的跨市场/跨境套利组合。例如美股 PDD (拼多多) 与 港股 美团-W (03690.HK) 的科技赛道配对,或者跨国资产的商品配对,这在以前几乎是遥不可及的数据门槛,而现在利用统一的 SDK 接口,甚至不需要更改代码。
相关链接 :
-
QuantDash 官方:QuantDash
-
Python SDK 快速开始:快速开始 - QuantDash