Python策略开发详解:均值回归与配对交易策略的回测及可视化实现

基于Python的策略开发与回测:均值回归 – 配对交易策略(附可视化代码)


1. 策略原理深度解析

核心逻辑
寻找两个具有长期均衡关系的资产(如可口可乐与百事可乐股票),当价差偏离历史均值时:

  • 做多低估资产 + 做空高估资产(价差扩大时)
  • 平仓回归(价差回归均值时)
  • 数学基础

    1. 协整检验:通过ADF检验判断价差序列的平稳性(p值<0.05)
    2. 对冲比例:通过OLS回归确定资产配比 ( y = βx + ε )
    3. 交易信号:价差Z-score突破±1.5标准差触发交易

    2. 完整策略实现代码

    pip install matplotlib statsmodels pandas numpy
    

    步骤1:生成协整资产模拟数据

    import numpy as np  
    import pandas as pd  
    import statsmodels.api as sm  
    from statsmodels.tsa.stattools import adfuller  
    
    # 生成具有协整关系的价格序列  
    np.random.seed(42)  
    days = 1000  
    
    # 基础资产X  
    x = np.cumprod(1 + np.random.normal(0.0005, 0.02, days)) * 100  
    
    # 协整资产Y = 0.8X + 噪声  
    spread = np.random.normal(0, 2, days)  # 平稳价差  
    y = 0.8 * x + spread  
    
    data = pd.DataFrame({'Asset_X': x, 'Asset_Y': y},  
                       index=pd.date_range('2020-01-01', periods=days))  
    

    步骤2:协整检验与对冲比例计算

    # 协整检验  
    def cointegration_test(series1, series2):  
        model = sm.OLS(series1, sm.add_constant(series2)).fit()  
        residuals = model.resid  
        adf_result = adfuller(residuals)  
        return adf_result[1]  # 返回p值  
    
    p_value = cointegration_test(data['Asset_X'], data['Asset_Y'])  
    print(f'ADF检验p值: {p_value:.4f}')  # 应小于0.05  
    
    # 计算对冲比例  
    model = sm.OLS(data['Asset_X'], sm.add_constant(data['Asset_Y'])).fit()  
    beta = model.params[1]  
    print(f'对冲比例: 1单位Y对应{beta:.2f}单位X')  
    

    输出结果:

    ADF检验p值: 0.0000
    对冲比例: 1单位Y对应1.24单位X
    

    步骤3:价差分析与信号生成

    # 计算价差序列  
    data['Spread'] = data['Asset_X'] - beta * data['Asset_Y']  
    
    # 计算Z-score  
    lookback = 60  
    data['Mean'] = data['Spread'].rolling(lookback).mean()  
    data['Std'] = data['Spread'].rolling(lookback).std()  
    data['Zscore'] = (data['Spread'] - data['Mean']) / data['Std']  
    
    # 生成交易信号  
    data['Signal'] = 0  
    data.loc[data['Zscore'] > 1.5, 'Signal'] = -1  # 做空价差(卖X买Y)  
    data.loc[data['Zscore'] < -1.5, 'Signal'] = 1   # 做多价差(买X卖Y)  
    data.loc[abs(data['Zscore']) < 0.5, 'Signal'] = 0  # 平仓  
    

    3. 可视化代码与解析

    可视化1:资产价格与价差关系

    plt.figure(figsize=(14, 9))  
    
    # 左轴绘制资产价格  
    ax1 = plt.subplot(211)  
    ax1.plot(data['Asset_X'], label='Asset X', color='#1f77b4')  
    ax1.plot(data['Asset_Y'], label='Asset Y', color='#ff7f0e')  
    ax1.set_title('Cointegrated Assets Price Movement', pad=15)  
    ax1.legend(loc='upper left')  
    ax1.grid(alpha=0.3)  
    
    # 右轴绘制价差  
    ax2 = plt.subplot(212)  
    ax2.plot(data['Spread'], label='Spread (X - βY)', color='#2ca02c')  
    ax2.axhline(data['Spread'].mean(), color='#d62728', linestyle='--', label='Mean')  
    ax2.fill_between(data.index,   
                    data['Mean'] + 1.5*data['Std'],  
                    data['Mean'] - 1.5*data['Std'],  
                    color='gray', alpha=0.2, label='±1.5σ')  
    ax2.set_title('Spread Series with Mean Reversion Bands', pad=15)  
    ax2.legend()  
    ax2.grid(alpha=0.3)  
    
    plt.tight_layout()  
    plt.show()  
    

    图表说明

  • 上图显示两个协整资产的价格走势
  • 下图展示价差序列的均值回归特性,灰色区域为交易触发带
  • 可视化2:Z-score信号触发点

    plt.figure(figsize=(12, 5))  
    
    # 绘制Z-score  
    plt.plot(data['Zscore'], color='#9467bd', label='Z-score')  
    plt.axhline(1.5, color='red', linestyle='--', alpha=0.7, label='Upper Threshold')  
    plt.axhline(-1.5, color='green', linestyle='--', alpha=0.7, label='Lower Threshold')  
    
    # 标注交易信号  
    buy_signals = data[data['Signal'] == 1]  
    sell_signals = data[data['Signal'] == -1]  
    plt.scatter(buy_signals.index, buy_signals['Zscore'],  
               marker='^', color='lime', s=100, edgecolors='black', label='Long Spread')  
    plt.scatter(sell_signals.index, sell_signals['Zscore'],  
               marker='v', color='red', s=100, edgecolors='black', label='Short Spread')  
    
    # 图表装饰  
    plt.title('Z-score Signal Triggers', pad=15)  
    plt.ylabel('Z-score')  
    plt.legend(loc='upper left', ncol=2)  
    plt.grid(alpha=0.3)  
    plt.tight_layout()  
    plt.show()  
    

    图表说明

  • 紫色曲线为标准化后的价差Z-score
  • 红/绿虚线为交易阈值线
  • 绿色▲标记做多价差信号,红色▼标记做空价差信号

  • 4. 关键风险控制

    1. 协整断裂监测
      # 滚动窗口协整检验  
      rolling_pvalues = [cointegration_test(data['Asset_X'].iloc[i-120:i],   
                        data['Asset_Y'].iloc[i-120:i])   
                      for i in range(120, len(data))]  
      
    2. 动态头寸调整:根据波动率调整仓位大小
    3. 交易成本模型
      commission = 0.001  # 单边千分之一手续费  
      slippage = 0.002    # 滑点成本  
      

    作者:灏瀚星空

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python策略开发详解:均值回归与配对交易策略的回测及可视化实现

    发表回复