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

# Horizon + Interactive Brokers

> Trade stocks, options, futures, and ForecastEx event contracts on Interactive Brokers.

<Note>
  **Partially verified.** As of v0.8.8+, the IBKR client has been audited against
  the official Client Portal Web API documentation. Significant fixes were applied:

  * Removed the fabricated `paper-api.ibkr.com` host. IBKR paper accounts share the
    same `api.ibkr.com` host as live accounts; the distinction is in the account ID
    prefix (`DU*` for paper). Pass your `DU…` account ID, not a `paper=True` flag.
  * Positions endpoint now includes the required `{pageId}` path segment and walks
    pages until the result set is exhausted (was returning 404 / nothing before).
  * Order submission now handles **chained** confirmation prompts (up to 5 hops).
    Previously the second prompt's reply id was silently returned as the order id,
    corrupting downstream tracking.
  * `cancel_all` and fill polling now filter results by `account_id`. Previously
    they touched orders/trades across **every** account on the session — dangerous
    on Financial Advisor or multi-account logins.
  * Commission strings like `"1.00 USD"` parse correctly (was silently zeroing fees).
  * Timestamps now read `trade_time_r` (epoch ms) — was returning `0.0` for every fill.
  * Contract multiplier is inferred from `secType` (`OPT`/`FOP` → 100x). Options PnL
    was previously off by 100x.
  * On 401, the client calls `/iserver/auth/ssodh/init` (which actually re-establishes
    the brokerage session) instead of just `/tickle` (which only keeps it alive).
  * `acctId` is now included in the order body for FA / multi-account safety.

  **Authentication:** Bearer token must come from one of three IBKR auth flows:

  1. The `private_key_jwt` SSO bearer (mint a short-lived JWT via the OAuth 2.0
     client-credentials handshake; refresh out-of-band before expiry).
  2. A local Client Portal Gateway running at `https://localhost:5000/v1/api`
     (pass the gateway URL via `api_url=` and any non-empty placeholder token).
  3. An OAuth 1.0a HMAC-SHA256 signer running as a sidecar that mints session
     bearers; this client does NOT implement OAuth 1.0a signing itself.

  These fixes have not been live-tested against a real IBKR account. Use paper
  (`DU*`) or small size first. Polymarket remains the only exchange with
  end-to-end verified live trading.
</Note>

