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

Synthetic Index

There is no S&P 500 for prediction markets. Horizon’s index module lets you build one. Combine multiple markets into a weighted index, track rebalancing drift, and detect arbitrage between the index level and its components. All math is in Rust.

Overview

Index Construction

hz.compute_index_level() computes a weighted index from component prices.

Weighting Methods

Equal, inverse-vol, liquidity, or custom weight schemes.

Rebalancing

hz.rebalance_weights() calculates drift and rebalance actions.

Index Arbitrage

hz.index_arb_signal() detects deviations between index and components.

Core Functions

hz.compute_index_level

Compute a weighted index level from component prices.
import horizon as hz

level = hz.compute_index_level(
    prices=[0.55, 0.60, 0.45],
    weights=[0.333, 0.333, 0.333],
    base_level=100.0,
)
print(f"Index: {level.level:.2f}")
print(f"Components: {level.num_components}")
ParameterTypeDefaultDescription
priceslist[float]requiredComponent prices
weightslist[float]requiredComponent weights (should sum to ~1.0)
base_levelfloat100.0Base index level

hz.compute_weights_equal / inverse_vol / liquidity

weights = hz.compute_weights_equal(3)           # [0.333, 0.333, 0.333]
weights = hz.compute_weights_inverse_vol([0.1, 0.2, 0.3])  # lower vol = higher weight
weights = hz.compute_weights_liquidity([1000, 500, 200])    # higher volume = higher weight

hz.rebalance_weights

Calculate delta between current and target weights.
actions = hz.rebalance_weights(
    market_ids=["A", "B", "C"],
    current_weights=[0.40, 0.35, 0.25],
    target_weights=[0.333, 0.333, 0.333],
)
for a in actions:
    print(f"{a.market_id}: delta={a.delta:+.3f}")

hz.index_tracking_error

Tracking error between a portfolio and an index.
te = hz.index_tracking_error(
    portfolio_returns=[0.01, -0.02, 0.015],
    index_returns=[0.012, -0.018, 0.014],
)
print(f"Tracking error: {te:.4f}")

hz.index_arb_signal

Detect deviation between the index level and its fair value from components.
signal = hz.index_arb_signal(
    index_level=102.0,
    component_prices=[0.55, 0.60, 0.45],
    weights=[0.333, 0.333, 0.333],
    threshold=0.02,
)
print(f"Signal: {signal.signal_strength:.4f}")
print(f"Deviation: {signal.deviation:.4f}")

Pipeline Functions

hz.index

Compute and track a synthetic index level each cycle.
idx = hz.index(
    market_feeds={"btc_100k": "btc_feed", "eth_10k": "eth_feed", "sol_500": "sol_feed"},
    weighting="inverse_vol",
    base_level=100.0,
)
ParameterTypeDefaultDescription
configIndexConfigNoneFull index configuration
market_feedsdict[str, str]Nonemarket_id -> feed_name mapping
weightingstr"equal"equal, inverse_vol, liquidity, or custom
base_levelfloat100.0Base index level

hz.track_index

Track index weights and signal when rebalancing is needed.
tracker = hz.track_index(
    market_feeds={"btc": "btc_feed", "eth": "eth_feed"},
    rebalance_threshold=0.05,
)

hz.index_arb

Detect arbitrage opportunities between the index and its components.
arb = hz.index_arb(
    market_feeds={"btc": "btc_feed", "eth": "eth_feed"},
    threshold=0.02,
)

Examples

Custom Prediction Market Index

import horizon as hz

hz.run(
    name="crypto_prediction_index",
    feeds={
        "btc_100k": hz.PolymarketBook("will-btc-hit-100k"),
        "eth_10k": hz.PolymarketBook("will-eth-hit-10k"),
        "sol_500": hz.PolymarketBook("will-sol-hit-500"),
    },
    pipeline=[
        hz.index(
            market_feeds={
                "btc_100k": "btc_100k",
                "eth_10k": "eth_10k",
                "sol_500": "sol_500",
            },
            weighting="inverse_vol",
        ),
    ],
)

Index Arbitrage Strategy

import horizon as hz

def arb_strategy(ctx):
    signal = ctx.params.get("arb_signal", 0.0)
    if abs(signal) < 0.02:
        return []
    # Trade the deviation
    side = "buy" if signal > 0 else "sell"
    return [hz.order(side=side, size=10, price=ctx.feed.price)]

hz.run(
    name="index_arb_trader",
    feeds={...},
    pipeline=[
        hz.index_arb(market_feeds={...}, threshold=0.02),
        arb_strategy,
    ],
)