architect-py 5.0.0b1__py3-none-any.whl → 5.0.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- architect_py/__init__.py +10 -3
- architect_py/async_client.py +283 -169
- architect_py/client_interface.py +19 -18
- architect_py/common_types/order_dir.py +12 -6
- architect_py/graphql_client/__init__.py +2 -0
- architect_py/graphql_client/enums.py +5 -0
- architect_py/grpc/__init__.py +25 -7
- architect_py/grpc/client.py +13 -5
- architect_py/grpc/models/Accounts/AccountsRequest.py +4 -1
- architect_py/grpc/models/Algo/AlgoOrder.py +114 -0
- architect_py/grpc/models/Algo/{ModifyAlgoOrderRequestForTwapAlgo.py → AlgoOrderRequest.py} +11 -10
- architect_py/grpc/models/Algo/AlgoOrdersRequest.py +72 -0
- architect_py/grpc/models/Algo/AlgoOrdersResponse.py +27 -0
- architect_py/grpc/models/Algo/CreateAlgoOrderRequest.py +56 -0
- architect_py/grpc/models/Algo/PauseAlgoRequest.py +42 -0
- architect_py/grpc/models/Algo/PauseAlgoResponse.py +20 -0
- architect_py/grpc/models/Algo/StartAlgoRequest.py +42 -0
- architect_py/grpc/models/Algo/StartAlgoResponse.py +20 -0
- architect_py/grpc/models/Algo/StopAlgoRequest.py +42 -0
- architect_py/grpc/models/Algo/StopAlgoResponse.py +20 -0
- architect_py/grpc/models/Boss/DepositsRequest.py +40 -0
- architect_py/grpc/models/Boss/DepositsResponse.py +27 -0
- architect_py/grpc/models/Boss/RqdAccountStatisticsRequest.py +42 -0
- architect_py/grpc/models/Boss/RqdAccountStatisticsResponse.py +25 -0
- architect_py/grpc/models/Boss/StatementUrlRequest.py +40 -0
- architect_py/grpc/models/Boss/StatementUrlResponse.py +23 -0
- architect_py/grpc/models/Boss/StatementsRequest.py +40 -0
- architect_py/grpc/models/Boss/StatementsResponse.py +27 -0
- architect_py/grpc/models/Boss/WithdrawalsRequest.py +40 -0
- architect_py/grpc/models/Boss/WithdrawalsResponse.py +27 -0
- architect_py/grpc/models/Boss/__init__.py +2 -0
- architect_py/grpc/models/Folio/HistoricalFillsRequest.py +4 -1
- architect_py/grpc/models/Marketdata/L1BookSnapshot.py +16 -2
- architect_py/grpc/models/Oms/Cancel.py +67 -19
- architect_py/grpc/models/Oms/Order.py +4 -11
- architect_py/grpc/models/Oms/PlaceOrderRequest.py +13 -20
- architect_py/grpc/models/OptionsMarketdata/OptionsChain.py +30 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsChainGreeks.py +30 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsChainGreeksRequest.py +47 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsChainRequest.py +45 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsExpirations.py +29 -0
- architect_py/grpc/models/OptionsMarketdata/OptionsExpirationsRequest.py +42 -0
- architect_py/grpc/models/OptionsMarketdata/__init__.py +2 -0
- architect_py/grpc/models/Symbology/ExecutionInfoRequest.py +47 -0
- architect_py/grpc/models/Symbology/ExecutionInfoResponse.py +27 -0
- architect_py/grpc/models/definitions.py +457 -790
- architect_py/grpc/resolve_endpoint.py +4 -1
- architect_py/internal_utils/__init__.py +0 -0
- architect_py/internal_utils/no_pandas.py +3 -0
- architect_py/tests/conftest.py +11 -6
- architect_py/tests/test_marketdata.py +4 -4
- architect_py/tests/test_orderflow.py +31 -28
- {architect_py-5.0.0b1.dist-info → architect_py-5.0.0b2.dist-info}/METADATA +2 -3
- {architect_py-5.0.0b1.dist-info → architect_py-5.0.0b2.dist-info}/RECORD +72 -42
- {architect_py-5.0.0b1.dist-info → architect_py-5.0.0b2.dist-info}/WHEEL +1 -1
- examples/book_subscription.py +2 -3
- examples/candles.py +3 -3
- examples/common.py +29 -20
- examples/external_cpty.py +4 -4
- examples/funding_rate_mean_reversion_algo.py +14 -20
- examples/order_sending.py +32 -33
- examples/stream_l1_marketdata.py +2 -2
- examples/stream_l2_marketdata.py +1 -3
- examples/trades.py +2 -2
- examples/tutorial_async.py +9 -7
- examples/tutorial_sync.py +5 -5
- scripts/generate_functions_md.py +3 -1
- scripts/generate_sync_interface.py +30 -11
- scripts/postprocess_grpc.py +21 -11
- scripts/preprocess_grpc_schema.py +174 -113
- architect_py/grpc/models/Algo/AlgoOrderForTwapAlgo.py +0 -61
- architect_py/grpc/models/Algo/CreateAlgoOrderRequestForTwapAlgo.py +0 -59
- {architect_py-5.0.0b1.dist-info → architect_py-5.0.0b2.dist-info}/licenses/LICENSE +0 -0
- {architect_py-5.0.0b1.dist-info → architect_py-5.0.0b2.dist-info}/top_level.txt +0 -0
architect_py/async_client.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
3
|
import re
|
4
|
-
from datetime import date, datetime, timedelta
|
4
|
+
from datetime import date, datetime, timedelta, timezone
|
5
5
|
from decimal import Decimal
|
6
6
|
from typing import (
|
7
|
+
Any,
|
8
|
+
AsyncGenerator,
|
7
9
|
AsyncIterator,
|
8
10
|
List,
|
9
11
|
Literal,
|
@@ -13,6 +15,17 @@ from typing import (
|
|
13
15
|
overload,
|
14
16
|
)
|
15
17
|
|
18
|
+
import grpc
|
19
|
+
import pandas as pd
|
20
|
+
|
21
|
+
from architect_py.grpc.models.Oms.Cancel import Cancel
|
22
|
+
from architect_py.grpc.models.Oms.CancelAllOrdersRequest import CancelAllOrdersRequest
|
23
|
+
from architect_py.grpc.models.Oms.CancelOrderRequest import CancelOrderRequest
|
24
|
+
from architect_py.grpc.models.Oms.OpenOrdersRequest import OpenOrdersRequest
|
25
|
+
from architect_py.grpc.models.Oms.Order import Order
|
26
|
+
from architect_py.grpc.models.Oms.PlaceOrderRequest import (
|
27
|
+
PlaceOrderRequest,
|
28
|
+
)
|
16
29
|
from architect_py.grpc.models.Orderflow.Orderflow import Orderflow
|
17
30
|
from architect_py.grpc.models.Orderflow.OrderflowRequest import (
|
18
31
|
OrderflowRequest,
|
@@ -25,38 +38,19 @@ from architect_py.grpc.models.Orderflow.SubscribeOrderflowRequest import (
|
|
25
38
|
|
26
39
|
from .common_types import OrderDir, TradableProduct, Venue
|
27
40
|
from .graphql_client import GraphQLClient
|
28
|
-
from .graphql_client.enums import (
|
29
|
-
OrderType,
|
30
|
-
TimeInForce,
|
31
|
-
)
|
32
41
|
from .graphql_client.exceptions import GraphQLClientGraphQLMultiError
|
33
42
|
from .graphql_client.fragments import (
|
34
|
-
AccountSummaryFields,
|
35
|
-
AccountWithPermissionsFields,
|
36
|
-
CancelFields,
|
37
43
|
ExecutionInfoFields,
|
38
|
-
OrderFields,
|
39
44
|
ProductInfoFields,
|
40
45
|
)
|
41
|
-
from .graphql_client.get_fills_query import GetFillsQueryFolioHistoricalFills
|
42
|
-
from .graphql_client.place_order_mutation import PlaceOrderMutationOms
|
43
46
|
from .grpc import *
|
44
47
|
from .grpc.client import GrpcClient
|
45
|
-
from .grpc.models import definitions as grpc_definitions
|
46
48
|
from .utils.nearest_tick import TickRoundMethod
|
47
49
|
from .utils.orderbook import update_orderbook_side
|
50
|
+
from .utils.pandas import candles_to_dataframe
|
48
51
|
from .utils.price_bands import price_band_pairs
|
49
52
|
from .utils.symbol_parsing import nominative_expiration
|
50
53
|
|
51
|
-
try:
|
52
|
-
import pandas as pd
|
53
|
-
|
54
|
-
from .utils.pandas import candles_to_dataframe
|
55
|
-
|
56
|
-
FEATURE_PANDAS = True
|
57
|
-
except ImportError:
|
58
|
-
FEATURE_PANDAS = False
|
59
|
-
|
60
54
|
|
61
55
|
class AsyncClient:
|
62
56
|
api_key: Optional[str] = None
|
@@ -84,6 +78,7 @@ class AsyncClient:
|
|
84
78
|
paper_trading: bool,
|
85
79
|
endpoint: str = "https://app.architect.co",
|
86
80
|
graphql_port: Optional[int] = None,
|
81
|
+
**kwargs: Any,
|
87
82
|
) -> "AsyncClient":
|
88
83
|
"""
|
89
84
|
Connect to an Architect installation.
|
@@ -95,6 +90,17 @@ class AsyncClient:
|
|
95
90
|
RESET = "\033[0m"
|
96
91
|
print(f"🧻 {COLOR} YOU ARE IN PAPER TRADING MODE {RESET}")
|
97
92
|
|
93
|
+
if "grpc_endpoint" in kwargs:
|
94
|
+
logging.warning(
|
95
|
+
"as of v5.0.0: grpc_endpoint parameter is deprecated; ignored"
|
96
|
+
)
|
97
|
+
if "host" in kwargs:
|
98
|
+
logging.warning(
|
99
|
+
"as of v5.0.0: host parameter is deprecated, use endpoint instead; setting endpoint to %s",
|
100
|
+
kwargs["endpoint"],
|
101
|
+
)
|
102
|
+
endpoint = kwargs["endpoint"]
|
103
|
+
|
98
104
|
grpc_host, grpc_port, use_ssl = await resolve_endpoint(endpoint)
|
99
105
|
logging.info(
|
100
106
|
f"Resolved endpoint {endpoint}: {grpc_host}:{grpc_port} use_ssl={use_ssl}"
|
@@ -318,6 +324,14 @@ class AsyncClient:
|
|
318
324
|
res = await self.graphql_client.user_id_query()
|
319
325
|
return res.user_id, res.user_email
|
320
326
|
|
327
|
+
def enable_orderflow(self):
|
328
|
+
"""
|
329
|
+
@deprecated(reason="No longer needed; orderflow is enabled by default")
|
330
|
+
"""
|
331
|
+
logging.warning(
|
332
|
+
"as of v5.0.0: enable_orderflow is deprecated; orderflow is enabled by default"
|
333
|
+
)
|
334
|
+
|
321
335
|
# ------------------------------------------------------------
|
322
336
|
# Symbology
|
323
337
|
# ------------------------------------------------------------
|
@@ -371,6 +385,10 @@ class AsyncClient:
|
|
371
385
|
|
372
386
|
Args:
|
373
387
|
symbol: the symbol to get information for
|
388
|
+
the symbol should *not* have a quote,
|
389
|
+
ie "ES 20250620 CME Future" instead of "ES 20250620 CME Future/USD"
|
390
|
+
|
391
|
+
If you used TradableProduct, you can use the base() method to get the symbol
|
374
392
|
|
375
393
|
Returns:
|
376
394
|
None if the symbol does not exist
|
@@ -459,6 +477,13 @@ class AsyncClient:
|
|
459
477
|
return None
|
460
478
|
return res.product_info.first_notice_date
|
461
479
|
|
480
|
+
async def get_future_series(self, series_symbol: str) -> list[str]:
|
481
|
+
"""
|
482
|
+
@deprecated(reason="Use get_futures_series instead")
|
483
|
+
"""
|
484
|
+
futures = await self.get_futures_series(series_symbol)
|
485
|
+
return futures
|
486
|
+
|
462
487
|
async def get_futures_series(self, series_symbol: str) -> list[str]:
|
463
488
|
"""
|
464
489
|
List all futures in a given series.
|
@@ -503,11 +528,14 @@ class AsyncClient:
|
|
503
528
|
the symbol for each future in the series
|
504
529
|
|
505
530
|
e.g.
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
531
|
+
```
|
532
|
+
[
|
533
|
+
(datetime.date(2025, 3, 21), 'ES 20250321 CME Future'),
|
534
|
+
(datetime.date(2025, 6, 20), 'ES 20250620 CME Future'),
|
535
|
+
(datetime.date(2025, 9, 19), 'ES 20250919 CME Future'),
|
536
|
+
# ...
|
510
537
|
]
|
538
|
+
```
|
511
539
|
"""
|
512
540
|
futures = await self.get_futures_series(series)
|
513
541
|
exp_and_futures = []
|
@@ -573,7 +601,7 @@ class AsyncClient:
|
|
573
601
|
symbol: the symbol to get the market snapshot for, e.g. "ES 20250321 CME Future/USD"
|
574
602
|
venue: the venue that the symbol is traded at, e.g. CME
|
575
603
|
Returns:
|
576
|
-
|
604
|
+
L1BookSnapshot for the symbol
|
577
605
|
"""
|
578
606
|
return await self.get_l1_book_snapshot(symbol=symbol, venue=venue)
|
579
607
|
|
@@ -591,7 +619,7 @@ class AsyncClient:
|
|
591
619
|
"""
|
592
620
|
return await self.get_l1_book_snapshots(
|
593
621
|
venue=venue,
|
594
|
-
symbols=symbols, #
|
622
|
+
symbols=symbols, # pyright: ignore[reportArgumentType]
|
595
623
|
)
|
596
624
|
|
597
625
|
@overload
|
@@ -634,13 +662,23 @@ class AsyncClient:
|
|
634
662
|
venue: the venue of the symbol
|
635
663
|
candle_width: the width of the candles
|
636
664
|
start: the start date to get candles for;
|
637
|
-
For naive datetimes, the server will assume UTC.
|
638
665
|
end: the end date to get candles for;
|
639
|
-
For naive datetimes, the server will assume UTC.
|
640
666
|
as_dataframe: if True, return a pandas DataFrame
|
641
667
|
|
642
668
|
"""
|
643
669
|
grpc_client = await self.hmart()
|
670
|
+
if start.tzinfo is not timezone.utc:
|
671
|
+
raise ValueError(
|
672
|
+
"start must be a utc datetime:\n"
|
673
|
+
"for example datetime.now(timezone.utc) or \n"
|
674
|
+
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
675
|
+
)
|
676
|
+
if end.tzinfo is not timezone.utc:
|
677
|
+
raise ValueError(
|
678
|
+
"end must be a utc datetime:\n"
|
679
|
+
"for example datetime.now(timezone.utc) or \n"
|
680
|
+
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
681
|
+
)
|
644
682
|
req = HistoricalCandlesRequest(
|
645
683
|
venue=venue,
|
646
684
|
symbol=str(symbol),
|
@@ -650,10 +688,8 @@ class AsyncClient:
|
|
650
688
|
)
|
651
689
|
res: HistoricalCandlesResponse = await grpc_client.unary_unary(req)
|
652
690
|
|
653
|
-
if as_dataframe
|
691
|
+
if as_dataframe:
|
654
692
|
return candles_to_dataframe(res.candles)
|
655
|
-
elif as_dataframe and not FEATURE_PANDAS:
|
656
|
-
raise RuntimeError("as_dataframe is True but pandas is not installed")
|
657
693
|
else:
|
658
694
|
return res.candles
|
659
695
|
|
@@ -686,7 +722,9 @@ class AsyncClient:
|
|
686
722
|
"""
|
687
723
|
grpc_client = await self.marketdata(venue)
|
688
724
|
req = L1BookSnapshotsRequest(symbols=symbols)
|
689
|
-
res: ArrayOfL1BookSnapshot = await grpc_client.unary_unary(
|
725
|
+
res: ArrayOfL1BookSnapshot = await grpc_client.unary_unary(
|
726
|
+
req # pyright: ignore[reportArgumentType]
|
727
|
+
)
|
690
728
|
return res
|
691
729
|
|
692
730
|
async def get_l2_book_snapshot(
|
@@ -715,7 +753,7 @@ class AsyncClient:
|
|
715
753
|
|
716
754
|
async def stream_l1_book_snapshots(
|
717
755
|
self, symbols: Sequence[TradableProduct | str], venue: Venue
|
718
|
-
) ->
|
756
|
+
) -> AsyncGenerator[L1BookSnapshot, None]:
|
719
757
|
"""
|
720
758
|
Subscribe to the stream of L1BookSnapshots for a symbol.
|
721
759
|
|
@@ -726,11 +764,12 @@ class AsyncClient:
|
|
726
764
|
"""
|
727
765
|
grpc_client = await self.marketdata(venue)
|
728
766
|
req = SubscribeL1BookSnapshotsRequest(symbols=list(symbols), venue=venue)
|
729
|
-
|
767
|
+
async for res in grpc_client.unary_stream(req):
|
768
|
+
yield res
|
730
769
|
|
731
770
|
async def stream_l2_book_updates(
|
732
771
|
self, symbol: TradableProduct | str, venue: Venue
|
733
|
-
) ->
|
772
|
+
) -> AsyncGenerator[L2BookUpdate, None]:
|
734
773
|
"""
|
735
774
|
Subscribe to the stream of L2BookUpdates for a symbol.
|
736
775
|
|
@@ -743,7 +782,10 @@ class AsyncClient:
|
|
743
782
|
"""
|
744
783
|
grpc_client = await self.marketdata(venue)
|
745
784
|
req = SubscribeL2BookUpdatesRequest(symbol=str(symbol), venue=venue)
|
746
|
-
|
785
|
+
async for res in grpc_client.unary_stream(
|
786
|
+
req # pyright: ignore[reportArgumentType]
|
787
|
+
):
|
788
|
+
yield res
|
747
789
|
|
748
790
|
async def subscribe_l1_book(
|
749
791
|
self, symbol: TradableProduct | str, venue: Venue
|
@@ -782,6 +824,9 @@ class AsyncClient:
|
|
782
824
|
return book
|
783
825
|
|
784
826
|
async def unsubscribe_l1_book(self, symbol: TradableProduct | str, venue: Venue):
|
827
|
+
"""
|
828
|
+
Unsubscribe from the L1 stream for a symbol, ie undoes subscribe_l1_book.
|
829
|
+
"""
|
785
830
|
symbol = TradableProduct(symbol)
|
786
831
|
try:
|
787
832
|
task = self.l1_books[venue][symbol][1]
|
@@ -865,7 +910,9 @@ class AsyncClient:
|
|
865
910
|
):
|
866
911
|
try:
|
867
912
|
req = SubscribeL2BookUpdatesRequest(symbol=str(symbol), venue=venue)
|
868
|
-
stream = grpc_client.unary_stream(
|
913
|
+
stream = grpc_client.unary_stream(
|
914
|
+
req # pyright: ignore[reportArgumentType]
|
915
|
+
)
|
869
916
|
async for up in stream:
|
870
917
|
if isinstance(up, L2BookDiff):
|
871
918
|
if (
|
@@ -899,20 +946,21 @@ class AsyncClient:
|
|
899
946
|
|
900
947
|
async def stream_trades(
|
901
948
|
self, symbol: TradableProduct | str, venue: Venue
|
902
|
-
) ->
|
949
|
+
) -> AsyncGenerator[Trade, None]:
|
903
950
|
"""
|
904
951
|
Subscribe to a stream of trades for a symbol.
|
905
952
|
"""
|
906
953
|
grpc_client = await self.marketdata(venue)
|
907
954
|
req = SubscribeTradesRequest(symbol=str(symbol), venue=venue)
|
908
|
-
|
955
|
+
async for res in grpc_client.unary_stream(req):
|
956
|
+
yield res
|
909
957
|
|
910
958
|
async def stream_candles(
|
911
959
|
self,
|
912
960
|
symbol: TradableProduct | str,
|
913
961
|
venue: Venue,
|
914
962
|
candle_widths: Optional[list[CandleWidth]],
|
915
|
-
) ->
|
963
|
+
) -> AsyncGenerator[Candle, None]:
|
916
964
|
"""
|
917
965
|
Subscribe to a stream of candles for a symbol.
|
918
966
|
"""
|
@@ -922,13 +970,14 @@ class AsyncClient:
|
|
922
970
|
venue=venue,
|
923
971
|
candle_widths=candle_widths,
|
924
972
|
)
|
925
|
-
|
973
|
+
async for res in grpc_client.unary_stream(req):
|
974
|
+
yield res
|
926
975
|
|
927
976
|
# ------------------------------------------------------------
|
928
977
|
# Portfolio management
|
929
978
|
# ------------------------------------------------------------
|
930
979
|
|
931
|
-
async def list_accounts(self) ->
|
980
|
+
async def list_accounts(self) -> List[AccountWithPermissions]:
|
932
981
|
"""
|
933
982
|
List accounts for the user that the API key belongs to.
|
934
983
|
|
@@ -937,17 +986,12 @@ class AsyncClient:
|
|
937
986
|
a list of AccountWithPermissions for the user that the API key belongs to
|
938
987
|
(use who_am_i to get the user_id / email)
|
939
988
|
"""
|
940
|
-
|
989
|
+
grpc_client = await self.core()
|
990
|
+
req = AccountsRequest(paper=self.paper_trading)
|
991
|
+
res = await grpc_client.unary_unary(req)
|
941
992
|
return res.accounts
|
942
993
|
|
943
|
-
|
944
|
-
async def list_accounts(self) -> List[grpc_definitions.AccountWithPermissions]:
|
945
|
-
request = AccountsRequest()
|
946
|
-
accounts = await self.grpc_client.request(request)
|
947
|
-
return accounts.accounts
|
948
|
-
"""
|
949
|
-
|
950
|
-
async def get_account_summary(self, account: str) -> AccountSummaryFields:
|
994
|
+
async def get_account_summary(self, account: str) -> AccountSummary:
|
951
995
|
"""
|
952
996
|
Get account summary, including balances, positions, pnls, etc.
|
953
997
|
|
@@ -955,20 +999,16 @@ class AsyncClient:
|
|
955
999
|
account: account uuid or name
|
956
1000
|
Examples: "00000000-0000-0000-0000-000000000000", "STONEX:000000/JDoe"
|
957
1001
|
"""
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
request = AccountSummaryRequest(account=account)
|
963
|
-
account_summary = await self.grpc_client.request(request)
|
964
|
-
return account_summary
|
965
|
-
"""
|
1002
|
+
grpc_client = await self.core()
|
1003
|
+
req = AccountSummaryRequest(account=account)
|
1004
|
+
res = await grpc_client.unary_unary(req)
|
1005
|
+
return res
|
966
1006
|
|
967
1007
|
async def get_account_summaries(
|
968
1008
|
self,
|
969
1009
|
accounts: Optional[list[str]] = None,
|
970
1010
|
trader: Optional[str] = None,
|
971
|
-
) ->
|
1011
|
+
) -> list[AccountSummary]:
|
972
1012
|
"""
|
973
1013
|
Get account summaries for accounts matching the filters.
|
974
1014
|
|
@@ -978,45 +1018,24 @@ class AsyncClient:
|
|
978
1018
|
|
979
1019
|
If both arguments are given, the union of matching accounts are returned.
|
980
1020
|
"""
|
981
|
-
|
982
|
-
trader=trader, accounts=accounts
|
983
|
-
)
|
984
|
-
return res.account_summaries
|
985
|
-
"""
|
986
|
-
async def get_account_summaries(
|
987
|
-
self,
|
988
|
-
accounts: Optional[list[str]] = None,
|
989
|
-
trader: Optional[str] = None,
|
990
|
-
) -> list[AccountSummary]:
|
1021
|
+
grpc_client = await self.core()
|
991
1022
|
request = AccountSummariesRequest(
|
992
1023
|
accounts=accounts,
|
993
1024
|
trader=trader,
|
994
1025
|
)
|
995
|
-
|
996
|
-
return
|
997
|
-
"""
|
1026
|
+
res = await grpc_client.unary_unary(request)
|
1027
|
+
return res.account_summaries
|
998
1028
|
|
999
1029
|
async def get_account_history(
|
1000
1030
|
self,
|
1001
1031
|
account: str,
|
1002
1032
|
from_inclusive: Optional[datetime] = None,
|
1003
1033
|
to_exclusive: Optional[datetime] = None,
|
1004
|
-
) ->
|
1034
|
+
) -> list[AccountSummary]:
|
1005
1035
|
"""
|
1006
1036
|
Get historical sequence of account summaries for the given account.
|
1007
1037
|
"""
|
1008
|
-
|
1009
|
-
account=account, from_inclusive=from_inclusive, to_exclusive=to_exclusive
|
1010
|
-
)
|
1011
|
-
return res.account_history
|
1012
|
-
|
1013
|
-
"""
|
1014
|
-
async def get_account_history(
|
1015
|
-
self,
|
1016
|
-
account: str,
|
1017
|
-
from_inclusive: Optional[datetime] = None,
|
1018
|
-
to_exclusive: Optional[datetime] = None,
|
1019
|
-
) -> list[AccountSummary]:
|
1038
|
+
grpc_client = await self.core()
|
1020
1039
|
if from_inclusive is not None:
|
1021
1040
|
assert from_inclusive.tzinfo is timezone.utc, (
|
1022
1041
|
"from_inclusive must be a utc datetime:\n"
|
@@ -1031,12 +1050,11 @@ class AsyncClient:
|
|
1031
1050
|
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
1032
1051
|
)
|
1033
1052
|
|
1034
|
-
|
1053
|
+
req = AccountHistoryRequest(
|
1035
1054
|
account=account, from_inclusive=from_inclusive, to_exclusive=to_exclusive
|
1036
1055
|
)
|
1037
|
-
|
1038
|
-
return
|
1039
|
-
"""
|
1056
|
+
res = await grpc_client.unary_unary(req)
|
1057
|
+
return res.history
|
1040
1058
|
|
1041
1059
|
# ------------------------------------------------------------
|
1042
1060
|
# Order management
|
@@ -1044,13 +1062,13 @@ class AsyncClient:
|
|
1044
1062
|
|
1045
1063
|
async def get_open_orders(
|
1046
1064
|
self,
|
1047
|
-
order_ids: Optional[list[
|
1065
|
+
order_ids: Optional[list[OrderId]] = None,
|
1048
1066
|
venue: Optional[str] = None,
|
1049
1067
|
account: Optional[str] = None,
|
1050
1068
|
trader: Optional[str] = None,
|
1051
1069
|
symbol: Optional[str] = None,
|
1052
|
-
parent_order_id: Optional[
|
1053
|
-
) ->
|
1070
|
+
parent_order_id: Optional[OrderId] = None,
|
1071
|
+
) -> list[Order]:
|
1054
1072
|
"""
|
1055
1073
|
Returns a list of open orders for the user that match the filters.
|
1056
1074
|
|
@@ -1065,7 +1083,8 @@ class AsyncClient:
|
|
1065
1083
|
Returns:
|
1066
1084
|
Open orders that match the union of the filters
|
1067
1085
|
"""
|
1068
|
-
|
1086
|
+
grpc_client = await self.core()
|
1087
|
+
open_orders_request = OpenOrdersRequest(
|
1069
1088
|
venue=venue,
|
1070
1089
|
account=account,
|
1071
1090
|
trader=trader,
|
@@ -1073,26 +1092,27 @@ class AsyncClient:
|
|
1073
1092
|
parent_order_id=parent_order_id,
|
1074
1093
|
order_ids=order_ids,
|
1075
1094
|
)
|
1076
|
-
return res.open_orders
|
1077
1095
|
|
1078
|
-
|
1096
|
+
open_orders = await grpc_client.unary_unary(open_orders_request)
|
1097
|
+
return open_orders.open_orders
|
1098
|
+
|
1099
|
+
async def get_all_open_orders(self) -> list[Order]:
|
1079
1100
|
"""
|
1080
1101
|
@deprecated(reason="Use get_open_orders with no parameters instead")
|
1081
1102
|
|
1082
1103
|
Returns a list of all open orders for the authenticated user.
|
1083
1104
|
"""
|
1084
|
-
|
1085
|
-
return res.open_orders
|
1105
|
+
return await self.get_open_orders()
|
1086
1106
|
|
1087
1107
|
async def get_historical_orders(
|
1088
1108
|
self,
|
1089
|
-
order_ids: Optional[list[
|
1109
|
+
order_ids: Optional[list[OrderId]] = None,
|
1090
1110
|
from_inclusive: Optional[datetime] = None,
|
1091
1111
|
to_exclusive: Optional[datetime] = None,
|
1092
1112
|
venue: Optional[str] = None,
|
1093
1113
|
account: Optional[str] = None,
|
1094
|
-
parent_order_id: Optional[
|
1095
|
-
) ->
|
1114
|
+
parent_order_id: Optional[OrderId] = None,
|
1115
|
+
) -> list[Order]:
|
1096
1116
|
"""
|
1097
1117
|
Returns a list of all historical orders that match the filters.
|
1098
1118
|
|
@@ -1112,7 +1132,23 @@ class AsyncClient:
|
|
1112
1132
|
If order_ids is not specified, then from_inclusive and to_exclusive
|
1113
1133
|
MUST be specified.
|
1114
1134
|
"""
|
1115
|
-
|
1135
|
+
grpc_client = await self.core()
|
1136
|
+
|
1137
|
+
if from_inclusive is not None:
|
1138
|
+
assert from_inclusive.tzinfo is timezone.utc, (
|
1139
|
+
"from_inclusive must be a utc datetime:\n"
|
1140
|
+
"for example datetime.now(timezone.utc) or \n"
|
1141
|
+
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
1142
|
+
)
|
1143
|
+
|
1144
|
+
if to_exclusive is not None:
|
1145
|
+
assert to_exclusive.tzinfo is timezone.utc, (
|
1146
|
+
"to_exclusive must be a utc datetime:\n"
|
1147
|
+
"for example datetime.now(timezone.utc) or \n"
|
1148
|
+
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
1149
|
+
)
|
1150
|
+
|
1151
|
+
historical_orders_request = HistoricalOrdersRequest.new(
|
1116
1152
|
order_ids=order_ids,
|
1117
1153
|
venue=venue,
|
1118
1154
|
account=account,
|
@@ -1120,9 +1156,10 @@ class AsyncClient:
|
|
1120
1156
|
from_inclusive=from_inclusive,
|
1121
1157
|
to_exclusive=to_exclusive,
|
1122
1158
|
)
|
1123
|
-
|
1159
|
+
orders = await grpc_client.unary_unary(historical_orders_request)
|
1160
|
+
return orders.orders
|
1124
1161
|
|
1125
|
-
async def get_order(self, order_id:
|
1162
|
+
async def get_order(self, order_id: OrderId) -> Optional[Order]:
|
1126
1163
|
"""
|
1127
1164
|
Returns the specified order. Useful for looking at past sent orders.
|
1128
1165
|
Queries open_orders first, then queries historical_orders.
|
@@ -1130,18 +1167,23 @@ class AsyncClient:
|
|
1130
1167
|
Args:
|
1131
1168
|
order_id: the order id to get
|
1132
1169
|
"""
|
1133
|
-
|
1170
|
+
grpc_client = await self.core()
|
1171
|
+
req = OpenOrdersRequest.new(
|
1172
|
+
order_ids=[order_id],
|
1173
|
+
)
|
1174
|
+
res = await grpc_client.unary_unary(req)
|
1134
1175
|
for open_order in res.open_orders:
|
1135
1176
|
if open_order.id == order_id:
|
1136
1177
|
return open_order
|
1137
1178
|
|
1138
|
-
|
1139
|
-
order_ids=[order_id]
|
1179
|
+
req = HistoricalOrdersRequest.new(
|
1180
|
+
order_ids=[order_id],
|
1140
1181
|
)
|
1141
|
-
|
1142
|
-
|
1182
|
+
res = await grpc_client.unary_unary(req)
|
1183
|
+
if res.orders and len(res.orders) == 1:
|
1184
|
+
return res.orders[0]
|
1143
1185
|
|
1144
|
-
async def get_orders(self, order_ids: list[
|
1186
|
+
async def get_orders(self, order_ids: list[OrderId]) -> list[Optional[Order]]:
|
1145
1187
|
"""
|
1146
1188
|
Returns the specified orders. Useful for looking at past sent orders.
|
1147
1189
|
Plural form of get_order.
|
@@ -1149,24 +1191,27 @@ class AsyncClient:
|
|
1149
1191
|
Args:
|
1150
1192
|
order_ids: a list of order ids to get
|
1151
1193
|
"""
|
1152
|
-
|
1194
|
+
grpc_client = await self.core()
|
1195
|
+
orders_dict: dict[OrderId, Optional[Order]] = {
|
1153
1196
|
order_id: None for order_id in order_ids
|
1154
1197
|
}
|
1198
|
+
req = OpenOrdersRequest.new(
|
1199
|
+
order_ids=order_ids,
|
1200
|
+
)
|
1155
1201
|
|
1156
|
-
res = await
|
1157
|
-
|
1158
|
-
for open_order in open_orders:
|
1202
|
+
res = await grpc_client.unary_unary(req)
|
1203
|
+
for open_order in res.open_orders:
|
1159
1204
|
orders_dict[open_order.id] = open_order
|
1160
1205
|
|
1161
1206
|
not_open_order_ids = [
|
1162
1207
|
order_id for order_id in order_ids if orders_dict[order_id] is None
|
1163
1208
|
]
|
1164
1209
|
|
1165
|
-
|
1166
|
-
order_ids=not_open_order_ids
|
1210
|
+
req = HistoricalOrdersRequest.new(
|
1211
|
+
order_ids=not_open_order_ids,
|
1167
1212
|
)
|
1168
|
-
|
1169
|
-
for historical_order in
|
1213
|
+
res = await grpc_client.unary_unary(req)
|
1214
|
+
for historical_order in res.orders:
|
1170
1215
|
orders_dict[historical_order.id] = historical_order
|
1171
1216
|
|
1172
1217
|
return [orders_dict[order_id] for order_id in order_ids]
|
@@ -1177,8 +1222,9 @@ class AsyncClient:
|
|
1177
1222
|
to_exclusive: Optional[datetime] = None,
|
1178
1223
|
venue: Optional[str] = None,
|
1179
1224
|
account: Optional[str] = None,
|
1180
|
-
order_id: Optional[
|
1181
|
-
|
1225
|
+
order_id: Optional[OrderId] = None,
|
1226
|
+
limit: Optional[int] = None,
|
1227
|
+
) -> HistoricalFillsResponse:
|
1182
1228
|
"""
|
1183
1229
|
Returns all fills matching the given filters.
|
1184
1230
|
|
@@ -1189,15 +1235,35 @@ class AsyncClient:
|
|
1189
1235
|
account: account uuid or name
|
1190
1236
|
order_id: the order id to get fills for
|
1191
1237
|
"""
|
1192
|
-
|
1193
|
-
|
1238
|
+
grpc_client = await self.core()
|
1239
|
+
if from_inclusive is not None:
|
1240
|
+
assert from_inclusive.tzinfo is timezone.utc, (
|
1241
|
+
"from_inclusive must be a utc datetime:\n"
|
1242
|
+
"for example datetime.now(timezone.utc) or \n"
|
1243
|
+
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
1244
|
+
)
|
1245
|
+
|
1246
|
+
if to_exclusive is not None:
|
1247
|
+
assert to_exclusive.tzinfo is timezone.utc, (
|
1248
|
+
"to_exclusive must be a utc datetime:\n"
|
1249
|
+
"for example datetime.now(timezone.utc) or \n"
|
1250
|
+
"dt = datetime(2025, 4, 15, 12, 0, 0, tzinfo=timezone.utc)"
|
1251
|
+
)
|
1252
|
+
req = HistoricalFillsRequest(
|
1253
|
+
account=account,
|
1254
|
+
from_inclusive=from_inclusive,
|
1255
|
+
limit=limit,
|
1256
|
+
order_id=order_id,
|
1257
|
+
to_exclusive=to_exclusive,
|
1258
|
+
venue=venue,
|
1194
1259
|
)
|
1195
|
-
|
1260
|
+
res = await grpc_client.unary_unary(req)
|
1261
|
+
return res
|
1196
1262
|
|
1197
1263
|
async def orderflow(
|
1198
1264
|
self,
|
1199
1265
|
request_iterator: AsyncIterator[OrderflowRequest],
|
1200
|
-
) ->
|
1266
|
+
) -> AsyncGenerator[Orderflow, None]:
|
1201
1267
|
"""
|
1202
1268
|
A two-way channel for both order entry and listening to order updates (fills, acks, outs, etc.).
|
1203
1269
|
|
@@ -1210,12 +1276,12 @@ class AsyncClient:
|
|
1210
1276
|
"""
|
1211
1277
|
grpc_client = await self.core()
|
1212
1278
|
decoder = grpc_client.get_decoder(OrderflowRequestUnannotatedResponseType)
|
1213
|
-
stub = grpc_client.channel.stream_stream(
|
1279
|
+
stub: grpc.aio.StreamStreamMultiCallable = grpc_client.channel.stream_stream(
|
1214
1280
|
OrderflowRequest_route,
|
1215
1281
|
request_serializer=grpc_client.encoder().encode,
|
1216
1282
|
response_deserializer=decoder.decode,
|
1217
1283
|
)
|
1218
|
-
call = stub(
|
1284
|
+
call: grpc.aio._base_call.StreamStreamCall[OrderflowRequest, Orderflow] = stub(
|
1219
1285
|
request_iterator, metadata=(("authorization", f"Bearer {grpc_client.jwt}"),)
|
1220
1286
|
)
|
1221
1287
|
async for update in call:
|
@@ -1223,10 +1289,10 @@ class AsyncClient:
|
|
1223
1289
|
|
1224
1290
|
async def stream_orderflow(
|
1225
1291
|
self,
|
1226
|
-
account: Optional[
|
1292
|
+
account: Optional[AccountIdOrName] = None,
|
1227
1293
|
execution_venue: Optional[str] = None,
|
1228
|
-
trader: Optional[
|
1229
|
-
) ->
|
1294
|
+
trader: Optional[TraderIdOrEmail] = None,
|
1295
|
+
) -> AsyncGenerator[Orderflow, None]:
|
1230
1296
|
"""
|
1231
1297
|
A stream for listening to order updates (fills, acks, outs, etc.).
|
1232
1298
|
|
@@ -1245,12 +1311,16 @@ class AsyncClient:
|
|
1245
1311
|
)
|
1246
1312
|
grpc_client = await self.core()
|
1247
1313
|
decoder = grpc_client.get_decoder(SubscribeOrderflowRequest)
|
1248
|
-
stub
|
1314
|
+
stub: grpc.aio.UnaryStreamMultiCallable[
|
1315
|
+
SubscribeOrderflowRequest, Orderflow
|
1316
|
+
] = grpc_client.channel.unary_stream(
|
1249
1317
|
SubscribeOrderflowRequest.get_route(),
|
1250
1318
|
request_serializer=grpc_client.encoder().encode,
|
1251
1319
|
response_deserializer=decoder.decode,
|
1252
1320
|
)
|
1253
|
-
call
|
1321
|
+
call: grpc.aio._base_call.UnaryStreamCall[
|
1322
|
+
SubscribeOrderflowRequest, Orderflow
|
1323
|
+
] = stub(request, metadata=(("authorization", f"Bearer {grpc_client.jwt}"),))
|
1254
1324
|
async for update in call:
|
1255
1325
|
yield update
|
1256
1326
|
|
@@ -1258,39 +1328,49 @@ class AsyncClient:
|
|
1258
1328
|
# Order entry
|
1259
1329
|
# ------------------------------------------------------------
|
1260
1330
|
|
1331
|
+
async def send_limit_order(
|
1332
|
+
self,
|
1333
|
+
*args,
|
1334
|
+
**kwargs,
|
1335
|
+
) -> Order:
|
1336
|
+
"""
|
1337
|
+
@deprecated(reason="Use place_limit_order instead")
|
1338
|
+
"""
|
1339
|
+
return await self.place_limit_order(*args, **kwargs)
|
1340
|
+
|
1261
1341
|
async def place_limit_order(
|
1262
1342
|
self,
|
1263
1343
|
*,
|
1264
|
-
id: Optional[
|
1344
|
+
id: Optional[OrderId] = None,
|
1265
1345
|
symbol: TradableProduct | str,
|
1266
|
-
execution_venue: Optional[str],
|
1267
|
-
|
1346
|
+
execution_venue: Optional[str] = None,
|
1347
|
+
dir: Optional[OrderDir] = None,
|
1268
1348
|
quantity: Decimal,
|
1269
1349
|
limit_price: Decimal,
|
1270
1350
|
order_type: OrderType = OrderType.LIMIT,
|
1271
|
-
time_in_force: TimeInForce =
|
1272
|
-
good_til_date: Optional[datetime] = None,
|
1351
|
+
time_in_force: TimeInForce = TimeInForceEnum.DAY,
|
1273
1352
|
price_round_method: Optional[TickRoundMethod] = None,
|
1274
1353
|
account: Optional[str] = None,
|
1275
1354
|
trader: Optional[str] = None,
|
1276
1355
|
post_only: bool = False,
|
1277
1356
|
trigger_price: Optional[Decimal] = None,
|
1278
|
-
|
1357
|
+
**kwargs: Any,
|
1358
|
+
) -> Order:
|
1279
1359
|
"""
|
1280
1360
|
Sends a regular limit order.
|
1281
1361
|
|
1282
1362
|
Args:
|
1363
|
+
id: in case user wants to generate their own order id, otherwise it will be generated automatically
|
1283
1364
|
symbol: the symbol to send the order for
|
1284
1365
|
execution_venue: the execution venue to send the order to,
|
1285
1366
|
if execution_venue is set to None, the OMS will send the order to the primary_exchange
|
1286
1367
|
the primary_exchange can be deduced from `get_product_info`
|
1287
|
-
|
1368
|
+
dir: the direction of the order, BUY or SELL
|
1288
1369
|
quantity: the quantity of the order
|
1289
1370
|
limit_price: the limit price of the order
|
1290
1371
|
It is highly recommended to make this a Decimal object from the decimal module to avoid floating point errors
|
1291
1372
|
order_type: the type of the order
|
1292
1373
|
time_in_force: the time in force of the order
|
1293
|
-
good_til_date: the date the order is good until, only relevant for time_in_force = "GTD"
|
1294
1374
|
price_round_method: the method to round the price to the nearest tick, will not round if None
|
1295
1375
|
account: the account to send the order for
|
1296
1376
|
While technically optional, for most order types, the account is required
|
@@ -1299,13 +1379,21 @@ class AsyncClient:
|
|
1299
1379
|
post_only: whether the order should be post only, not supported by all exchanges
|
1300
1380
|
trigger_price: the trigger price for the order, only relevant for stop / take_profit orders
|
1301
1381
|
Returns:
|
1302
|
-
the
|
1382
|
+
the Order object for the order
|
1303
1383
|
The order.status should be "PENDING" until the order is "OPEN" / "REJECTED" / "OUT" / "CANCELED" / "STALE"
|
1304
1384
|
|
1305
1385
|
If the order is rejected, the order.reject_reason and order.reject_message will be set
|
1306
1386
|
"""
|
1387
|
+
grpc_client = await self.core()
|
1307
1388
|
assert quantity > 0, "quantity must be positive"
|
1308
1389
|
|
1390
|
+
if dir is None:
|
1391
|
+
if "odir" in kwargs and isinstance(kwargs["odir"], OrderDir):
|
1392
|
+
logging.warning("odir is deprecated, use dir instead")
|
1393
|
+
dir = kwargs["odir"]
|
1394
|
+
else:
|
1395
|
+
raise ValueError("dir is required")
|
1396
|
+
|
1309
1397
|
if price_round_method is not None:
|
1310
1398
|
if execution_venue is None:
|
1311
1399
|
product_info = await self.get_product_info(symbol)
|
@@ -1331,44 +1419,43 @@ class AsyncClient:
|
|
1331
1419
|
else:
|
1332
1420
|
raise ValueError(f"Could not find market information for {symbol}")
|
1333
1421
|
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
post_only,
|
1348
|
-
trigger_price,
|
1349
|
-
good_til_date,
|
1350
|
-
execution_venue,
|
1422
|
+
req: PlaceOrderRequest = PlaceOrderRequest.new(
|
1423
|
+
dir=dir,
|
1424
|
+
quantity=quantity,
|
1425
|
+
symbol=symbol,
|
1426
|
+
time_in_force=time_in_force,
|
1427
|
+
limit_price=limit_price,
|
1428
|
+
order_type=order_type,
|
1429
|
+
account=account,
|
1430
|
+
id=id,
|
1431
|
+
parent_id=None,
|
1432
|
+
source=OrderSource.API,
|
1433
|
+
trader=trader,
|
1434
|
+
execution_venue=execution_venue,
|
1435
|
+
post_only=post_only,
|
1436
|
+
trigger_price=trigger_price,
|
1351
1437
|
)
|
1352
|
-
|
1353
|
-
return
|
1438
|
+
res = await grpc_client.unary_unary(req)
|
1439
|
+
return res
|
1354
1440
|
|
1355
1441
|
async def send_market_pro_order(
|
1356
1442
|
self,
|
1357
1443
|
*,
|
1358
|
-
id: Optional[
|
1444
|
+
id: Optional[OrderId] = None,
|
1359
1445
|
symbol: TradableProduct | str,
|
1360
1446
|
execution_venue: str,
|
1361
1447
|
odir: OrderDir,
|
1362
1448
|
quantity: Decimal,
|
1363
|
-
time_in_force: TimeInForce =
|
1449
|
+
time_in_force: TimeInForce = TimeInForceEnum.DAY,
|
1364
1450
|
account: Optional[str] = None,
|
1365
1451
|
fraction_through_market: Decimal = Decimal("0.001"),
|
1366
|
-
) ->
|
1452
|
+
) -> Order:
|
1367
1453
|
"""
|
1368
1454
|
Sends a market-order like limit price based on the BBO.
|
1369
1455
|
Meant to behave as a market order but with more protections.
|
1370
1456
|
|
1371
1457
|
Args:
|
1458
|
+
id: in case user wants to generate their own order id, otherwise it will be generated automatically
|
1372
1459
|
symbol: the symbol to send the order for
|
1373
1460
|
execution_venue: the execution venue to send the order to
|
1374
1461
|
odir: the direction of the order
|
@@ -1440,7 +1527,7 @@ class AsyncClient:
|
|
1440
1527
|
time_in_force=time_in_force,
|
1441
1528
|
)
|
1442
1529
|
|
1443
|
-
async def cancel_order(self, order_id:
|
1530
|
+
async def cancel_order(self, order_id: OrderId) -> Cancel:
|
1444
1531
|
"""
|
1445
1532
|
Cancels an order by order id.
|
1446
1533
|
|
@@ -1449,10 +1536,17 @@ class AsyncClient:
|
|
1449
1536
|
Returns:
|
1450
1537
|
the CancelFields object
|
1451
1538
|
"""
|
1452
|
-
|
1453
|
-
|
1539
|
+
grpc_client = await self.core()
|
1540
|
+
req = CancelOrderRequest(id=order_id)
|
1541
|
+
res = await grpc_client.unary_unary(req)
|
1542
|
+
return res
|
1454
1543
|
|
1455
|
-
async def cancel_all_orders(
|
1544
|
+
async def cancel_all_orders(
|
1545
|
+
self,
|
1546
|
+
account: Optional[AccountIdOrName] = None,
|
1547
|
+
execution_venue: Optional[str] = None,
|
1548
|
+
trader: Optional[TraderIdOrEmail] = None,
|
1549
|
+
) -> bool:
|
1456
1550
|
"""
|
1457
1551
|
Cancels all open orders.
|
1458
1552
|
|
@@ -1460,5 +1554,25 @@ class AsyncClient:
|
|
1460
1554
|
True if all orders were cancelled successfully
|
1461
1555
|
False if there was an error
|
1462
1556
|
"""
|
1463
|
-
|
1464
|
-
|
1557
|
+
|
1558
|
+
open_orders = await self.get_open_orders(
|
1559
|
+
account=account,
|
1560
|
+
venue=execution_venue,
|
1561
|
+
trader=trader,
|
1562
|
+
)
|
1563
|
+
outputs = await asyncio.gather(
|
1564
|
+
*(self.cancel_order(order.id) for order in open_orders)
|
1565
|
+
)
|
1566
|
+
|
1567
|
+
for cancel in outputs:
|
1568
|
+
if cancel.reject_reason is not None:
|
1569
|
+
return False
|
1570
|
+
return True
|
1571
|
+
grpc_client = await self.core()
|
1572
|
+
req = CancelAllOrdersRequest(
|
1573
|
+
account=account,
|
1574
|
+
execution_venue=execution_venue,
|
1575
|
+
trader=trader,
|
1576
|
+
)
|
1577
|
+
res = await grpc_client.unary_unary(req)
|
1578
|
+
return res
|