mcpField
S
stock-correlation

stock-correlation

github.com/himself65数据与数据库3.5k3.6k 次安装3 天前更新
代码仓库

关于 stock-correlation

stock-correlation 是用于股票相关性分析的技能,基于 Yahoo Finance 的历史价格数据和 yfinance,按需求分析个股联动、指定股票关系、群组结构或随时间变化的相关性。

主要功能

  1. 01发现与单只股票联动的标的
  2. 02计算指定股票的收益相关性
  3. 03生成股票群组相关矩阵与聚类
  4. 04分析滚动及市场状态相关性
  5. 05提供参数默认值与结果解读指引

适用场景

  1. 01寻找与某只股票共同波动的标的
  2. 02比较两只股票的相关性与回归指标
  3. 03梳理一组股票的相关结构和离群项
  4. 04观察相关性在下跌或高波动期间的变化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/himself65/finance-skills --skill stock-correlation

安装后在 Claude Code 中输入/stock-correlation确认已加载。

附带文件README.mdreferences/sector_universes.md

详细介绍

股票相关性分析技能

如果你的宿主尚未执行以下 shell 探测(例如在 Codex 中),请先使用其 shell 工具运行 ! 包裹的命令,再选择设置路径。请根据实际输出进行判断;如果无法访问 shell,请说明这一限制。

使用 yfinance 获取 Yahoo Finance 的历史价格数据,查找并分析相关股票。根据用户意图,转到相应的专用子技能。

重要提示:本内容仅用于研究和教育目的,不构成财务建议。yfinance 与 Yahoo, Inc. 无关联。


第 1 步:确保依赖项可用

当前环境状态:

!`python3 -c "exec('try:\n import yfinance, pandas, numpy\n print(f\'yfinance={yfinance.__version__} pandas={pandas.__version__} numpy={numpy.__version__}\')\nexcept Exception:\n print(\'DEPS_MISSING\')')"`

如果 DEPS_MISSING,请在运行任何代码前安装所需软件包:

import subprocess, sys
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "yfinance", "pandas", "numpy"])

如果所有依赖项均已安装,请跳过安装步骤,直接继续。


第 2 步:转到正确的子技能

对用户的请求进行分类,并跳转到下方相应的子技能部分。

用户请求转到示例
指定单只股票,想查找相关股票子技能 A:联动发现“哪些股票与 NVDA 相关”,“查找与 AMD 相关的股票”,“TSLA 的联动股”
指定两只或更多股票,想了解其关系详情子技能 B:收益率相关性“AMD 和 NVDA 之间的相关性”,“LITE 和 COHR 如何联动”,“比较 AAPL 与 MSFT”
指定一组股票,想了解其结构或分组子技能 C:行业聚类“FAANG 相关性矩阵”,“对这些半导体股票进行聚类”,“AMD 的行业同类股”
想了解随时间变化或有条件的相关性子技能 D:已实现相关性“AMD 和 NVDA 的滚动相关性”,“NVDA 下跌时还有哪些股票也会下跌”,“相关性发生了怎样的变化”

如果意图不明确,单只股票默认使用子技能 A(联动发现),两只股票默认使用子技能 B(收益率相关性)。

所有子技能的默认值
参数默认值
回溯期1y(1 年)
数据间隔1d(每日)
相关性方法Pearson
最低相关性阈值0.60
结果数量前 10 个
收益率类型每日对数收益率
滚动窗口60 个交易日

子技能 A:联动发现

目标:给定一只股票,查找与其走势一致的股票。

A1:构建同类股票范围

需要 15–30 个候选对象。不要使用硬编码的股票代码列表——请在运行时动态构建范围。完整实现请参见 references/sector_universes.md。方法如下:

  1. 筛选同一行业的股票:使用 yf.screen() + yf.EquityQuery 查找与目标股票属于同一行业的股票
  2. 扩展到整个板块:如果行业筛选返回的同类股票少于 10 只,则扩展范围至整个板块
  3. 添加主题相关或相邻行业:读取目标股票的 longBusinessSummary,筛选 1–2 个相关行业(例如,半导体公司 → 同时筛选半导体设备公司)
  4. 合并、去重并移除目标股票代码
A2:计算相关性
import yfinance as yf
import pandas as pd
import numpy as np

