К основному содержанию
скилл CX Codex

stock-correlation — скилл для Claude Code: корреляция акций

Скилл находит бумаги, которые ходят вместе с выбранным тикером, и меряет связь: корреляция, бета, спред, матрица по группе. Нужен, когда непонятно, что потянет за собой акцию.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add himself65/finance-skills --skill stock-correlation -a claude-code
Открыть на GitHub

Что делает stock-correlation

Скилл отвечает на вопрос «что ещё двигается вместе с этой бумагой». Берёт историю цен с Yahoo Finance через yfinance, считает корреляцию лог-доходностей и сортирует тикеры по абсолютному значению. Если на входе один тикер, вселенную кандидатов он собирает сам: сперва та же отрасль, затем сектор, если отрасль дала меньше десяти бумаг, потом смежные отрасли по описанию бизнеса. Готовых списков тикеров в скилле нет.

Дальше запрос уходит в один из четырёх сценариев. Поиск соседей для одного тикера. Разбор конкретной пары: корреляция, бета, R², спред и его z-score, плюс скользящее окно на 60 торговых дней. Матрица по группе тикеров. И отдельно — как корреляция менялась во времени. По умолчанию год дневных данных, метод Пирсона, порог 0.60 и топ-10 результатов.

Внутри — Python-код, который качает котировки, поэтому нужен интерпретатор с yfinance, pandas и numpy. Скилл сначала проверяет окружение shell-пробой, при нехватке пакетов ставит их через pip, а без доступа к shell сообщит об ограничении. Проверьте это заранее — на хостах с урезанным окружением агента установка и упрётся. Автор сразу оговаривает: это исследование, не инвестиционный совет.

Какие задачи решает

  • найти акции, которые двигаются вместе с NVDA
  • посчитать бету и R² для пары LITE/COHR
  • собрать матрицу корреляции по группе тикеров
  • отследить, как корреляция пары менялась за год
  • подобрать отрицательно correlated бумагу под хедж

Примеры запросов агенту

  • Что коррелирует с NVDA за последний год?
  • Посчитай корреляцию, бету и спред между LITE и COHR
  • Собери матрицу корреляции по FAANG и покажи, кто выбивается

Как установить stock-correlation

1Через Skills CLI (Vercel)

npx skills add himself65/finance-skills --skill stock-correlation -a claude-code

2Вручную: положить файлы

~/.claude/skills/stock-correlation/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/stock-correlation/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о stock-correlation

Как установить stock-correlation в Claude Code?

Выполните npx skills add himself65/finance-skills --skill stock-correlation -a claude-code. Файл скилла появится по пути ~/.claude/skills/stock-correlation/SKILL.md.

Что делает stock-correlation?

Ищет акции, которые двигаются синхронно с заданным тикером, и считает корреляцию, бету и спред по истории цен с Yahoo Finance. По группе тикеров строит корреляционную матрицу или показывает скользящую корреляцию.

Что нужно для работы скилла?

Python-окружение с yfinance, pandas и numpy и доступ к shell: скилл проверяет зависимости командой и при нехватке ставит пакеты через pip. Без shell-доступа он просто сообщит об ограничении.

Исходный текст

SKILL.md · MIT
---
name: stock-correlation
description: >
  Analyze how stocks move together using Yahoo Finance price history (yfinance): find
  correlated peers for a ticker, measure correlation, beta, and spread between
  specific tickers, cluster a group into a correlation matrix, and track rolling or
  regime-dependent correlation. Use this skill whenever the user asks what moves with
  a stock, what else drops when it drops, related tickers or sympathy plays, sector or
  supply-chain peers, pair trading or hedging pairs, beta or relative performance,
  correlation matrices, co-movement, or rolling/realized correlation — including
  well-known pairs like AMD/NVDA, GOOGL/AVGO, or LITE/COHR. With a single ticker,
  assume the user wants its correlated peers.
---

# Stock Correlation Analysis Skill

If your host has not already executed the shell probes below (for example, in Codex), run the commands inside the `!` wrappers with its shell tool before choosing a setup path. Use the actual output; if shell access is unavailable, report that limitation.

