You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
OpenAPI v3.18.0 added fields to Market, Order, and Fill that the SDK does not yet model. Currently TestSpecDrift::test_additive_drift emits UserWarning for each one; these warnings do not fail CI. This is the largest backfill in the stack — 23 fields across the three highest-traffic response models — and lands the new direction-encoding fields (outcome_side / book_side) that supersede the deprecated Order.action.
Depends on #158 (EXCLUSIONS infrastructure). Once #158 lands the warning floor drops; this PR removes 23 of the remaining warnings.
Scope
Files
kalshi/models/markets.py — add 11 fields to Market
kalshi/models/orders.py — add 8 fields to Order, 4 fields to Fill
tests/test_orders.py — extend existing happy-path tests to cover the new fields' (de)serialization
tests/test_models_markets.py (or wherever Market is exercised — confirm at edit time)
Field-level changes
Market (+11):
Field
Spec type
SDK type
Notes
custom_strike
object
dict[str, Any] | None = None
per-market custom strike spec
early_close_condition
string
str | None = None
enum on the wire; keep str until #PR? for Literal
exchange_index
integer
int | None = None
matches request-side already on CreateOrderRequest
fee_waiver_expiration_time
string (date-time)
datetime | None = None
functional_strike
string
str | None = None
is_provisional
boolean
bool | None = None
mve_collection_ticker
string
str | None = None
multivariate event collection linkage
mve_selected_legs
array
list[str] | None = None
verify element type at edit time
price_level_structure
string
str | None = None
replaces deprecated response_price_units
price_ranges
array
list[dict[str, Any]] | None = None
confirm element schema
primary_participant_key
string
str | None = None
Order (+8):
Field
Spec type
SDK type
Notes
book_side
string
BookSideLiteral | None = None
Literal["bid", "ask"] — already defined in orders.py
For fields with spec _dollars / _fp suffix wire names: use Field(default=None, validation_alias=AliasChoices("<wire>_dollars", "<short>")) — see existing examples in the same file.
For enum-like string fields: type as the existing *Literal alias when one exists; otherwise plain str | None. Don't invent new Literal aliases in this PR — that's separable polish.
Don't reorder existing fields. Append new ones at the end of each model (matches the spec's append-only evolution).
Do not touch the model docstrings except to add a one-line note about new fields where it improves clarity.
Acceptance criteria
uv run pytest tests/test_contracts.py::TestSpecDrift::test_additive_drift -v shows no warnings for Market, Order, Fill (the three parameterized cases pass cleanly).
Other test_additive_drift cases still warn for the remaining un-backfilled models (these are addressed in #PR2–#PR4).
uv run pytest tests/test_orders.py -v passes; new (de)serialization tests cover at least one field per backfilled model.
uv run pytest tests/ -q --ignore=tests/integration passes (1945 → 1945+N).
uv run mypy kalshi/ strict-clean.
uv run ruff check . clean.
No changes to request-body models or resource methods.
subaccount_number is not the same as the existing Order.subaccount: int | None. Verify against specs/openapi.yamlOrder schema at edit time; the spec adds it as a separate property.
Effort
~80 lines model code + ~30 lines tests.
Part of the response-side spec drift hardening stack.
Context
OpenAPI v3.18.0 added fields to
Market,Order, andFillthat the SDK does not yet model. CurrentlyTestSpecDrift::test_additive_driftemitsUserWarningfor each one; these warnings do not fail CI. This is the largest backfill in the stack — 23 fields across the three highest-traffic response models — and lands the new direction-encoding fields (outcome_side/book_side) that supersede the deprecatedOrder.action.Depends on #158 (EXCLUSIONS infrastructure). Once #158 lands the warning floor drops; this PR removes 23 of the remaining warnings.
Scope
Files
kalshi/models/markets.py— add 11 fields toMarketkalshi/models/orders.py— add 8 fields toOrder, 4 fields toFilltests/test_orders.py— extend existing happy-path tests to cover the new fields' (de)serializationtests/test_models_markets.py(or whereverMarketis exercised — confirm at edit time)Field-level changes
Market(+11):custom_strikedict[str, Any] | None = Noneearly_close_conditionstr | None = Nonestruntil #PR? forLiteralexchange_indexint | None = NoneCreateOrderRequestfee_waiver_expiration_timedatetime | None = Nonefunctional_strikestr | None = Noneis_provisionalbool | None = Nonemve_collection_tickerstr | None = Nonemve_selected_legslist[str] | None = Noneprice_level_structurestr | None = Noneresponse_price_unitsprice_rangeslist[dict[str, Any]] | None = Noneprimary_participant_keystr | None = NoneOrder(+8):book_sideBookSideLiteral | None = NoneLiteral["bid", "ask"]— already defined inorders.pycancel_order_on_pausebool | None = Noneexchange_indexint | None = Nonelast_update_timedatetime | None = Noneorder_group_idstr | None = Noneoutcome_sideSideLiteral | None = NoneLiteral["yes", "no"]— replacesOrder.action(already deprecated; stays asstr | None)self_trade_prevention_typeSelfTradePreventionTypeLiteral | None = Nonesubaccount_numberint | None = Nonesubaccountfield — verify shapeFill(+4):book_sideBookSideLiteral | None = Noneoutcome_sideSideLiteral | None = Nonesubaccount_numberint | None = Nonetsint | None = Nonecreated_time: datetime; do NOT auto-convertConventions to follow
model_config = {"extra": "allow", "populate_by_name": True}(existing pattern)._dollars/_fpsuffix wire names: useField(default=None, validation_alias=AliasChoices("<wire>_dollars", "<short>"))— see existing examples in the same file.*Literalalias when one exists; otherwise plainstr | None. Don't invent newLiteralaliases in this PR — that's separable polish.Acceptance criteria
uv run pytest tests/test_contracts.py::TestSpecDrift::test_additive_drift -vshows no warnings forMarket,Order,Fill(the three parameterized cases pass cleanly).test_additive_driftcases still warn for the remaining un-backfilled models (these are addressed in #PR2–#PR4).uv run pytest tests/test_orders.py -vpasses; new (de)serialization tests cover at least one field per backfilled model.uv run pytest tests/ -q --ignore=tests/integrationpasses (1945 → 1945+N).uv run mypy kalshi/strict-clean.uv run ruff check .clean.Notes
Order.outcome_sideandOrder.book_sideare the canonical direction encodings going forward.Order.actionstays in the model (allowlisted in PR0: test infra — wire response-side drift through EXCLUSIONS map #158) for back-compat — the spec still emits it.subaccount_numberis not the same as the existingOrder.subaccount: int | None. Verify againstspecs/openapi.yamlOrderschema at edit time; the spec adds it as a separate property.Effort
~80 lines model code + ~30 lines tests.
Part of the response-side spec drift hardening stack.
Tracking: #157.