Skip to main content
Ultra Feature. Requires an Ultra subscription. Get started at api.mathematicalcompany.com

Correlation Regime

Markets that were uncorrelated yesterday can suddenly move in lockstep during a crisis. Horizon’s correlation regime module tracks live pairwise correlations, detects regime shifts via z-score analysis, scores contagion risk, and finds the most decorrelated markets for diversification. All math is in Rust with O(1) incremental updates.

Overview

Live Correlation Matrix

hz.live_correlation_matrix() computes pairwise correlations across markets.

Regime Shift Detection

hz.detect_regime_shift() flags when correlations break from historical norms.

Contagion Scoring

hz.contagion_score() identifies which markets would drag others with them.

Decorrelation Finder

hz.find_decorrelated() ranks markets by diversification value.

Core Functions

hz.live_correlation_matrix

Compute all pairwise Pearson correlations from return series.
import horizon as hz

entries = hz.live_correlation_matrix(
    market_ids=["btc", "eth", "fed_rate"],
    returns_matrix=[btc_returns, eth_returns, fed_returns],
)
for e in entries:
    print(f"{e.market_a} / {e.market_b}: {e.correlation:.4f} (n={e.num_observations})")
ParameterTypeDescription
market_idslist[str]Market identifiers
returns_matrixlist[list[float]]Return series for each market
Returns a list of CorrelationEntry objects (one per pair).

hz.detect_regime_shift

Compare historical correlation distribution to recent window using z-score.
result = hz.detect_regime_shift(
    historical_correlations=[0.3, 0.35, 0.28, 0.32, 0.31],
    recent_correlations=[0.8, 0.85, 0.9],
    threshold=2.0,
)
if result.shifted:
    print(f"Regime shift detected! Confidence: {result.confidence:.2f}")
    print(f"Old mean: {result.old_mean_corr:.4f} -> New mean: {result.new_mean_corr:.4f}")
ParameterTypeDefaultDescription
historical_correlationslist[float]requiredHistorical correlation values
recent_correlationslist[float]requiredRecent correlation values
thresholdfloat2.0Z-score threshold for shift detection

hz.contagion_score

Score how much a source market would drag others with it.
alert = hz.contagion_score(
    source_market="btc",
    market_ids=["btc", "eth", "sol"],
    correlations=[1.0, 0.85, 0.3],
    price_changes=[0.05, 0.04, 0.01],
    threshold=0.5,
)
print(f"Contagion score: {alert.contagion_score:.4f}")
print(f"Affected: {alert.affected_markets}")
ParameterTypeDescription
source_marketstrMarket to analyze as contagion source
market_idslist[str]All market identifiers
correlationslist[float]Correlation of each market to the source
price_changeslist[float]Recent price changes
thresholdfloatMinimum correlation to count as affected

hz.find_decorrelated

Rank markets by diversification value (low average correlation).
results = hz.find_decorrelated(
    market_ids=["btc", "eth", "fed_rate", "weather"],
    returns_matrix=[...],
    top_n=3,
)
for r in results:
    print(f"{r.market_id}: avg_corr={r.avg_correlation:.4f}, div_score={r.diversification_score:.4f}")

hz.incremental_correlation_update

O(1) single-pass correlation update. Maintain running statistics without recomputing from scratch.
n, sx, sy, sxy, sx2, sy2, corr = hz.incremental_correlation_update(
    n=0, sum_x=0.0, sum_y=0.0,
    sum_xy=0.0, sum_x2=0.0, sum_y2=0.0,
    new_x=1.0, new_y=2.0,
)
print(f"Running correlation after {n} points: {corr:.4f}")

Pipeline Functions

hz.correlation_matrix

Track live correlations across feeds each cycle.
corr = hz.correlation_matrix(
    feed_names=["btc", "eth", "sol", "fed_rate"],
    window=50,
)
ParameterTypeDefaultDescription
feed_nameslist[str]requiredFeed names to track
windowint50Rolling window size

hz.regime_shift

Detect correlation regime shifts.
shift = hz.regime_shift(
    feed_names=["btc", "eth"],
    lookback=100,
    recent_window=20,
    threshold=2.0,
)

hz.contagion_alert

Monitor for contagion risk across markets.
alert = hz.contagion_alert(
    feed_names=["btc", "eth", "sol"],
    correlation_threshold=0.5,
    window=50,
)

hz.decorrelation_finder

Find the most decorrelated markets for portfolio diversification.
finder = hz.decorrelation_finder(
    feed_names=["btc", "eth", "sol", "fed_rate", "weather"],
    top_n=3,
    window=50,
)

Examples

Correlation-Aware Portfolio

import horizon as hz

def portfolio_strategy(ctx):
    alerts = ctx.params.get("alerts", [])
    if any(a["score"] > 0.8 for a in alerts):
        return []  # high contagion risk, stand aside
    return hz.quotes(fair=ctx.feed.price, spread=0.03, size=10)

hz.run(
    name="corr_aware",
    feeds={
        "btc": hz.PolymarketBook("will-btc-hit-100k"),
        "eth": hz.PolymarketBook("will-eth-hit-10k"),
    },
    pipeline=[
        hz.contagion_alert(feed_names=["btc", "eth"], correlation_threshold=0.5),
        portfolio_strategy,
    ],
)

Mathematical Background

For two return series X and Y:r = [nSXY - SXSY] / sqrt([nSX2 - SX^2] * [nSY2 - SY^2])Where SX, SY are sums, SXY is sum of products, SX2, SY2 are sums of squares. The incremental update adds one (x, y) pair and recomputes in O(1).
Compares the mean of recent correlations to the historical distribution:z = (mean_recent - mean_historical) / std_historicalIf |z| exceeds the threshold (default 2.0), a regime shift is flagged. The confidence score equals the z-value.
For a source market, contagion score is the correlation-weighted sum of absolute price changes across affected markets (those with correlation above the threshold).