🚀 AI 一键生成 ptrade 策略代码

PTrade 数据分析:计算多只股票的相关性系数 (Correlation)

ptrade | 发布时间: 2025/12/22
以下内容由 EasyQuant 生成。

问题描述

怎么计算两只股票的相关性?

解决方案

在量化交易中,计算两只股票的相关性通常使用的是皮尔逊相关系数(Pearson Correlation Coefficient)。这个系数衡量的是两个变量之间线性关系的强度和方向。

核心概念

  1. 取值范围:-1 到 +1。
    • +1:完全正相关(两只股票涨跌完全同步)。
    • 0:不相关(两只股票的走势没有线性关系)。
    • -1:完全负相关(一只涨,另一只一定跌)。
  2. 数据选择:通常使用**收益率(Pct Change)**而不是原始收盘价来计算相关性。因为原始价格通常是不平稳的(有趋势),直接计算价格相关性容易产生“伪相关”,而收益率更能反映两者的波动关系。

PTrade 实现步骤

  1. 获取数据:使用 get_history 获取两只股票的历史收盘价。
  2. 数据清洗:将数据整理成 Pandas DataFrame 格式。
  3. 计算收益率:使用 .pct_change() 计算日收益率。
  4. 计算相关性:使用 Pandas 的 .corr() 方法计算相关系数。

PTrade 策略代码示例

以下是一个完整的策略代码,可以在 PTrade 的回测或研究环境中运行。该策略会在每天盘前计算两只股票(以贵州茅台和五粮液为例)过去 100 天的相关性并打印日志。

import pandas as pd
import numpy as np

def initialize(context):
    # 设置两只股票:贵州茅台(600519.SS) 和 五粮液(000858.SZ)
    g.stock1 = '600519.SS'
    g.stock2 = '000858.SZ'
    
    # 设置股票池
    set_universe([g.stock1, g.stock2])
    
    # 设定计算相关性的历史窗口长度(例如过去100个交易日)
    g.window_length = 100

def before_trading_start(context, data):
    # 1. 获取历史行情数据
    # 分别获取两只股票的收盘价,count设置为窗口长度+1,因为计算收益率会损失一天数据
    # get_history 返回的是 DataFrame,索引为日期
    hist1 = get_history(g.window_length + 1, '1d', 'close', g.stock1, fq='pre', include=False)
    hist2 = get_history(g.window_length + 1, '1d', 'close', g.stock2, fq='pre', include=False)
    
    # 检查数据是否获取成功
    if len(hist1) < g.window_length or len(hist2) < g.window_length:
        log.info("历史数据不足,跳过计算")
        return

    # 2. 整理数据
    # 创建一个新的 DataFrame 来存储两只股票的价格
    df_prices = pd.DataFrame()
    df_prices[g.stock1] = hist1['close']
    df_prices[g.stock2] = hist2['close']
    
    # 3. 计算日收益率
    # pct_change() 计算 (今日价格-昨日价格)/昨日价格
    # dropna() 去除第一行产生的 NaN 数据
    df_returns = df_prices.pct_change().dropna()
    
    # 4. 计算相关性矩阵
    correlation_matrix = df_returns.corr()
    
    # 提取两只股票的相关系数
    # 矩阵格式如下:
    #           stock1  stock2
    # stock1    1.0     0.85
    # stock2    0.85    1.0
    correlation = correlation_matrix.iloc[0, 1]
    
    # 5. 打印结果
    log.info("日期: %s" % context.blotter.current_dt.strftime("%Y-%m-%d"))
    log.info("股票 %s 和 %s 的过去 %d 日收益率相关系数为: %.4f" % (g.stock1, g.stock2, g.window_length, correlation))
    
    # 简单的策略逻辑示例:如果相关性极高,可以视为配对交易的观察对象
    if correlation > 0.8:
        log.info(">> 两者呈现高度正相关")
    elif correlation < -0.5:
        log.info(">> 两者呈现负相关")

def handle_data(context, data):
    pass

代码关键点解析

  1. get_history 参数

    • count: 设置为 g.window_length + 1。因为计算收益率(涨跌幅)时,第一天的数据没有前一天做对比,会变成 NaN,所以多取一天数据可以保证有效数据长度满足要求。
    • fq='pre': 使用前复权数据。计算历史收益率时,必须使用复权价格,否则分红派息会导致价格跳空,计算出的收益率会失真,从而影响相关性计算。
  2. pd.DataFrame 拼接

    • 我们将两只股票的 close 列合并到一个 DataFrame 中,这样每一行代表同一天,每一列代表一只股票。这是使用 Pandas 进行多维数据分析的标准格式。
  3. .corr() 方法

    • 这是 Pandas 提供的计算相关系数的方法,默认使用 Pearson 方法。它返回一个相关系数矩阵。我们通过 .iloc[0, 1] 取出第一行第二列的值,即两只不同股票之间的相关系数。

常见问题 (Q&A)

Q1: 为什么要用收益率计算,直接用收盘价计算行不行?
A: 不建议直接用收盘价。因为股票价格通常是不平稳的时间序列(即价格有趋势性)。如果两只股票都在长期上涨(例如牛市),即使它们的基本面毫无关系,直接计算价格的相关性也会很高(伪相关)。使用收益率(差分)可以消除趋势影响,反映两者真实的波动关系。

Q2: 窗口期(window_length)设置多少合适?
A: 这取决于你的策略周期。

  • 短线策略:通常使用 30-60 天,反应更灵敏,但噪音较大。
  • 中长线策略:通常使用 120-250 天(半年到一年),数据更稳定,更能反映长期的联动关系。

Q3: 计算出的相关性有什么实际用途?
A:

  1. 配对交易(Pairs Trading):寻找两只历史上高度正相关的股票,当它们的价格走势短期背离(相关性暂时减弱)时,做多落后的、做空领先的,等待回归。
  2. 分散风险:在构建投资组合时,选择相关性低(甚至负相关)的股票组合,可以有效降低非系统性风险。
  3. 多因子选股:避免选择同质化严重的因子或股票。