Finds and analyzes correlated stocks using historical price data from Yahoo Finance via [yfinance](https://github.com/ranaroussi/yfinance). Routes to specialized sub-skills based on user intent.

**Important**: This is for research and educational purposes only. Not financial advice. yfinance is not affiliated with Yahoo, Inc.

---

## Step 1: Ensure Dependencies Are Available

**Current environment status:**

```
!`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\')')"`
```

If `DEPS_MISSING`, install required packages before running any code:

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

If all dependencies are already installed, skip the install step and proceed directly.

---

## Step 2: Route to the Correct Sub-Skill

Classify the user's request and jump to the matching sub-skill section below.

| User Request | Route To | Examples |
|---|---|---|
| Single ticker, wants to find related stocks | **Sub-Skill A: Co-movement Discovery** | "what correlates with NVDA", "find stocks related to AMD", "sympathy plays for TSLA" |
| Two or more specific tickers, wants relationship details | **Sub-Skill B: Return Correlation** | "correlation between AMD and NVDA", "how do LITE and COHR move together", "compare AAPL vs MSFT" |
| Group of tickers, wants structure/grouping | **Sub-Skill C: Sector Clustering** | "correlation matrix for FAANG", "cluster these semiconductor stocks", "sector peers for AMD" |
| Wants time-varying or conditional correlation | **Sub-Skill D: Realized Correlation** | "rolling correlation AMD NVDA", "when NVDA drops what else drops", "how has correlation changed" |

If ambiguous, default to **Sub-Skill A** (Co-movement Discovery) for single tickers, or **Sub-Skill B** (Return Correlation) for two tickers.

### Defaults for all sub-skills

| Parameter | Default |
|---|---|
| Lookback period | `1y` (1 year) |
| Data interval | `1d` (daily) |
| Correlation method | Pearson |
| Minimum correlation threshold | 0.60 |
| Number of results | Top 10 |
| Return type | Daily log returns |
| Rolling window | 60 trading days |

---

## Sub-Skill A: Co-movement Discovery

**Goal**: Given a single ticker, find stocks that move with it.

### A1: Build the peer universe

You need 15-30 candidates. **Do not use hardcoded ticker lists** — build the universe dynamically at runtime. See `references/sector_universes.md` for the full implementation. The approach:

1. **Screen same-industry stocks** using `yf.screen()` + `yf.EquityQuery` to find stocks in the same industry as the target
2. **Broaden to sector** if the industry screen returns fewer than 10 peers
3. **Add thematic/adjacent industries** — read the target's `longBusinessSummary` and screen 1-2 related industries (e.g., a semiconductor company → also screen semiconductor equipment)
4. **Combine, deduplicate, remove target ticker**

### A2: Compute correlations

```python
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: Present results

Show a ranked table with company names and sectors (fetch via `yf.Ticker(t).info.get("shortName")`). Values below are illustrative:

| Rank | Ticker | Company | Correlation | Why linked |
|---|---|---|---|---|
| 1 | AMD | Advanced Micro Devices | 0.82 | Same industry — GPU/CPU |
| 2 | AVGO | Broadcom | 0.78 | AI infrastructure peer |

Include:
- Top 10 positively correlated stocks
- Any notable negatively correlated stocks (potential hedges)
- Brief explanation of **why** each might be linked (sector, supply chain, customer overlap)

---

## Sub-Skill B: Return Correlation

**Goal**: Deep-dive into the relationship between two (or a few) specific tickers.

### B1: Download and compute

```python
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: Present results

Show a summary card (illustrative values):

| Metric | Value |
|---|---|
| Pearson Correlation | 0.82 |
| Beta (B vs A) | 1.15 |
| R-squared | 0.67 |
| Rolling Corr (60d avg) | 0.80 |
| Rolling Corr Range | [0.55, 0.94] |
| Rolling Corr Std Dev | 0.08 |
| Spread Z-Score (current) | +1.2 |
| Observations | 250 |

Interpretation guide:
- **Correlation > 0.80**: Strong co-movement — these stocks are tightly linked
- **Correlation 0.50–0.80**: Moderate — shared sector drivers but independent factors too
- **Correlation < 0.50**: Weak — limited co-movement despite possible sector overlap
- **High rolling std**: Unstable relationship — correlation varies significantly over time
- **Spread Z > |2|**: Unusual divergence from historical relationship

---

## Sub-Skill C: Sector Clustering

**Goal**: Given a group of tickers, show the full correlation structure and identify clusters.

### C1: Build the correlation matrix

```python
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
```

Note: if `scipy` is not available, fall back to sorting by average correlation instead of hierarchical clustering.

### C2: Present results

1. **Full correlation matrix** — formatted as a table. For more than 8 tickers, show as a heatmap description or highlight only the strongest/weakest pairs.

2. **Identified clusters** — group tickers that have high intra-group correlation:
   - Cluster 1: [NVDA, AMD, AVGO] — avg intra-correlation 0.82
   - Cluster 2: [AAPL, MSFT] — avg intra-correlation 0.75

3. **Outliers** — tickers with low average correlation to the group (potential diversifiers).

4. **Strongest pairs** — top 5 highest-correlation pairs in the matrix.

5. **Weakest pairs** — top 5 lowest/negative-correlation pairs (hedging candidates).

---

## Sub-Skill D: Realized Correlation

**Goal**: Show how correlation changes over time and under different market conditions.

### D1: Rolling correlation

```python
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: Regime-conditional correlation

