Skip to main content

cross-asset-relationships

Cross-asset and quantitative analysis: pair correlations, correlation heatmaps, currency strength, cross-timeframe divergence, intermarket analysis, market breadth, carry trades, swap rates, risk premia, and multi-pair baskets. USE FOR: correlation, currency strength, intermarket, market breadth, carry trade, swap rate, risk premia, basket, pair trading, cross asset, quant.

Aller à l'installation

Informations de source

Dépôt
mahmoud20138/Tradecraft
Dernière activité de la source
23 avril 2026 à 08:40
Langue détectée de SKILL.md
anglais
Étoiles
15
Forks
4

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
cross-asset-relationships
description
Cross-asset and quantitative analysis: pair correlations, correlation heatmaps, currency strength, cross-timeframe divergence, intermarket analysis, market breadth, carry trades, swap rates, risk premia, and multi-pair baskets. USE FOR: correlation, currency strength, intermarket, market breadth, carry trade, swap rate, risk premia, basket, pair trading, cross asset, quant.
related_skills
["market-intelligence","portfolio-optimization","forex-trading","risk-and-portfolio"]
tags
["trading","fundamentals","correlation","intermarket","carry-trade","cross-asset"]
skill_level
advanced
kind
reference
category
trading/market-context
status
active
> **Skill:** Cross Asset Relationships | **Domain:** trading | **Category:** fundamentals | **Level:** advanced > **Tags:** `trading`, `fundamentals`, `correlation`, `intermarket`, `carry-trade`, `cross-asset` --- ## Pair Correlation Engine # Pair Correlation Engine ## Overview Analyzes statistical relationships between financial instruments across multiple timeframes and historical periods. Detects regime shifts, divergences, lead-lag relationships, and provides actionable correlation intelligence for trading decisions. ## Architecture ``` ┌───────────────────────────────────────────────────┐ │ Pair Correlation Engine │ ├────────────┬─────────────┬────────────────────────┤ │ Correlation│ History vs │ Regime Detection & │ │ Matrix │ Current │ Divergence Scanner │ └────────────┴─────────────┴────────────────────────┘ ``` --- ## 1. Core Correlation Computation ```python import pandas as pd import numpy as np from scipy import stats from scipy.cluster.hierarchy import linkage, fcluster, dendrogram from typing import Optional from datetime import datetime, timedelta def compute_returns(prices: pd.DataFrame, method: str = "log") -> pd.DataFrame: """Convert price DataFrame to returns. Columns = symbols.""" if method == "log": return np.log(prices / prices.shift(1)).dropna() return prices.pct_change().dropna() def correlation_matrix( prices: pd.DataFrame, method: str = "pearson", window: Optional[int] = None ) -> pd.DataFrame: """ Full correlation matrix. method: pearson, spearman, kendall window: if set, uses last N bars only """ returns = compute_returns(prices) if window: returns = returns.tail(window) return returns.corr(method=method) def rolling_correlation( series_a: pd.Series, series_b: pd.Series, window: int = 60, method: str = "pearson" ) -> pd.Series: """Rolling window correlation between two series.""" ret_a = np.log(series_a / series_a.shift(1)).dropna() ret_b = np.log(series_b / series_b.shift(1)).dropna() aligned = pd.concat([ret_a, ret_b], axis=1).dropna() aligned.columns = ["a", "b"] return aligned["a"].rolling(window).corr(aligned["b"]) ``` --- ## 2. Historical vs Current Correlation (Core Feature) ```python def historical_vs_current( prices: pd.DataFrame, current_window: int = 30, historical_windows: list[int] = [90, 180, 365], method: str = "pearson" ) -> dict: """ Compare current correlation regime vs historical norms. Returns: {pair: {current, hist_90d, hist_180d, hist_365d, deviation, regime_shift}} """ returns = compute_returns(prices) symbols = returns.columns.tolist() results = {} for i, sym_a in enumerate(symbols): for sym_b in symbols[i + 1:]: pair_key = f"{sym_a}/{sym_b}" pair_data = returns[[sym_a, sym_b]].dropna() current_corr = pair_data.tail(current_window).corr().iloc[0, 1] hist_corrs = {} for w in historical_windows: if len(pair_data) >= w: hist_corrs[f"hist_{w}d"] = pair_data.tail(w).corr().iloc[0, 1] else: hist_corrs[f"hist_{w}d"] = np.nan # Compute deviation from longest available history longest_hist = next((hist_corrs[f"hist_{w}d"] for w in sorted(historical_windows, reverse=True) if not np.isnan(hist_corrs.get(f"hist_{w}d", np.nan))), np.nan) deviation = current_corr - longest_hist if not np.isnan(longest_hist) else 0 regime_shift = abs(deviation) > 0.3 # >0.3 = significant regime change results[pair_key] = { "current": round(current_corr, 4), **{k: round(v, 4) for k, v in hist_corrs.items()}, "deviation": round(deviation, 4), "regime_shift": regime_shift, "signal": _interpret_deviation(deviation), } return results def _interpret_deviation(dev: float) -> str: """Interpret correlation deviation into actionable signal.""" if abs(dev) < 0.1: return "STABLE — correlations normal" if dev > 0.3: return "CONVERGENCE — pairs moving together unusually strongly" if dev < -0.3: return "DIVERGENCE — pairs decoupling, watch for mean reversion" if dev > 0.1: return "STRENGTHENING — correlation increasing" return "WEAKENING — correlation decreasing" ``` --- ## 3. Divergence Detection ```python def detect_divergences( prices: pd.DataFrame, lookback: int = 60, threshold: float = 0.3 ) -> list[dict]: """ Find pairs that have recently diverged from their historical correlation. These are potential mean-reversion or trend-change signals. """ hvc = historical_vs_current(prices, current_window=lookback // 2) divergences = [] for pair, data in hvc.items(): if data["regime_shift"]: divergences.append({ "pair": pair, "current_corr": data["current"], "historical_corr": data.get("hist_365d", data.get("hist_180d", np.nan)), "deviation": data["deviation"], "type": "convergence_anomaly" if data["deviation"] > 0 else "divergence_anomaly", "signal": data["signal"], "priority": abs(data["deviation"]), }) return sorted(divergences, key=lambda x: x["priority"], reverse=True) def spread_analysis( price_a: pd.Series, price_b: pd.Series, window: int = 60 ) -> pd.DataFrame: """ Compute normalized spread between two series for pair trading. Z-score indicates mean-reversion opportunity. """ # Normalize both series to start at 1.0 norm_a = price_a / price_a.iloc[0] norm_b = price_b / price_b.iloc[0] spread = norm_a - norm_b z_score = (spread - spread.rolling(window).mean()) / spread.rolling(window).std() return pd.DataFrame({ "spread": spread, "z_score": z_score, "upper_band": spread.rolling(window).mean() + 2 * spread.rolling(window).std(), "lower_band": spread.rolling(window).mean() - 2 * spread.rolling(window).std(), }) ``` --- ## 4. Lead-Lag Analysis ```python def lead_lag_analysis( series_a: pd.Series, series_b: pd.Series, max_lag: int = 10 ) -> pd.DataFrame: """ Cross-correlation at different lags to detect if one pair leads another. Positive lag = A leads B. Negative lag = B leads A. """ ret_a = np.log(series_a / series_a.shift(1)).dropna() ret_b = np.log(series_b / series_b.shift(1)).dropna() aligned = pd.concat([ret_a, ret_b], axis=1).dropna() aligned.columns = ["a", "b"] results = [] for lag in range(-max_lag, max_lag + 1): if lag >= 0: corr = aligned["a"].iloc[lag:].reset_index(drop=True).corr(aligned["b"].iloc[:len(aligned) - lag].reset_index(drop=True)) else: corr = aligned["a"].iloc[:len(aligned) + lag].reset_index(drop=True).corr(aligned["b"].iloc[-lag:].reset_index(drop=True)) results.append({"lag": lag, "correlation": round(corr, 4)}) df = pd.DataFrame(results) best = df.loc[df["correlation"].abs().idxmax()] df.attrs["best_lag"] = int(best["lag"]) df.attrs["best_corr"] = float(best["correlation"]) df.attrs["interpretation"] = ( f"{'A leads B' if best['lag'] > 0 else 'B leads A' if best['lag'] < 0 else 'Synchronous'} " f"by {abs(int(best['lag']))} bars (r={best['correlation']:.4f})" ) return df ``` --- ## 5. Cluster Analysis — Group Correlated Pairs ```python def cluster_pairs( prices: pd.DataFrame, n_clusters: int = 4, method: str = "ward" ) -> dict: """ Hierarchical clustering of instruments by correlation. Returns cluster assignments and cluster statistics. """ corr = correlation_matrix(prices) distance = np.sqrt(2 * (1 - corr)) np.fill_diagonal(distance.values, 0) condensed = distance.values[np.triu_indices_from(distance.values, k=1)] Z = linkage(condensed, method=method) labels = fcluster(Z, t=n_clusters, criterion="maxclust") clusters = {} for sym, cluster_id in zip(corr.columns, labels): cid = int(cluster_id) if cid not in clusters: clusters[cid] = [] clusters[cid].append(sym) return { "n_clusters": n_clusters, "clusters": clusters, "linkage": Z, "assignments": dict(zip(corr.columns.tolist(), [int(l) for l in labels])), } def find_hedge_pairs( prices: pd.DataFrame, target_symbol: str, min_negative_corr: float = -0.5 ) -> list[dict]: """Find instruments negatively correlated to target — potential hedges.""" corr = correlation_matrix(prices) if target_symbol not in corr.columns: return [] target_corr = corr[target_symbol].drop(target_symbol).sort_values() hedges = [] for sym, c in target_corr.items(): if c <= min_negative_corr: hedges.append({"symbol": sym, "correlation": round(c, 4), "hedge_quality": "strong" if c < -0.7 else "moderate"}) return hedges ``` --- ## 6. Correlation Report Generator ```python def full_correlation_report( prices: pd.DataFrame, current_window: int = 30 ) -> dict: """ Complete correlation intelligence report. Pipe this to trading-brain for decision-making. """ return { "timestamp": datetime.utcnow().isoformat(), "symbols_analyzed": prices.columns.tolist(), "n_bars": len(prices), "current_matrix": correlation_matrix(prices, window=current_window).to_dict(), "historical_matrix": correlation_matrix(prices).to_dict(), "historical_vs_current": historical_vs_current(prices, current_window), "divergences": detect_divergences(prices), "clusters": cluster_pairs(prices), } ``` --- ## Usage Conventions 1. **Always use log returns** for correlation — more statistically stable than simple returns 2. **Check sample size** — need minimum 30 bars for meaningful correlation 3. **Multi-timeframe** — compute correlations on H1, H4, and D1 for robust signals 4. **Regime shifts > 0.3** are significant and should trigger alerts 5. **Lead-lag > 2 bars** with |r| > 0.3 is a potential predictive signal 6. **Correlation ≠ causation** — always note this in reports --- ## Correlation Heatmap Visualizer # Correlation Heatmap Visualizer ```python import pandas as pd, numpy as np, matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import io, base64 class CorrelationHeatmapVisualizer: @staticmethod def render(prices: pd.DataFrame, method: str = "pearson", window: int = None, save_path: str = None) -> str: returns = np.log(prices / prices.shift(1)).dropna() if window: returns = returns.tail(window) corr = returns.corr(method=method) fig, ax = plt.subplots(figsize=(12, 10), facecolor="#131722") ax.set_facecolor("#131722") im = ax.imshow(corr.values, cmap="RdYlGn", vmin=-1, vmax=1, aspect="auto") ax.set_xticks(range(len(corr.columns))); ax.set_yticks(range(len(corr.columns)))
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub