极简回测:用 Python 30行代码快速复现经典 A 股“白酒双子星”配对交易策略

AI6小时前发布 beixibaobao
2 0 0

在量化投资中,**配对交易(Pair Trading)**是一种经典的统计套利策略。其核心思想是:寻找两只在行业属性、经营逻辑上高度相关的股票,通过统计学方法(如协整检验)确认它们价格比率的长期均衡关系。当它们短期内价格偏离均值时进行逆向建仓,等待价差回归以获利。

在 A 股市场,“贵州茅台 (600519.SH) 与 五粮液 (000858.SZ)” 是公认最完美的配对交易标的。它们同属高端白酒,具有几乎相同的行业周期和估值锚点,极少出现因基本面脱节导致的价差彻底分化。

本文将演示如何通过 QuantDash 获取干净无错的历史日 K 线数据,并使用纯 NumPy 和 Pandas 快速复现这一策略。


一、 策略数学逻辑拆解

  1. 计算价差 (Spread):其中 β 是通过历史价格做 OLS 线性回归(或历史均值比率)得到的对冲比例。

    极简回测:用 Python 30行代码快速复现经典 A 股“白酒双子星”配对交易策略

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

    极简回测:用 Python 30行代码快速复现经典 A 股“白酒双子星”配对交易策略

  3. 交易信号

    • 当 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

© 版权声明

相关文章