```python
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: Present results

1. **Rolling correlation summary table** (illustrative values here and in the regime table):

| Window | Current | Mean | Min | Max | Std |
|---|---|---|---|---|---|
| 20-day | 0.88 | 0.76 | 0.32 | 0.95 | 0.12 |
| 60-day | 0.82 | 0.78 | 0.55 | 0.92 | 0.08 |
| 120-day | 0.80 | 0.79 | 0.68 | 0.88 | 0.05 |

2. **Regime correlation table**:

| Regime | Correlation | Days |
|---|---|---|
| All Days | 0.82 | 250 |
| Up Days | 0.75 | 132 |
| Down Days | 0.87 | 118 |
| High Vol (top 25%) | 0.90 | 63 |
| Large Drawdown (< -2%) | 0.93 | 28 |

3. **Key insight**: Highlight whether correlation **increases during sell-offs** (very common — "correlations go to 1 in a crisis"). This is critical for risk management.

4. **Trend**: Is correlation trending higher or lower recently vs. its historical average?

---

## Step 3: Respond to the User

After running the appropriate sub-skill, present results clearly:

### Always include

- The **lookback period** and **data interval** used
- The **number of observations** (trading days)
- Any tickers **dropped due to insufficient data**

### Always caveat

- **Correlation is not causation** — co-movement does not imply a causal link
- **Past correlation does not guarantee future correlation** — regimes shift
- **Short lookback windows** produce noisy estimates; longer windows smooth but may miss regime changes

### Practical applications (mention when relevant)

- **Sympathy plays**: Stocks likely to follow a peer's earnings/news move
- **Pair trading**: High-correlation pairs where the spread has diverged from its mean
- **Portfolio diversification**: Finding low-correlation assets to reduce risk
- **Hedging**: Identifying inversely correlated instruments
- **Sector rotation**: Understanding which sectors move together
- **Risk management**: Correlation spikes during stress — diversification may fail when needed most

Present the data and let the user draw conclusions; don't recommend specific trades.

---

## Reference Files

- `references/sector_universes.md` — Dynamic peer universe construction using yfinance Screener API

Read the reference file when you need to build a peer universe for a given ticker.

© himself65 · MIT · himself65/finance-skills

Похожие скиллы

Всё по теме «Финансы и бизнес» →
alphaear-stock RKiding Ищет тикеры рынков A-Share, HK и US, выгружает котировки OHLCV и фундаментальные показатели компании. CX Codex +1 1 200установок stock-market-pro sundial-org Скилл для анализа акций, крипты и форекса: тянет котировки, фундаментальные метрики и рисует свечные графики прямо в терминале. CX Codex +1 4 100установок stock-quote OctagonAI Запрашивает котировки акций через Octagon MCP в реальном времени. Пригодится, когда нужны текущая цена, объём торгов, диапазон за 52 недели и скользящие средние. CX Codex +1 691установок correlation-analysis agiprolabs Считает корреляции между активами: скользящие окна, кластеризация, хвостовая зависимость. Нужен для оценки диверсификации и парного трейдинга. CX Codex +1 464установок alphaear-deepear-lite RKiding Получает свежие финансовые сигналы и цепочки трансмиссионного анализа из DeepEar Lite. Помогает следить за динамикой рынков и факторами движения акций прямо в чате с агентом. CX Codex +1 334установок market-data rebyteai-template Даёт агенту доступ к историческим котировкам, текущим ценам, новостям и фундаментальным показателям. Пригодится для анализа рынка и бэктестов. CX Codex +1 380установок

Из того же набора22

yfinance-data Скилл загружает котировки, финансовые отчёты, опционы, дивиденды и данные по держателям акций через библиотеку yfinance (Yahoo Finance). CX Codex +1 3 900установок options-payoff Строит интерактивный график доходности опционной позиции с расчётом на экспирацию и теоретической стоимостью по Black–Scholes. CX Codex +1 3 400установок generative-ui Задаёт правила дизайн-системы для интерактивных HTML- и SVG-виджетов. Нужен, когда вместо текста агенту поручают показать графики, диаграммы или калькуляторы. CX Codex +1 3 200установок earnings-recap Разбирает опубликованный квартальный отчёт компании: EPS, выручку, маржи и реакцию акций. Нужен для вопросов о результате, сюрпризе и движении после отчёта. CX Codex +1 3 200установок earnings-preview Собирает брифинг перед отчётом компании: дата и время публикации, консенсус по EPS и выручке, история beat/miss, оценки аналитиков. CX Codex +1 3 200установок twitter-reader Скилл читает Twitter/X через opencli: лента, поиск твитов, тренды, закладки, профили и уведомления. Только чтение, для финансовых исследований. CX Codex +1 3 100установок etf-premium Считает премию или дисконт ETF к NAV по данным Yahoo Finance, сравнивает фонды между собой и раскладывает резкий скачок цены на причины. CX Codex +1 3 100установок stock-liquidity Оценивает ликвидность акций через библиотеку yfinance: спреды bid-ask, объёмы торгов и рыночный импакт. Помогает рассчитать издержки перед входом в позицию. CX Codex +1 3 100установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой