---
title: "Horizon + Kalshi"
description: "Trade on Kalshi with Horizon, a US-regulated (CFTC) prediction market."
icon: "/images/exchanges/kalshi.svg"
---

[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

## 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
# 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")`
