Skip to content

Commit

Permalink
feat(api): add modify orders endpoint (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-app[bot] authored and stainless-bot committed Nov 29, 2024
1 parent 929f6de commit f02195a
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
configured_endpoints: 30
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/clear-street%2Fstudio-sdk-468b5da24bbf73b3a3861d44c5a8051fe6c55a6ec64c5c6f2d45f22c76bf35b2.yml
configured_endpoints: 31
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/clear-street%2Fstudio-sdk-5efb317738842339f6e8bd32592691a65d19a54adc34bfa319d6bac2404404a7.yml
1 change: 1 addition & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Methods:
- <code title="get /accounts/{account_id}/orders">client.accounts.orders.<a href="./src/studio_sdk/resources/accounts/orders.py">list</a>(account_id, \*\*<a href="src/studio_sdk/types/accounts/order_list_params.py">params</a>) -> <a href="./src/studio_sdk/types/accounts/order_list_response.py">OrderListResponse</a></code>
- <code title="delete /accounts/{account_id}/orders">client.accounts.orders.<a href="./src/studio_sdk/resources/accounts/orders.py">delete</a>(account_id, \*\*<a href="src/studio_sdk/types/accounts/order_delete_params.py">params</a>) -> <a href="./src/studio_sdk/types/accounts/order_delete_response.py">OrderDeleteResponse</a></code>
- <code title="delete /accounts/{account_id}/orders/{order_id}">client.accounts.orders.<a href="./src/studio_sdk/resources/accounts/orders.py">cancel</a>(order_id, \*, account_id) -> None</code>
- <code title="patch /accounts/{account_id}/orders/{order_id}">client.accounts.orders.<a href="./src/studio_sdk/resources/accounts/orders.py">patch</a>(order_id, \*, account_id, \*\*<a href="src/studio_sdk/types/accounts/order_patch_params.py">params</a>) -> None</code>

## Trades

Expand Down
134 changes: 133 additions & 1 deletion src/studio_sdk/resources/accounts/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
async_to_streamed_response_wrapper,
)
from ..._base_client import make_request_options
from ...types.accounts import order_list_params, order_create_params, order_delete_params
from ...types.accounts import order_list_params, order_patch_params, order_create_params, order_delete_params
from ...types.shared_params.strategy import Strategy
from ...types.accounts.order_list_response import OrderListResponse
from ...types.accounts.order_create_response import OrderCreateResponse
Expand Down Expand Up @@ -359,6 +359,66 @@ def cancel(
cast_to=NoneType,
)

