From c594d64497b66ccbb6c4c6b10d8289094c2f12f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:28:29 +0000 Subject: [PATCH 1/2] feat(api): api update (#51) --- .stats.yml | 4 +- api.md | 24 ++ src/studio_sdk/resources/accounts/__init__.py | 28 +++ src/studio_sdk/resources/accounts/accounts.py | 64 +++++ src/studio_sdk/resources/accounts/holdings.py | 200 ++++++++++++++++ src/studio_sdk/resources/accounts/pnl_sums.py | 224 ++++++++++++++++++ src/studio_sdk/types/accounts/__init__.py | 4 + .../types/accounts/holding_list_params.py | 15 ++ .../types/accounts/holding_list_response.py | 50 ++++ .../accounts/pnl_detail_list_response.py | 2 +- .../types/accounts/pnl_sum_list_params.py | 24 ++ .../types/accounts/pnl_sum_list_response.py | 99 ++++++++ src/studio_sdk/types/instrument.py | 2 +- src/studio_sdk/types/portfolio_margin.py | 2 +- src/studio_sdk/types/regt_margin.py | 2 +- src/studio_sdk/types/shared/strategy.py | 29 +-- .../types/shared_params/strategy.py | 31 +-- tests/api_resources/accounts/test_holdings.py | 114 +++++++++ tests/api_resources/accounts/test_pnl_sums.py | 136 +++++++++++ 19 files changed, 990 insertions(+), 64 deletions(-) create mode 100644 src/studio_sdk/resources/accounts/holdings.py create mode 100644 src/studio_sdk/resources/accounts/pnl_sums.py create mode 100644 src/studio_sdk/types/accounts/holding_list_params.py create mode 100644 src/studio_sdk/types/accounts/holding_list_response.py create mode 100644 src/studio_sdk/types/accounts/pnl_sum_list_params.py create mode 100644 src/studio_sdk/types/accounts/pnl_sum_list_response.py create mode 100644 tests/api_resources/accounts/test_holdings.py create mode 100644 tests/api_resources/accounts/test_pnl_sums.py diff --git a/.stats.yml b/.stats.yml index 9c54f2d..7c7707f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 27 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/clear-street%2Fstudio-sdk-414d28e743994ae591921b9df65e07bbd8d423d847d9607a0363c510d6d79e36.yml +configured_endpoints: 29 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/clear-street%2Fstudio-sdk-468b5da24bbf73b3a3861d44c5a8051fe6c55a6ec64c5c6f2d45f22c76bf35b2.yml diff --git a/api.md b/api.md index 7b4e6d6..4da6f26 100644 --- a/api.md +++ b/api.md @@ -173,6 +173,30 @@ Methods: - client.accounts.pnl_details.list(account_id) -> PnlDetailListResponse +## PnlSums + +Types: + +```python +from studio_sdk.types.accounts import PnlSumListResponse +``` + +Methods: + +- client.accounts.pnl_sums.list(account_id, \*\*params) -> PnlSumListResponse + +## Holdings + +Types: + +```python +from studio_sdk.types.accounts import HoldingListResponse +``` + +Methods: + +- client.accounts.holdings.list(account_id, \*\*params) -> HoldingListResponse + # Instruments Types: diff --git a/src/studio_sdk/resources/accounts/__init__.py b/src/studio_sdk/resources/accounts/__init__.py index 1a5803c..99fbacb 100644 --- a/src/studio_sdk/resources/accounts/__init__.py +++ b/src/studio_sdk/resources/accounts/__init__.py @@ -24,6 +24,22 @@ AccountsResourceWithStreamingResponse, AsyncAccountsResourceWithStreamingResponse, ) +from .holdings import ( + HoldingsResource, + AsyncHoldingsResource, + HoldingsResourceWithRawResponse, + AsyncHoldingsResourceWithRawResponse, + HoldingsResourceWithStreamingResponse, + AsyncHoldingsResourceWithStreamingResponse, +) +from .pnl_sums import ( + PnlSumsResource, + AsyncPnlSumsResource, + PnlSumsResourceWithRawResponse, + AsyncPnlSumsResourceWithRawResponse, + PnlSumsResourceWithStreamingResponse, + AsyncPnlSumsResourceWithStreamingResponse, +) from .positions import ( PositionsResource, AsyncPositionsResource, @@ -122,6 +138,18 @@ "AsyncPnlDetailsResourceWithRawResponse", "PnlDetailsResourceWithStreamingResponse", "AsyncPnlDetailsResourceWithStreamingResponse", + "PnlSumsResource", + "AsyncPnlSumsResource", + "PnlSumsResourceWithRawResponse", + "AsyncPnlSumsResourceWithRawResponse", + "PnlSumsResourceWithStreamingResponse", + "AsyncPnlSumsResourceWithStreamingResponse", + "HoldingsResource", + "AsyncHoldingsResource", + "HoldingsResourceWithRawResponse", + "AsyncHoldingsResourceWithRawResponse", + "HoldingsResourceWithStreamingResponse", + "AsyncHoldingsResourceWithStreamingResponse", "AccountsResource", "AsyncAccountsResource", "AccountsResourceWithRawResponse", diff --git a/src/studio_sdk/resources/accounts/accounts.py b/src/studio_sdk/resources/accounts/accounts.py index 4c441e8..a87dd7b 100644 --- a/src/studio_sdk/resources/accounts/accounts.py +++ b/src/studio_sdk/resources/accounts/accounts.py @@ -21,6 +21,22 @@ AsyncTradesResourceWithStreamingResponse, ) from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .holdings import ( + HoldingsResource, + AsyncHoldingsResource, + HoldingsResourceWithRawResponse, + AsyncHoldingsResourceWithRawResponse, + HoldingsResourceWithStreamingResponse, + AsyncHoldingsResourceWithStreamingResponse, +) +from .pnl_sums import ( + PnlSumsResource, + AsyncPnlSumsResource, + PnlSumsResourceWithRawResponse, + AsyncPnlSumsResourceWithRawResponse, + PnlSumsResourceWithStreamingResponse, + AsyncPnlSumsResourceWithStreamingResponse, +) from ..._compat import cached_property from .positions import ( PositionsResource, @@ -117,6 +133,14 @@ def pnl_summary(self) -> PnlSummaryResource: def pnl_details(self) -> PnlDetailsResource: return PnlDetailsResource(self._client) + @cached_property + def pnl_sums(self) -> PnlSumsResource: + return PnlSumsResource(self._client) + + @cached_property + def holdings(self) -> HoldingsResource: + return HoldingsResource(self._client) + @cached_property def with_raw_response(self) -> AccountsResourceWithRawResponse: """ @@ -224,6 +248,14 @@ def pnl_summary(self) -> AsyncPnlSummaryResource: def pnl_details(self) -> AsyncPnlDetailsResource: return AsyncPnlDetailsResource(self._client) + @cached_property + def pnl_sums(self) -> AsyncPnlSumsResource: + return AsyncPnlSumsResource(self._client) + + @cached_property + def holdings(self) -> AsyncHoldingsResource: + return AsyncHoldingsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncAccountsResourceWithRawResponse: """ @@ -341,6 +373,14 @@ def pnl_summary(self) -> PnlSummaryResourceWithRawResponse: def pnl_details(self) -> PnlDetailsResourceWithRawResponse: return PnlDetailsResourceWithRawResponse(self._accounts.pnl_details) + @cached_property + def pnl_sums(self) -> PnlSumsResourceWithRawResponse: + return PnlSumsResourceWithRawResponse(self._accounts.pnl_sums) + + @cached_property + def holdings(self) -> HoldingsResourceWithRawResponse: + return HoldingsResourceWithRawResponse(self._accounts.holdings) + class AsyncAccountsResourceWithRawResponse: def __init__(self, accounts: AsyncAccountsResource) -> None: @@ -385,6 +425,14 @@ def pnl_summary(self) -> AsyncPnlSummaryResourceWithRawResponse: def pnl_details(self) -> AsyncPnlDetailsResourceWithRawResponse: return AsyncPnlDetailsResourceWithRawResponse(self._accounts.pnl_details) + @cached_property + def pnl_sums(self) -> AsyncPnlSumsResourceWithRawResponse: + return AsyncPnlSumsResourceWithRawResponse(self._accounts.pnl_sums) + + @cached_property + def holdings(self) -> AsyncHoldingsResourceWithRawResponse: + return AsyncHoldingsResourceWithRawResponse(self._accounts.holdings) + class AccountsResourceWithStreamingResponse: def __init__(self, accounts: AccountsResource) -> None: @@ -429,6 +477,14 @@ def pnl_summary(self) -> PnlSummaryResourceWithStreamingResponse: def pnl_details(self) -> PnlDetailsResourceWithStreamingResponse: return PnlDetailsResourceWithStreamingResponse(self._accounts.pnl_details) + @cached_property + def pnl_sums(self) -> PnlSumsResourceWithStreamingResponse: + return PnlSumsResourceWithStreamingResponse(self._accounts.pnl_sums) + + @cached_property + def holdings(self) -> HoldingsResourceWithStreamingResponse: + return HoldingsResourceWithStreamingResponse(self._accounts.holdings) + class AsyncAccountsResourceWithStreamingResponse: def __init__(self, accounts: AsyncAccountsResource) -> None: @@ -472,3 +528,11 @@ def pnl_summary(self) -> AsyncPnlSummaryResourceWithStreamingResponse: @cached_property def pnl_details(self) -> AsyncPnlDetailsResourceWithStreamingResponse: return AsyncPnlDetailsResourceWithStreamingResponse(self._accounts.pnl_details) + + @cached_property + def pnl_sums(self) -> AsyncPnlSumsResourceWithStreamingResponse: + return AsyncPnlSumsResourceWithStreamingResponse(self._accounts.pnl_sums) + + @cached_property + def holdings(self) -> AsyncHoldingsResourceWithStreamingResponse: + return AsyncHoldingsResourceWithStreamingResponse(self._accounts.holdings) diff --git a/src/studio_sdk/resources/accounts/holdings.py b/src/studio_sdk/resources/accounts/holdings.py new file mode 100644 index 0000000..074ad5f --- /dev/null +++ b/src/studio_sdk/resources/accounts/holdings.py @@ -0,0 +1,200 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import ( + maybe_transform, + async_maybe_transform, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.accounts import holding_list_params +from ...types.accounts.holding_list_response import HoldingListResponse + +__all__ = ["HoldingsResource", "AsyncHoldingsResource"] + + +class HoldingsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> HoldingsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#accessing-raw-response-data-eg-headers + """ + return HoldingsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> HoldingsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#with_streaming_response + """ + return HoldingsResourceWithStreamingResponse(self) + + def list( + self, + account_id: str, + *, + date: int | 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, + ) -> HoldingListResponse: + """List holdings for a given account, filtered on the given query parameters. + + This + endpoint will return either historical or real-time holdings directly from our + custodial systems. Positions returned here are can be different than positions + returned from the Execution API. While the Execution API returns positions based + on trading activity within Studio, our custodial system returns all positions + regardless of where trades occur. + + Args: + account_id: Account ID for the account. + + date: The historical date to get holdings for. If omitted, current real-time holdings + will be returned. + + 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}") + return self._get( + f"/accounts/{account_id}/holdings", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"date": date}, holding_list_params.HoldingListParams), + ), + cast_to=HoldingListResponse, + ) + + +class AsyncHoldingsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncHoldingsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncHoldingsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncHoldingsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#with_streaming_response + """ + return AsyncHoldingsResourceWithStreamingResponse(self) + + async def list( + self, + account_id: str, + *, + date: int | 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, + ) -> HoldingListResponse: + """List holdings for a given account, filtered on the given query parameters. + + This + endpoint will return either historical or real-time holdings directly from our + custodial systems. Positions returned here are can be different than positions + returned from the Execution API. While the Execution API returns positions based + on trading activity within Studio, our custodial system returns all positions + regardless of where trades occur. + + Args: + account_id: Account ID for the account. + + date: The historical date to get holdings for. If omitted, current real-time holdings + will be returned. + + 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}") + return await self._get( + f"/accounts/{account_id}/holdings", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"date": date}, holding_list_params.HoldingListParams), + ), + cast_to=HoldingListResponse, + ) + + +class HoldingsResourceWithRawResponse: + def __init__(self, holdings: HoldingsResource) -> None: + self._holdings = holdings + + self.list = to_raw_response_wrapper( + holdings.list, + ) + + +class AsyncHoldingsResourceWithRawResponse: + def __init__(self, holdings: AsyncHoldingsResource) -> None: + self._holdings = holdings + + self.list = async_to_raw_response_wrapper( + holdings.list, + ) + + +class HoldingsResourceWithStreamingResponse: + def __init__(self, holdings: HoldingsResource) -> None: + self._holdings = holdings + + self.list = to_streamed_response_wrapper( + holdings.list, + ) + + +class AsyncHoldingsResourceWithStreamingResponse: + def __init__(self, holdings: AsyncHoldingsResource) -> None: + self._holdings = holdings + + self.list = async_to_streamed_response_wrapper( + holdings.list, + ) diff --git a/src/studio_sdk/resources/accounts/pnl_sums.py b/src/studio_sdk/resources/accounts/pnl_sums.py new file mode 100644 index 0000000..c2e1882 --- /dev/null +++ b/src/studio_sdk/resources/accounts/pnl_sums.py @@ -0,0 +1,224 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from ..._utils import ( + maybe_transform, + async_maybe_transform, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.accounts import pnl_sum_list_params +from ...types.accounts.pnl_sum_list_response import PnlSumListResponse + +__all__ = ["PnlSumsResource", "AsyncPnlSumsResource"] + + +class PnlSumsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> PnlSumsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#accessing-raw-response-data-eg-headers + """ + return PnlSumsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PnlSumsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#with_streaming_response + """ + return PnlSumsResourceWithStreamingResponse(self) + + def list( + self, + account_id: str, + *, + ending_date: int, + starting_date: int, + symbol: str | NotGiven = NOT_GIVEN, + underlying_symbol: 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, + ) -> PnlSumListResponse: + """ + List historical PNL summations for a given account over a given date range, + filtered on the given query parameters. + + Args: + account_id: Account ID for the account. + + ending_date: The ending date to accumulate PNL data for, inclusive. + + starting_date: The starting date to accumulate PNL data for. + + symbol: Filters for a specific symbol. + + underlying_symbol: Filters for a specific underlying symbol, e.g. all options for a particular + underlying. + + 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}") + return self._get( + f"/accounts/{account_id}/pnl-sums", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "ending_date": ending_date, + "starting_date": starting_date, + "symbol": symbol, + "underlying_symbol": underlying_symbol, + }, + pnl_sum_list_params.PnlSumListParams, + ), + ), + cast_to=PnlSumListResponse, + ) + + +class AsyncPnlSumsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncPnlSumsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return the + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncPnlSumsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPnlSumsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/clear-street/studio-sdk-python#with_streaming_response + """ + return AsyncPnlSumsResourceWithStreamingResponse(self) + + async def list( + self, + account_id: str, + *, + ending_date: int, + starting_date: int, + symbol: str | NotGiven = NOT_GIVEN, + underlying_symbol: 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, + ) -> PnlSumListResponse: + """ + List historical PNL summations for a given account over a given date range, + filtered on the given query parameters. + + Args: + account_id: Account ID for the account. + + ending_date: The ending date to accumulate PNL data for, inclusive. + + starting_date: The starting date to accumulate PNL data for. + + symbol: Filters for a specific symbol. + + underlying_symbol: Filters for a specific underlying symbol, e.g. all options for a particular + underlying. + + 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}") + return await self._get( + f"/accounts/{account_id}/pnl-sums", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "ending_date": ending_date, + "starting_date": starting_date, + "symbol": symbol, + "underlying_symbol": underlying_symbol, + }, + pnl_sum_list_params.PnlSumListParams, + ), + ), + cast_to=PnlSumListResponse, + ) + + +class PnlSumsResourceWithRawResponse: + def __init__(self, pnl_sums: PnlSumsResource) -> None: + self._pnl_sums = pnl_sums + + self.list = to_raw_response_wrapper( + pnl_sums.list, + ) + + +class AsyncPnlSumsResourceWithRawResponse: + def __init__(self, pnl_sums: AsyncPnlSumsResource) -> None: + self._pnl_sums = pnl_sums + + self.list = async_to_raw_response_wrapper( + pnl_sums.list, + ) + + +class PnlSumsResourceWithStreamingResponse: + def __init__(self, pnl_sums: PnlSumsResource) -> None: + self._pnl_sums = pnl_sums + + self.list = to_streamed_response_wrapper( + pnl_sums.list, + ) + + +class AsyncPnlSumsResourceWithStreamingResponse: + def __init__(self, pnl_sums: AsyncPnlSumsResource) -> None: + self._pnl_sums = pnl_sums + + self.list = async_to_streamed_response_wrapper( + pnl_sums.list, + ) diff --git a/src/studio_sdk/types/accounts/__init__.py b/src/studio_sdk/types/accounts/__init__.py index 02e032e..707f897 100644 --- a/src/studio_sdk/types/accounts/__init__.py +++ b/src/studio_sdk/types/accounts/__init__.py @@ -4,13 +4,17 @@ from .order_list_params import OrderListParams as OrderListParams from .trade_list_params import TradeListParams as TradeListParams +from .holding_list_params import HoldingListParams as HoldingListParams from .order_create_params import OrderCreateParams as OrderCreateParams from .order_delete_params import OrderDeleteParams as OrderDeleteParams from .order_list_response import OrderListResponse as OrderListResponse +from .pnl_sum_list_params import PnlSumListParams as PnlSumListParams from .trade_list_response import TradeListResponse as TradeListResponse from .position_list_params import PositionListParams as PositionListParams +from .holding_list_response import HoldingListResponse as HoldingListResponse from .order_create_response import OrderCreateResponse as OrderCreateResponse from .order_delete_response import OrderDeleteResponse as OrderDeleteResponse +from .pnl_sum_list_response import PnlSumListResponse as PnlSumListResponse from .position_list_response import PositionListResponse as PositionListResponse from .order_retrieve_response import OrderRetrieveResponse as OrderRetrieveResponse from .bulk_order_create_params import BulkOrderCreateParams as BulkOrderCreateParams diff --git a/src/studio_sdk/types/accounts/holding_list_params.py b/src/studio_sdk/types/accounts/holding_list_params.py new file mode 100644 index 0000000..87762ba --- /dev/null +++ b/src/studio_sdk/types/accounts/holding_list_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["HoldingListParams"] + + +class HoldingListParams(TypedDict, total=False): + date: int + """The historical date to get holdings for. + + If omitted, current real-time holdings will be returned. + """ diff --git a/src/studio_sdk/types/accounts/holding_list_response.py b/src/studio_sdk/types/accounts/holding_list_response.py new file mode 100644 index 0000000..d0bee2f --- /dev/null +++ b/src/studio_sdk/types/accounts/holding_list_response.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["HoldingListResponse", "Data"] + + +class Data(BaseModel): + asset_class: Literal["other", "currency", "equity", "option", "debt", "fund"] + """The asset class of the symbol.""" + + quantity: str + """The quantity held for the given symbol. + + This is an EOD quantity if querying historically, else the current real-time + quantity for the current date. + """ + + sod_quantity: str + """The quantity held for the given symbol at the start of the day.""" + + symbol: str + + symbol_description: Optional[str] = None + """Description of the symbol.""" + + +class HoldingListResponse(BaseModel): + account_id: str + """Account ID for the account.""" + + data: List[Data] + + date: int + """Integer in YYYYMMDD representing a date.""" + + sod_equity: float + """Start of day equity.""" + + eod_equity: Optional[float] = None + """For historical holdings, the end of day equity. Omitted for real-time holdings.""" + + timestamp: Optional[int] = None + """ + For real-time holdings, the timestamp reflecting the last update made to the + holdings data. Omitted for historical holdings. + """ diff --git a/src/studio_sdk/types/accounts/pnl_detail_list_response.py b/src/studio_sdk/types/accounts/pnl_detail_list_response.py index 6ced21d..b655b3d 100644 --- a/src/studio_sdk/types/accounts/pnl_detail_list_response.py +++ b/src/studio_sdk/types/accounts/pnl_detail_list_response.py @@ -12,7 +12,7 @@ class Data(BaseModel): account_id: str """Account ID for the account.""" - asset_class: Literal["other", "equity", "option", "debt"] + asset_class: Literal["other", "currency", "equity", "option", "debt", "fund"] """The asset class of the symbol.""" bought_quantity: str diff --git a/src/studio_sdk/types/accounts/pnl_sum_list_params.py b/src/studio_sdk/types/accounts/pnl_sum_list_params.py new file mode 100644 index 0000000..77274a5 --- /dev/null +++ b/src/studio_sdk/types/accounts/pnl_sum_list_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["PnlSumListParams"] + + +class PnlSumListParams(TypedDict, total=False): + ending_date: Required[int] + """The ending date to accumulate PNL data for, inclusive.""" + + starting_date: Required[int] + """The starting date to accumulate PNL data for.""" + + symbol: str + """Filters for a specific symbol.""" + + underlying_symbol: str + """Filters for a specific underlying symbol, e.g. + + all options for a particular underlying. + """ diff --git a/src/studio_sdk/types/accounts/pnl_sum_list_response.py b/src/studio_sdk/types/accounts/pnl_sum_list_response.py new file mode 100644 index 0000000..420366f --- /dev/null +++ b/src/studio_sdk/types/accounts/pnl_sum_list_response.py @@ -0,0 +1,99 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["PnlSumListResponse", "Data"] + + +class Data(BaseModel): + asset_class: Optional[Literal["other", "currency", "equity", "option", "debt", "fund"]] = None + """The asset class of the symbol.""" + + bought_notional: Optional[float] = None + """Sum of the notional bought.""" + + bought_quantity: Optional[str] = None + """Sum of quantity bought.""" + + day_pnl: Optional[float] = None + """ + Sum of profit and loss from intraday trading activities for the given date range + """ + + position_pnl: Optional[float] = None + """Sum of profit and loss from previous trading date.""" + + realized_pnl: Optional[float] = None + """Sum of profit and loss realized from position closing trading activity.""" + + sold_notional: Optional[float] = None + """Sum of the notional sold.""" + + sold_quantity: Optional[str] = None + """Sum of quantity sold.""" + + symbol: Optional[str] = None + + total_pnl: Optional[float] = None + """`realized_pnl + unrealized_pnl`""" + + unrealized_pnl: Optional[float] = None + """Sum of profit and loss from market changes.""" + + +class PnlSumListResponse(BaseModel): + account_id: Optional[str] = None + """Account ID for the account.""" + + data: Optional[List[Data]] = None + + day_pnl: Optional[float] = None + """ + Sum of profit and loss from intraday trading activities for the given date range + across all symbols. + """ + + ending_date: Optional[int] = None + """Echoed back from the provided query param.""" + + ending_equity: Optional[float] = None + """The equity at the end of the date range. + + End of day equity of the ending date in the date range. + """ + + entity_id: Optional[str] = None + """Entity ID for the legal entity.""" + + position_pnl: Optional[float] = None + """Sum of profit and loss from previous trading date across all symbols.""" + + realized_pnl: Optional[float] = None + """ + Sum of profit and loss realized from position closing trading activity across + all symbols. + """ + + starting_date: Optional[int] = None + """Echoed back from the provided query param.""" + + starting_equity: Optional[float] = None + """The equity at the start of the date range. + + Start of day equity of the starting date in the date range. + """ + + symbol: Optional[str] = None + """Echoed back from the provided query param.""" + + total_pnl: Optional[float] = None + """`realized_pnl + unrealized_pnl`""" + + underlying_symbol: Optional[str] = None + """Echoed back from the provided query param.""" + + unrealized_pnl: Optional[float] = None + """Sum of profit and loss from market changes across all symbols.""" diff --git a/src/studio_sdk/types/instrument.py b/src/studio_sdk/types/instrument.py index 3e38cb5..8d18102 100644 --- a/src/studio_sdk/types/instrument.py +++ b/src/studio_sdk/types/instrument.py @@ -16,7 +16,7 @@ class Symbol(BaseModel): class Instrument(BaseModel): - asset_class: Literal["other", "equity", "option", "debt"] + asset_class: Literal["other", "currency", "equity", "option", "debt", "fund"] """The asset class of the symbol.""" description: str diff --git a/src/studio_sdk/types/portfolio_margin.py b/src/studio_sdk/types/portfolio_margin.py index 8bbdd9f..af37924 100644 --- a/src/studio_sdk/types/portfolio_margin.py +++ b/src/studio_sdk/types/portfolio_margin.py @@ -9,7 +9,7 @@ class GroupMember(BaseModel): - asset_class: Optional[Literal["other", "equity", "option", "debt"]] = None + asset_class: Optional[Literal["other", "currency", "equity", "option", "debt", "fund"]] = None """The asset class of the symbol.""" market_value: Optional[float] = None diff --git a/src/studio_sdk/types/regt_margin.py b/src/studio_sdk/types/regt_margin.py index 25903c0..22b38c0 100644 --- a/src/studio_sdk/types/regt_margin.py +++ b/src/studio_sdk/types/regt_margin.py @@ -9,7 +9,7 @@ class GroupMember(BaseModel): - asset_class: Literal["other", "equity", "option", "debt"] + asset_class: Literal["other", "currency", "equity", "option", "debt", "fund"] """The asset class of the symbol.""" market_value: float diff --git a/src/studio_sdk/types/shared/strategy.py b/src/studio_sdk/types/shared/strategy.py index 1e44cfa..1078d95 100644 --- a/src/studio_sdk/types/shared/strategy.py +++ b/src/studio_sdk/types/shared/strategy.py @@ -11,22 +11,7 @@ class DmaStrategy(BaseModel): destination: Literal[ - "arcx", - "bats", - "baty", - "edga", - "edgx", - "eprl", - "gotc", - "iexg", - "memx", - "xase", - "xbos", - "xcis", - "xchi", - "xnms", - "xnys", - "xphl", + "arcx", "bats", "baty", "edga", "edgx", "eprl", "iexg", "memx", "xase", "xbos", "xcis", "xnms", "xnys" ] """Order Destination. @@ -61,10 +46,6 @@ class DmaStrategy(BaseModel): MIAX Pearl Equities - GOTC - ARCA Global OTC - - IEXG Investors' Exchange @@ -85,10 +66,6 @@ class DmaStrategy(BaseModel): NYSE National - XCHI - Chicago Stock Exchange - - XNMS NASDAQ/NMS (Global Market) @@ -96,10 +73,6 @@ class DmaStrategy(BaseModel): XNYS New York Stock Exchange - - XPHL - NASDAQ PHLX Exchange - """ diff --git a/src/studio_sdk/types/shared_params/strategy.py b/src/studio_sdk/types/shared_params/strategy.py index fc777d9..f335b19 100644 --- a/src/studio_sdk/types/shared_params/strategy.py +++ b/src/studio_sdk/types/shared_params/strategy.py @@ -12,24 +12,7 @@ class DmaStrategy(TypedDict, total=False): destination: Required[ - Literal[ - "arcx", - "bats", - "baty", - "edga", - "edgx", - "eprl", - "gotc", - "iexg", - "memx", - "xase", - "xbos", - "xcis", - "xchi", - "xnms", - "xnys", - "xphl", - ] + Literal["arcx", "bats", "baty", "edga", "edgx", "eprl", "iexg", "memx", "xase", "xbos", "xcis", "xnms", "xnys"] ] """Order Destination. @@ -64,10 +47,6 @@ class DmaStrategy(TypedDict, total=False): MIAX Pearl Equities - GOTC - ARCA Global OTC - - IEXG Investors' Exchange @@ -88,10 +67,6 @@ class DmaStrategy(TypedDict, total=False): NYSE National - XCHI - Chicago Stock Exchange - - XNMS NASDAQ/NMS (Global Market) @@ -99,10 +74,6 @@ class DmaStrategy(TypedDict, total=False): XNYS New York Stock Exchange - - XPHL - NASDAQ PHLX Exchange - """ diff --git a/tests/api_resources/accounts/test_holdings.py b/tests/api_resources/accounts/test_holdings.py new file mode 100644 index 0000000..6e0b194 --- /dev/null +++ b/tests/api_resources/accounts/test_holdings.py @@ -0,0 +1,114 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from studio_sdk import StudioSDK, AsyncStudioSDK +from tests.utils import assert_matches_type +from studio_sdk.types.accounts import HoldingListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestHoldings: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: StudioSDK) -> None: + holding = client.accounts.holdings.list( + account_id="x", + ) + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: StudioSDK) -> None: + holding = client.accounts.holdings.list( + account_id="x", + date=20240101, + ) + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: StudioSDK) -> None: + response = client.accounts.holdings.with_raw_response.list( + account_id="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + holding = response.parse() + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: StudioSDK) -> None: + with client.accounts.holdings.with_streaming_response.list( + account_id="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + holding = response.parse() + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: StudioSDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.accounts.holdings.with_raw_response.list( + account_id="", + ) + + +class TestAsyncHoldings: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_list(self, async_client: AsyncStudioSDK) -> None: + holding = await async_client.accounts.holdings.list( + account_id="x", + ) + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncStudioSDK) -> None: + holding = await async_client.accounts.holdings.list( + account_id="x", + date=20240101, + ) + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncStudioSDK) -> None: + response = await async_client.accounts.holdings.with_raw_response.list( + account_id="x", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + holding = await response.parse() + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncStudioSDK) -> None: + async with async_client.accounts.holdings.with_streaming_response.list( + account_id="x", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + holding = await response.parse() + assert_matches_type(HoldingListResponse, holding, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(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.holdings.with_raw_response.list( + account_id="", + ) diff --git a/tests/api_resources/accounts/test_pnl_sums.py b/tests/api_resources/accounts/test_pnl_sums.py new file mode 100644 index 0000000..6ffb784 --- /dev/null +++ b/tests/api_resources/accounts/test_pnl_sums.py @@ -0,0 +1,136 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from studio_sdk import StudioSDK, AsyncStudioSDK +from tests.utils import assert_matches_type +from studio_sdk.types.accounts import PnlSumListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestPnlSums: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: StudioSDK) -> None: + pnl_sum = client.accounts.pnl_sums.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + ) + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + @parametrize + def test_method_list_with_all_params(self, client: StudioSDK) -> None: + pnl_sum = client.accounts.pnl_sums.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + symbol="AAPL", + underlying_symbol="AAPL", + ) + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: StudioSDK) -> None: + response = client.accounts.pnl_sums.with_raw_response.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + pnl_sum = response.parse() + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: StudioSDK) -> None: + with client.accounts.pnl_sums.with_streaming_response.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + pnl_sum = response.parse() + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: StudioSDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"): + client.accounts.pnl_sums.with_raw_response.list( + account_id="", + ending_date=20240101, + starting_date=20240101, + ) + + +class TestAsyncPnlSums: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_list(self, async_client: AsyncStudioSDK) -> None: + pnl_sum = await async_client.accounts.pnl_sums.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + ) + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncStudioSDK) -> None: + pnl_sum = await async_client.accounts.pnl_sums.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + symbol="AAPL", + underlying_symbol="AAPL", + ) + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncStudioSDK) -> None: + response = await async_client.accounts.pnl_sums.with_raw_response.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + pnl_sum = await response.parse() + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncStudioSDK) -> None: + async with async_client.accounts.pnl_sums.with_streaming_response.list( + account_id="x", + ending_date=20240101, + starting_date=20240101, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + pnl_sum = await response.parse() + assert_matches_type(PnlSumListResponse, pnl_sum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(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.pnl_sums.with_raw_response.list( + account_id="", + ending_date=20240101, + starting_date=20240101, + ) From 05f239eabd75b0ce17574865e394c162e98f0e76 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:28:46 +0000 Subject: [PATCH 2/2] release: 0.1.0-alpha.11 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- src/studio_sdk/_version.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3b005e5..ee49ac2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.10" + ".": "0.1.0-alpha.11" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 51b3653..f54c2b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.1.0-alpha.11 (2024-10-11) + +Full Changelog: [v0.1.0-alpha.10...v0.1.0-alpha.11](https://github.com/clear-street/studio-sdk-python/compare/v0.1.0-alpha.10...v0.1.0-alpha.11) + +### Features + +* **api:** api update ([#51](https://github.com/clear-street/studio-sdk-python/issues/51)) ([c594d64](https://github.com/clear-street/studio-sdk-python/commit/c594d64497b66ccbb6c4c6b10d8289094c2f12f0)) + ## 0.1.0-alpha.10 (2024-10-04) Full Changelog: [v0.1.0-alpha.9...v0.1.0-alpha.10](https://github.com/clear-street/studio-sdk-python/compare/v0.1.0-alpha.9...v0.1.0-alpha.10) diff --git a/pyproject.toml b/pyproject.toml index 06aa257..c830484 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "clear-street-studio-sdk" -version = "0.1.0-alpha.10" +version = "0.1.0-alpha.11" description = "The official Python library for the studio-sdk API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/studio_sdk/_version.py b/src/studio_sdk/_version.py index 7338253..275d8ae 100644 --- a/src/studio_sdk/_version.py +++ b/src/studio_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "studio_sdk" -__version__ = "0.1.0-alpha.10" # x-release-please-version +__version__ = "0.1.0-alpha.11" # x-release-please-version