Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion kalshi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
WeeklySchedule,
Withdrawal,
)
from kalshi.types import NullableList
from kalshi.types import NullableList, StrictInt

__all__ = [
"RFQ",
Expand Down Expand Up @@ -320,6 +320,7 @@
"SettlementStatusLiteral",
"SideLiteral",
"SportFilterDetails",
"StrictInt",
"StructuredTarget",
"SubaccountBalance",
"SubaccountNettingConfig",
Expand Down
8 changes: 4 additions & 4 deletions kalshi/models/communications.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pydantic import AliasChoices, AwareDatetime, BaseModel, Field

from kalshi.types import DollarDecimal, FixedPointCount
from kalshi.types import DollarDecimal, FixedPointCount, StrictInt

UserFilterLiteral = Literal["self"]
"""Filter for items created by the authenticated user. Spec: UserFilter enum."""
Expand Down Expand Up @@ -150,14 +150,14 @@ class CreateRFQRequest(BaseModel):

market_ticker: str
rest_remainder: bool
contracts: int | None = Field(default=None, ge=1)
contracts: StrictInt | None = Field(default=None, ge=1)
target_cost: DollarDecimal | None = Field(
default=None,
serialization_alias="target_cost_dollars",
)
replace_existing: bool | None = None
subtrader_id: str | None = None
subaccount: int | None = Field(default=None, ge=0)
subaccount: StrictInt | None = Field(default=None, ge=0)

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -199,7 +199,7 @@ class CreateQuoteRequest(BaseModel):
yes_bid: DollarDecimal
no_bid: DollarDecimal
rest_remainder: bool
subaccount: int | None = Field(default=None, ge=0)
subaccount: StrictInt | None = Field(default=None, ge=0)
post_only: bool | None = None

model_config = {"extra": "forbid"}
Expand Down
10 changes: 5 additions & 5 deletions kalshi/models/order_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import AliasChoices, BaseModel, Field

from kalshi.types import FixedPointCount, NullableList
from kalshi.types import FixedPointCount, NullableList, StrictInt


class OrderGroup(BaseModel):
Expand Down Expand Up @@ -55,16 +55,16 @@ class CreateOrderGroupResponse(BaseModel):
class CreateOrderGroupRequest(BaseModel):
"""Create body. SDK sends integer form; spec's `contracts_limit_fp` string variant unused."""

contracts_limit: int = Field(..., ge=1)
subaccount: int | None = Field(default=None, ge=0)
exchange_index: int | None = None
contracts_limit: StrictInt = Field(..., ge=1)
subaccount: StrictInt | None = Field(default=None, ge=0)
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}


class UpdateOrderGroupLimitRequest(BaseModel):
"""Update-limit body. No `subaccount` — spec omits SubaccountQuery on /limit."""

contracts_limit: int = Field(..., ge=1)
contracts_limit: StrictInt = Field(..., ge=1)

model_config = {"extra": "forbid"}
38 changes: 19 additions & 19 deletions kalshi/models/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from pydantic import AliasChoices, AwareDatetime, BaseModel, Field, field_validator, model_validator

from kalshi.types import DollarDecimal, FixedPointCount
from kalshi.types import DollarDecimal, FixedPointCount, StrictInt

# Literal aliases for fixed-enum kwargs on order resource methods.
# Source of truth: OpenAPI spec v3.13.0 (specs/openapi.yaml).
Expand Down Expand Up @@ -183,16 +183,16 @@ class CreateOrderRequest(BaseModel):
serialization_alias="no_price_dollars",
)
client_order_id: str | None = None
expiration_ts: int | None = None
expiration_ts: StrictInt | None = None
buy_max_cost: int | None = None
time_in_force: TimeInForceLiteral | None = None
post_only: bool | None = None
reduce_only: bool | None = None
self_trade_prevention_type: SelfTradePreventionTypeLiteral | None = None
order_group_id: str | None = None
cancel_order_on_pause: bool | None = None
subaccount: int | None = None
exchange_index: int | None = None
subaccount: StrictInt | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -266,8 +266,8 @@ class AmendOrderRequest(BaseModel):
)
client_order_id: str | None = None
updated_client_order_id: str | None = None
subaccount: int | None = None
exchange_index: int | None = None
subaccount: StrictInt | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand All @@ -286,10 +286,10 @@ class DecreaseOrderRequest(BaseModel):
builds this model internally; method signature unchanged.
"""

reduce_by: int | None = None
reduce_to: int | None = None
subaccount: int | None = None
exchange_index: int | None = None
reduce_by: StrictInt | None = None
reduce_to: StrictInt | None = None
subaccount: StrictInt | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -332,8 +332,8 @@ class BatchCancelOrdersRequestOrder(BaseModel):
"""

