---
title: "Synthetic Index"
description: "Construct custom indices from prediction market prices. Equal, inverse-vol, and liquidity weighting. Rebalancing signals and index arbitrage detection."
icon: "chart-pie"
---

<Warning>
  **Ultra Feature.** Requires an Ultra subscription. [Get started at api.mathematicalcompany.com](https://api.mathematicalcompany.com)
</Warning>

# 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

<CardGroup cols={2}>
  <Card title="Index Construction" icon="chart-line">
    `hz.compute_index_level()` computes a weighted index from component prices.
  </Card>
  <Card title="Weighting Methods" icon="scale-balanced">
    Equal, inverse-vol, liquidity, or custom weight schemes.
  </Card>
  <Card title="Rebalancing" icon="arrows-rotate">
    `hz.rebalance_weights()` calculates drift and rebalance actions.
  </Card>
  <Card title="Index Arbitrage" icon="magnifying-glass-dollar">
    `hz.index_arb_signal()` detects deviations between index and components.
  </Card>
</CardGroup>

---

## Core Functions

### hz.compute_index_level

Compute a weighted index level from component prices.

```python
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}")
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `prices` | `list[float]` | required | Component prices |
| `weights` | `list[float]` | required | Component weights (should sum to ~1.0) |
| `base_level` | `float` | `100.0` | Base index level |

### hz.compute_weights_equal / inverse_vol / liquidity

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

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

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

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

```python
idx = hz.index(
    market_feeds={"btc_100k": "btc_feed", "eth_10k": "eth_feed", "sol_500": "sol_feed"},
    weighting="inverse_vol",
    base_level=100.0,
)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `config` | `IndexConfig` | `None` | Full index configuration |
| `market_feeds` | `dict[str, str]` | `None` | market_id -> feed_name mapping |
| `weighting` | `str` | `"equal"` | `equal`, `inverse_vol`, `liquidity`, or `custom` |
| `base_level` | `float` | `100.0` | Base index level |

### hz.track_index

Track index weights and signal when rebalancing is needed.

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

```python
arb = hz.index_arb(
    market_feeds={"btc": "btc_feed", "eth": "eth_feed"},
    threshold=0.02,
)
```

---

## Examples

### Custom Prediction Market Index

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

```python
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,
    ],
)
```
