Python functions:
screenKalshiMarkets(), screenKalshiEvents(), getKalshiMarket(), getKalshiOrderbook(), getKalshiCandles(), getKalshiTrades()Product Overview
Kalshi Data exposes Kalshi’s public event-contract markets through Scalar Field. Markets are binary YES/NO contracts priced as probabilities.screenKalshiMarkets(query=...) searches live Kalshi public APIs — with a query, Kalshi’s /v1/search/series index; without, GET /markets (one page each). Pass symbol (YES) or symbol_no (NO) into venue.trade() and strategy agents.
Kalshi’s order book returns bids only on each leg. A YES ask is derived as 1 − best NO bid (and vice versa). Candlesticks try the live series path first and fail over to GET /historical/markets/{ticker}/candlesticks for markets that have rolled off the live set. Intervals with no trades are returned with null OHLC, volume 0, and populated open interest.
Kalshi is a tradable venue on Scalar Field. See Trading on Kalshi for connect flow, order semantics, and settlement.
Functions at a Glance
Kalshi does not publish participant-level research APIs (no public wallets, positions, fills-by-trader, or leaderboards). That is a regulated-exchange constraint, not a missing wrapper. Research here is market-level: books, tape, candles, and resolution metadata.
Querying the Data
screenKalshiMarkets()
ticker, symbol (YES), symbol_no (NO), bids/asks, volume, open interest, close_time (expiration), created_time, price_ranges, and settlement columns result, settlement_ts, settlement_value_dollars, expiration_value. Filter expiration with start_date / end_date (YYYY-MM-DD).
status is a query filter: "open" (default; None is the same as omit), "closed", "settled", "unopened", "paused", or aliases "active" / "finalized". Other values raise ValueError; a non-string raises TypeError. Ignored when closed is set. Returned rows often have lifecycle labels "active" or "finalized"; this screener maps those aliases to "open" / "settled".
Search-index rows may leave settlement columns null even after a market has determined. Use getKalshiMarket(ticker) for the authoritative Market object.
screenKalshiEvents()
status query values: "open", "closed", "settled", or omit/None for any. Matches events that have at least one child market in that state. Other values, including "active" and "finalized", raise ValueError before the request. Event-row status is often null.
mutually_exclusive is Kalshi’s event flag: true means only one child market can resolve YES; false means more than one child can resolve YES. It is not inferred by Scalar Field.
getKalshiMarket()
GET /markets/{ticker}, then GET /historical/markets/{ticker} when the live ticker has rolled off Kalshi’s ~3-month settled-market cutoff.
Fields come from Kalshi’s Market schema and market lifecycle:
disputed / amended are lifecycle states on this object, not a separate dispute feed. Kalshi does not publish a settlement-rule revision log — rules_* is the current text. There is no resolution_source field in the Trade API.
getKalshiOrderbook()
- YES bid at
X≡ NO ask at1 − X(same size) - NO bid at
Y≡ YES ask at1 − Y(same size)
yes.bids / no.bids are [[price, size], ...] best-first.
getKalshiCandles()
period_interval must be 1, 60, or 1440. Columns: end_period_ts, open, high, low, close, volume, open_interest. The index is end_period (UTC). Prices are the YES trade distribution from Kalshi (price.open_dollars / high / low / close, or historical price.open / high / low / close — both map into the same columns).
Sparse / zero-trade intervals
Kalshi returns a row for intervals with no trades. That is valid, not a gap in the series.
Do not forward-fill null OHLC unless that is an explicit choice for your analysis. This wrapper does not substitute
previous_dollars into OHLC.
Kalshi can also prepend a synthetic candle when include_latest_before_start=true (null OHLC, previous_price set). getKalshiCandles does not pass that flag.
Live vs historical coverage
Candlesticks for markets that settled before Kalshi’s rolling live cutoff (market_settled_ts from GET /historical/cutoff, target window ~3 months) are only on GET /historical/markets/{ticker}/candlesticks. getKalshiCandles calls the live series path first and fails over to that historical endpoint when live is 404/empty.
There is no documented hard row cap on the candlestick endpoint (it is a time-range query, not a limit page). df.attrs["is_complete"] is True after a successful time-range response. df.attrs["source"] is "live" or "historical". df.attrs["last_ts"] is the last end_period_ts in the frame.
getKalshiTrades()
GET /markets/trades, then GET /historical/trades when the live cursor is exhausted and limit still has room (include_historical=True by default). Columns: trade_id, ticker, symbol, outcome, price, yes_price, no_price, count, taker_side, created_time.
yes_price + no_price = 1. outcome / price are the taker’s taker_outcome_side and that leg’s price — the same complement encoding as private fills (sell-YES prints as NO at 1 - yes_price). taker_side is the legacy YES/NO of the aggressive order.
Optional filters: min_ts / max_ts (Unix seconds, forwarded to Kalshi), cursor, source (live / historical / omit for auto).