Skip to content

feat(kalshi): /v1/kalshi/* endpoints - #559

Open
0237h wants to merge 1 commit into
mainfrom
feat/kalshi-endpoints
Open

feat(kalshi): /v1/kalshi/* endpoints#559
0237h wants to merge 1 commit into
mainfrom
feat/kalshi-endpoints

Conversation

@0237h

@0237h 0237h commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds six endpoints under /v1/kalshi/* backed by the substreams-kalshi v0.4.0 schema:

Endpoint Source table Notes
GET /v1/kalshi/markets markets (RMT) settled-market snapshots; binary/scalar both
GET /v1/kalshi/markets/trades trades fill history; requires ticker / series / start_time
GET /v1/kalshi/markets/ohlc ohlcv_trades view 1m / 1h / 1d bars per ticker (Kalshi's native intervals)
GET /v1/kalshi/markets/settlement market_lifecycle canonical resolution records
GET /v1/kalshi/series state_ohlcv_trades_by_series series leaderboard rollup
GET /v1/kalshi/platform ohlcv_platform view platform-wide time-series

Plus the network-type wiring: dbsConfig accepts type: kalshi and exposes kalshiDatabases, the routes mount under /v1/kalshi/* with cacheControl(), and 15 cases land in routes.sql.spec.ts for per-endpoint smoke + filter combinations + error paths.

Why

Kalshi is Phase 1 of the prediction-markets roadmap. The substreams pipeline (firehose-kalshi → substreams-kalshi → sink-sql) produces the schema this PR consumes — v0.4.0 added the state_platform + state_ohlcv_trades_by_series rollups so /platform and /series serve flat reads instead of fanning out across every ticker bar at query time.

Code references

  • src/types/zod.tskalshiTickerSchema (accepts . for strike values like KXBTCD-26APR3020-T76299.99), kalshiSeriesSchema, kalshiEventTickerSchema, kalshiIntervalSchema (1m/1h/1d), kalshiMarketStatusSchema.
  • src/config/dbsConfig.ts'kalshi' added to the network-type enum and kalshiDatabases to ParsedDbsConfig.
  • src/routes/kalshi/ — six route handlers + SQL files.
  • src/routes/index.ts/v1/kalshi/* mounts.
  • src/routes/routes.sql.spec.ts — kalshi suite under the existing SQL queries describe block.

Design calls worth flagging:

  • Numeric typing: decimals returned as z.number() (matches polymarket / hyperliquid OHLCV). The exception is trades.timestamp_us — stringified, because 16-digit microseconds-since-epoch eventually approaches Number.MAX_SAFE_INTEGER. Same precedent as polymarket's UInt256 amount field.
  • series_from_ticker(ticker) — the ClickHouse function defined in the substreams schema — is used in ohlc.sql and settlement.sql instead of inline splitByChar, so the parsing rule stays single-sourced.
  • /markets/trades requires at least one of ticker / series / start_time (returns 400 bad_query_input otherwise) — mirrors polymarket activity, avoids an unbounded full-table sort.
  • /platform and /series use SETTINGS optimize_aggregation_in_order = 1 since their GROUP BY matches the source AggregatingMergeTree sort-key prefix.
  • markets.expiration_value goes through toFloat64OrNull(toString(...)) — works against both the legacy String column and the v0.4.0 Nullable(Float64) column, so no follow-up is needed once dev1 catches up.

🤖 Generated with Claude Code

Adds six endpoints under /v1/kalshi/ backed by the substreams-kalshi
v0.4.0 schema (state_platform + state_ohlcv_trades_by_series rollups
plus expiration_value as Nullable(Float64)):

- GET /v1/kalshi/markets             — settled-market snapshots
- GET /v1/kalshi/markets/trades      — fill-by-fill history (filter required)
- GET /v1/kalshi/markets/ohlc        — 1m/1h/1d OHLCV bars per ticker
- GET /v1/kalshi/markets/settlement  — canonical resolution records
- GET /v1/kalshi/series              — series leaderboard via state_ohlcv_trades_by_series
- GET /v1/kalshi/platform            — platform-wide aggregate via state_platform

Wiring:
- dbsConfig: `kalshi` added to the network-type enum and a `kalshiDatabases`
  map alongside the existing per-type maps.
- routes/index: `cacheControl()` applied to /v1/kalshi/*; the six routes
  mounted in path-specificity order.
- zod: kalshiTickerSchema (accepts `.` for strike values), kalshiSeriesSchema,
  kalshiEventTickerSchema, kalshiIntervalSchema (1m / 1h / 1d — Kalshi's
  native /markets/candlesticks granularities), kalshiMarketStatusSchema.

Notable design calls:
- Decimals returned as z.number() (matches polymarket / hyperliquid OHLCV);
  the µs trade timestamp is the one exception — z.string() per the
  BigInt-as-string precedent, since 16-digit microseconds-since-epoch will
  approach JS Number.MAX_SAFE_INTEGER in time.
- /platform and /series read state_platform / state_ohlcv_trades_by_series
  with SETTINGS optimize_aggregation_in_order = 1 — the GROUP BY matches
  the source AggregatingMergeTree sort key prefix.
- /markets/trades requires at least one of ticker / series / start_time
  (mirrors polymarket activity); returns 400 bad_query_input otherwise.
- series_from_ticker(ticker) — the ClickHouse function defined in the
  substreams schema — is used in ohlc.sql and settlement.sql instead of
  inline splitByChar, so the parsing rule stays single-sourced.
- markets.expiration_value goes through toFloat64OrNull(toString(...))
  so the same SQL works against both the legacy String column and the
  v0.4.0 Nullable(Float64) shape — no follow-up needed once dev1 catches up.

Test coverage in routes.sql.spec.ts adds 15 cases mirroring the
hyperliquid / polymarket coverage: per-endpoint smoke, key filter
combinations, error paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@0237h 0237h changed the title feat(kalshi): /v1/kalshi/* endpoints for the Kalshi data family feat(kalshi): /v1/kalshi/* endpoints Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants