> ## 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 + Kalshi

> Trade on Kalshi with Horizon, a US-regulated (CFTC) prediction market.

<Note>
  **Partially verified.** As of v0.8.7+, Kalshi now targets the modern host
  (`api.elections.kalshi.com`) and uses RSA-PSS API key authentication. Pass
  the key ID as `api_key` and the PEM-encoded private key as `password` on
  the `Kalshi(...)` config. Order, cancel, fill polling, and position fetching
  have been updated for the new fixed-point dollar string field format. Has
  not been tested against a live Kalshi account, so verify the behavior
  matches expectations before deploying significant size.
</Note>

[Kalshi](https://kalshi.com) is a CFTC-regulated prediction market in the United States. Horizon supports the Kalshi REST API with bearer token authentication and automatic retry on 401.

## Quick Setup

```python theme={null}
hz.run(
    name="kalshi_mm",
    exchange=hz.Kalshi(api_key="..."),
    mode="live",
    ...
)
```

## Credentials

<Tabs>
  <Tab title="API key">
    ```python theme={null}
    hz.Kalshi(api_key="your_api_key")
    ```
  </Tab>

  <Tab title="Email / password">
    ```python theme={null}
    hz.Kalshi(email="you@example.com", password="...")
    ```
  </Tab>

  <Tab title="Environment variables">
    ```bash theme={null}
    export KALSHI_API_KEY="..."
    # or
    export KALSHI_EMAIL="..."
    export KALSHI_PASSWORD="..."
    ```

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

## Kalshi Configuration

```python theme={null}
@dataclass
class Kalshi:
    email: str | None = None
    password: str | None = None
    api_key: str | None = None
    api_url: str = "https://trading-api.kalshi.com/trade-api/v2"
```

| Field      | Default                                       | Description                |
| ---------- | --------------------------------------------- | -------------------------- |
| `email`    | `None`                                        | Kalshi account email       |
| `password` | `None`                                        | Kalshi account password    |
| `api_key`  | `None`                                        | Kalshi API key (preferred) |
| `api_url`  | `https://trading-api.kalshi.com/trade-api/v2` | API base URL               |

## Demo Environment

Kalshi provides a demo environment for testing:

```python theme={null}
hz.Kalshi(
    api_key="...",
    api_url="https://demo-api.kalshi.co/trade-api/v2",
)
```

<Tip>
  Use the demo environment to test your strategy with real market data but fake money. You can also override the URL via the `KALSHI_API_URL` environment variable.
</Tip>

## Ticker Mapping

Kalshi markets use **tickers** (e.g., `KXBTC-25FEB16`) instead of slugs. When `mode="live"`, Horizon automatically sets the ticker from the market ID:

```python theme={null}
# Market ID is used as the ticker (uppercased)
hz.run(markets=["KXBTC-25FEB16"], ...)
```

Or set it explicitly:

```python theme={null}
market = hz.Market(
    id="btc-100k",
    ticker="KXBTC-25FEB16",
    exchange="kalshi",
)
```

## Side Mapping

Kalshi uses two separate concepts for order direction:

| Concept    | Values         | Description                                    |
| ---------- | -------------- | ---------------------------------------------- |
| **action** | `buy` / `sell` | Whether you're buying or selling (`OrderSide`) |
| **side**   | `yes` / `no`   | Which outcome you're trading (`Side`)          |

This means "buy yes", "sell yes", "buy no", and "sell no" are all valid combinations.

## Authentication

Kalshi uses **bearer token** authentication:

1. On first request, the client authenticates with API key (or email/password)
2. Receives a bearer token
3. Token is included in subsequent requests via `Authorization: Bearer <token>`
4. On 401 response, the client automatically re-authenticates and retries (loop-based, not recursive)

## Fill Polling

Kalshi fills are polled from the `/portfolio/fills` endpoint. Each cycle:

1. Queries recent fills with tracked order IDs
2. Deduplicates against previously seen fill IDs
3. Maps Kalshi's price format (cents) and timestamps to Horizon's format

## Feature Support Matrix

| Feature                  | Polymarket       | Kalshi                |
| ------------------------ | ---------------- | --------------------- |
| Trading (orders/fills)   | Yes              | Yes                   |
| Orderbook feed           | Yes (WS)         | Yes (REST)            |
| Market discovery         | Yes              | Yes                   |
| Cross-exchange arbitrage | Yes              | Yes                   |
| LLM forecasting          | Yes              | Yes                   |
| Resolution analysis      | Yes              | Yes                   |
| Resolution sniping       | Yes              | Yes                   |
| Oracle ensemble          | Full (6 signals) | Partial (3 signals)   |
| Flow analysis            | Yes              | No (no on-chain data) |
| Whale tracking           | Yes              | No                    |
| Copy trading             | Yes              | No                    |
| Wallet intelligence      | Yes              | No                    |

<Note>
  The oracle ensemble runs all 6 signal extractors on Kalshi, but signals that depend on Polymarket on-chain data (smart money flow, microstructure, holder concentration) return neutral (0.5). The remaining signals (momentum, volume profile, temporal patterns) also return neutral since Kalshi has no public trade-level data. LLM forecasting and resolution analysis work fully on both exchanges.
</Note>

## Intelligence Suite with Kalshi

All intelligence tools accept an `exchange` parameter:

```python theme={null}
# Resolution analysis
analysis = hz.analyze_resolution("KXBTC100K", exchange="kalshi")

# LLM scan
edges = hz.llm_scan(exchange="kalshi")

# Oracle forecast
forecast = hz.forecast_market("KXBTC100K", exchange="kalshi")

# Edge scanning
edges = hz.scan_edges(exchange="kalshi")
```

### MCP Server

MCP tools also accept the `exchange` parameter:

* `analyze_resolution(market_id, exchange="kalshi")`
* `llm_scan(exchange="kalshi")`
* `sniper_scan(exchange="kalshi")`
* `oracle_forecast(market_id, exchange="kalshi")`
* `oracle_edges(exchange="kalshi")`
