---
title: "Horizon + Kalshi"
description: "Trade on Kalshi with Horizon, a US-regulated (CFTC) prediction market."
icon: "scale-balanced"
---

[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
hz.run(
    name="kalshi_mm",
    exchange=hz.Kalshi(api_key="..."),
    mode="live",
    ...
)
```

## Credentials

<Tabs>
  <Tab title="API key">
    ```python
    hz.Kalshi(api_key="your_api_key")
    ```
  </Tab>
  <Tab title="Email / password">
    ```python
    hz.Kalshi(email="you@example.com", password="...")
    ```
  </Tab>
  <Tab title="Environment variables">
    ```bash
    export KALSHI_API_KEY="..."
    # or
    export KALSHI_EMAIL="..."
    export KALSHI_PASSWORD="..."
    ```

    ```python
    hz.Kalshi()  # reads from env
    ```
  </Tab>
</Tabs>

## Kalshi Configuration

```python
@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
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
# Market ID is used as the ticker (uppercased)
hz.run(markets=["KXBTC-25FEB16"], ...)
```

Or set it explicitly:

```python
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
