Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Onfido endpoints #329

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
19b0b55
adding import to trading init file
andrewwoood Oct 3, 2022
12dd729
fixing an issue that prevented orders from being created because of h…
gageorsburn Apr 20, 2023
6098259
fix type return
gageorsburn Apr 20, 2023
013e25d
add pre validator
gageorsburn Apr 20, 2023
f1d4132
type dict -> Dict
gageorsburn Apr 20, 2023
5899b03
Merge branch 'alpacahq:master' into master
alessiocastrica Jun 27, 2023
3251233
Merge pull request #173 from andrewwoood/fix/trading_stream_import_mi…
haxdds Jul 12, 2023
0665d88
Merge branch 'alpacahq:master' into master
alessiocastrica Jul 17, 2023
53e4c8f
feat: migration to pydantic v2.0.3
alessiocastrica Jul 17, 2023
06fb1bd
Merge pull request #275 from gageorsburn/fix-order-type-currency-vali…
haxdds Jul 18, 2023
0fd3deb
Merge branch 'staging' into pydantic-v2
haxdds Jul 18, 2023
752efb7
Merge pull request #315 from alessiocastrica/pydantic-v2
haxdds Jul 18, 2023
27d401c
fix: replaced root_validator
alessiocastrica Jul 26, 2023
7ead956
feat: bump websockets to latest version
alessiocastrica Jul 26, 2023
621dcee
Merge pull request #321 from alessiocastrica/develop
haxdds Jul 28, 2023
a8cf389
fix: del unused websocket
alessiocastrica Jul 28, 2023
61d43cd
fix: models dump and config for pydantic v2
alessiocastrica Jul 28, 2023
7407b93
Merge pull request #325 from alessiocastrica/develop
haxdds Aug 2, 2023
28ece5d
Merge pull request #322 from alessiocastrica/bump-websockets-to-v11
haxdds Aug 2, 2023
4452d9e
fix: relative to absolute imports and explicit exports
alessiocastrica Aug 2, 2023
728d2cb
merge conflict resolve
Aug 2, 2023
4e4b148
Merge pull request #326 from alessiocastrica/fix-320
haxdds Aug 2, 2023
89dd3d3
feat: draft onfido endpoints
alessiocastrica Aug 4, 2023
7e27ff2
fix: linting
alessiocastrica Aug 4, 2023
3d5bec0
fixes and tests
alessiocastrica Aug 25, 2023
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: 8 additions & 4 deletions alpaca/broker/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from .client import BrokerClient
from .enums import *
from .models import *
from .requests import *
from alpaca.broker.client import BrokerClient
from alpaca.broker.enums import *
from alpaca.broker.models import *
from alpaca.broker.requests import *

__all__ = [
"BrokerClient",
]
118 changes: 88 additions & 30 deletions alpaca/broker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,32 @@

import sseclient

from pydantic import parse_obj_as
from pydantic import TypeAdapter
from requests import HTTPError, Response

from .enums import ACHRelationshipStatus

