Horizon supports ten exchange backends that all implement the sameDocumentation Index
Fetch the complete documentation index at: https://mathematicalcompany.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Exchange trait. You can trade on a single exchange or multiple exchanges simultaneously.
Verification Status
Different exchanges have received different levels of audit. Verification status below reflects how rigorously each backend has been compared against its reference implementation or live API behavior.| Exchange | Status | Notes |
|---|---|---|
| Paper | β Verified | In-process simulation, exhaustively unit-tested |
| Polymarket | β Verified | Byte-for-byte HMAC parity with py_clob_client (regression-tested), live API endpoints confirmed, EOA + Gnosis Safe both supported |
| Hyperliquid | π‘ Fixes pushed | msgpack ordering, cloid format, spot offset, error handling, cancelByCloid all fixed in v0.8.7. Needs live verification. |
| Kalshi | π‘ Fixes pushed | Modern host + RSA-PSS auth + fixed-point dollar field format in v0.8.7. Needs live verification. |
| Coinbase | π‘ Fixes pushed | ES256 JWT auth + correct list-orders endpoint in v0.8.7. Needs live verification. |
| Limitless | π‘ Fixes pushed | Polymarket fork β same salt/field name fixes applied in v0.8.7. Needs live verification. |
| Alpaca | π‘ Fixes pushed | v0.8.8: switched fill polling to /v2/account/activities/FILL (the previous /v2/orders?status=filled query was invalid and never returned fills). Added client_order_id for idempotent retries, fixed limit-price formatter to preserve precision for sub-dollar stocks, added Day TIF, signed-qty parsing for short positions, per-order status check on cancel-all. Needs live verification. |
| IBKR | π‘ Fixes pushed | v0.8.8: dropped fabricated paper-api.ibkr.com host (paper accounts use the same host), fixed positions endpoint to include the required {pageId} segment, added multi-step order-confirmation loop, account-id filtering on cancel_all and fill polling (was previously cross-account), commission string parsing ("1.00 USD"), epoch-ms timestamp via trade_time_r, contract multiplier inference for options, /iserver/auth/ssodh/init on session timeout, acctId in order body. Needs live verification β and remember the bearer token must come from IBKRβs private_key_jwt SSO flow or a local Client Portal Gateway. |
| Robinhood | β Unverified | Code paths exist, never byte-for-byte audited (Bearer token may need replacement with Ed25519 for newer Crypto API) |
Prediction Markets
Paper
Local simulated exchange with tick-based matching. No credentials needed. Default for development.
Polymarket
Largest prediction market on Polygon. EIP-712 signed orders via the CLOB API.
Kalshi
US-regulated (CFTC) prediction market. REST API with bearer token auth.
Limitless
Base chain prediction market. REST client for on-chain trading.
Traditional & Crypto
Alpaca
Commission-free stock and ETF trading. Paper and live modes.
Coinbase
Crypto exchange with deep liquidity. HMAC-SHA256 auth via Advanced Trade API.
Robinhood
Commission-free crypto trading via REST API.
Hyperliquid
Decentralized perpetuals + spot on its own L1 chain. Wallet-based EIP-712 auth.
Interactive Brokers
Multi-asset broker: stocks, options, futures, and ForecastEx prediction markets. Bridges equities/options and prediction market trading.
Exchange Model
All exchanges implement a common trait:ExchangeBackend enum for dispatch without trait objects:
Single vs Multi-Exchange
Single exchange (default)
Multi-exchange
Fill Model
All exchanges use a pull model for fills:| Exchange | Fill Source | Method |
|---|---|---|
| Paper | tick(market_id, mid_price) | Matches orders against mid price |
| Polymarket | drain_fills() β poll_fills_async() | Polls /trades endpoint |
| Kalshi | drain_fills() β poll_fills_async() | Polls /portfolio/fills endpoint |
| Alpaca | drain_fills() β poll_fills_async() | Polls /v2/orders?status=filled |
| Coinbase | drain_fills() β poll_fills_async() | Polls /orders/historical/fills |
| Robinhood | drain_fills() β poll_fills_async() | Polls /crypto/trading/orders/?status=filled |
| IBKR | drain_fills() β poll_fills_async() | Polls /iserver/account/trades |
| Hyperliquid | drain_fills() β poll_fills_async() | Polls /info with userFillsByTime |
poll_fills() each cycle for live exchanges, and tick() for paper exchanges.
Order Routing
When you submit an order viahz.run(), itβs automatically routed to the correct exchange based on the market.exchange field:
- Markets resolved as
"polymarket"β routed to the Polymarket backend - Markets resolved as
"kalshi"β routed to the Kalshi backend - Markets with
"alpaca"β routed to the Alpaca backend - Markets with
"ibkr"β routed to the IBKR backend - Markets with
"coinbase"β routed to the Coinbase backend - Markets with
"robinhood"β routed to the Robinhood backend - Markets with
"hyperliquid"β routed to the Hyperliquid backend - Markets with
"paper"or empty exchange β routed to the primary exchange
Side Mapping
| Exchange | Side Used | Notes |
|---|---|---|
| Polymarket | Side.Yes / Side.No | Binary prediction contracts |
| Kalshi | Side.Yes / Side.No | Binary prediction contracts |
| Limitless | Side.Yes / Side.No | Binary prediction contracts |
| Alpaca | Side.Long | Equities β no Yes/No concept |
| Coinbase | Side.Long | Crypto β no Yes/No concept |
| Hyperliquid | Side.Long | Perps/spot β no Yes/No concept |
| Robinhood | Side.Long | Crypto β no Yes/No concept |
| IBKR | Side.Long | Multi-asset β no Yes/No concept |
| Paper | Any | Copies the side from the order request |
Exchange Fields on Types
Orders, Fills, and Positions all carry anexchange field indicating which exchange they belong to: