Skip to content

What (One-liner)

N×N correlation matrix over N symbols' daily returns, with three estimators: Pearson / Ledoit-Wolf shrinkage / OAS shrinkage. The Batch Signals multi-select helper and a portfolio-diversification diagnostic.

How to use

In Batch Signals / Canvas, drag portfolio_correlation, fill the symbols list (≥2) plus optional period (default '6mo') and optional method (default 'pearson'). Output is the N×N matrix plus a shrinkage coefficient (LW/OAS).

Typical usage:

symbols=[SPY, QQQ, IWM, EFA, TLT, GLD, DBC], period=1y, method=ledoit_wolf
→ 7×7 PSD correlation matrix + shrinkage_coef ≈ 0.08

Core formulas

# Preprocessing:
returns = fetch_daily_pct_change(symbols, period)         # 60s cached
X = returns.values                                         # (T, N)

# Method branch:
if method == "pearson":
  M = np.corrcoef(X.T)
  shrinkage = null

elif method == "ledoit_wolf":
  cov, coef = sklearn.covariance.ledoit_wolf(X)
  M = diag_normalize(cov, clip=[-1, 1])
  shrinkage = coef

elif method == "oas":
  cov, coef = sklearn.covariance.oas(X)
  M = diag_normalize(cov, clip=[-1, 1])
  shrinkage = coef

# matrix round(4) on output

Assumptions & applicability

Assumptions: daily frequency + yfinance auto_adjust + at least 2 symbols + 60s cache + 100-symbol hard cap.

Fits: US equity/ETF/FX diversification diagnostics, covariance ahead of risk parity, quarterly-review correlation snapshots.

Does not fit: tick data, >100 symbols, <2 symbols, non-linear dependence, time-varying correlation, copulas.

Input / Output contract

{symbols: list, period: str, method: 'pearson'|'ledoit_wolf'|'oas'}{symbols, period, n_observations, matrix, dropped_symbols, truncated, method, shrinkage, windows}.

Matrix round(4); shrinkage is null for pearson.

Known limitations

  1. Pearson goes rank-deficient at large N/T (use LW/OAS when N/T ≥ 0.5)
  2. Matrix round(4) hides fine-grained shrinkage differences
  3. 100-symbol hard cap (flagged via truncated)
  4. Cache TTL 60s (freshness vs coalescing)
  5. Symbol alias map hardcoded
  6. Zero-variance columns fall back to 1.0 (already filtered by _fetch_returns; defence-in-depth)
  7. No automatic method recommendation based on the N/T ratio

References

Pearson (1895) original + Ledoit-Wolf (2004) shrinkage + Chen et al. (2010) OAS + Fama-French (1993) factor-model background. Full citations in the frontmatter.

Golden Test

tests/golden/fixtures/tier2/portfolio_correlation/ — a 3-method parametrized regression over synthetic 3-symbol returns, 1e-10 tolerance post-round(4), 9 tests:

  • matches_reference[pearson] / [ledoit_wolf] / [oas] — 3 methods byte-equal
  • determinism — 5 reruns identical
  • diagonal_is_one — diagonal = 1.0 contract for every method
  • matrix_symmetric — symmetry contract
  • rejects_single_symbol — < 2 → error
  • rejects_unknown_method — invalid method → error
  • shrinkage_comparison — OAS > LW on small T/N, ordering contract

The reference replays a synthetic 3-symbol series (seed=42) with _fetch_returns monkey-patched, bypassing yfinance.

Changelog

  • 1.0.0 (2026-04-20) — First Active (Tier 2 batch 5)

Verifiable intelligence for the decisions that demand scrutiny.