architect-py 3.2.1__py3-none-any.whl → 3.2.2__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 +1 -1
- architect_py/async_client.py +14 -5
- architect_py/client.py +16 -12
- architect_py/client_protocol.py +3 -2
- architect_py/grpc_client/Cpty/CptyRequest.py +3 -2
- architect_py/grpc_client/Cpty/CptyResponse.py +3 -3
- architect_py/grpc_client/Cpty/CptyStatus.py +48 -0
- architect_py/grpc_client/Cpty/CptyStatusRequest.py +45 -0
- architect_py/grpc_client/Cpty/CptysRequest.py +37 -0
- architect_py/grpc_client/Cpty/CptysResponse.py +27 -0
- architect_py/grpc_client/Marketdata/Ticker.py +13 -2
- architect_py/grpc_client/Orderflow/OrderflowRequest.py +1 -0
- architect_py/grpc_client/definitions.py +45 -157
- architect_py/grpc_client/grpc_client.py +8 -0
- architect_py/grpc_client/grpc_server.py +7 -6
- architect_py/tests/conftest.py +4 -2
- architect_py/tests/test_order_sending.py +7 -3
- architect_py/tests/test_subscriptions.py +2 -5
- architect_py-3.2.2.dist-info/METADATA +191 -0
- {architect_py-3.2.1.dist-info → architect_py-3.2.2.dist-info}/RECORD +22 -20
- {architect_py-3.2.1.dist-info → architect_py-3.2.2.dist-info}/WHEEL +1 -1
- architect_py/grpc_client/Folio/AggregatedAccountSummariesRequest.py +0 -59
- architect_py/grpc_client/Folio/AggregatedAccountSummariesResponse.py +0 -27
- architect_py-3.2.1.dist-info/METADATA +0 -212
- {architect_py-3.2.1.dist-info → architect_py-3.2.2.dist-info}/LICENSE +0 -0
@@ -159,124 +159,26 @@ class AccountStatistics(Struct, omit_defaults=True):
|
|
159
159
|
return f"AccountStatistics(cash_excess={self.cash_excess},equity={self.equity},position_margin={self.position_margin},purchasing_power={self.purchasing_power},realized_pnl={self.realized_pnl},total_margin={self.total_margin},unrealized_pnl={self.unrealized_pnl},yesterday_equity={self.yesterday_equity})"
|
160
160
|
|
161
161
|
|
162
|
-
class AggregatedAccountSummary(Struct, omit_defaults=True):
|
163
|
-
account: str
|
164
|
-
balances: Dict[str, Decimal]
|
165
|
-
positions: Dict[str, AccountPosition]
|
166
|
-
timestamp: datetime
|
167
|
-
cash_excess: Optional[
|
168
|
-
Annotated[Optional[Decimal], Meta(description="Cash available to withdraw.")]
|
169
|
-
] = None
|
170
|
-
"""
|
171
|
-
Cash available to withdraw.
|
172
|
-
"""
|
173
|
-
equity: Optional[
|
174
|
-
Annotated[
|
175
|
-
Optional[Decimal],
|
176
|
-
Meta(description="Total account equity; net liquidation value."),
|
177
|
-
]
|
178
|
-
] = None
|
179
|
-
"""
|
180
|
-
Total account equity; net liquidation value.
|
181
|
-
"""
|
182
|
-
position_margin: Optional[
|
183
|
-
Annotated[
|
184
|
-
Optional[Decimal],
|
185
|
-
Meta(description="Margin requirement based on current positions only."),
|
186
|
-
]
|
187
|
-
] = None
|
188
|
-
"""
|
189
|
-
Margin requirement based on current positions only.
|
190
|
-
"""
|
191
|
-
purchasing_power: Optional[
|
192
|
-
Annotated[
|
193
|
-
Optional[Decimal],
|
194
|
-
Meta(
|
195
|
-
description="Total purchasing power; post-multiplied. (e.g. for cash margin account could be 2x available cash)"
|
196
|
-
),
|
197
|
-
]
|
198
|
-
] = None
|
199
|
-
"""
|
200
|
-
Total purchasing power; post-multiplied. (e.g. for cash margin account could be 2x available cash)
|
201
|
-
"""
|
202
|
-
realized_pnl: Optional[Decimal] = None
|
203
|
-
total_margin: Optional[
|
204
|
-
Annotated[
|
205
|
-
Optional[Decimal],
|
206
|
-
Meta(
|
207
|
-
description="Margin requirement calculated for worst-case based on open positions and working orders."
|
208
|
-
),
|
209
|
-
]
|
210
|
-
] = None
|
211
|
-
"""
|
212
|
-
Margin requirement calculated for worst-case based on open positions and working orders.
|
213
|
-
"""
|
214
|
-
unrealized_pnl: Optional[Decimal] = None
|
215
|
-
yesterday_equity: Optional[
|
216
|
-
Annotated[
|
217
|
-
Optional[Decimal], Meta(description="Yesterday total account equity.")
|
218
|
-
]
|
219
|
-
] = None
|
220
|
-
"""
|
221
|
-
Yesterday total account equity.
|
222
|
-
"""
|
223
|
-
|
224
|
-
# below is a constructor that takes all field titles as arguments for convenience
|
225
|
-
@classmethod
|
226
|
-
def new(
|
227
|
-
cls,
|
228
|
-
account: str,
|
229
|
-
balances: Dict[str, Decimal],
|
230
|
-
positions: Dict[str, AccountPosition],
|
231
|
-
timestamp: datetime,
|
232
|
-
cash_excess: Optional[Decimal] = None,
|
233
|
-
equity: Optional[Decimal] = None,
|
234
|
-
position_margin: Optional[Decimal] = None,
|
235
|
-
purchasing_power: Optional[Decimal] = None,
|
236
|
-
realized_pnl: Optional[Decimal] = None,
|
237
|
-
total_margin: Optional[Decimal] = None,
|
238
|
-
unrealized_pnl: Optional[Decimal] = None,
|
239
|
-
yesterday_equity: Optional[Decimal] = None,
|
240
|
-
):
|
241
|
-
return cls(
|
242
|
-
account,
|
243
|
-
balances,
|
244
|
-
positions,
|
245
|
-
timestamp,
|
246
|
-
cash_excess,
|
247
|
-
equity,
|
248
|
-
position_margin,
|
249
|
-
purchasing_power,
|
250
|
-
realized_pnl,
|
251
|
-
total_margin,
|
252
|
-
unrealized_pnl,
|
253
|
-
yesterday_equity,
|
254
|
-
)
|
255
|
-
|
256
|
-
def __str__(self) -> str:
|
257
|
-
return f"AggregatedAccountSummary(account={self.account},balances={self.balances},positions={self.positions},timestamp={self.timestamp},cash_excess={self.cash_excess},equity={self.equity},position_margin={self.position_margin},purchasing_power={self.purchasing_power},realized_pnl={self.realized_pnl},total_margin={self.total_margin},unrealized_pnl={self.unrealized_pnl},yesterday_equity={self.yesterday_equity})"
|
258
|
-
|
259
|
-
|
260
162
|
class AlgoState(str, Enum):
|
261
163
|
Pending = "Pending"
|
262
164
|
Running = "Running"
|
263
165
|
Stopped = "Stopped"
|
264
166
|
|
265
167
|
|
266
|
-
class CancelStatus(
|
267
|
-
Pending =
|
268
|
-
Acked =
|
269
|
-
Rejected =
|
270
|
-
Out =
|
168
|
+
class CancelStatus(str, Enum):
|
169
|
+
Pending = "Pending"
|
170
|
+
Acked = "Acked"
|
171
|
+
Rejected = "Rejected"
|
172
|
+
Out = "Out"
|
271
173
|
|
272
174
|
|
273
|
-
class CandleWidth(
|
274
|
-
OneSecond =
|
275
|
-
FiveSecond =
|
276
|
-
OneMinute =
|
277
|
-
FifteenMinute =
|
278
|
-
OneHour =
|
279
|
-
OneDay =
|
175
|
+
class CandleWidth(str, Enum):
|
176
|
+
OneSecond = "OneSecond"
|
177
|
+
FiveSecond = "FiveSecond"
|
178
|
+
OneMinute = "OneMinute"
|
179
|
+
FifteenMinute = "FifteenMinute"
|
180
|
+
OneHour = "OneHour"
|
181
|
+
OneDay = "OneDay"
|
280
182
|
|
281
183
|
|
282
184
|
class CptyLogoutRequest(Struct, omit_defaults=True):
|
@@ -503,14 +405,14 @@ class OrderRejectReason(str, Enum):
|
|
503
405
|
Unknown = "Unknown"
|
504
406
|
|
505
407
|
|
506
|
-
class OrderSource(
|
507
|
-
API =
|
508
|
-
GUI =
|
509
|
-
Algo =
|
510
|
-
Reconciled =
|
511
|
-
CLI =
|
512
|
-
Telegram =
|
513
|
-
Other =
|
408
|
+
class OrderSource(str, Enum):
|
409
|
+
API = "API"
|
410
|
+
GUI = "GUI"
|
411
|
+
Algo = "Algo"
|
412
|
+
Reconciled = "Reconciled"
|
413
|
+
CLI = "CLI"
|
414
|
+
Telegram = "Telegram"
|
415
|
+
Other = "Other"
|
514
416
|
|
515
417
|
|
516
418
|
class OrderStale(Struct, omit_defaults=True):
|
@@ -530,16 +432,16 @@ class OrderStale(Struct, omit_defaults=True):
|
|
530
432
|
return f"OrderStale(id={self.id})"
|
531
433
|
|
532
434
|
|
533
|
-
class OrderStatus(
|
534
|
-
Pending =
|
535
|
-
Open =
|
536
|
-
Rejected =
|
537
|
-
Out =
|
538
|
-
Canceling =
|
539
|
-
Canceled =
|
540
|
-
ReconciledOut =
|
541
|
-
Stale =
|
542
|
-
Unknown =
|
435
|
+
class OrderStatus(str, Enum):
|
436
|
+
Pending = "Pending"
|
437
|
+
Open = "Open"
|
438
|
+
Rejected = "Rejected"
|
439
|
+
Out = "Out"
|
440
|
+
Canceling = "Canceling"
|
441
|
+
Canceled = "Canceled"
|
442
|
+
ReconciledOut = "ReconciledOut"
|
443
|
+
Stale = "Stale"
|
444
|
+
Unknown = "Unknown"
|
543
445
|
|
544
446
|
|
545
447
|
class SortTickersBy(str, Enum):
|
@@ -648,50 +550,35 @@ class DerivativeKind(str, Enum):
|
|
648
550
|
Quanto = "Quanto"
|
649
551
|
|
650
552
|
|
651
|
-
class FillKind(
|
652
|
-
Normal =
|
653
|
-
Reversal =
|
654
|
-
Correction =
|
553
|
+
class FillKind(str, Enum):
|
554
|
+
Normal = "Normal"
|
555
|
+
Reversal = "Reversal"
|
556
|
+
Correction = "Correction"
|
655
557
|
|
656
558
|
|
657
559
|
HumanDuration = str
|
658
560
|
|
659
561
|
|
660
|
-
class
|
661
|
-
|
562
|
+
class Unit(str, Enum):
|
563
|
+
base = "base"
|
564
|
+
quote = "quote"
|
662
565
|
|
663
|
-
# below is a constructor that takes all field titles as arguments for convenience
|
664
|
-
@classmethod
|
665
|
-
def new(
|
666
|
-
cls,
|
667
|
-
unit: Literal["base"],
|
668
|
-
):
|
669
|
-
return cls(
|
670
|
-
unit,
|
671
|
-
)
|
672
|
-
|
673
|
-
def __str__(self) -> str:
|
674
|
-
return f"Base(unit={self.unit})"
|
675
566
|
|
676
|
-
|
677
|
-
|
678
|
-
unit: Literal["quote"]
|
567
|
+
class MinOrderQuantityUnit(Struct, omit_defaults=True):
|
568
|
+
unit: Unit
|
679
569
|
|
680
570
|
# below is a constructor that takes all field titles as arguments for convenience
|
681
571
|
@classmethod
|
682
572
|
def new(
|
683
573
|
cls,
|
684
|
-
unit:
|
574
|
+
unit: Unit,
|
685
575
|
):
|
686
576
|
return cls(
|
687
577
|
unit,
|
688
578
|
)
|
689
579
|
|
690
580
|
def __str__(self) -> str:
|
691
|
-
return f"
|
692
|
-
|
693
|
-
|
694
|
-
MinOrderQuantityUnit = Union[Base, Quote]
|
581
|
+
return f"MinOrderQuantityUnit(unit={self.unit})"
|
695
582
|
|
696
583
|
|
697
584
|
class OptionsExerciseType(str, Enum):
|
@@ -1072,6 +959,7 @@ class TimeZone(str, Enum):
|
|
1072
959
|
America_Coral_Harbour = "America/Coral_Harbour"
|
1073
960
|
America_Cordoba = "America/Cordoba"
|
1074
961
|
America_Costa_Rica = "America/Costa_Rica"
|
962
|
+
America_Coyhaique = "America/Coyhaique"
|
1075
963
|
America_Creston = "America/Creston"
|
1076
964
|
America_Cuiaba = "America/Cuiaba"
|
1077
965
|
America_Curacao = "America/Curacao"
|
@@ -1669,7 +1557,7 @@ class AberrantFill(Struct, omit_defaults=True):
|
|
1669
1557
|
id: Annotated[str, Meta(title="fill_id")]
|
1670
1558
|
x: Annotated[str, Meta(title="execution_venue")]
|
1671
1559
|
a: Optional[Annotated[Optional[str], Meta(title="account")]] = None
|
1672
|
-
atn: Optional[Annotated[Optional[int], Meta(
|
1560
|
+
atn: Optional[Annotated[Optional[int], Meta(title="recv_time_ns")]] = None
|
1673
1561
|
ats: Optional[Annotated[Optional[int], Meta(title="recv_time")]] = None
|
1674
1562
|
d: Optional[Annotated[Optional[OrderDir], Meta(title="direction")]] = None
|
1675
1563
|
f: Optional[Annotated[Optional[Decimal], Meta(title="fee")]] = None
|
@@ -1679,7 +1567,7 @@ class AberrantFill(Struct, omit_defaults=True):
|
|
1679
1567
|
p: Optional[Annotated[Optional[Decimal], Meta(title="price")]] = None
|
1680
1568
|
q: Optional[Annotated[Optional[Decimal], Meta(title="quantity")]] = None
|
1681
1569
|
s: Optional[Annotated[Optional[str], Meta(title="symbol")]] = None
|
1682
|
-
tn: Optional[Annotated[Optional[int], Meta(
|
1570
|
+
tn: Optional[Annotated[Optional[int], Meta(title="trade_time_ns")]] = None
|
1683
1571
|
ts: Optional[Annotated[Optional[int], Meta(title="trade_time")]] = None
|
1684
1572
|
u: Optional[Annotated[Optional[UserId], Meta(title="trader")]] = None
|
1685
1573
|
xid: Optional[Annotated[Optional[str], Meta(title="exchange_fill_id")]] = None
|
@@ -1982,7 +1870,7 @@ class Fill(Struct, omit_defaults=True):
|
|
1982
1870
|
x: Annotated[str, Meta(title="execution_venue")]
|
1983
1871
|
a: Optional[Annotated[Optional[str], Meta(title="account")]] = None
|
1984
1872
|
agg: Optional[Annotated[int, Meta(title="is_taker")]] = None
|
1985
|
-
atn: Optional[Annotated[Optional[int], Meta(
|
1873
|
+
atn: Optional[Annotated[Optional[int], Meta(title="recv_time_ns")]] = None
|
1986
1874
|
ats: Optional[
|
1987
1875
|
Annotated[
|
1988
1876
|
Optional[int],
|
@@ -49,6 +49,9 @@ from architect_py.grpc_client.Orderflow.OrderflowRequest import (
|
|
49
49
|
OrderflowRequest_route,
|
50
50
|
OrderflowRequestUnannotatedResponseType,
|
51
51
|
)
|
52
|
+
from architect_py.grpc_client.Symbology.SymbolsRequest import (
|
53
|
+
SymbolsRequest,
|
54
|
+
)
|
52
55
|
from architect_py.grpc_client.definitions import L2BookDiff
|
53
56
|
from architect_py.scalars import TradableProduct
|
54
57
|
|
@@ -192,6 +195,11 @@ class GRPCClient:
|
|
192
195
|
self._decoders[response_type] = decoder
|
193
196
|
return decoder
|
194
197
|
|
198
|
+
async def symbols(self) -> list[str]:
|
199
|
+
request = SymbolsRequest()
|
200
|
+
response = await self.request(request)
|
201
|
+
return response.symbols
|
202
|
+
|
195
203
|
async def request_l1_book_snapshot(self, symbol: TradableProduct) -> L1BookSnapshot:
|
196
204
|
request = L1BookSnapshotRequest(symbol=symbol)
|
197
205
|
return await self.request(request)
|
@@ -2,7 +2,9 @@ import grpc
|
|
2
2
|
import msgspec
|
3
3
|
from typing import Union
|
4
4
|
from .grpc_client import encoder
|
5
|
-
from .Cpty.CptyRequest import
|
5
|
+
from .Cpty.CptyRequest import (
|
6
|
+
UnannotatedCptyRequest,
|
7
|
+
)
|
6
8
|
from .Orderflow.SubscribeOrderflowRequest import SubscribeOrderflowRequest
|
7
9
|
|
8
10
|
|
@@ -14,8 +16,7 @@ class CptyServicer(object):
|
|
14
16
|
|
15
17
|
|
16
18
|
def add_CptyServicer_to_server(servicer, server):
|
17
|
-
|
18
|
-
decoder = msgspec.json.Decoder(type=Union[Login, Logout, PlaceOrder, CancelOrder])
|
19
|
+
decoder = msgspec.json.Decoder(type=UnannotatedCptyRequest)
|
19
20
|
rpc_method_handlers = {
|
20
21
|
"Cpty": grpc.stream_stream_rpc_method_handler(
|
21
22
|
servicer.Cpty,
|
@@ -37,9 +38,9 @@ class OrderflowServicer(object):
|
|
37
38
|
|
38
39
|
|
39
40
|
def add_OrderflowServicer_to_server(servicer, server):
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
decoder = msgspec.json.Decoder(
|
42
|
+
type=SubscribeOrderflowRequest.get_unannotated_response_type()
|
43
|
+
)
|
43
44
|
rpc_method_handlers = {
|
44
45
|
"SubscribeOrderflow": grpc.unary_stream_rpc_method_handler(
|
45
46
|
servicer.SubscribeOrderflow,
|
architect_py/tests/conftest.py
CHANGED
@@ -99,9 +99,10 @@ def sync_client():
|
|
99
99
|
@pytest_asyncio.fixture
|
100
100
|
async def front_ES_future(async_client: AsyncClient) -> str:
|
101
101
|
series = await async_client.get_cme_futures_series("ES CME Futures")
|
102
|
+
assert async_client.get_expiration_from_CME_name(series[0][1]) == series[0][0]
|
102
103
|
|
103
104
|
inc = 0
|
104
|
-
if datetime.now().date() >=
|
105
|
+
if datetime.now().date() >= series[0][0]:
|
105
106
|
inc += 1
|
106
107
|
|
107
108
|
return series[inc][1]
|
@@ -110,9 +111,10 @@ async def front_ES_future(async_client: AsyncClient) -> str:
|
|
110
111
|
@pytest_asyncio.fixture
|
111
112
|
async def front_ES_future_tp(async_client: AsyncClient) -> str:
|
112
113
|
series = await async_client.get_cme_futures_series("ES CME Futures")
|
114
|
+
assert async_client.get_expiration_from_CME_name(series[0][1]) == series[0][0]
|
113
115
|
|
114
116
|
inc = 0
|
115
|
-
if datetime.now().date() >=
|
117
|
+
if datetime.now().date() >= series[0][0]:
|
116
118
|
inc += 1
|
117
119
|
|
118
120
|
return f"{series[inc][1]}/USD"
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import asyncio
|
1
2
|
from decimal import Decimal
|
2
3
|
|
3
4
|
import pytest
|
@@ -31,7 +32,7 @@ async def test_live_far_order_cancel(async_client: AsyncClient, front_ES_future:
|
|
31
32
|
min_qty = Decimal(execution_info.min_order_quantity)
|
32
33
|
|
33
34
|
if bid_price := snapshot.bid_price:
|
34
|
-
far_price = bid_price * Decimal("0.
|
35
|
+
far_price = bid_price * Decimal("0.9")
|
35
36
|
else:
|
36
37
|
raise ValueError(f"No bid price in snapshot for {tp} at venue {venue}")
|
37
38
|
limit_price = TickRoundMethod.FLOOR(far_price, execution_info.tick_size)
|
@@ -53,9 +54,12 @@ async def test_live_far_order_cancel(async_client: AsyncClient, front_ES_future:
|
|
53
54
|
|
54
55
|
assert order is not None
|
55
56
|
|
57
|
+
await asyncio.sleep(1)
|
58
|
+
|
56
59
|
order_query = await async_client.get_order(order.id)
|
57
60
|
if order_query is None:
|
58
61
|
raise ValueError("Order is None")
|
59
62
|
else:
|
60
|
-
|
61
|
-
|
63
|
+
if order_query.reject_reason is None and order_query.reject_message is None:
|
64
|
+
cancel = await async_client.cancel_order(order.id)
|
65
|
+
assert cancel
|
@@ -108,12 +108,9 @@ async def test_subscribe_l2_stream(
|
|
108
108
|
|
109
109
|
@pytest.mark.asyncio
|
110
110
|
@pytest.mark.timeout(15)
|
111
|
-
async def test_subscribe_cme_trades(async_client: AsyncClient):
|
111
|
+
async def test_subscribe_cme_trades(async_client: AsyncClient, front_ES_future_tp: str):
|
112
112
|
venue = "CME"
|
113
|
-
|
114
|
-
_, market = markets[0]
|
115
|
-
|
116
|
-
market = TradableProduct(market, "USD")
|
113
|
+
market = TradableProduct(front_ES_future_tp)
|
117
114
|
market_status = await async_client.get_market_status(market, venue)
|
118
115
|
|
119
116
|
if not market_status.is_trading:
|
@@ -0,0 +1,191 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: architect-py
|
3
|
+
Version: 3.2.2
|
4
|
+
Summary: Client library for the Architect trading platform.
|
5
|
+
Author: Architect Financial Technologies, Inc.
|
6
|
+
Author-email: hello@architect.xyz
|
7
|
+
Requires-Python: >=3.10,<4
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Requires-Dist: asyncio (>=3)
|
17
|
+
Requires-Dist: dnspython (>=2.0)
|
18
|
+
Requires-Dist: gql[httpx] (>=3.5.0,<4.0.0)
|
19
|
+
Requires-Dist: grpcio (>=1.66.1)
|
20
|
+
Requires-Dist: msgspec (>=0.19,<0.20)
|
21
|
+
Requires-Dist: pydantic (>=2.10,<3.0)
|
22
|
+
Requires-Dist: websockets (>=11)
|
23
|
+
Description-Content-Type: text/markdown
|
24
|
+
|
25
|
+
# [](https://architect.co) architect_py
|
26
|
+
[](https://pypi.org/project/architect-py/)
|
27
|
+
|
28
|
+
A Python API for [Architect](https://architect.co).
|
29
|
+
|
30
|
+
Just some of the features of this API:
|
31
|
+
symbology, market snapshots, past trades, account queries, order management (including sending advanced algos!), and market feed subscriptions.
|
32
|
+
|
33
|
+
This repo heavily uses type hinting, so using a type checker such as Pylance or mypy is suggestible to reduce potential for error.
|
34
|
+
|
35
|
+
|
36
|
+
## Example usage
|
37
|
+
|
38
|
+
`AsyncClient` and `Client` are the entryways into making calls to the Architect backend.
|
39
|
+
Note that the sync `Client` does not have access to any subscription functions, because they are async by nature.
|
40
|
+
|
41
|
+
|
42
|
+
```python
|
43
|
+
import asyncio
|
44
|
+
|
45
|
+
from architect_py.async_client import AsyncClient
|
46
|
+
from architect_py.scalars import TradableProduct
|
47
|
+
|
48
|
+
async def main():
|
49
|
+
c = await AsyncClient.connect(
|
50
|
+
host="<your installation domain>", # e.g. app.architect.co for the brokerage
|
51
|
+
api_key="<api key>",
|
52
|
+
api_secret="<api secret>"
|
53
|
+
paper_trading=True,
|
54
|
+
)
|
55
|
+
print(await c.who_am_i())
|
56
|
+
|
57
|
+
series = await async_client.get_cme_futures_series("ES CME Futures")
|
58
|
+
front_ES_future = series[0][1]
|
59
|
+
|
60
|
+
s = c.subscribe_trades_stream(front_ES_future)
|
61
|
+
async for trade in s:
|
62
|
+
print(trade)
|
63
|
+
|
64
|
+
asyncio.run(main())
|
65
|
+
```
|
66
|
+
|
67
|
+
```python
|
68
|
+
from architect_py.client import Client
|
69
|
+
|
70
|
+
def main():
|
71
|
+
c = Client(
|
72
|
+
host="<your installation domain>",
|
73
|
+
api_key="<api key>",
|
74
|
+
api_secret="<api secret>"
|
75
|
+
paper_trading=True,
|
76
|
+
)
|
77
|
+
print(c.who_am_i())
|
78
|
+
|
79
|
+
print(client.get_account_summaries())
|
80
|
+
|
81
|
+
print(client.search_symbols("ES"))
|
82
|
+
```
|
83
|
+
|
84
|
+
While the AsyncClient is the recommended way to use the Architect API, the Client instead without any familiarity with `async/await`.
|
85
|
+
The sync clients and async clients usage is identical, except one removes the `await` before the call. The only exception to this is that the sync client does not support any subscriptions, because they are inherently asynchronous.
|
86
|
+
|
87
|
+
Check the `examples` folder or the `architect_py/tests` folders for example usages.
|
88
|
+
|
89
|
+
|
90
|
+
## Function Breakdown
|
91
|
+
|
92
|
+
|
93
|
+
The `async` client has the following functions
|
94
|
+
|
95
|
+
### 🚀 Initialization
|
96
|
+
|
97
|
+
- **`connect`**: The main way to create an AsyncClient object.
|
98
|
+
- **`__init__`**: Users should not be using this constructor directly, unless they do not want to use any subscription methods.
|
99
|
+
|
100
|
+
---
|
101
|
+
|
102
|
+
### 🔍 Symbology
|
103
|
+
|
104
|
+
- **`search_symbols`**: Search for symbols in the Architect database.
|
105
|
+
- **`get_product_info`**: Get the product information (product_type, underlying, multiplier, etc.) for a symbol.
|
106
|
+
- **`get_product_infos`**: Get the product information (product_type, underlying, multiplier, etc.) for a list of symbols.
|
107
|
+
- **`get_execution_info`**: Get the execution information (tick_size, step_size, margin, etc.) for a symbol.
|
108
|
+
- **`get_execution_infos`**: Get the execution information (tick_size, step_size, etc.) for a list of symbols.
|
109
|
+
- **`get_cme_first_notice_date`**: Get the first notice date for a CME future.
|
110
|
+
- **`get_future_series`**: Get the series of futures for a given series symbol.
|
111
|
+
- **`get_expiration_from_CME_name`**: Get the expiration date from a CME future name.
|
112
|
+
- **`get_cme_futures_series`**: Get the futures in a series from the CME.
|
113
|
+
- **`get_cme_future_from_root_month_year`**: Get the symbol for a CME future from the root, month, and year.
|
114
|
+
|
115
|
+
---
|
116
|
+
|
117
|
+
### 👤 Account Management
|
118
|
+
|
119
|
+
- **`who_am_i`**: Gets the user_id and user_email for the user that the API key belongs to.
|
120
|
+
- **`list_accounts`**: List accounts for the user that the API key belongs to.
|
121
|
+
- **`get_account_summary`**: Gets the account summary for the given account.
|
122
|
+
- **`get_account_summaries`**: Gets the account summaries for the given accounts and trader.
|
123
|
+
- **`get_account_history`**: Gets the account history for the given account and dates.
|
124
|
+
|
125
|
+
---
|
126
|
+
|
127
|
+
### 📑 Order Management
|
128
|
+
|
129
|
+
- **`get_open_orders`**: Returns a list of open orders for the user that match the filters.
|
130
|
+
- **`get_all_open_orders`**: Returns a list of all open orders for the user.
|
131
|
+
- **`get_historical_orders`**: Gets the historical orders that match the filters.
|
132
|
+
- **`get_order`**: Returns the OrderFields object for the specified order.
|
133
|
+
- **`get_orders`**: Returns a list of OrderFields objects for the specified orders.
|
134
|
+
- **`get_fills`**: Returns a list of fills for the given filters.
|
135
|
+
|
136
|
+
---
|
137
|
+
|
138
|
+
### 📈 Market Data
|
139
|
+
|
140
|
+
- **`get_market_status`**: Returns market status for symbol (ie if it is quoting and trading).
|
141
|
+
- **`get_market_snapshot`**: This is an alias for l1_book_snapshot.
|
142
|
+
- **`get_market_snapshots`**: This is an alias for l1_book_snapshot.
|
143
|
+
- **`get_historical_candles`**: Gets the historical candles for a symbol.
|
144
|
+
- **`get_l1_book_snapshot`**: Gets the L1 book snapshot for a symbol.
|
145
|
+
- **`get_l1_book_snapshots`**: Gets the L1 book snapshots for a list of symbols.
|
146
|
+
- **`get_l2_book_snapshot`**: Gets the L2 book snapshot for a symbol.
|
147
|
+
- **`subscribe_l1_book_stream`**: Subscribe to the stream of L1BookSnapshots for a symbol.
|
148
|
+
- **`subscribe_l2_book_stream`**: Subscribe to the stream of L2BookUpdates for a symbol.
|
149
|
+
- **`subscribe_l1_book`**: Returns a L1BookSnapshot object that is constantly updating in the background.
|
150
|
+
- **`subscribe_l2_book`**: Returns a L2BookSnapshot object that is constantly updating in the background.
|
151
|
+
- **`subscribe_trades_stream`**: Subscribe to a stream of trades for a symbol.
|
152
|
+
- **`subscribe_candles_stream`**: Subscribe to a stream of candles for a symbol.
|
153
|
+
|
154
|
+
---
|
155
|
+
|
156
|
+
### 📝 Order Entry and Cancellation
|
157
|
+
|
158
|
+
- **`send_limit_order`**: Sends a regular limit order.
|
159
|
+
- **`send_market_pro_order`**: Sends a market-order like limit price based on the BBO.
|
160
|
+
- **`cancel_order`**: Cancels an order by order id.
|
161
|
+
- **`cancel_all_orders`**: Cancels all open orders.
|
162
|
+
|
163
|
+
|
164
|
+
### Running examples from this package
|
165
|
+
|
166
|
+
Clone this repository to run examples in the `examples` directory. This package
|
167
|
+
uses poetry for dependency management. To enter a poetry virtual environment, make
|
168
|
+
sure you have [poetry](https://python-poetry.org/docs/) installed and run the
|
169
|
+
following from the repository root.
|
170
|
+
|
171
|
+
```bash
|
172
|
+
poetry shell
|
173
|
+
poetry install --sync
|
174
|
+
|
175
|
+
export ARCHITECT_HOST="<your installation domain>"
|
176
|
+
export ARCHITECT_API_KEY="<api key>"
|
177
|
+
export ARCHITECT_API_SECRET="<api secret>"
|
178
|
+
|
179
|
+
python -m examples.trades
|
180
|
+
```
|
181
|
+
|
182
|
+
You can exit the poetry shell by running `exit`. Environment variables set
|
183
|
+
within the shell are not persisted.
|
184
|
+
|
185
|
+
|
186
|
+
## API keys for the brokerage
|
187
|
+
|
188
|
+
API keys/secrets for the brokerage can be generated on the [user account page](https://app.architect.co/user/account).
|
189
|
+
|
190
|
+
|
191
|
+
|