from alpaca.broker.enums import ACHRelationshipStatus
from alpaca.broker.models import (
ACHRelationship,
Account,
Bank,
CIPInfo,
OnfidoToken,
TradeAccount,
TradeDocument,
Transfer,
Order,
BatchJournalResponse,
Journal,
)
from .requests import (
from alpaca.broker.requests import (
CreateJournalRequest,
CreateBatchJournalRequest,
CreateReverseBatchJournalRequest,
GetJournalsRequest,
GetOnfidoTokenRequest,
OrderRequest,
CancelOrderResponse,
UpdateOnfidoOutcomeRequest,
UploadDocumentRequest,
CreateACHRelationshipRequest,
CreateACHTransferRequest,
Expand Down Expand Up @@ -126,7 +129,7 @@ def __init__(
base_url = (
url_override
if url_override is not None
else BaseURL.BROKER_SANDBOX
else BaseURL.BROKER_SANDBOX.value
if sandbox
else BaseURL.BROKER_PRODUCTION
)
Expand Down Expand Up @@ -273,8 +276,7 @@ def list_accounts(

if self._use_raw_data:
return response

return parse_obj_as(List[Account], response)
return TypeAdapter(List[Account]).validate_python(response)

def get_trade_account_by_id(
self,
Expand Down Expand Up @@ -378,7 +380,8 @@ def update_trade_configuration_for_account(
account_id = validate_uuid_id_param(account_id, "account_id")

result = self.patch(
f"/trading/accounts/{account_id}/account/configurations", config.json()
f"/trading/accounts/{account_id}/account/configurations",
config.model_dump_json(),
)

if self._use_raw_data:
Expand Down Expand Up @@ -459,8 +462,8 @@ def get_account_activities(
def _get_account_activities_iterator(
self,
activity_filter: GetAccountActivitiesRequest,
max_items_limit: Optional[int],
mapping: Callable[[HTTPResult], List[BaseActivity]],
max_items_limit: Optional[int] = None,
) -> Iterator[List[BaseActivity]]:
"""
Private method for handling the iterator parts of get_account_activities
Expand Down Expand Up @@ -535,7 +538,7 @@ def _get_account_activities_iterator(
@staticmethod
def _parse_activity(data: dict) -> Union[TradeActivity, NonTradeActivity]:
"""
We cannot just use parse_obj_as for Activity types since we need to know what child instance to cast it into.
We cannot just use TypeAdapter for Activity types since we need to know what child instance to cast it into.

So this method does just that.

Expand All @@ -552,9 +555,58 @@ def _parse_activity(data: dict) -> Union[TradeActivity, NonTradeActivity]:
)

if ActivityType.is_str_trade_activity(data["activity_type"]):
return parse_obj_as(TradeActivity, data)
return TypeAdapter(TradeActivity).validate_python(data)
else:
return parse_obj_as(NonTradeActivity, data)
return TypeAdapter(NonTradeActivity).validate_python(data)

# ############################## ONFIDO SDK ############################################# #

def get_onfido_sdk_token(
self,
account_id: Union[UUID, str],
token_filter: Optional[GetOnfidoTokenRequest] = None,
) -> Union[OnfidoToken, RawData]:
"""Gets the Onfido SDK token.
See https://alpaca.markets/docs/api-references/broker-api/accounts/accounts/#retrieving-an-onfido-sdk-token

Args:
account_id (Union[UUID, str]): The id of the Account you wish to retrieve the token for. str values will
attempt to be upcast into UUID instances.
token_filter: (Optional[GetOnfidoTokenRequest]): The optional set of query parameters.

Returns:
OnfidoToken: the Onfido SDK token.
"""
result = self.get(
f"/accounts/{account_id}/onfido/sdk/tokens",
token_filter.to_request_fields() if token_filter else {},
)

if self._use_raw_data:
return result

return TypeAdapter(OnfidoToken).validate_python(result)

def update_onfido_sdk_outcome(
self,
account_id: Union[UUID, str],
onfido_outcome: UpdateOnfidoOutcomeRequest,
) -> None:
"""Gets the Onfido SDK token.
See https://alpaca.markets/docs/api-references/broker-api/accounts/accounts/#retrieving-an-onfido-sdk-token

Args:
account_id (Union[UUID, str]): The id of the Account you wish to retrieve the token for. str values will
attempt to be upcast into UUID instances.
onfido_outcome: (Optional[UpdateOnfidoOutcomeRequest]): The result of the Onfido SK flow in your app.

Returns:
OnfidoToken: the Onfido SDK token.
"""
self.patch(
f"/accounts/{account_id}/onfido/sdk/",
onfido_outcome.to_request_fields() if onfido_outcome else {},
)

# ############################## TRADE ACCOUNT DOCUMENTS ################################# #

Expand Down Expand Up @@ -585,7 +637,7 @@ def get_trade_documents_for_account(
if self._use_raw_data:
return result

return parse_obj_as(List[TradeDocument], result)
return TypeAdapter(List[TradeDocument]).validate_python(result)

def get_trade_document_for_account_by_id(
self,
Expand Down Expand Up @@ -614,7 +666,7 @@ def get_trade_document_for_account_by_id(
if self._use_raw_data:
return response

return parse_obj_as(TradeDocument, response)
return TypeAdapter(TradeDocument).validate_python(response)

def download_trade_document_for_account_by_id(
self,
Expand Down Expand Up @@ -741,7 +793,7 @@ def get_ach_relationships_for_account(
if self._use_raw_data:
return response

return parse_obj_as(List[ACHRelationship], response)
return TypeAdapter(List[ACHRelationship]).validate_python(response)

def delete_ach_relationship_for_account(
self,
Expand Down Expand Up @@ -808,7 +860,7 @@ def get_banks_for_account(
if self._use_raw_data:
return response

return parse_obj_as(List[Bank], response)
return TypeAdapter(List[Bank]).validate_python(response)

def delete_bank_for_account(
self,
Expand Down Expand Up @@ -924,7 +976,7 @@ def _get_transfers_iterator(
else:
total_items += num_items_returned

yield parse_obj_as(List[Transfer], result)
yield TypeAdapter(List[Transfer]).validate_python(result)

if max_items_limit is not None and total_items >= max_items_limit:
break
Expand Down Expand Up @@ -968,8 +1020,7 @@ def get_all_positions_for_account(

if self._use_raw_data:
return response

return parse_obj_as(List[Position], response)
return TypeAdapter(List[Position]).validate_python(response)

def get_all_accounts_positions(
self,
Expand Down Expand Up @@ -1035,8 +1086,7 @@ def close_all_positions_for_account(

if self._use_raw_data:
return response

return parse_obj_as(List[ClosePositionResponse], response)
return TypeAdapter(List[ClosePositionResponse]).validate_python(response)

def close_position_for_account(
self,
Expand Down Expand Up @@ -1139,7 +1189,7 @@ def get_calendar(
if self._use_raw_data:
return result

return parse_obj_as(List[Calendar], result)
return TypeAdapter(List[Calendar]).validate_python(result)

# ############################## WATCHLISTS ################################# #

Expand All @@ -1163,7 +1213,7 @@ def get_watchlists_for_account(
if self._use_raw_data:
return result

return parse_obj_as(List[Watchlist], result)
return TypeAdapter(List[Watchlist]).validate_python(result)

def get_watchlist_for_account_by_id(
self,
Expand Down Expand Up @@ -1376,7 +1426,7 @@ def create_batch_journal(
if self._use_raw_data:
return response

return parse_obj_as(List[BatchJournalResponse], response)
return TypeAdapter(List[BatchJournalResponse]).validate_python(response)

def create_reverse_batch_journal(
self,
Expand All @@ -1400,7 +1450,7 @@ def create_reverse_batch_journal(
if self._use_raw_data:
return response

return parse_obj_as(List[BatchJournalResponse], response)
return TypeAdapter(List[BatchJournalResponse]).validate_python(response)

def get_journals(
self, journal_filter: Optional[GetJournalsRequest] = None
Expand All @@ -1421,7 +1471,7 @@ def get_journals(
if self._use_raw_data:
return response

return parse_obj_as(List[Journal], response)
return TypeAdapter(List[Journal]).validate_python(response)

def get_journal_by_id(
self, journal_id: Union[UUID, str] = None
Expand Down Expand Up @@ -1484,7 +1534,9 @@ def get_all_assets(
if self._use_raw_data:
return response

return parse_obj_as(List[Asset], response)
return TypeAdapter(
List[Asset],
).validate_python(response)

def get_asset(self, symbol_or_asset_id: Union[UUID, str]) -> Union[Asset, RawData]:
"""
Expand Down Expand Up @@ -1559,7 +1611,9 @@ def get_orders_for_account(
if self._use_raw_data:
return response

return parse_obj_as(List[Order], response)
return TypeAdapter(
List[Order],
).validate_python(response)

def get_order_for_account_by_id(
self,
Expand Down Expand Up @@ -1668,7 +1722,9 @@ def cancel_orders_for_account(
if self._use_raw_data:
return response

return parse_obj_as(List[CancelOrderResponse], response)
return TypeAdapter(
List[CancelOrderResponse],
).validate_python(response)

def cancel_order_for_account_by_id(
self, account_id: Union[UUID, str], order_id: Union[UUID, str]
Expand Down Expand Up @@ -1710,7 +1766,9 @@ def get_corporate_announcements(
if self._use_raw_data:
return response

return parse_obj_as(List[CorporateActionAnnouncement], response)
return TypeAdapter(
List[CorporateActionAnnouncement],
).validate_python(response)

def get_corporate_announcement_by_id(
self, corporate_announcment_id: Union[UUID, str]
Expand Down
Loading