[Interactive Brokers](https://www.interactivebrokers.com) (IBKR) is a multi-asset broker supporting stocks, options, futures, forex, and **ForecastEx event contracts** (IBKR's prediction market). Horizon connects to IBKR's Client Portal API for both traditional asset hedging and event contract trading.

## Quick Setup

```python theme={null}
hz.run(
    name="ibkr_strategy",
    exchange=hz.InteractiveBrokers(
        access_token="...",
        account_id="U1234567",
    ),
    mode="live",
    ...
)
```

## Credentials

<Tabs>
  <Tab title="Explicit">
    ```python theme={null}
    hz.InteractiveBrokers(
        access_token="eyJ0eXAi...",
        account_id="U1234567",
    )
    ```
  </Tab>

  <Tab title="Environment variables">
    ```bash theme={null}
    export IBKR_ACCESS_TOKEN="eyJ0eXAi..."
    export IBKR_ACCOUNT_ID="U1234567"
    ```

    ```python theme={null}
    hz.InteractiveBrokers()  # reads from env
    ```
  </Tab>
</Tabs>

## Configuration

```python theme={null}
@dataclass
class InteractiveBrokers:
    access_token: str | None = None
    account_id: str | None = None
    paper: bool = True
    api_url: str | None = None
```

| Field          | Default | Description                                                 |
| -------------- | ------- | ----------------------------------------------------------- |
| `access_token` | `None`  | OAuth2 access token (env: `IBKR_ACCESS_TOKEN`)              |
| `account_id`   | `None`  | IBKR account ID, e.g. `"U1234567"` (env: `IBKR_ACCOUNT_ID`) |
| `paper`        | `True`  | Use paper trading URL                                       |
| `api_url`      | Auto    | Override API URL (set automatically from `paper` flag)      |

## Paper vs Live

```python theme={null}
# Paper trading (default)
hz.InteractiveBrokers(paper=True)   # https://paper-api.ibkr.com/v1/api

# Live trading
hz.InteractiveBrokers(paper=False)  # https://api.ibkr.com/v1/api
```

<Tip>
  IBKR paper accounts are full-featured simulations. Test your strategy thoroughly before switching to live.
</Tip>

## Authentication

IBKR uses OAuth2 Bearer token auth via the Client Portal API:

* `Authorization: Bearer {access_token}`

The token is obtained through IBKR's OAuth2 flow. Session keepalive is handled automatically.

## Market Data Feed

IBKR market data via REST snapshot polling:

```python theme={null}
hz.run(
    feeds={
        "aapl": hz.IBKRFeed(conids=["265598"]),            # AAPL
        "stocks": hz.IBKRFeed(conids=["265598", "8314"]),   # AAPL + SPY
    },
    ...
)
```

The feed polls IBKR's market data snapshot endpoint for each conid at the configured interval.

| Field          | Type        | Default  | Description                                 |
| -------------- | ----------- | -------- | ------------------------------------------- |
| `conids`       | `list[str]` | required | IBKR contract IDs to poll                   |
| `access_token` | `str`       | `None`   | Override access token (defaults to env var) |
| `api_url`      | `str`       | Auto     | Override API URL                            |
| `paper`        | `bool`      | `True`   | Use paper trading URL                       |
| `interval`     | `float`     | `5.0`    | Polling interval in seconds                 |

## ForecastEx Event Contracts

IBKR's **ForecastEx** is a CFTC-regulated event contracts platform, similar to Polymarket and Kalshi. You can trade event contracts on economics, elections, and more directly through the same `InteractiveBrokers` exchange.

```python theme={null}
# Trade ForecastEx event contracts through the same exchange
hz.run(
    name="forecastex_mm",
    exchange=hz.InteractiveBrokers(),
    markets=[
        hz.Market(id="690123456", name="Fed Rate Cut March"),  # ForecastEx conid
    ],
    feeds={
        "fed_event": hz.IBKRFeed(conids=["690123456"]),
    },
    pipeline=[my_strategy],
)
```

<Note>
  ForecastEx contracts use IBKR conids just like stocks and options. Look up conids in the IBKR contract search or TWS.
</Note>

## Symbol Mapping

IBKR uses integer contract IDs (conids):

```python theme={null}
# Look up conids in TWS or IBKR's contract search
market = hz.Market(id="265598", name="AAPL")  # Apple stock
market = hz.Market(id="8314", name="SPY")     # S&P 500 ETF
```

| Horizon Field             | IBKR Field | Notes                         |
| ------------------------- | ---------- | ----------------------------- |
| `OrderRequest.market_id`  | `conid`    | Integer contract ID as string |
| `OrderRequest.order_side` | `side`     | `"BUY"` or `"SELL"`           |
| `OrderRequest.price`      | `price`    | Limit order price             |
| `OrderRequest.size`       | `quantity` | Number of shares/contracts    |

<Note>
  IBKR uses `Side.Long` for stock and option positions. Prediction market concepts like `Side.Yes` / `Side.No` only apply to ForecastEx event contracts.
</Note>

## Multi-Exchange

Use IBKR for stock/options hedging alongside prediction markets:

```python theme={null}
hz.run(
    name="full_hedge",
    exchange=[
        hz.Polymarket(),           # prediction market
        hz.InteractiveBrokers(),   # stocks + options hedge
    ],
    feeds={
        "election": hz.PolymarketBook("presidential-election"),
        "spy": hz.IBKRFeed(conids=["8314"]),
    },
    pipeline=[
        hz.stock_hedge(hz.HedgeConfig(
            prediction_feed="election",
            stock_feed="spy",
            stock_symbol="8314",
            auto_rebalance=True,
        )),
        my_strategy,
    ],
)
```

## Getting API Keys

1. Log in at [interactivebrokers.com](https://www.interactivebrokers.com)
2. Navigate to **Settings** > **API** > **OAuth2**
3. Register a client application and obtain an access token
4. Note your account ID from the top of any account page (format: `U1234567`)
5. For paper trading, create a paper account under **Account Management**