def discover_comovement(target_ticker, peer_tickers, period="1y"):
    all_tickers = [target_ticker] + [t for t in peer_tickers if t != target_ticker]
    data = yf.download(all_tickers, period=period, auto_adjust=True, progress=False)

    # Extract close prices — yf.download returns MultiIndex (Price, Ticker) columns
    closes = data["Close"].dropna(axis=1, thresh=max(60, len(data) // 2))

    # Log returns
    returns = np.log(closes / closes.shift(1)).dropna()
    corr_series = returns.corr()[target_ticker].drop(target_ticker, errors="ignore")

    # Rank by absolute correlation
    ranked = corr_series.abs().sort_values(ascending=False)

    result = pd.DataFrame({
        "Ticker": ranked.index,
        "Correlation": [round(corr_series[t], 4) for t in ranked.index],
    })
    return result, returns
A3:展示结果

展示带公司名称和行业的排名表(通过 yf.Ticker(t).info.get("shortName") 获取)。以下数值仅供示例:

排名股票代码公司相关性关联原因
1AMDAdvanced Micro Devices0.82同一行业 — GPU/CPU
2AVGOBroadcom0.78AI 基础设施同类股

包括:

  • 相关性最高的 10 只正相关股票
  • 值得关注的负相关股票(潜在对冲标的)
  • 简要说明每只股票可能的关联原因(行业、供应链、客户重叠)

子技能 B:收益率相关性

目标:深入分析两只(或少数几只)指定股票之间的关系。

B1:下载并计算
import yfinance as yf
import pandas as pd
import numpy as np

def return_correlation(ticker_a, ticker_b, period="1y"):
    data = yf.download([ticker_a, ticker_b], period=period, auto_adjust=True, progress=False)
    closes = data["Close"][[ticker_a, ticker_b]].dropna()

    returns = np.log(closes / closes.shift(1)).dropna()
    corr = returns[ticker_a].corr(returns[ticker_b])

    # Beta: how much does B move per unit move of A
    cov_matrix = returns.cov()
    beta = cov_matrix.loc[ticker_b, ticker_a] / cov_matrix.loc[ticker_a, ticker_a]

    # R-squared
    r_squared = corr ** 2

    # Rolling 60-day correlation for stability
    rolling_corr = returns[ticker_a].rolling(60).corr(returns[ticker_b])

    # Spread (log price ratio) for mean-reversion
    spread = np.log(closes[ticker_a] / closes[ticker_b])
    spread_z = (spread - spread.mean()) / spread.std()

    return {
        "correlation": round(corr, 4),
        "beta": round(beta, 4),
        "r_squared": round(r_squared, 4),
        "rolling_corr_mean": round(rolling_corr.mean(), 4),
        "rolling_corr_std": round(rolling_corr.std(), 4),
        "rolling_corr_min": round(rolling_corr.min(), 4),
        "rolling_corr_max": round(rolling_corr.max(), 4),
        "spread_z_current": round(spread_z.iloc[-1], 4),
        "observations": len(returns),
    }
B2:呈现结果

显示摘要卡片(示例数值):

指标数值
Pearson 相关系数0.82
Beta(B 相对于 A)1.15
R-squared0.67
滚动相关系数(60 天均值)0.80
滚动相关系数范围[0.55, 0.94]
滚动相关系数标准差0.08
利差 Z 分数(当前)+1.2
观测值250

解读指南:

  • 相关系数 > 0.80:高度同向变动——这些股票紧密联动
  • 相关系数 0.50–0.80:中度同向变动——存在共同的行业驱动因素,但也受各自独立因素影响
  • 相关系数 < 0.50:同向变动较弱——即使可能属于同一行业,联动也有限
  • 滚动标准差高:关系不稳定——相关性随时间显著变化
  • 利差 Z > |2|:相对于历史关系出现了异常背离

子技能 C:行业聚类

目标:给定一组股票代码,展示完整的相关结构并识别集群。

C1:构建相关矩阵
import yfinance as yf
import pandas as pd
import numpy as np

def sector_clustering(tickers, period="1y"):
    data = yf.download(tickers, period=period, auto_adjust=True, progress=False)

    # yf.download returns MultiIndex (Price, Ticker) columns
    closes = data["Close"].dropna(axis=1, thresh=max(60, len(data) // 2))
    returns = np.log(closes / closes.shift(1)).dropna()
    corr_matrix = returns.corr()

    # Hierarchical clustering order
    from scipy.cluster.hierarchy import linkage, leaves_list
    from scipy.spatial.distance import squareform

    dist_matrix = 1 - corr_matrix.abs()
    np.fill_diagonal(dist_matrix.values, 0)
    condensed = squareform(dist_matrix)
    linkage_matrix = linkage(condensed, method="ward")
    order = leaves_list(linkage_matrix)
    ordered_tickers = [corr_matrix.columns[i] for i in order]

    # Reorder matrix
    clustered = corr_matrix.loc[ordered_tickers, ordered_tickers]

    return clustered, returns

注意:如果没有 scipy,则改为按平均相关系数排序,而不是进行层次聚类。

C2:呈现结果
  1. 完整相关矩阵——以表格形式展示。如果股票代码超过 8 个,则以热力图形式说明,或仅突出显示相关性最高和最低的配对。

  2. 识别出的集群——将组内相关性较高的股票代码分组:

    • 集群 1:[NVDA, AMD, AVGO]——组内平均相关系数 0.82
    • 集群 2:[AAPL, MSFT]——组内平均相关系数 0.75
  3. 离群项——与组内其他股票平均相关性较低的股票代码(可能有助于分散风险)。

  4. 相关性最高的配对——矩阵中相关性最高的前 5 组配对。

  5. 相关性最低的配对——相关性最低或为负的前 5 组配对(可作为对冲候选)。


子技能 D:实现相关性

目标:展示相关性随时间及不同市场环境的变化情况。

D1:滚动相关系数
import yfinance as yf
import pandas as pd
import numpy as np

def realized_correlation(ticker_a, ticker_b, period="2y", windows=[20, 60, 120]):
    data = yf.download([ticker_a, ticker_b], period=period, auto_adjust=True, progress=False)
    closes = data["Close"][[ticker_a, ticker_b]].dropna()

    returns = np.log(closes / closes.shift(1)).dropna()

    rolling = {}
    for w in windows:
        rolling[f"{w}d"] = returns[ticker_a].rolling(w).corr(returns[ticker_b])

    return rolling, returns
D2:按市场环境划分的相关系数
def regime_correlation(returns, ticker_a, ticker_b, condition_ticker=None):
    """Compare correlation across up/down/volatile regimes."""
    if condition_ticker is None:
        condition_ticker = ticker_a

    ret = returns[condition_ticker]

    regimes = {
        "All Days": pd.Series(True, index=returns.index),
        "Up Days (target > 0)": ret > 0,
        "Down Days (target < 0)": ret < 0,
        "High Vol (top 25%)": ret.abs() > ret.abs().quantile(0.75),
        "Low Vol (bottom 25%)": ret.abs() < ret.abs().quantile(0.25),
        "Large Drawdown (< -2%)": ret < -0.02,
    }

    results = {}
    for name, mask in regimes.items():
        subset = returns[mask]
        if len(subset) >= 20:
            results[name] = {
                "correlation": round(subset[ticker_a].corr(subset[ticker_b]), 4),
                "days": int(mask.sum()),
            }

    return results
D3:呈现结果
  1. 滚动相关系数摘要表(此处及市场环境表中的数值均为示例):
窗口当前值均值最小值最大值标准差
20 天0.880.760.320.950.12
60 天0.820.780.550.920.08
120 天0.800.790.680.880.05
  1. 市场环境相关系数表:
市场环境相关系数天数
所有交易日0.82250
上涨日0.75132
下跌日0.87118
高波动(前 25%)0.9063
大幅回撤(< -2%)0.9328
  1. 关键见解:指出抛售期间相关性是否上升(这种情况很常见——“危机时相关性会趋近于 1”)。这对风险管理至关重要。

  2. 趋势:与历史均值相比,近期相关性是在上升还是下降?


步骤 3:回复用户

运行适当的子技能后,清晰地呈现结果:

始终包含
  • 使用的回溯期和数据间隔
  • 观测值数量(交易日)
  • 因数据不足而剔除的股票代码
始终注明
  • 相关性不代表因果关系——同向变动不意味着存在因果联系
  • 过去的相关性不能保证未来的相关性——市场环境会变化
  • 较短的回溯窗口会产生噪声较大的估算;较长的窗口虽能平滑数据,但可能无法捕捉市场环境变化
实际应用(相关时提及)
  • 跟随行情:可能跟随同行公司财报或新闻行情变动的股票
  • 配对交易:高相关性配对中,利差已偏离均值的情况
  • 投资组合分散化:寻找低相关性资产以降低风险
  • 对冲:识别负相关的工具
  • 行业轮动:了解哪些行业走势一致
  • 风险管理:市场承压时相关性会飙升——最需要分散风险时,分散化可能失效

呈现数据,让用户自行得出结论;不要推荐具体交易。


参考文件

  • references/sector_universes.md — 使用 yfinance Screener API 动态构建同行集合

需要为指定股票代码构建同行集合时,请阅读此参考文件。

评论

支持 Markdown