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
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,45 @@ All notable changes to kalshi-sdk will be documented in this file.

## Unreleased

Reconciles nightly spec drift (Closes #544). **Breaking** for constructors
of `ObligationEntry` that omit the new required `corporate_action_payments`.
Re-vendored `specs/openapi.yaml` (hash
`3877d38d095f4004e325aaa8766f24dabeb1c2dc3fb8d37b9ccac82ca5734d8a`),
`specs/asyncapi.yaml` (hash
`3c86bae7d89b44baba1119b3a097a54054c1d851e1dcd8ad894c7cb35b9890b6`;
channel description only — no WebSocket payload schema change), and
`specs/perps_scm_openapi.yaml` (hash
`1f58b54b6bef44852b4a9a3fd7ad707668258a2516801a076ffe468a1807806f`).
Core OpenAPI remains 3.34.0.

### Changed (breaking)

- Klear **`ObligationEntry.corporate_action_payments`** (required
`list[CorporateActionPaymentDetail]`, may be empty). Cash and split
corporate-action payments already reflected in settlement PnL; do not
add them to the obligation total. Live responses include the array;
constructors and fixtures must pass it (use `[]` when none apply).

### Added

- **`events.list_multivariate` / `list_all_multivariate(..., tickers=)`**
(sync + async) — optional event-ticker filter on
`GET /events/multivariate`. A `list[str]` or a comma-separated string is
sent as one comma-separated query value. Empty elements and embedded
commas are rejected before the request. `None` and `[]` omit the param.

- Klear **`margin.corporate_action_payments` /
`corporate_action_payments_all`** (sync + async) —
`GET /margin/obligations/{obligation_id}/corporate_action_payments`.
Pages the full set when `corporate_action_payments_truncated` is set.
Limit max 1000.

- Klear **`ObligationEntry.corporate_action_payments_truncated`**
(`bool | None`).

- Klear **`AssetClassLiteral`** also accepts `"Equities"`, `"Metals"`,
`"Indices"`, and `"Energy"` (alongside `"Crypto"`).

Reconciles perps spec drift after nightly contract failures (Closes #540).
**Breaking** for constructors of `MarginMarket` that omit the new required
`funding_invalid_premium_handling`. Re-vendored `specs/perps_openapi.yaml`
Expand Down
34 changes: 34 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,40 @@ MarginMarket(
`GET /margin/markets/orderbooks`. Required `tickers` (1–100),
comma-joined on the wire. Returns `list[MarginOrderbook]`.

### Klear corporate-action payments (Closes #544)

**Breaking** for constructors and `model_validate` fixtures of
`ObligationEntry` that omit the new required `corporate_action_payments`.

- **`ObligationEntry.corporate_action_payments`** — required
`list[CorporateActionPaymentDetail]` (may be empty). Cash and split
corporate-action payments already reflected in settlement PnL. Do not
add them to the obligation total. Live responses include the array;
constructors and fixtures must pass it.

```python
# Before (constructors / test fixtures):
# ObligationEntry(
# ...,
# funding_payments=[],
# )

# After:
ObligationEntry(
...,
funding_payments=[],
corporate_action_payments=[],
)
```

`corporate_action_payments_truncated` is optional. Page the full set with
`klear.margin.corporate_action_payments` / `corporate_action_payments_all`
(sync + async) when the flag is set.

`AssetClassLiteral` also accepts `"Equities"`, `"Metals"`, `"Indices"`, and
`"Energy"` (previously `"Crypto"` only). Existing `"Crypto"` callers are
unchanged.

See the [changelog](https://github.com/TexasCoding/kalshi-python-sdk/blob/main/CHANGELOG.md)
for the full list.

Expand Down
17 changes: 15 additions & 2 deletions docs/perps.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ next-settlement estimates keyed by asset class. (The singular
`active_obligation()` / `settlement_estimate()` endpoints were removed upstream
in the v11.0.0 reconcile.)

`klear.margin.settlement_prices(asset_class="Crypto", settlement_time=...)`
`AssetClassLiteral` is `"Crypto"`, `"Equities"`, `"Metals"`, `"Indices"`,
or `"Energy"`. `klear.margin.settlement_prices(asset_class="Crypto", settlement_time=...)`
returns a ticker → centicents map at a settlement cycle.
`klear.margin.estimate_maintenance_margin(asset_class="Crypto", positions=[...])`
margins a hypothetical portfolio. Optional `date=` (YYYY-MM-DD) and
Expand Down Expand Up @@ -329,7 +330,17 @@ klear.margin.delete_fcm_api_key(created.api_key_id)
```

When an `ObligationEntry` inline detail array is capped at 1000 rows, the
matching `*_truncated` flag is set; page the full set via:
matching `*_truncated` flag is set; page the full set via the methods below.

`corporate_action_payments` is required and may be empty. Those rows are
cash and split corporate-action payments already included in settlement PnL
— do not add them to the obligation total.
`CorporateActionPaymentDetail.payment_time` is always present and is `null`
for splits. Centicents fields on that model are plain integers;
`position_quantity_fp` and `post_position_quantity_fp` are fixed-point
contract counts. `corporate_action_payments` / `corporate_action_payments_all`
page the full set when `corporate_action_payments_truncated` is true (limit
max 1000):

```python
for row in klear.margin.settlement_details_all(ob.id):
Expand All @@ -338,6 +349,8 @@ for row in klear.margin.maintenance_margin_details_all(ob.id):
...
for row in klear.margin.funding_payments_all(ob.id):
...
for row in klear.margin.corporate_action_payments_all(ob.id):
...
```

Each `AssetClassSettlementEstimate` exposes optional
Expand Down
11 changes: 9 additions & 2 deletions docs/resources/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,15 @@ one comma-separated value).
## Multivariate events

`list_multivariate(...)` returns only events that participate in a
multivariate event collection. Same kwargs as `list`. See
[Multivariate](multivariate.md) for the surrounding API.
multivariate event collection. See [Multivariate](multivariate.md) for the
surrounding API.

`tickers` (optional on `list_multivariate` and `list_all_multivariate`)
restricts the page to specific event tickers, same wire format as
[`list`](#list-events): a `list[str]` or a comma-separated string, sent as
one comma-separated query value. Individual tickers must be non-empty and
must not contain commas. Omit `tickers`, or pass `None` or `[]`, to leave
the filter off.

## Get one event

Expand Down
10 changes: 10 additions & 0 deletions kalshi/_contract_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,10 @@ class ContractEntry:
sdk_model="kalshi.perps.klear.models.margin.FundingPaymentDetail",
spec_schema="FundingPaymentDetail",
),
ContractEntry(
sdk_model="kalshi.perps.klear.models.margin.CorporateActionPaymentDetail",
spec_schema="CorporateActionPaymentDetail",
),
ContractEntry(
sdk_model="kalshi.perps.klear.models.margin.ObligationEntry",
spec_schema="ObligationEntry",
Expand All @@ -1007,6 +1011,12 @@ class ContractEntry:
sdk_model="kalshi.perps.klear.models.margin.GetObligationFundingPaymentsResponse",
spec_schema="GetObligationFundingPaymentsResponse",
),
ContractEntry(
sdk_model=(
"kalshi.perps.klear.models.margin.GetObligationCorporateActionPaymentsResponse"
),
spec_schema="GetObligationCorporateActionPaymentsResponse",
),
ContractEntry(
sdk_model="kalshi.perps.klear.models.margin.MarketSettlementEstimate",
spec_schema="MarketSettlementEstimate",
Expand Down
4 changes: 4 additions & 0 deletions kalshi/perps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
KlearConfig,
)
from kalshi.perps.klear.models.margin import (
CorporateActionPaymentDetail,
FundingPaymentDetail,
GetActiveMarginObligationsResponse,
GetGuarantyFundBalanceResponse,
GetMarginReportsResponse,
GetObligationCorporateActionPaymentsResponse,
GetObligationFundingPaymentsResponse,
GetObligationHistoryResponse,
GetObligationMaintenanceMarginDetailsResponse,
Expand Down Expand Up @@ -249,6 +251,7 @@
"BookSideLiteral",
"CancelMarginOrderResponse",
"ConnectionState",
"CorporateActionPaymentDetail",
"CreateMarginOrderRequest",
"CreateMarginOrderResponse",
"CreateOrderGroupRequest",
Expand Down Expand Up @@ -291,6 +294,7 @@
"GetMarginRiskParametersResponse",
"GetMarginRiskResponse",
"GetMarginTradesResponse",
"GetObligationCorporateActionPaymentsResponse",
"GetObligationFundingPaymentsResponse",
"GetObligationHistoryResponse",
"GetObligationMaintenanceMarginDetailsResponse",
Expand Down
4 changes: 4 additions & 0 deletions kalshi/perps/klear/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
AssetClassLiteral,
AssetClassSettlementEstimate,
ClearingTypeLiteral,
CorporateActionPaymentDetail,
CreateMarginFcmApiKeyRequest,
CreateMarginFcmApiKeyResponse,
CreateMarginSubtraderGroupRequest,
Expand All @@ -27,6 +28,7 @@
GetMarginReportsResponse,
GetMarginSubtraderGroupsResponse,
GetMemberFundingPaymentsResponse,
GetObligationCorporateActionPaymentsResponse,
GetObligationFundingPaymentsResponse,
GetObligationHistoryResponse,
GetObligationMaintenanceMarginDetailsResponse,
Expand Down Expand Up @@ -64,6 +66,7 @@
"AssetClassLiteral",
"AssetClassSettlementEstimate",
"ClearingTypeLiteral",
"CorporateActionPaymentDetail",
"CreateMarginFcmApiKeyRequest",
"CreateMarginFcmApiKeyResponse",
"CreateMarginSubtraderGroupRequest",
Expand All @@ -84,6 +87,7 @@
"GetMarginReportsResponse",
"GetMarginSubtraderGroupsResponse",
"GetMemberFundingPaymentsResponse",
"GetObligationCorporateActionPaymentsResponse",
"GetObligationFundingPaymentsResponse",
"GetObligationHistoryResponse",
"GetObligationMaintenanceMarginDetailsResponse",
Expand Down
63 changes: 57 additions & 6 deletions kalshi/perps/klear/models/margin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
NOT :data:`DollarDecimal` / :data:`FixedPointCount`. This mirrors the
integer-cents precedent in ``kalshi/models/portfolio.py`` (``Balance.balance``,
``Deposit.amount_cents``). Fixed-point **count** strings appear on
:attr:`SettlementDetail.position_quantity_fp` and
:attr:`FundingPaymentDetail.position_quantity_fp`. The fixed-point
:attr:`SettlementDetail.position_quantity_fp`,
:attr:`FundingPaymentDetail.position_quantity_fp`, and
:attr:`CorporateActionPaymentDetail.position_quantity_fp` /
:attr:`CorporateActionPaymentDetail.post_position_quantity_fp`. The fixed-point
**dollar-string** fields are :attr:`WithdrawSettlementBalanceRequest.amount`,
:attr:`GetSettlementBalanceWithdrawalResponse.amount`, and
:attr:`MarketSettlementEstimate.session_avg_price_fp` (e.g. ``"500.00"``);
Expand Down Expand Up @@ -79,10 +81,10 @@ def _require_positive_withdrawal(value: Decimal) -> Decimal:
# Spec ``GetSettlementBalanceWithdrawalResponse.status`` enum.
WithdrawalStatusLiteral = Literal["pending", "processing", "processed", "failed"]

# Spec ``AssetClass`` enum (single value today). Named alias mirrors the other
# *Literal aliases; shared by ObligationEntry.asset_class and the settlement
# estimates keyed by asset class (spec sync 3.24.0).
AssetClassLiteral = Literal["Crypto"]
# Spec ``AssetClass`` enum. Named alias mirrors the other *Literal aliases;
# shared by ObligationEntry.asset_class, corporate-action payments, and the
# settlement / funding estimates keyed by asset class.
AssetClassLiteral = Literal["Crypto", "Equities", "Metals", "Indices", "Energy"]
"""Spec withdrawal ``status`` — lifecycle of an async settlement-balance withdrawal."""


Expand Down Expand Up @@ -181,6 +183,40 @@ class FundingPaymentDetail(BaseModel):
model_config = {"extra": "allow"}


class CorporateActionPaymentDetail(BaseModel):
"""Spec ``CorporateActionPaymentDetail`` — cash or split already in settlement PnL.

These rows explain amounts included in the obligation's settlement PnL.
They are not additional amounts to add to the obligation total.

``position_quantity_fp`` / ``post_position_quantity_fp`` are fixed-point
contract counts. Centicents fields are plain ``int``. ``payment_time`` is
a required key that is ``null`` for splits (no scheduled cash time).
``pre_split_price_centicents`` / ``post_split_price_centicents`` /
``exchange_ts`` are omitted when they do not apply.
"""

id: str
type: str
ca_id: str
market_id: str
market_ticker: str
asset_class: AssetClassLiteral
subtrader_id: str
position_quantity_fp: FixedPointCount
post_position_quantity_fp: FixedPointCount
payment_amount_centicents: int
# Required key; null for splits.
payment_time: AwareDatetime | None
settlement_execution_time: AwareDatetime
created_ts: AwareDatetime
pre_split_price_centicents: int | None = None
post_split_price_centicents: int | None = None
exchange_ts: AwareDatetime | None = None

model_config = {"extra": "allow"}


class ObligationEntry(BaseModel):
"""Spec ``ObligationEntry`` — a settlement obligation (flattened ``allOf``).

Expand Down Expand Up @@ -212,9 +248,11 @@ class ObligationEntry(BaseModel):
settlement_details: NullableList[SettlementDetail]
maintenance_margin_details: NullableList[MaintenanceMarginDetail]
funding_payments: NullableList[FundingPaymentDetail]
corporate_action_payments: NullableList[CorporateActionPaymentDetail]
settlement_details_truncated: bool | None = None
maintenance_margin_details_truncated: bool | None = None
funding_payments_truncated: bool | None = None
corporate_action_payments_truncated: bool | None = None

model_config = {"extra": "allow"}

Expand Down Expand Up @@ -275,6 +313,19 @@ def has_next(self) -> bool:
model_config = {"extra": "allow"}


class GetObligationCorporateActionPaymentsResponse(BaseModel):
"""Spec ``GetObligationCorporateActionPaymentsResponse`` — paged corporate actions."""

corporate_action_payments: NullableList[CorporateActionPaymentDetail]
cursor: str | None = None

@property
def has_next(self) -> bool:
return bool(self.cursor)

model_config = {"extra": "allow"}


class MarketSettlementEstimate(BaseModel):
"""Spec ``MarketSettlementEstimate`` — per-market settlement breakdown (centi units)."""

Expand Down
Loading
Loading