首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >怎么分析2只股票的相关度

怎么分析2只股票的相关度

作者头像
子晓聊技术
发布2026-04-23 16:20:23
发布2026-04-23 16:20:23
840
举报
文章被收录于专栏:子晓AI量化子晓AI量化

昨天有个同学问我,怎么分析2只股票的相关度。 我心里想, 他该不是看了某些公众号 来问我的吧,我前几天貌似刷到过这样的文章。

其实我在看到那篇文章前, 之前就有所了解。 只是个人感觉对我没多大用,哪些概念个股比较相关,我自己脑海里基本有个七七八八。觉得没啥必要。 比如 中际旭创和新易盛, 中科曙光和浪潮信息, 贵州茅台和五粮液 什么的。

这2天qmt、ptrade 测试版关停了,没法登录上去。那这2天写点什么呢,那要不就写一写这个。 希望对大家有所帮助。

首先,我们先了解下,怎么判断2只股票的相关度?

思路基本是 选择这2只股票的相同时间的涨跌幅,看他们的相关度。相关度怎么判定,知道的同学应该明白答案了。一般采用皮尔逊相关系数、斯皮尔曼相关系数。这里解释下

皮尔逊相关系数: 皮尔逊相关系数(Pearson correlation coefficient)是一种线性相关系数,用来反映两个变量线性相关程度的统计量。它的核心是衡量两个变量之间线性关系的强度和方向。

  • 计算公式:其值定义为两个变量之间的协方差和标准差的商,即 𝑟 = cov(𝑋,𝑌) / (𝜎𝑋 * 𝜎𝑄)。
  • 结果解读:系数值 𝒓 在 -1 到 +1 之间
    • ∙𝒓 > 0 表示正相关,𝒓 < 0 表示负相关
    • ∙|𝒓| 越接近 1,表示线性关系越强;𝒓 = 0 表示无线性相关关系(但可能存在其他方式的相关)。
    • ∙通常 |𝒓| < 0.4 视为低度线性相关,0.4 ≤ |𝒓| < 0.7 为显著性相关,0.7 ≤ |𝒓| < 1 为高度线性相关。
  • 特点与局限
    • ∙对数据的分布形态有一定要求,即两个变量的分布应该近似于正态分布
    • ∙对异常值比较敏感,数据中存在异常值可能会导致计算结果不准确。
    • ∙只能用于衡量两个变量之间的线性关系,不能用于衡量非线性关系。

斯皮尔曼相关系数: 斯皮尔曼等级相关系数(Spearman's rank correlation coefficient)经常用希腊字母ρ表示,是衡量两个变量的依赖性非参数 指标。它利用单调方程评价两个统计变量的相关性,不要求数据是连续的,也不要求数据呈正态分布

  • 核心思想:斯皮尔曼相关性的基本思想是分别对两个变量 X 、Y 做等级变换(rank transformation),用等级 R_X 和 R_Y 表示;然后按Pearson相关性分析的方法计算 R_X 和 R_Y 的相关性。
  • 结果解读:系数值 ρ 同样在 -1 到 +1 之间
    • ∙ρ > 0 表示单调正相关,ρ < 0 表示单调负相关
    • ∙|ρ| 越接近 1,表示单调关系越强;ρ = 0 表示无单调关系
    • ∙如果当X增加时,Y趋向于增加,斯皮尔曼相关系数则为正;如果当X增加时,Y趋向于减少,斯皮尔曼相关系数则为负。
  • 特点与优势
    • 对异常值不敏感,因为它是基于数据的秩次(排序)进行计算。
    • ∙能够捕捉单调关系(无论是线性的还是非线性的),而不仅仅是线性关系。
    • ∙适用于非线性或有序数据的情况。

如何选择这两种系数?

选择使用皮尔逊相关系数还是斯皮尔曼相关系数,主要取决于你的数据特征分析目的。

用AI辅助写了一个例子,你可以试一试。 如果大A全市场,那就最好把所有数据集用自己本地的数据集, 多线性循环实现。

这里贴一下完整代码,参考下思路, 具体根据自己的实际情况改造。 备注:如果发现格式有多余的特殊字符,用普通浏览器打开复制应该没问题。 希望我的分享对大家有所帮助

代码语言:javascript
复制
# -*- coding: utf-8 -*-
"""
使用AkShare计算两只股票收益率相关性的完整代码
"""
import akshare as ak
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
plt.style.use('seaborn-v0_8')  # 设置图形风格
def get_stock_data(symbol, start_date, end_date):
    """
    获取单只股票历史数据
    Parameters:
    symbol (str): 股票代码,如"000001"
    start_date (str): 开始日期,格式"YYYYMMDD"
    end_date (str): 结束日期,格式"YYYYMMDD"
    Returns:
    pandas.DataFrame: 股票历史数据
    """
    try:
        # 获取前复权数据
        df = ak.stock_zh_a_hist(symbol=symbol, period="daily",
                                start_date=start_date, end_date=end_date,
                                adjust="qfq")
        # 确保日期格式正确并设置为索引
        df['日期'] = pd.to_datetime(df['日期'])
        df.set_index('日期', inplace=True)
        return df
    except Exception as e:
        print(f"获取股票 {symbol} 数据时出错: {e}")
        return None
def calculate_correlation(returns_df, col1, col2, method='pearson'):
    """
    计算两只股票收益率的相关系数
    Parameters:
    returns_df (pandas.DataFrame): 包含收益率的DataFrame
    col1 (str): 第一只股票的列名
    col2 (str): 第二只股票的列名
    method (str): 相关系数计算方法,'pearson'或'spearman'
    Returns:
    float: 相关系数
    """
    return returns_df[col1].corr(returns_df[col2], method=method)
def analyze_stock_correlation(symbol1, symbol2, start_date, end_date, window=30):
    """
    分析两只股票的相关性
    Parameters:
    symbol1 (str): 第一只股票代码
    symbol2 (str): 第二只股票代码
    start_date (str): 开始日期
    end_date (str): 结束日期
    window (int): 滚动相关性窗口大小
    Returns:
    dict: 包含分析结果的字典
    """
    # 获取数据
    print("正在获取股票数据...")
    stock1_data = get_stock_data(symbol1, start_date, end_date)
    stock2_data = get_stock_data(symbol2, start_date, end_date)
    if stock1_data is None or stock2_data is None:
        print("数据获取失败,请检查股票代码和日期范围")
        return None
    # 合并两只股票的收盘价数据
    combined_data = pd.DataFrame({
        f'{symbol1}_close': stock1_data['收盘'],
        f'{symbol2}_close': stock2_data['收盘']
    })
    # 处理缺失值
    combined_data.dropna(inplace=True)
    # 计算每日收益率(百分比变化)
    returns = combined_data.pct_change().dropna()
    returns.columns = [f'{symbol1}_return', f'{symbol2}_return']
    # 计算相关系数
    pearson_corr = calculate_correlation(returns, f'{symbol1}_return', f'{symbol2}_return', 'pearson')
    spearman_corr = calculate_correlation(returns, f'{symbol1}_return', f'{symbol2}_return', 'spearman')
    # 计算滚动相关性
    rolling_corr = returns[f'{symbol1}_return'].rolling(window=window).corr(returns[f'{symbol2}_return'])
    # 计算协方差
    covariance = np.cov(returns[f'{symbol1}_return'], returns[f'{symbol2}_return'])[0, 1]
    return {
        'combined_data': combined_data,
        'returns': returns,
        'pearson_corr': pearson_corr,
        'spearman_corr': spearman_corr,
        'rolling_corr': rolling_corr,
        'covariance': covariance
    }
def plot_correlation_analysis(results, symbol1, symbol2):
    """
    绘制相关性分析图表
    Parameters:
    results (dict): 分析结果字典
    symbol1 (str): 第一只股票代码
    symbol2 (str): 第二只股票代码
    """
    # 准备数据
    returns = results['returns']
    rolling_corr = results['rolling_corr']
    combined_data = results['combined_data']
    # 创建图表
    fig, axes = plt.subplots(2, 2, figsize=(15, 12))
    fig.suptitle(f'{symbol1} 与 {symbol2} 相关性分析', fontsize=16)
    # 1. 价格走势对比图(标准化)
    ax1 = axes[0, 0]
    normalized_prices = combined_data / combined_data.iloc[0]
    ax1.plot(normalized_prices[f'{symbol1}_close'], label=f'股票{symbol1}')
    ax1.plot(normalized_prices[f'{symbol2}_close'], label=f'股票{symbol2}')
    ax1.set_title('标准化价格走势对比')
    ax1.set_xlabel('日期')
    ax1.set_ylabel('标准化价格')
    ax1.legend()
    ax1.grid(True)
    # 2. 收益率散点图
    ax2 = axes[0, 1]
    ax2.scatter(returns[f'{symbol1}_return'], returns[f'{symbol2}_return'], alpha=0.5)
    # 添加趋势线
    z = np.polyfit(returns[f'{symbol1}_return'], returns[f'{symbol2}_return'], 1)
    p = np.poly1d(z)
    x_range = np.linspace(returns[f'{symbol1}_return'].min(), returns[f'{symbol1}_return'].max(), 100)
    ax2.plot(x_range, p(x_range), "r--", alpha=0.8, label='趋势线')
    ax2.set_xlabel(f'{symbol1}收益率')
    ax2.set_ylabel(f'{symbol2}收益率')
    ax2.set_title('每日收益率散点图')
    ax2.legend()
    ax2.grid(True)
    # 3. 滚动相关系数图
    ax3 = axes[1, 0]
    ax3.plot(rolling_corr, label=f'{window}日滚动相关系数', color='purple')
    ax3.axhline(y=results['pearson_corr'], color='r', linestyle='--', label='整体皮尔逊相关系数')
    ax3.axhline(y=0, color='gray', linestyle='-', alpha=0.3)
    ax3.set_xlabel('日期')
    ax3.set_ylabel('相关系数')
    ax3.set_title('滚动相关系数趋势')
    ax3.legend()
    ax3.grid(True)
    # 4. 收益率分布直方图
    ax4 = axes[1, 1]
    ax4.hist(returns[f'{symbol1}_return'], bins=50, alpha=0.5, label=f'股票{symbol1}', density=True)
    ax4.hist(returns[f'{symbol2}_return'], bins=50, alpha=0.5, label=f'股票{symbol2}', density=True)
    ax4.set_xlabel('日收益率')
    ax4.set_ylabel('密度')
    ax4.set_title('收益率分布对比')
    ax4.legend()
    ax4.grid(True)
    plt.tight_layout()
    plt.show()
def print_correlation_summary(results, symbol1, symbol2):
    """
    打印相关性分析摘要
    Parameters:
    results (dict): 分析结果字典
    symbol1 (str): 第一只股票代码
    symbol2 (str): 第二只股票代码
    """
    print("=" * 60)
    print(f"{symbol1} 与 {symbol2} 相关性分析结果")
    print("=" * 60)
    print(f"分析期间: {start_date} 至 {end_date}")
    print(f"样本数量: {len(results['returns'])} 个交易日")
    print(f"皮尔逊相关系数: {results['pearson_corr']:.4f}")
    print(f"斯皮尔曼相关系数: {results['spearman_corr']:.4f}")
    print(f"协方差: {results['covariance']:.6f}")
    # 解释相关性强度
    def interpret_correlation(corr_value):
        abs_value = abs(corr_value)
        if abs_value >= 0.7:
            return "强相关"
        elif abs_value >= 0.4:
            return "中等相关"
        elif abs_value >= 0.2:
            return "弱相关"
        else:
            return "极弱相关或不相关"
    print(f"\n相关性解释:")
    print(f"皮尔逊相关系数表明两只股票存在{interpret_correlation(results['pearson_corr'])}关系")
    print(f"斯皮尔曼相关系数表明两只股票存在{interpret_correlation(results['spearman_corr'])}关系")
    # 滚动相关性的统计特征
    rolling_corr = results['rolling_corr'].dropna()
    if len(rolling_corr) > 0:
        print(f"\n滚动相关性统计 ({window}日窗口):")
        print(f"  均值: {rolling_corr.mean():.4f}")
        print(f"  标准差: {rolling_corr.std():.4f}")
        print(f"  最大值: {rolling_corr.max():.4f}")
        print(f"  最小值: {rolling_corr.min():.4f}")
        print(f"  最后值: {rolling_corr.iloc[-1]:.4f}")
    print("=" * 60)
# 主程序
if __name__ == "__main__":
    # 设置分析参数
    symbol1 = "300308"  # 中际旭创
    symbol2 = "300502"  # 新易盛
    start_date = "20240101"  # 开始日期
    end_date = "20250901"  # 结束日期
    window = 30  # 滚动相关性窗口大小
    # 执行相关性分析
    results = analyze_stock_correlation(symbol1, symbol2, start_date, end_date, window)
    if results is not None:
        # 打印分析结果
        print_correlation_summary(results, symbol1, symbol2)
        # 绘制图表
        plot_correlation_analysis(results, symbol1, symbol2)
        # 保存结果到CSV文件
        results['returns'].to_csv(f'stock_returns_{symbol1}_{symbol2}.csv')
        results['rolling_corr'].to_csv(f'rolling_correlation_{symbol1}_{symbol2}.csv')
        print("结果已保存到CSV文件")

如果我的分享对你投资有所帮助,不吝啬给个点赞关注呗。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 子晓聊技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档