> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openpx.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Market mapping

> How each upstream exchange schema maps to OpenPX Market.

*A prediction market on the unified surface. Prices are YES probabilities in `[0, 1]`.*

Every field is one of three entry types — **direct** (taken from upstream), **synthetic** (computed by OpenPX), or **omitted** (not exposed upstream).

## Coverage

| Exchange   | Direct | Synthetic | Omitted |
| ---------- | ------ | --------- | ------- |
| kalshi     | 13     | 8         | 4       |
| polymarket | 18     | 7         | 0       |

## Field crosswalk

| Unified field        | Type                | kalshi source               | polymarket source              | Notes                                                                                                                                                                                                                     |
| -------------------- | ------------------- | --------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `openpx_id`          | string              | *synthetic*                 | *synthetic*                    | **kalshi:** Composite key `\{exchange\}:\{ticker\}`. **polymarket:** Composite key `\{exchange\}:\{ticker\}`.                                                                                                             |
| `exchange`           | string              | *synthetic*                 | *synthetic*                    | **kalshi:** Literal string `"kalshi"`. **polymarket:** Literal string `"polymarket"`.                                                                                                                                     |
| `ticker`             | string              | `Market.ticker`             | `Market.slug`                  | **kalshi:** Native Kalshi market ticker. **polymarket:** Polymarket slug; stable, human-readable identifier (numeric id lives in `numeric_id`).                                                                           |
| `numeric_id`         | string?             | *omitted*                   | `Market.id`                    | **kalshi:** Kalshi has no separate numeric id surface. **polymarket:** Polymarket numeric DB id used for REST deep-links.                                                                                                 |
| `event_ticker`       | string?             | `Market.event_ticker`       | *synthetic*                    | **kalshi:** Native Kalshi event ticker. **polymarket:** Read from the embedded `events[0].slug` (falls back to `events[0].id`).                                                                                           |
| `title`              | string              | *synthetic*                 | `Market.question`              | **kalshi:** Composed as `\{yes_sub_title\} \| \{no_sub_title\}`. **polymarket:** Polymarket market question text.                                                                                                         |
| `rules`              | string?             | *synthetic*                 | `Market.description`           | **kalshi:** Composed as `\{rules_primary\} \| \{rules_secondary\}`. **polymarket:** Polymarket market description.                                                                                                        |
| `status`             | MarketStatus        | *synthetic*                 | *synthetic*                    | **kalshi:** Mapped from Kalshi's `status` enum (initialized/active/closed/determined/...) to unified `MarketStatus`. **polymarket:** Combined from the `active`/`closed`/`archived` booleans into unified `MarketStatus`. |
| `market_type`        | MarketType          | *synthetic*                 | *synthetic*                    | **kalshi:** Mapped from Kalshi's `market_type` enum (binary/scalar) to unified `MarketType`. **polymarket:** Derived from `outcomes.len()` — binary if 2, otherwise categorical.                                          |
| `outcomes`           | array               | *synthetic*                 | *synthetic*                    | **kalshi:** Two entries (`Yes`/`No`); price computed from `yes_ask_dollars`/`last_price_dollars`. **polymarket:** Zipped element-wise from the stringified-JSON arrays `outcomes`, `outcomePrices`, `clobTokenIds`.       |
| `condition_id`       | string?             | *omitted*                   | `Market.conditionId`           | **kalshi:** Kalshi has no CTF condition id. **polymarket:** On-chain CTF condition id.                                                                                                                                    |
| `volume`             | number (double)     | `Market.volume_fp`          | `Market.volumeNum`             | **kalshi:** FixedPointCount string parsed to f64 USD. **polymarket:** Lifetime volume in USD.                                                                                                                             |
| `volume_24h`         | number? (double)    | `Market.volume_24h_fp`      | `Market.volume24hr`            | **kalshi:** FixedPointCount string parsed to f64 USD. **polymarket:** 24-hour volume in USD.                                                                                                                              |
| `last_trade_price`   | number? (double)    | `Market.last_price_dollars` | `Market.lastTradePrice`        | **kalshi:** Fixed-point dollar string parsed to YES probability in \[0, 1]. **polymarket:** Already a YES probability in \[0, 1].                                                                                         |
| `best_bid`           | number? (double)    | `Market.yes_bid_dollars`    | `Market.bestBid`               | **kalshi:** Fixed-point dollar string parsed to YES probability in \[0, 1]. **polymarket:** Already a YES probability in \[0, 1].                                                                                         |
| `best_ask`           | number? (double)    | `Market.yes_ask_dollars`    | `Market.bestAsk`               | **kalshi:** Fixed-point dollar string parsed to YES probability in \[0, 1]. **polymarket:** Already a YES probability in \[0, 1].                                                                                         |
| `tick_size`          | number? (double)    | `Market.price_ranges`       | `Market.orderPriceMinTickSize` | **kalshi:** Smallest `step` across all tiers in the `price_ranges` array. **polymarket:** Single scalar tick size.                                                                                                        |
| `min_order_size`     | number? (double)    | *synthetic*                 | `Market.orderMinSize`          | **kalshi:** 1.0 by default, 0.01 when `fractional_trading_enabled`. **polymarket:** Polymarket minimum order size in contracts.                                                                                           |
| `open_time`          | string? (date-time) | `Market.open_time`          | `Market.startDate`             | **kalshi:** RFC3339 string parsed to UTC. **polymarket:** ISO 8601 string parsed to UTC.                                                                                                                                  |
| `close_time`         | string? (date-time) | `Market.close_time`         | `Market.endDate`               | **kalshi:** RFC3339 string parsed to UTC. **polymarket:** ISO 8601 string parsed to UTC.                                                                                                                                  |
| `created_at`         | string? (date-time) | `Market.created_time`       | `Market.createdAt`             | **kalshi:** RFC3339 string parsed to UTC. **polymarket:** ISO 8601 string parsed to UTC.                                                                                                                                  |
| `settlement_time`    | string? (date-time) | `Market.settlement_ts`      | `Market.closedTime`            | **kalshi:** RFC3339 string parsed to UTC. **polymarket:** On-chain settlement time, populated only after the market resolves.                                                                                             |
| `neg_risk`           | boolean?            | *omitted*                   | `negRisk` *(spec gap)*         | **kalshi:** Kalshi has no neg-risk concept. **polymarket:** Spec gap: `negRisk` is present on every live `/markets` row but undeclared on `Market` in the gamma OpenAPI.                                                  |
| `neg_risk_market_id` | string?             | *omitted*                   | `negRiskMarketID` *(spec gap)* | **kalshi:** Kalshi has no neg-risk concept. **polymarket:** Spec gap: present on every live `/markets` row but undeclared on `Market` in the gamma OpenAPI.                                                               |
| `result`             | string?             | `Market.result`             | *synthetic*                    | **kalshi:** Native Kalshi resolution enum string. **polymarket:** Winning `outcomes[i]` where `outcomePrices[i] == 1.0` after settlement.                                                                                 |

## Source specs

* **kalshi** · [`schema/upstream/kalshi.openapi.yaml`](https://github.com/openpx-trade/openpx/blob/main/schema/upstream/kalshi.openapi.yaml)
* **polymarket** · [`schema/upstream/polymarket-gamma.openapi.yaml`](https://github.com/openpx-trade/openpx/blob/main/schema/upstream/polymarket-gamma.openapi.yaml)

> Tables are auto-generated from `schema/mappings/`. CI fails if any `direct` ref no longer resolves in the cached upstream spec; the daily upstream-refresh PR surfaces drift here.
