> ## 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.

# Cross-Exchange Arb

> Atomic cross-exchange arbitrage with auto-rollback, pipeline scanner, and one-shot sweep.

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

# Cross-Exchange Arbitrage

Buy on one exchange where the price is low, sell on another where it's high. Horizon's executor handles both legs atomically with auto-rollback on failure.

## How It Works

When the same market is priced differently across exchanges (e.g., Polymarket bid > Kalshi ask), you can buy on the cheap exchange and sell on the expensive one for risk-free profit.

```
Kalshi ask      = $0.48  (buy here)
Polymarket bid  = $0.52  (sell here)
Raw edge        = $0.04
Net edge        = $0.04 - fees
```

## Engine Methods

### scan\_arbitrage

```python theme={null}
opps = engine.scan_arbitrage(
    "election-winner",
    [("polymarket", "polymarket", 0.002), ("kalshi", "kalshi", 0.002)],
    max_liquidity=100.0,
)
```

The tuple format is `(feed_name, exchange_name, fee_rate)`.

### execute\_arbitrage

```python theme={null}
buy_id, sell_id = engine.execute_arbitrage(
    market_id="election-winner",
    buy_exchange="kalshi",
    sell_exchange="polymarket",
    buy_price=0.48,
    sell_price=0.52,
    size=10.0,
)
```

**Behavior:**

1. Both legs go through the full risk pipeline
2. Orders use Fill-Or-Kill (FOK) time-in-force
3. If the buy succeeds but the sell fails, the buy is automatically canceled
4. Returns `(buy_order_id, sell_order_id)` on success

## Pipeline: arb\_scanner

```python theme={null}
scanner = hz.arb_scanner(
    market_id="election-winner",
    exchanges=["polymarket", "kalshi"],
    feed_map={"polymarket": "polymarket", "kalshi": "kalshi"},
    min_edge=0.02,
    auto_execute=True,
    cooldown=10.0,
)

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

| Parameter      | Type                       | Default  | Description                |
| -------------- | -------------------------- | -------- | -------------------------- |
| `market_id`    | `str`                      | required | Market to scan             |
| `exchanges`    | `list[str]`                | required | Exchanges to compare       |
| `feed_map`     | `dict[str, str]`           | required | Exchange name -> feed name |
| `min_edge`     | `float`                    | `0.01`   | Minimum net edge           |
| `max_size`     | `float`                    | `50.0`   | Max execution size         |
| `fee_rates`    | `dict[str, float] or None` | `None`   | Fee rates per exchange     |
| `auto_execute` | `bool`                     | `False`  | Auto-execute               |
| `cooldown`     | `float`                    | `5.0`    | Seconds between executions |

Stores `ArbResult` in `ctx.params["last_arb"]` on execution.

## One-Shot: arb\_sweep

```python theme={null}
result = hz.arb_sweep(
    engine=engine,
    market_id="election-winner",
    feed_map={"polymarket": "polymarket", "kalshi": "kalshi"},
    min_edge=0.01,
)
```

Returns `ArbResult` or `None`.

## Example: Full Cross-Exchange Bot

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

scanner = hz.arb_scanner(
    market_id="election-winner",
    exchanges=["polymarket", "kalshi"],
    feed_map={"polymarket": "polymarket", "kalshi": "kalshi"},
    min_edge=0.02,
    auto_execute=True,
    cooldown=10.0,
)

hz.run(
    name="cross_exchange_arb",
    exchanges=[
        hz.Polymarket(private_key="0x..."),
        hz.Kalshi(api_key="..."),
    ],
    markets=["election-winner"],
    feeds={
        "polymarket": hz.PolymarketBook("election-winner"),
        "kalshi": hz.KalshiBook("KXELECTION-25"),
    },
    pipeline=[scanner],
    interval=0.5,
)
```

<Warning>
  Cross-exchange arb requires active accounts on both exchanges with sufficient margin. The atomic rollback only cancels the buy leg. It cannot guarantee cancel success if the order was already filled.
</Warning>
