关于 stock-correlation
stock-correlation 是用于股票相关性分析的技能,基于 Yahoo Finance 的历史价格数据和 yfinance,按需求分析个股联动、指定股票关系、群组结构或随时间变化的相关性。
主要功能
- 01发现与单只股票联动的标的
- 02计算指定股票的收益相关性
- 03生成股票群组相关矩阵与聚类
- 04分析滚动及市场状态相关性
- 05提供参数默认值与结果解读指引
适用场景
- 01寻找与某只股票共同波动的标的
- 02比较两只股票的相关性与回归指标
- 03梳理一组股票的相关结构和离群项
- 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。方法如下:
- 筛选同一行业的股票:使用
yf.screen()+yf.EquityQuery查找与目标股票属于同一行业的股票 - 扩展到整个板块:如果行业筛选返回的同类股票少于 10 只,则扩展范围至整个板块
- 添加主题相关或相邻行业:读取目标股票的
longBusinessSummary,筛选 1–2 个相关行业(例如,半导体公司 → 同时筛选半导体设备公司) - 合并、去重并移除目标股票代码
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") 获取)。以下数值仅供示例:
| 排名 | 股票代码 | 公司 | 相关性 | 关联原因 |
|---|---|---|---|---|
| 1 | AMD | Advanced Micro Devices | 0.82 | 同一行业 — GPU/CPU |
| 2 | AVGO | Broadcom | 0.78 | AI 基础设施同类股 |
包括:
- 相关性最高的 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-squared | 0.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:呈现结果
-
完整相关矩阵——以表格形式展示。如果股票代码超过 8 个,则以热力图形式说明,或仅突出显示相关性最高和最低的配对。
-
识别出的集群——将组内相关性较高的股票代码分组:
- 集群 1:[NVDA, AMD, AVGO]——组内平均相关系数 0.82
- 集群 2:[AAPL, MSFT]——组内平均相关系数 0.75
-
离群项——与组内其他股票平均相关性较低的股票代码(可能有助于分散风险)。
-
相关性最高的配对——矩阵中相关性最高的前 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:呈现结果
- 滚动相关系数摘要表(此处及市场环境表中的数值均为示例):
| 窗口 | 当前值 | 均值 | 最小值 | 最大值 | 标准差 |
|---|---|---|---|---|---|
| 20 天 | 0.88 | 0.76 | 0.32 | 0.95 | 0.12 |
| 60 天 | 0.82 | 0.78 | 0.55 | 0.92 | 0.08 |
| 120 天 | 0.80 | 0.79 | 0.68 | 0.88 | 0.05 |
- 市场环境相关系数表:
| 市场环境 | 相关系数 | 天数 |
|---|---|---|
| 所有交易日 | 0.82 | 250 |
| 上涨日 | 0.75 | 132 |
| 下跌日 | 0.87 | 118 |
| 高波动(前 25%) | 0.90 | 63 |
| 大幅回撤(< -2%) | 0.93 | 28 |
-
关键见解:指出抛售期间相关性是否上升(这种情况很常见——“危机时相关性会趋近于 1”)。这对风险管理至关重要。
-
趋势:与历史均值相比,近期相关性是在上升还是下降?
步骤 3:回复用户
运行适当的子技能后,清晰地呈现结果:
始终包含
- 使用的回溯期和数据间隔
- 观测值数量(交易日)
- 因数据不足而剔除的股票代码
始终注明
- 相关性不代表因果关系——同向变动不意味着存在因果联系
- 过去的相关性不能保证未来的相关性——市场环境会变化
- 较短的回溯窗口会产生噪声较大的估算;较长的窗口虽能平滑数据,但可能无法捕捉市场环境变化
实际应用(相关时提及)
- 跟随行情:可能跟随同行公司财报或新闻行情变动的股票
- 配对交易:高相关性配对中,利差已偏离均值的情况
- 投资组合分散化:寻找低相关性资产以降低风险
- 对冲:识别负相关的工具
- 行业轮动:了解哪些行业走势一致
- 风险管理:市场承压时相关性会飙升——最需要分散风险时,分散化可能失效
呈现数据,让用户自行得出结论;不要推荐具体交易。
参考文件
references/sector_universes.md— 使用 yfinance Screener API 动态构建同行集合
需要为指定股票代码构建同行集合时,请阅读此参考文件。