极简回测:用 Python 30行代码快速复现经典 A 股“白酒双子星”配对交易策略
在量化投资中,**配对交易(Pair Trading)**是一种经典的统计套利策略。其核心思想是:寻找两只在行业属性、经营逻辑上高度相关的股票,通过统计学方法(如协整检验)确认它们价格比率的长期均衡关系。当它们短期内价格偏离均值时进行逆向建仓,等待价差回归以获利。
在 A 股市场,“贵州茅台 (600519.SH) 与 五粮液 (000858.SZ)” 是公认最完美的配对交易标的。它们同属高端白酒,具有几乎相同的行业周期和估值锚点,极少出现因基本面脱节导致的价差彻底分化。
本文将演示如何通过 QuantDash 获取干净无错的历史日 K 线数据,并使用纯 NumPy 和 Pandas 快速复现这一策略。
一、 策略数学逻辑拆解
-
计算价差 (Spread):其中 β 是通过历史价格做 OLS 线性回归(或历史均值比率)得到的对冲比例。

-
计算 Z-Score(价差偏离标准度):

-
交易信号:
-
当 Z-Score>1.5 :说明价差严重偏离均值,茅台被相对高估,五粮液被相对低估。卖出(做空)茅台,买入(做多)五粮液。
-
当 Z-Score<−1.5 :反向操作。
-
当 Z-Score 回归至 0.0 :平仓获利。
-
二、 方案对比:多市场量化回测的数据准备
| 维度 | 传统爬虫/零散数据源 | QuantDash 标准 SDK 方案(全账户支持) |
| 除权处理 | 需要手动寻找分红配股数据,手动计算前/后复权价格,极易出错 | 传入 adjust="forward",直接返回精准复权价格 |
| 数据清洗开销 | 必须写多层 for 循环处理空值、缺失值和格式转换 | DataFrame 字段直接可用,直接带入 Pandas 矩阵计算 |
| 接口健壮度 | 网页结构一旦改版,爬虫脚本直接崩溃,维护成本极高 | 云端统一升级,SDK 采用向下兼容的协议标准 |
三、 实战:极简白酒双子星配对策略复现
以下为全流程 Python 代码,数据拉取采用标准单只获取接口,100% 保证任何 QuantDash 免费或基础账户都能无阻运行:
import numpy as np
import pandas as pd
from quantdash import QuantDash
# 初始化 QuantDash API (免费注册:https://quantdash.net/dashboard/keys/)
qd = QuantDash(api_key="your_api_key_here")
def calculate_pairs_trading_signals():
# 1. 选定配对资产:白酒双子星(100% 兼容免费账户)
symbols = ["600519.SH", "000858.SZ"]
# 2. 依次拉取 100 天前复权历史日K线
dfs = {}
for symbol in symbols:
try:
# adjust="forward" 获取前复权历史收盘价,确保除权准确性
df = qd.klines.get(symbol, period="1d", count=100, adjust="forward", to_dataframe=True)
if df is not None and not df.empty:
df['trade_date'] = pd.to_datetime(df['trade_date'])
dfs[symbol] = df
except Exception as e:
print(f"拉取 {symbol} 失败: {e}")
return
# 3. 数据合并与时序对齐
df_moutai = dfs["600519.SH"][['trade_date', 'close']].rename(columns={'close': 'Moutai'})
df_wuliangye = dfs["000858.SZ"][['trade_date', 'close']].rename(columns={'close': 'Wuliangye'})
merged_df = pd.merge(df_moutai, df_wuliangye, on='trade_date', how='outer').sort_values('trade_date').ffill()
merged_df = merged_df.dropna().set_index('trade_date')
# 4. 计算价差 (Spread) 与滚动 Z-Score
# 估算对冲比例 beta (以两者的均值之比作为基准)
beta = merged_df['Moutai'].mean() / merged_df['Wuliangye'].mean()
merged_df['Spread'] = merged_df['Moutai'] - beta * merged_df['Wuliangye']
# 计算 20 日滚动均值和标准差
window = 20
merged_df['Spread_Mean'] = merged_df['Spread'].rolling(window=window).mean()
merged_df['Spread_Std'] = merged_df['Spread'].rolling(window=window).std()
merged_df['Z_Score'] = (merged_df['Spread'] - merged_df['Spread_Mean']) / (merged_df['Spread_Std'] + 1e-5)
# 5. 生成交易信号逻辑
merged_df['Signal'] = 0
# 当 Z-Score 突破 1.5 视为偏离,建议做空茅台做多五粮液 (信号为 -1)
merged_df.loc[merged_df['Z_Score'] > 1.5, 'Signal'] = -1
# 当 Z-Score 低于 -1.5 信号为 1 (买入茅台做空五粮液)
merged_df.loc[merged_df['Z_Score'] < -1.5, 'Signal'] = 1
print("n--- 最新 10 天配对交易 Z-Score 信号列表 ---")
print(merged_df[['Moutai', 'Wuliangye', 'Spread', 'Z_Score', 'Signal']].tail(10))
if __name__ == "__main__":
calculate_pairs_trading_signals()
真实数据输出:
--- 最新 10 天配对交易 Z-Score 信号列表 ---
Moutai Wuliangye Spread Z_Score Signal
trade_date
2026-07-13 1210.99 70.260413 142.406232 1.427436 0
2026-07-14 1214.88 70.820026 137.785128 1.130899 0
2026-07-15 1251.06 73.714578 129.942177 0.729227 0
2026-07-16 1258.99 73.900000 135.052111 0.867566 0
2026-07-17 1253.00 72.760000 146.400260 1.295298 0
2026-07-20 1327.50 76.240000 167.973279 2.010122 -1
2026-07-21 1308.00 74.380000 176.761838 2.035949 -1
2026-07-22 1305.00 74.750000 168.134544 1.488588 0
2026-07-23 1292.01 74.840000 153.775743 0.850729 0
2026-07-24 1297.41 73.570000 178.491049 1.732964 -1
四、 策略开发者 FAQ
Q1:前复权价格(Forward Adjusted)对配对交易为什么至关重要?
配对交易极度依赖“价差比率的稳定性”。如果在回测期间某只股票发生分红送股导致除权缺口,未复权的价格会突变,导致 Z-Score 指标失真并产生大量的假套利信号。QuantDash 的 adjust="forward" 参数可以在服务端一次性输出干净的前复权价格,保障回测的统计学效力。
Q2:如何根据信号自动下单或报警?
您可以将这个脚本托管在云服务器(如腾讯云、阿里云)上,并设置一个每日 15:00 收盘前的 Cron 任务。当最新的 Signal != 0 时,利用 Webhook 将具体的套利配对比例推送到您的微信或钉钉群中,实现半自动化套利追踪。
-
注册获取 API Key:https://quantdash.net/dashboard/keys/
-
详细接口开发文档:https://docs.quantdash.net/zh-Hans/sdk/python-quickstart

