stock-correlation について
stock-correlation は、yfinance 経由で Yahoo Finance の過去価格を使って株式の関係を分析するスキルです。依頼に応じて、連動銘柄の探索、ペア分析、グループ分類、期間別・相場環境別の相関分析に振り分けます。
主な機能
- 01対象銘柄と連動する株式の探索
- 02指定銘柄間のリターン相関の計算
- 03相関行列と銘柄クラスターの作成
- 04ローリング相関と相場環境別の分析
- 05初期設定と結果解釈のガイド
活用シーン
- 01特定銘柄と連動する株式の探索
- 022銘柄の相関や回帰指標の比較
- 03株式グループの関係や外れ値の把握
- 04下落時や高ボラティリティ時の変化の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ himself65/ finance-skills --skill stock-correlationインストール後、Claude Code で/stock-correlationを入力して読み込まれたか確認します。
同梱ファイルREADME.mdreferences/sector_universes.md
詳細
株価相関分析スキル
ホストが以下のシェルプローブをまだ実行していない場合(たとえば、Codex の場合)、セットアップ方法を選ぶ前に、シェルツールで ! ラッパー内のコマンドを実行してください。実際の出力を使用してください。シェルにアクセスできない場合は、その制限を報告してください。
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 の連れ高・連れ安銘柄」 |
| 2 つ以上の特定ティッカーについて、関係の詳細を知りたい | サブスキル B:リターン相関 | 「AMD と NVDA の相関」「LITE と COHR はどのように連動する?」「AAPL と MSFT を比較」 |
| ティッカーのグループについて、構造やグループ分けを知りたい | サブスキル C:セクターのクラスター分析 | 「FAANG の相関行列」「これらの半導体株をクラスター化して」「AMD のセクターピア」 |
| 時間とともに変化する相関や条件付き相関を知りたい | サブスキル D:実現相関 | 「AMD と NVDA のローリング相関」「NVDA が下落したとき、他に何が下落する?」「相関はどう変化した?」 |
曖昧な場合は、単一のティッカーならデフォルトで サブスキル A(連動銘柄の探索)、2 つのティッカーなら サブスキル 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:リターン相関
目標:2 つ(または少数)の特定ティッカー間の関係を詳しく分析します。
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: 結果を提示する
要約カードを表示します(以下は説明用の値です)。
| 指標 | 値 |
|---|---|
| ピアソン相関係数 | 0.82 |
| ベータ(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 を使用した、動的な同業銘柄ユニバースの構築
指定したティッカーの同業銘柄ユニバースを構築する必要がある場合は、参考ファイルをお読みください。