order_id: str
subaccount: int | None = None
exchange_index: int | None = None
subaccount: StrictInt | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -475,13 +475,13 @@ class CreateOrderV2Request(BaseModel):
price: DollarDecimal
time_in_force: TimeInForceLiteral
self_trade_prevention_type: SelfTradePreventionTypeLiteral
expiration_time: int | None = None
expiration_time: StrictInt | None = None
post_only: bool | None = None
cancel_order_on_pause: bool | None = None
reduce_only: bool | None = None
subaccount: int | None = Field(default=None, ge=0)
subaccount: StrictInt | None = Field(default=None, ge=0)
order_group_id: str | None = None
exchange_index: int | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -520,7 +520,7 @@ class DecreaseOrderV2Request(BaseModel):

reduce_by: FixedPointCount | None = None
reduce_to: FixedPointCount | None = None
exchange_index: int | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -560,7 +560,7 @@ class AmendOrderV2Request(BaseModel):
count: FixedPointCount
client_order_id: str | None = None
updated_client_order_id: str | None = None
exchange_index: int | None = None
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -622,8 +622,8 @@ class BatchCancelOrdersV2RequestOrder(BaseModel):
"""Single entry in BatchCancelOrdersV2Request.orders."""

order_id: str
subaccount: int | None = Field(default=None, ge=0)
exchange_index: int | None = None
subaccount: StrictInt | None = Field(default=None, ge=0)
exchange_index: StrictInt | None = None

model_config = {"extra": "forbid"}

Expand Down
10 changes: 5 additions & 5 deletions kalshi/models/subaccounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pydantic import BaseModel, Field

from kalshi.types import DollarDecimal
from kalshi.types import DollarDecimal, StrictInt


class CreateSubaccountResponse(BaseModel):
Expand All @@ -31,9 +31,9 @@ class ApplySubaccountTransferRequest(BaseModel):
"""

client_transfer_id: UUID
from_subaccount: int = Field(ge=0)
to_subaccount: int = Field(ge=0)
amount_cents: int = Field(gt=0)
from_subaccount: StrictInt = Field(ge=0)
to_subaccount: StrictInt = Field(ge=0)
amount_cents: StrictInt = Field(gt=0)

model_config = {"extra": "forbid"}

Expand Down Expand Up @@ -83,7 +83,7 @@ class SubaccountTransfer(BaseModel):
class UpdateSubaccountNettingRequest(BaseModel):
"""Body for PUT /portfolio/subaccounts/netting."""

subaccount_number: int = Field(ge=0)
subaccount_number: StrictInt = Field(ge=0)
enabled: bool

model_config = {"extra": "forbid"}
Expand Down
15 changes: 15 additions & 0 deletions kalshi/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,18 @@ def _none_to_empty_list(value: Any) -> Any:
Callers wanting a :class:`datetime.datetime` can use
``datetime.fromtimestamp(value, tz=timezone.utc)``.
"""


def _reject_bool_int(value: object) -> object:
"""Reject ``bool`` so True->1 / False->0 cannot silently route money (#243 pattern, #295)."""
if isinstance(value, bool):
raise ValueError(
"bool is not a valid int here — pass an explicit integer "
"(e.g. 1 instead of True). bool is an int subclass so True "
"would otherwise silently become 1."
)
return value


StrictInt = Annotated[int, BeforeValidator(_reject_bool_int)]
"""``int`` that rejects ``bool`` — use on every Request-model integer field. See #295."""
Loading
Loading