> ## Documentation Index
> Fetch the complete documentation index at: https://mathematicalcompany.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Spread Convergence

> Mean-reversion trading between two correlated prediction markets.

<Note>
  **Pro Feature.** Requires a Pro or Ultra subscription. [Get started at api.mathematicalcompany.com](https://api.mathematicalcompany.com)
</Note>

# Spread Convergence

Track the price spread between two correlated markets. Enter when the spread deviates beyond a z-score threshold, exit when it reverts to the mean.

## How It Works

1. Compute `spread = price_a - price_b` each cycle
2. Maintain a rolling window of spread values
3. Compute z-score of current spread vs historical mean/std
4. Enter when `|z| > entry_zscore`, exit when `|z| < exit_zscore`

```
Spread history: mean=0.02, std=0.01
Current spread: 0.05 → z-score = 3.0
Signal: long_b_short_a (spread too high, expect reversion)
```

## Pipeline: spread\_convergence

```python theme={null}
scanner = hz.spread_convergence(
    market_a="btc-100k",
    market_b="eth-5k",
    feed_a="btc_feed",
    feed_b="eth_feed",
    lookback=100,
    entry_zscore=2.0,
    exit_zscore=0.5,
    max_spread=0.20,
    size=10.0,
    auto_execute=False,
    cooldown=30.0,
)

hz.run(pipeline=[scanner], ...)
```

| Parameter      | Type    | Default  | Description                           |
| -------------- | ------- | -------- | ------------------------------------- |
| `market_a`     | `str`   | required | First market ID                       |
| `market_b`     | `str`   | required | Second market ID                      |
| `feed_a`       | `str`   | required | Feed for market A                     |
| `feed_b`       | `str`   | required | Feed for market B                     |
| `lookback`     | `int`   | `100`    | Rolling window size                   |
| `entry_zscore` | `float` | `2.0`    | Z-score to enter                      |
| `exit_zscore`  | `float` | `0.5`    | Z-score to exit                       |
| `max_spread`   | `float` | `0.20`   | Max absolute spread to consider valid |
| `size`         | `float` | `10.0`   | Trade size per leg                    |
| `auto_execute` | `bool`  | `False`  | Auto-execute signals                  |
| `cooldown`     | `float` | `30.0`   | Seconds between trades                |

## SpreadSignal

Stored in `ctx.params["last_spread_signal"]`.

| Field         | Type    | Description                                                   |
| ------------- | ------- | ------------------------------------------------------------- |
| `market_a`    | `str`   | First market                                                  |
| `market_b`    | `str`   | Second market                                                 |
| `spread`      | `float` | Current spread value                                          |
| `spread_mean` | `float` | Rolling mean                                                  |
| `spread_std`  | `float` | Rolling standard deviation                                    |
| `zscore`      | `float` | Current z-score                                               |
| `signal`      | `str`   | `"long_a_short_b"`, `"long_b_short_a"`, `"exit"`, or `"hold"` |

## Signal Logic

| Condition           | Position | Signal            |            |        |
| ------------------- | -------- | ----------------- | ---------- | ------ |
| `z > entry_zscore`  | flat     | `long_b_short_a`  |            |        |
| `z < -entry_zscore` | flat     | `long_a_short_b`  |            |        |
| \`                  | z        | \< exit\_zscore\` | positioned | `exit` |
| otherwise           | any      | `hold`            |            |        |

## Example

```python theme={null}
import horizon as hz

# Spread trade between two correlated political markets
spread = hz.spread_convergence(
    market_a="gop-senate",
    market_b="gop-house",
    feed_a="gop_senate_feed",
    feed_b="gop_house_feed",
    lookback=200,
    entry_zscore=2.5,
    exit_zscore=0.3,
    auto_execute=True,
)

hz.run(
    name="spread_trader",
    exchanges=[hz.Polymarket(private_key="0x...")],
    markets=["gop-senate", "gop-house"],
    feeds={
        "gop_senate_feed": hz.PolymarketBook("gop-senate"),
        "gop_house_feed": hz.PolymarketBook("gop-house"),
    },
    pipeline=[spread],
    interval=1.0,
)
```

<Note>
  For more rigorous pairs trading with cointegration testing and half-life filtering, see [Statistical Arb](/arbitrage/stat-arb).
</Note>
