Skip to main content

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.

Normalized public market trade, suitable for “tape” UIs.

Coverage

ExchangeSourcedSyntheticOmitted
kalshi721
polymarket640
Sourced — value copied or transformed from a documented upstream field.
Synthetic — computed by OpenPX, not present upstream.
Omitted — upstream does not expose this concept.

Field crosswalk

Unified fieldTypekalshi sourcepolymarket sourceTransformNotes
idstringTrade.trade_id (string)Trade.transactionHash (string)directkalshi: Kalshi-issued unique trade id, stable across replays. Required on the unified surface; rows missing this field are dropped at parse time rather than synthesized. polymarket: On-chain transaction hash. Doubles as the unified id because Polymarket’s public tape has no separate trade id — every executed trade lands in exactly one Polygon tx. Rows without a tx hash are dropped (the Data API only emits null transactionHash for unsettled trades, which we exclude from the tape view).
pricenumber (double)Trade.yes_price_dollars (FixedPointDollars), fallback Trade.no_price_dollarsTrade.price (number)fixed_point_dollars / directkalshi: Yes-anchored: unified price is always the Yes-side execution price. Kalshi emits both yes_price_dollars and no_price_dollars on every row (Oct 9, 2025 changelog). Cents-form legacy values (e.g. 99.0) are normalized by dividing by 100. Rows that fail to parse a Yes price are dropped. polymarket: Polymarket already returns price as a decimal probability in [0,1]; copied as-is. On binary markets the unified row’s price is the executed price of the specific outcome token (use outcome to know whether it’s Yes-side or No-side).
sizenumber (double)Trade.count_fp (FixedPointCount)Trade.size (number)fixed_point_count / directkalshi: Number of contracts at fixed-point precision (e.g. "10.00"10.0). The legacy integer count field is no longer mapped — count_fp is required on every trade per the spec. polymarket: Already a number in the spec. Copied as-is.
aggressor_sidestring?Trade.taker_side (string)computed{Trade.side, Trade.outcome} → buy|sell, Yes-anchoredkalshi_taker_to_buy_sell / synthetickalshi: Yes-anchored: taker_side=yes (taker bought Yes) → "buy"; taker_side=no (taker bought No, equivalent to selling Yes) → "sell". Encodes whether the trade pushed Yes price up or down. polymarket: Polymarket’s top-level side is the proxyWallet’s BUY/SELL on the specific outcome token. With takerOnly=true (the unified tape default) the proxyWallet is the taker. We anchor to the Yes side: BUY of Yes or SELL of No → "buy"; SELL of Yes or BUY of No → "sell". Non-binary markets fall through to the raw side string.
outcomestring?computedTrade.taker_side ∈ {yes, no} → {"Yes", "No"}Trade.outcome (string)synthetic / directkalshi: Kalshi binary markets only address Yes/No; the row’s outcome mirrors which side the taker took. Synthetic rather than sourced because no top-level outcome field exists on the upstream Trade — we re-canonicalize the enum. polymarket: Free-form outcome label as published by Polymarket (typically "Yes"/"No" on binary markets, but categorical markets emit the outcome string as-is, e.g. "Trump").
yes_pricenumber? (double)Trade.yes_price_dollars (FixedPointDollars)computed — Trade.price when Trade.outcome == “Yes”; else nullfixed_point_dollars / synthetickalshi: Same source as the canonical price; restated here so consumers can read the Yes reference without inspecting outcome. polymarket: Polymarket trades are per-outcome-token, so only one of yes_price / no_price can be filled per row. Set when the row’s outcome is "Yes"; otherwise None. Do NOT derive from 1 - no_price — the spreads are not mirror-image-tight.
no_pricenumber? (double)Trade.no_price_dollars (FixedPointDollars)computed — Trade.price when Trade.outcome == “No”; else nullfixed_point_dollars / synthetickalshi: Direct No-side reference; available on every Kalshi trade alongside yes_price_dollars. Do NOT derive as 1 - yes_price — the mirror identity holds at top-of-book but not on every executed trade (Kalshi’s matching engine can fill both sides at non-mirrored prices on subpenny ticks). polymarket: Symmetric counterpart of yes_price for the No-side outcome token. None when the row is a Yes-token trade.
taker_addressstring?not exposedTrade.proxyWallet (Address)directkalshi: Kalshi public trades expose no wallet/account identifiers — the tape is fully anonymous beyond taker_side. Always None. polymarket: On-chain proxy wallet address of the taker. We hardcode takerOnly=true on the underlying Data API call, so this is unambiguously the taker. Polymarket’s public tape exposes no maker-side identifier (Jun 3, 2025 changelog mentioned a MakerOrder.side nested object that does not appear in the current spec).
exchange_tsstring (date-time)Trade.created_time (string (date-time))Trade.timestamp (integer (int64))parse_datetime / unix_seconds_to_utckalshi: RFC3339 string from the upstream; parsed to UTC. polymarket: Polymarket emits trade timestamps as int64 unix seconds (NOT milliseconds — the orderbook surface uses ms strings, but the tape uses second-precision integers). Parsed via chrono::DateTime::\<Utc\>::from_timestamp.
openpx_tsstring (date-time)computed — wall-clock UTC stamped at response-serialization timecomputed — wall-clock UTC stamped at response-serialization timesyntheticStamped once per fetch_trades call (not per row) so a single page shares one openpx_ts. Lets consumers compute end-to-end latency against exchange_ts and de-duplicate retries that produce identical payloads.

Source specs

Tables are auto-generated from schema/mappings/. CI fails on unresolved $refs and on type mismatches for transform: direct. Drift in upstream specs surfaces here on the daily refresh PR.