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.
@@ -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(int, Enum):
267
- Pending = 0
268
- Acked = 1
269
- Rejected = 2
270
- Out = 127
168
+ class CancelStatus(str, Enum):
169
+ Pending = "Pending"
170
+ Acked = "Acked"
171
+ Rejected = "Rejected"
172
+ Out = "Out"
271
173
 
272
174
 
273
- class CandleWidth(int, Enum):
274
- OneSecond = 1
275
- FiveSecond = 2
276
- OneMinute = 4
277
- FifteenMinute = 8
278
- OneHour = 16
279
- OneDay = 32
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(int, Enum):
507
- API = 0
508
- GUI = 1
509
- Algo = 2
510
- Reconciled = 3
511
- CLI = 4
512
- Telegram = 5
513
- Other = 255
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(int, Enum):
534
- Pending = 0
535
- Open = 1
536
- Rejected = 2
537
- Out = 127
538
- Canceling = 128
539
- Canceled = 129
540
- ReconciledOut = 130
541
- Stale = 254
542
- Unknown = 255
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(int, Enum):
652
- Normal = 0
653
- Reversal = 1
654
- Correction = 2
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 Base(Struct, omit_defaults=True):
661
- unit: Literal["base"]
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
- class Quote(Struct, omit_defaults=True):
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: Literal["quote"],
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"Quote(unit={self.unit})"
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(ge=0, title="recv_time_ns")]] = None
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(ge=0, title="trade_time_ns")]] = None
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(ge=0, title="recv_time_ns")]] = None
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 Login, Logout, PlaceOrder, CancelOrder
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
- # CR alee: there must be a better way to get the unannotated request type
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
- # CR alee: this doesn't work
41
- # decoder = msgspec.json.Decoder(type=SubscribeOrderflowRequest.get_unannotated_response_type())
42
- decoder = msgspec.json.Decoder(type=dict)
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,
@@ -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() >= async_client.get_expiration_from_CME_name(series[0][1]):
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() >= async_client.get_expiration_from_CME_name(series[0][1]):
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.8")
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
- cancel = await async_client.cancel_order(order.id)
61
- assert cancel
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
- markets = await async_client.get_cme_futures_series("ES CME Futures")
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
+ # [![Architect](https://avatars.githubusercontent.com/u/116864654?s=29&v=2)](https://architect.co) architect_py
26
+ [![PyPI version](https://img.shields.io/pypi/v/architect-py.svg)](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
+