def patch(
self,
order_id: str,
*,
account_id: str,
quantity: str,
price: str | NotGiven = NOT_GIVEN,
stop_price: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> None:
"""Attempts to update an existing order.
This can be used to update a subset of an
order's attributes, for example price and quantity.
Args:
account_id: Account ID for the account.
order_id: Unique order ID assigned by us.
quantity: The maximum quantity to be executed.
price: The price to execute at-or-better for limit orders.
stop_price: The price at which stop orders become marketable.
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
extra_body: Add additional JSON properties to the request
timeout: Override the client-level default timeout for this request, in seconds
"""
if not account_id:
raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
if not order_id:
raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._patch(
f"/accounts/{account_id}/orders/{order_id}",
body=maybe_transform(
{
"quantity": quantity,
"price": price,
"stop_price": stop_price,
},
order_patch_params.OrderPatchParams,
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=NoneType,
)


class AsyncOrdersResource(AsyncAPIResource):
@cached_property
Expand Down Expand Up @@ -689,6 +749,66 @@ async def cancel(
cast_to=NoneType,
)

async def patch(
self,
order_id: str,
*,
account_id: str,
quantity: str,
price: str | NotGiven = NOT_GIVEN,
stop_price: str | NotGiven = NOT_GIVEN,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
) -> None:
"""Attempts to update an existing order.
This can be used to update a subset of an
order's attributes, for example price and quantity.
Args:
account_id: Account ID for the account.
order_id: Unique order ID assigned by us.
quantity: The maximum quantity to be executed.
price: The price to execute at-or-better for limit orders.
stop_price: The price at which stop orders become marketable.
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
extra_body: Add additional JSON properties to the request
timeout: Override the client-level default timeout for this request, in seconds
"""
if not account_id:
raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
if not order_id:
raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._patch(
f"/accounts/{account_id}/orders/{order_id}",
body=await async_maybe_transform(
{
"quantity": quantity,
"price": price,
"stop_price": stop_price,
},
order_patch_params.OrderPatchParams,
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=NoneType,
)


class OrdersResourceWithRawResponse:
def __init__(self, orders: OrdersResource) -> None:
Expand All @@ -709,6 +829,9 @@ def __init__(self, orders: OrdersResource) -> None:
self.cancel = to_raw_response_wrapper(
orders.cancel,
)
self.patch = to_raw_response_wrapper(
orders.patch,
)


class AsyncOrdersResourceWithRawResponse:
Expand All @@ -730,6 +853,9 @@ def __init__(self, orders: AsyncOrdersResource) -> None:
self.cancel = async_to_raw_response_wrapper(
orders.cancel,
)
self.patch = async_to_raw_response_wrapper(
orders.patch,
)


class OrdersResourceWithStreamingResponse:
Expand All @@ -751,6 +877,9 @@ def __init__(self, orders: OrdersResource) -> None:
self.cancel = to_streamed_response_wrapper(
orders.cancel,
)
self.patch = to_streamed_response_wrapper(
orders.patch,
)


class AsyncOrdersResourceWithStreamingResponse:
Expand All @@ -772,3 +901,6 @@ def __init__(self, orders: AsyncOrdersResource) -> None:
self.cancel = async_to_streamed_response_wrapper(
orders.cancel,
)
self.patch = async_to_streamed_response_wrapper(
orders.patch,
)
1 change: 1 addition & 0 deletions src/studio_sdk/types/accounts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from .order_list_params import OrderListParams as OrderListParams
from .trade_list_params import TradeListParams as TradeListParams
from .order_patch_params import OrderPatchParams as OrderPatchParams
from .holding_list_params import HoldingListParams as HoldingListParams
from .order_create_params import OrderCreateParams as OrderCreateParams
from .order_delete_params import OrderDeleteParams as OrderDeleteParams
Expand Down
21 changes: 21 additions & 0 deletions src/studio_sdk/types/accounts/order_patch_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing_extensions import Required, TypedDict

__all__ = ["OrderPatchParams"]


class OrderPatchParams(TypedDict, total=False):
account_id: Required[str]
"""Account ID for the account."""

quantity: Required[str]
"""The maximum quantity to be executed."""

price: str
"""The price to execute at-or-better for limit orders."""

stop_price: str
"""The price at which stop orders become marketable."""
3 changes: 3 additions & 0 deletions src/studio_sdk/types/shared/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class Order(BaseModel):
quantity: str
"""The requested quantity on this order."""

running_position: str
"""The position quantity at the time of this order."""

side: Literal["buy", "sell", "sell-short"]
"""Buy, sell, sell-short indicator."""

Expand Down
3 changes: 3 additions & 0 deletions src/studio_sdk/types/shared/trade.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class Trade(BaseModel):
quantity: str
"""The amount that was traded."""

running_position: str
"""The position quantity at the time of this trade."""

side: Literal["buy", "sell", "sell-short"]
"""The side this trade occurred on."""

Expand Down
128 changes: 128 additions & 0 deletions tests/api_resources/accounts/test_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,70 @@ def test_path_params_cancel(self, client: StudioSDK) -> None:
account_id="x",
)

@parametrize
def test_method_patch(self, client: StudioSDK) -> None:
order = client.accounts.orders.patch(
order_id="x",
account_id="x",
quantity="x",
)
assert order is None

@parametrize
def test_method_patch_with_all_params(self, client: StudioSDK) -> None:
order = client.accounts.orders.patch(
order_id="x",
account_id="x",
quantity="x",
price="x",
stop_price="x",
)
assert order is None

@parametrize
def test_raw_response_patch(self, client: StudioSDK) -> None:
response = client.accounts.orders.with_raw_response.patch(
order_id="x",
account_id="x",
quantity="x",
)

assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
order = response.parse()
assert order is None

@parametrize
def test_streaming_response_patch(self, client: StudioSDK) -> None:
with client.accounts.orders.with_streaming_response.patch(
order_id="x",
account_id="x",
quantity="x",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"

order = response.parse()
assert order is None

assert cast(Any, response.is_closed) is True

@parametrize
def test_path_params_patch(self, client: StudioSDK) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
client.accounts.orders.with_raw_response.patch(
order_id="x",
account_id="",
quantity="x",
)

with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"):
client.accounts.orders.with_raw_response.patch(
order_id="",
account_id="x",
quantity="x",
)


class TestAsyncOrders:
parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
Expand Down Expand Up @@ -571,3 +635,67 @@ async def test_path_params_cancel(self, async_client: AsyncStudioSDK) -> None:
order_id="",
account_id="x",
)

@parametrize
async def test_method_patch(self, async_client: AsyncStudioSDK) -> None:
order = await async_client.accounts.orders.patch(
order_id="x",
account_id="x",
quantity="x",
)
assert order is None

@parametrize
async def test_method_patch_with_all_params(self, async_client: AsyncStudioSDK) -> None:
order = await async_client.accounts.orders.patch(
order_id="x",
account_id="x",
quantity="x",
price="x",
stop_price="x",
)
assert order is None

@parametrize
async def test_raw_response_patch(self, async_client: AsyncStudioSDK) -> None:
response = await async_client.accounts.orders.with_raw_response.patch(
order_id="x",
account_id="x",
quantity="x",
)

assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
order = await response.parse()
assert order is None

@parametrize
async def test_streaming_response_patch(self, async_client: AsyncStudioSDK) -> None:
async with async_client.accounts.orders.with_streaming_response.patch(
order_id="x",
account_id="x",
quantity="x",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"

order = await response.parse()
assert order is None

assert cast(Any, response.is_closed) is True

@parametrize
async def test_path_params_patch(self, async_client: AsyncStudioSDK) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
await async_client.accounts.orders.with_raw_response.patch(
order_id="x",
account_id="",
quantity="x",
)

with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"):
await async_client.accounts.orders.with_raw_response.patch(
order_id="",
account_id="x",
quantity="x",
)

0 comments on commit f02195a

Please sign in to comment.