---
title: "Horizon + Alpaca"
description: "Trade stocks and ETFs on Alpaca Markets for hedging prediction market positions."
icon: "/images/exchanges/alpaca.svg"
---

[Alpaca Markets](https://alpaca.markets) is a stock trading API. Horizon uses Alpaca to hedge prediction market positions with correlated stocks or ETFs (e.g., TLT for rate bets, SPY for broad market exposure).

## Quick Setup

```python
hz.run(
    name="stock_hedge",
    exchange=hz.Alpaca(api_key="...", api_secret="..."),
    mode="live",
    ...
)
```

## Credentials

<Tabs>
  <Tab title="Explicit">
    ```python
    hz.Alpaca(api_key="PKXXXXXX", api_secret="XXXXXX")
    ```
  </Tab>
  <Tab title="Environment variables">
    ```bash
    export ALPACA_API_KEY="PKXXXXXX"
    export ALPACA_API_SECRET="XXXXXXXX"
    # or use Alpaca's native env var names:
    export APCA_API_KEY_ID="PKXXXXXX"
    export APCA_API_SECRET_KEY="XXXXXXXX"
    ```

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

## Paper vs Live

```python
# Paper trading (default)
hz.Alpaca(paper=True)   # https://paper-api.alpaca.markets

# Live trading
hz.Alpaca(paper=False)  # https://api.alpaca.markets
```

<Tip>
  Test with `paper=True` before switching to live. Paper mode uses the same API with simulated fills, so your strategy logic runs the same way.
</Tip>

## Alpaca Configuration

```python
@dataclass
class Alpaca:
    api_key: str | None = None
    api_secret: str | None = None
    paper: bool = True
    api_url: str | None = None
    data_source: str = "iex"
```

| Field | Default | Description |
|-------|---------|-------------|
| `api_key` | `None` | Alpaca API key ID (env: `ALPACA_API_KEY` or `APCA_API_KEY_ID`) |
| `api_secret` | `None` | Alpaca API secret key (env: `ALPACA_API_SECRET` or `APCA_API_SECRET_KEY`) |
| `paper` | `True` | Use paper trading URL |
| `api_url` | Auto | Override API URL (set automatically from `paper` flag) |
| `data_source` | `"iex"` | Market data source: `"iex"` (free) or `"sip"` (paid, full NBBO) |

## Authentication

Alpaca uses header-based auth. No token refresh needed.

- `APCA-API-KEY-ID: {api_key}`
- `APCA-API-SECRET-KEY: {api_secret}`

Both headers are sent on every request.

## Market Data Feed

Stock quotes via WebSocket:

```python
hz.run(
    feeds={
        "spy": hz.AlpacaFeed(symbols=["SPY"]),
        "tlt": hz.AlpacaFeed(symbols=["TLT"]),
    },
    ...
)
```

The feed connects to `wss://stream.data.alpaca.markets/v2/{source}` and subscribes to both trades and quotes for each symbol.

Each symbol gets its own snapshot entry keyed by `{feed_name}:{SYMBOL}` (e.g., `tlt:TLT`), plus a feed-level entry under the feed name with the last update across all symbols.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `symbols` | `list[str]` | required | Stock/ETF tickers to subscribe (e.g., `["TLT", "SPY"]`) |
| `api_key` | `str` | `None` | Override API key (defaults to env vars) |
| `api_secret` | `str` | `None` | Override API secret (defaults to env vars) |
| `data_source` | `str` | `"iex"` | `"iex"` (free, 15-min delayed for some symbols) or `"sip"` (paid, real-time NBBO) |

## Symbol Mapping

Alpaca uses standard stock tickers. No token ID resolution needed:

```python
# Market ID maps directly to the Alpaca symbol
market = hz.Market(id="TLT", name="iShares 20+ Year Treasury Bond ETF")
```

| Horizon Field | Alpaca Field | Notes |
|---------------|-------------|-------|
| `OrderRequest.market_id` | `symbol` | Standard ticker (e.g., "AAPL", "SPY", "TLT") |
| `OrderRequest.order_side` | `side` | `"buy"` or `"sell"` |
| `OrderRequest.price` | `limit_price` | Limit order price |
| `OrderRequest.size` | `qty` | Supports fractional shares |

<Note>
  Prediction market concepts like `Side.Yes` / `Side.No` do not apply to stock orders. Alpaca orders use `buy` / `sell` only.
</Note>

## Fill Polling

Alpaca fills are polled from the `GET /v2/orders?status=filled` endpoint. Each cycle:

1. Queries recently filled orders
2. Deduplicates against previously seen fill IDs (FIFO eviction at 10k)
3. Maps Alpaca's response to Horizon `Fill` objects with exchange-assigned timestamps

## Multi-Exchange Hedging

Use Alpaca alongside Polymarket or Kalshi for hedged strategies:

```python
hz.run(
    name="hedged_fed_rate",
    exchange=[
        hz.Polymarket(),       # prediction market
        hz.Alpaca(paper=True), # stock hedge
    ],
    feeds={
        "fed_rate": hz.PolymarketBook("will-fed-cut-rates"),
        "tlt": hz.AlpacaFeed(symbols=["TLT"]),
    },
    pipeline=[
        hz.stock_hedge(hz.HedgeConfig(
            prediction_feed="fed_rate",
            stock_feed="tlt",
            stock_symbol="TLT",
            auto_rebalance=True,
        )),
        my_strategy,
    ],
)
```

The first exchange (Polymarket) becomes the primary. Orders are routed based on `market.exchange`.

## Feature Support Matrix

| Feature | Polymarket | Kalshi | Alpaca |
|---------|-----------|--------|--------|
| Trading (orders/fills) | Yes | Yes | Yes |
| Orderbook feed | Yes (WS) | Yes (REST) | Yes (WS) |
| Market discovery | Yes | Yes | No |
| Hedge pipeline | No | No | Yes |
| Paper trading | No | Yes (demo) | Yes |
| Fractional shares | No | No | Yes |
| LLM forecasting | Yes | Yes | No |
| Resolution analysis | Yes | Yes | No |

<Note>
  Alpaca is used for hedging, not as a standalone trading venue. Pair it with `hz.stock_hedge()` or `hz.hedge_monitor()` alongside a prediction market exchange.
</Note>

## Getting API Keys

1. Sign up at [alpaca.markets](https://alpaca.markets)
2. Go to **Paper Trading** > **API Keys**
3. Generate a new key pair
4. For live trading, switch to **Live Trading** and generate live keys

See [Stock Market Hedging](/stock-hedging) for the full hedging guide and [Stock Hedge Strategy](/examples/stock-hedge-strategy) for a complete worked example.
