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
12 changes: 7 additions & 5 deletions docs/resources/orders.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Every method here requires auth.
| `batch_cancel(orders)` | `DELETE /portfolio/orders/batched` | never |
| `amend(order_id, ...)` | `POST /portfolio/orders/{order_id}/amend` | never |
| `decrease(order_id, *, reduce_by, reduce_to)` | `POST /portfolio/orders/{order_id}/decrease` | never |
| `fills(...)` / `fills_all(...)` | `GET /portfolio/fills` | yes |
| ~~`fills(...)` / `fills_all(...)`~~ | moved to `PortfolioResource` in v3.0.0 — see [Portfolio › Fills](portfolio.md#fills); the old methods remain as deprecated aliases until removal in a future release. |
| `queue_positions(*, market_tickers, event_ticker)` | `GET /portfolio/orders/queue_positions` | yes |
| `queue_position(order_id)` | `GET /portfolio/orders/{order_id}/queue_position` | yes |

Expand Down Expand Up @@ -198,19 +198,21 @@ order = client.orders.decrease("ord_abc", reduce_to=5) # decrease size to 5
Passing neither or both raises `ValidationError` at construction (XOR enforced
by the model).

## List orders and fills
## List orders

```python
for order in client.orders.list_all(status="resting"):
print(order.order_id, order.ticker, order.remaining_count)

for fill in client.orders.fills_all(ticker="KXPRES-24-DJT"):
print(fill.fill_id, fill.price, fill.count, fill.is_taker)
```

`status` accepts an `OrderStatusLiteral`: `"resting"`, `"canceled"`,
`"executed"`. `min_ts` / `max_ts` (Unix seconds) bound by created time.

Fills (`fills` / `fills_all`) moved to `PortfolioResource` in v3.0.0 — see
[Portfolio › Fills](portfolio.md#fills). `client.orders.fills(...)` /
`client.orders.fills_all(...)` still work in v3.0.0 but emit a
`DeprecationWarning` and will be removed in a future release.

## Queue position

```python
Expand Down
26 changes: 26 additions & 0 deletions docs/resources/portfolio.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Auth required throughout.
| `balance(*, subaccount=None)` | `GET /portfolio/balance` |
| `positions(*, ...)` | `GET /portfolio/positions` |
| `settlements(...)` / `settlements_all(...)` | `GET /portfolio/settlements` |
| `fills(...)` / `fills_all(...)` | `GET /portfolio/fills` |
| `total_resting_order_value()` | `GET /portfolio/summary/total_resting_order_value` (FCM only) |
| `deposits(*, limit, cursor)` / `deposits_all(*, limit, max_pages)` | `GET /portfolio/deposits` |
| `withdrawals(*, limit, cursor)` / `withdrawals_all(*, limit, max_pages)` | `GET /portfolio/withdrawals` |
Expand Down Expand Up @@ -115,6 +116,31 @@ for s in client.portfolio.settlements_all():

Standard `Page[Settlement]` pagination — see [Pagination](../pagination.md).

## Fills

```python
page = client.portfolio.fills(
ticker="KXPRES-24-DJT",
min_ts=1_700_000_000,
max_ts=1_800_000_000,
limit=200,
)
for f in page:
print(f.trade_id, f.order_id, f.yes_price, f.count, f.is_taker)

# Or auto-paginate:
for f in client.portfolio.fills_all(ticker="KXPRES-24-DJT"):
...
```

Standard `Page[Fill]` pagination — see [Pagination](../pagination.md).

!!! note "Moved from `OrdersResource` in v3.0.0 (issue #351)"
`client.orders.fills(...)` / `client.orders.fills_all(...)` still work
in v3.0.0 but emit a `DeprecationWarning` and will be removed in a
future release. Update call sites to `client.portfolio.fills(...)` /
`client.portfolio.fills_all(...)`.

## Total resting order value

```python
Expand Down
23 changes: 23 additions & 0 deletions kalshi/resources/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ def _params(**kwargs: Any) -> dict[str, Any]:
return {k: v for k, v in kwargs.items() if v is not None}


def _fills_params(
*,
ticker: str | None,
order_id: str | None,
min_ts: int | None,
max_ts: int | None,
limit: int | None,
cursor: str | None,
subaccount: int | None,
) -> dict[str, Any]:
"""Build query params for ``/portfolio/fills`` (shared by sync/async)."""
limit = _validate_limit(limit, hi=1000)
return _params(
ticker=ticker,
order_id=order_id,
min_ts=min_ts,
max_ts=max_ts,
limit=limit,
cursor=cursor,
subaccount=subaccount,
)


def _bool_param(value: bool | None) -> str | None:
"""Serialize a tri-state bool for query params.

Expand Down
42 changes: 19 additions & 23 deletions kalshi/resources/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from decimal import Decimal
from typing import Any, overload

from typing_extensions import deprecated

from kalshi.errors import KalshiError
from kalshi.models.common import Page
from kalshi.models.orders import (
Expand Down Expand Up @@ -43,6 +45,7 @@
AsyncResource,
SyncResource,
_check_request_exclusive,
_fills_params,
_join_tickers,
_params,
_seg,
Expand Down Expand Up @@ -274,28 +277,6 @@ def _list_orders_params(
)


def _fills_params(
*,
ticker: str | None,
order_id: str | None,
min_ts: int | None,
max_ts: int | None,
limit: int | None,
cursor: str | None,
subaccount: int | None,
) -> dict[str, Any]:
limit = _validate_limit(limit, hi=1000)
return _params(
ticker=ticker,
order_id=order_id,
min_ts=min_ts,
max_ts=max_ts,
limit=limit,
cursor=cursor,
subaccount=subaccount,
)


def _queue_positions_params(
*,
market_tickers: builtins.list[str] | str | None,
Expand Down Expand Up @@ -582,6 +563,9 @@ def batch_cancel(
raise KalshiError("Expected BatchCancelOrdersResponse body, got 204 No Content.")
return BatchCancelOrdersResponse.model_validate(data)

@deprecated(
"OrdersResource.fills is deprecated; use client.portfolio.fills instead."
)
def fills(
self,
*,
Expand All @@ -594,6 +578,7 @@ def fills(
subaccount: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> Page[Fill]:
"""List trade fills."""
self._require_auth()
params = _fills_params(
ticker=ticker,
Expand All @@ -608,6 +593,9 @@ def fills(
"/portfolio/fills", Fill, "fills", params=params, extra_headers=extra_headers
)

@deprecated(
"OrdersResource.fills_all is deprecated; use client.portfolio.fills_all instead."
)
def fills_all(
self,
*,
Expand All @@ -620,6 +608,7 @@ def fills_all(
max_pages: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> Iterator[Fill]:
"""Auto-paginate trade fills."""
self._require_auth()
_validate_max_pages(max_pages)
params = _fills_params(
Expand Down Expand Up @@ -1125,6 +1114,9 @@ async def batch_cancel(
raise KalshiError("Expected BatchCancelOrdersResponse body, got 204 No Content.")
return BatchCancelOrdersResponse.model_validate(data)

@deprecated(
"AsyncOrdersResource.fills is deprecated; use client.portfolio.fills instead."
)
async def fills(
self,
*,
Expand All @@ -1137,6 +1129,7 @@ async def fills(
subaccount: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> Page[Fill]:
"""List trade fills (async)."""
self._require_auth()
params = _fills_params(
ticker=ticker,
Expand All @@ -1151,6 +1144,9 @@ async def fills(
"/portfolio/fills", Fill, "fills", params=params, extra_headers=extra_headers
)

@deprecated(
"AsyncOrdersResource.fills_all is deprecated; use client.portfolio.fills_all instead."
)
def fills_all(
self,
*,
Expand All @@ -1163,7 +1159,7 @@ def fills_all(
max_pages: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> AsyncIterator[Fill]:
"""Returns an async iterator — use ``async for``."""
"""Auto-paginate trade fills (async). Use ``async for``."""
self._require_auth()
_validate_max_pages(max_pages)
params = _fills_params(
Expand Down
134 changes: 133 additions & 1 deletion kalshi/resources/portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import Any

from kalshi.models.common import Page
from kalshi.models.orders import Fill
from kalshi.models.portfolio import (
Balance,
Deposit,
Expand All @@ -18,6 +19,7 @@
from kalshi.resources._base import (
AsyncResource,
SyncResource,
_fills_params,
_params,
_validate_limit,
_validate_max_pages,
Expand Down Expand Up @@ -67,7 +69,6 @@ def _settlements_params(
subaccount=subaccount,
)


class PortfolioResource(SyncResource):
"""Sync portfolio API."""

Expand Down Expand Up @@ -203,6 +204,71 @@ def settlements_all(
extra_headers=extra_headers,
)

def fills(
self,
*,
ticker: str | None = None,
order_id: str | None = None,
min_ts: int | None = None,
max_ts: int | None = None,
limit: int | None = None,
cursor: str | None = None,
subaccount: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> Page[Fill]:
"""List trade fills (``GET /portfolio/fills``).

Moved from :class:`OrdersResource` in v3.0.0 (issue #351) to group
with the rest of the ``/portfolio/*`` family (``settlements``,
``deposits``, ``withdrawals``).
"""
self._require_auth()
params = _fills_params(
ticker=ticker,
order_id=order_id,
min_ts=min_ts,
max_ts=max_ts,
limit=limit,
cursor=cursor,
subaccount=subaccount,
)
return self._list(
"/portfolio/fills", Fill, "fills", params=params, extra_headers=extra_headers
)

def fills_all(
self,
*,
ticker: str | None = None,
order_id: str | None = None,
min_ts: int | None = None,
max_ts: int | None = None,
limit: int | None = None,
subaccount: int | None = None,
max_pages: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> Iterator[Fill]:
"""Auto-paginate trade fills. Moved from :class:`OrdersResource` in v3.0.0."""
self._require_auth()
_validate_max_pages(max_pages)
params = _fills_params(
ticker=ticker,
order_id=order_id,
min_ts=min_ts,
max_ts=max_ts,
limit=limit,
cursor=None,
subaccount=subaccount,
)
return self._list_all(
"/portfolio/fills",
Fill,
"fills",
params=params,
max_pages=max_pages,
extra_headers=extra_headers,
)

def total_resting_order_value(
self, *, extra_headers: dict[str, str] | None = None
) -> TotalRestingOrderValue:
Expand Down Expand Up @@ -426,6 +492,72 @@ def settlements_all(
extra_headers=extra_headers,
)

async def fills(
self,
*,
ticker: str | None = None,
order_id: str | None = None,
min_ts: int | None = None,
max_ts: int | None = None,
limit: int | None = None,
cursor: str | None = None,
subaccount: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> Page[Fill]:
"""List trade fills (``GET /portfolio/fills``, async).

Moved from :class:`AsyncOrdersResource` in v3.0.0 (issue #351).
"""
self._require_auth()
params = _fills_params(
ticker=ticker,
order_id=order_id,
min_ts=min_ts,
max_ts=max_ts,
limit=limit,
cursor=cursor,
subaccount=subaccount,
)
return await self._list(
"/portfolio/fills", Fill, "fills", params=params, extra_headers=extra_headers
)

def fills_all(
self,
*,
ticker: str | None = None,
order_id: str | None = None,
min_ts: int | None = None,
max_ts: int | None = None,
limit: int | None = None,
subaccount: int | None = None,
max_pages: int | None = None,
extra_headers: dict[str, str] | None = None,
) -> AsyncIterator[Fill]:
"""Auto-paginate trade fills (async). Use ``async for``.

Moved from :class:`AsyncOrdersResource` in v3.0.0 (issue #351).
"""
self._require_auth()
_validate_max_pages(max_pages)
params = _fills_params(
ticker=ticker,
order_id=order_id,
min_ts=min_ts,
max_ts=max_ts,
limit=limit,
cursor=None,
subaccount=subaccount,
)
return self._list_all(
"/portfolio/fills",
Fill,
"fills",
params=params,
max_pages=max_pages,
extra_headers=extra_headers,
)

async def total_resting_order_value(
self, *, extra_headers: dict[str, str] | None = None
) -> TotalRestingOrderValue:
Expand Down
Loading
Loading