architect-py 5.1.2__py3-none-any.whl → 5.1.3__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 -17
- architect_py/grpc/models/Marketdata/SubscribeL1BookSnapshotsRequest.py +14 -1
- {architect_py-5.1.2.dist-info → architect_py-5.1.3.dist-info}/METADATA +3 -3
- {architect_py-5.1.2.dist-info → architect_py-5.1.3.dist-info}/RECORD +21 -18
- examples/book_subscription.py +1 -1
- examples/candles.py +1 -1
- examples/{common.py → config.py} +4 -48
- examples/funding_rate_mean_reversion_algo.py +1 -1
- examples/order_sending.py +1 -1
- examples/orderflow_channel.py +56 -0
- examples/orderflow_streaming.py +47 -0
- examples/stream_l1_marketdata.py +1 -1
- examples/stream_l2_marketdata.py +1 -1
- examples/termutils.py +44 -0
- examples/trades.py +1 -1
- examples/tutorial_async.py +2 -1
- examples/tutorial_sync.py +2 -1
- {architect_py-5.1.2.dist-info → architect_py-5.1.3.dist-info}/WHEEL +0 -0
- {architect_py-5.1.2.dist-info → architect_py-5.1.3.dist-info}/licenses/LICENSE +0 -0
- {architect_py-5.1.2.dist-info → architect_py-5.1.3.dist-info}/top_level.txt +0 -0
architect_py/__init__.py
CHANGED
architect_py/async_client.py
CHANGED
@@ -364,6 +364,15 @@ class AsyncClient:
|
|
364
364
|
"as of v5.0.0: enable_orderflow is deprecated; orderflow is enabled by default"
|
365
365
|
)
|
366
366
|
|
367
|
+
async def cpty_status(self, kind: str, instance: Optional[str] = None) -> CptyStatus:
|
368
|
+
"""
|
369
|
+
Get cpty status.
|
370
|
+
"""
|
371
|
+
grpc_client = await self.core()
|
372
|
+
req = CptyStatusRequest(kind=kind, instance=instance)
|
373
|
+
res: CptyStatus = await grpc_client.unary_unary(req)
|
374
|
+
return res
|
375
|
+
|
367
376
|
# ------------------------------------------------------------
|
368
377
|
# Symbology
|
369
378
|
# ------------------------------------------------------------
|
@@ -1382,28 +1391,16 @@ class AsyncClient:
|
|
1382
1391
|
|
1383
1392
|
Example:
|
1384
1393
|
```python
|
1385
|
-
async for
|
1386
|
-
print(
|
1394
|
+
async for event in client.stream_orderflow(account, execution_venue, trader):
|
1395
|
+
print(event)
|
1387
1396
|
```
|
1388
1397
|
"""
|
1389
1398
|
grpc_client = await self.core()
|
1390
|
-
|
1399
|
+
req: SubscribeOrderflowRequest = SubscribeOrderflowRequest(
|
1391
1400
|
account=account, execution_venue=execution_venue, trader=trader
|
1392
1401
|
)
|
1393
|
-
|
1394
|
-
|
1395
|
-
stub: grpc.aio.UnaryStreamMultiCallable[
|
1396
|
-
SubscribeOrderflowRequest, Orderflow
|
1397
|
-
] = grpc_client.channel.unary_stream(
|
1398
|
-
SubscribeOrderflowRequest.get_route(),
|
1399
|
-
request_serializer=grpc_client.encoder().encode,
|
1400
|
-
response_deserializer=decoder.decode,
|
1401
|
-
)
|
1402
|
-
call: grpc.aio._base_call.UnaryStreamCall[
|
1403
|
-
SubscribeOrderflowRequest, Orderflow
|
1404
|
-
] = stub(request, metadata=(("authorization", f"Bearer {grpc_client.jwt}"),))
|
1405
|
-
async for update in call:
|
1406
|
-
yield update
|
1402
|
+
async for res in grpc_client.unary_stream(req): # type: ignore
|
1403
|
+
yield res
|
1407
1404
|
|
1408
1405
|
# ------------------------------------------------------------
|
1409
1406
|
# Order entry
|
@@ -10,6 +10,17 @@ from msgspec import Meta, Struct
|
|
10
10
|
|
11
11
|
|
12
12
|
class SubscribeL1BookSnapshotsRequest(Struct, omit_defaults=True):
|
13
|
+
send_initial_snapshots: Optional[
|
14
|
+
Annotated[
|
15
|
+
bool,
|
16
|
+
Meta(
|
17
|
+
description="If true, send an initial snapshot to subscribers on symbol subscription"
|
18
|
+
),
|
19
|
+
]
|
20
|
+
] = False
|
21
|
+
"""
|
22
|
+
If true, send an initial snapshot to subscribers on symbol subscription
|
23
|
+
"""
|
13
24
|
symbols: Optional[
|
14
25
|
Annotated[
|
15
26
|
List[str],
|
@@ -25,16 +36,18 @@ class SubscribeL1BookSnapshotsRequest(Struct, omit_defaults=True):
|
|
25
36
|
@classmethod
|
26
37
|
def new(
|
27
38
|
cls,
|
39
|
+
send_initial_snapshots: Optional[bool] = False,
|
28
40
|
symbols: Optional[List[str]] = None,
|
29
41
|
venue: Optional[str] = None,
|
30
42
|
):
|
31
43
|
return cls(
|
44
|
+
send_initial_snapshots,
|
32
45
|
symbols,
|
33
46
|
venue,
|
34
47
|
)
|
35
48
|
|
36
49
|
def __str__(self) -> str:
|
37
|
-
return f"SubscribeL1BookSnapshotsRequest(symbols={self.symbols},venue={self.venue})"
|
50
|
+
return f"SubscribeL1BookSnapshotsRequest(send_initial_snapshots={self.send_initial_snapshots},symbols={self.symbols},venue={self.venue})"
|
38
51
|
|
39
52
|
@staticmethod
|
40
53
|
def get_response_type():
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: architect-py
|
3
|
-
Version: 5.1.
|
3
|
+
Version: 5.1.3
|
4
4
|
Summary: Python SDK for the Architect trading platform and brokerage.
|
5
5
|
Author-email: "Architect Financial Technologies, Inc." <hello@architect.co>
|
6
6
|
License-Expression: Apache-2.0
|
7
|
-
Project-URL: Homepage, https://www.architect.co/brokerage/overview
|
8
7
|
Project-URL: Documentation, https://docs.architect.co
|
8
|
+
Project-URL: Homepage, https://www.architect.co/brokerage/overview
|
9
9
|
Project-URL: Repository, https://github.com/architect-xyz/architect-py
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
11
11
|
Classifier: Operating System :: OS Independent
|
@@ -48,7 +48,7 @@ Go to [FUNCTIONS.md](FUNCTIONS.md) file to see a catalog of methods.
|
|
48
48
|
|
49
49
|
## Examples
|
50
50
|
|
51
|
-
Go to the [Examples](./examples) to see examples of a variety of common use cases.
|
51
|
+
Go to the [Examples](./examples) to see examples of a variety of common use cases. To run a specific example, use e.g. `python -m examples.orderflow_streaming`.
|
52
52
|
|
53
53
|
## Documentation
|
54
54
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
architect_py/__init__.py,sha256=
|
2
|
-
architect_py/async_client.py,sha256=
|
1
|
+
architect_py/__init__.py,sha256=IA3WJIRKMNE_PPf4JFDfvwwcgS0692icwFM1ckFL8Fk,16121
|
2
|
+
architect_py/async_client.py,sha256=IdR1vtC4eGRXKBUZ7A5bxaX6jh5jXPSgcHxl22dZ5eQ,61394
|
3
3
|
architect_py/client.py,sha256=yC0OVzz6uXUMdIIhqqR3GyVuBApYSm00AS51QM8xPak,4911
|
4
4
|
architect_py/client.pyi,sha256=VJrg85KaupKzWY4BvS86xREs67S_TFrItNirczYLrgc,24565
|
5
5
|
architect_py/common_types/__init__.py,sha256=fzOdIlKGWVN9V2Onc5z1v2bpvtZ4H9RSFA9ymJcBi3k,197
|
@@ -99,7 +99,7 @@ architect_py/grpc/models/Marketdata/MarketStatus.py,sha256=4Kt2z16t7dpjpiELWshJy
|
|
99
99
|
architect_py/grpc/models/Marketdata/MarketStatusRequest.py,sha256=ajyI4UlvFusyM0743dukT4KFZTlp9iUh0lTGWl6n7nw,1056
|
100
100
|
architect_py/grpc/models/Marketdata/SubscribeCandlesRequest.py,sha256=ck5pQx54uymlpR-jxFpxcW0LPDLU7R8GvqLqF-7GmoU,1508
|
101
101
|
architect_py/grpc/models/Marketdata/SubscribeCurrentCandlesRequest.py,sha256=QuSNIXARFT--djk_Kl3SUWHfUwAfaasqzZ0cyZfzeN0,1930
|
102
|
-
architect_py/grpc/models/Marketdata/SubscribeL1BookSnapshotsRequest.py,sha256=
|
102
|
+
architect_py/grpc/models/Marketdata/SubscribeL1BookSnapshotsRequest.py,sha256=Pq8tqLBHLwGbcJwWqKvurvRT3ARXVktLYWhyQtIeHX0,1855
|
103
103
|
architect_py/grpc/models/Marketdata/SubscribeL2BookUpdatesRequest.py,sha256=8olH2zWguzq1RnmIAZ59tFTmGIBLAYuGanbiI3kamm0,1133
|
104
104
|
architect_py/grpc/models/Marketdata/SubscribeLiquidationsRequest.py,sha256=6BhC4FJvHxm4yq9l_TmEioegdu8ZMFaoEA-bRC8WY7A,1039
|
105
105
|
architect_py/grpc/models/Marketdata/SubscribeManyCandlesRequest.py,sha256=pel2GGysDsJXjPY7rkyqqyGS3MPl13YezJS7apihiFc,1512
|
@@ -170,19 +170,22 @@ architect_py/utils/orderbook.py,sha256=JM02NhHbmK3sNaS2Ara8FBY4TvKvtMIzJW1oVd8KC
|
|
170
170
|
architect_py/utils/pandas.py,sha256=QHz2ynj4T92FobuzRaNoH3ypArHoSDCiGtZ3PVXJ2vo,1017
|
171
171
|
architect_py/utils/price_bands.py,sha256=j7ioSA3dx025CD5E2Vg7XQvmjPvxQb-gzQBfQTovpTw,21874
|
172
172
|
architect_py/utils/symbol_parsing.py,sha256=OjJzk2c6QU2s0aJMSyVEzlWD5Vy-RlakJVW7jNHVDJk,845
|
173
|
-
architect_py-5.1.
|
173
|
+
architect_py-5.1.3.dist-info/licenses/LICENSE,sha256=6P0_5gYN8iPWPZeqA9nxiO3tRQmcSA1ijAVR7C8j1SI,11362
|
174
174
|
examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
175
|
-
examples/book_subscription.py,sha256=
|
176
|
-
examples/candles.py,sha256=
|
177
|
-
examples/
|
175
|
+
examples/book_subscription.py,sha256=1WFQN_QCE8cRS_CIv2k0NxqpK37fA9-Ja2Kfxs8vsb8,1461
|
176
|
+
examples/candles.py,sha256=T71TsxbfXCT6mrJZmTgdTKesJFdQhYP_4AsiNK-8KyQ,756
|
177
|
+
examples/config.py,sha256=rv6x7QYJO6ckvpRcwghyJbkL_lTBPnK0u6nKgkYTvxQ,1858
|
178
178
|
examples/external_cpty.py,sha256=xxGXONXwoWIS8ys0SgxHLSmntAi1BlwV2NR9WD1kvpc,2527
|
179
|
-
examples/funding_rate_mean_reversion_algo.py,sha256=
|
180
|
-
examples/order_sending.py,sha256=
|
181
|
-
examples/
|
182
|
-
examples/
|
183
|
-
examples/
|
184
|
-
examples/
|
185
|
-
examples/
|
179
|
+
examples/funding_rate_mean_reversion_algo.py,sha256=Y9zJ7N4TEm36TH3jIHMbDxucKOOlD2VHe5oNcLai11o,6502
|
180
|
+
examples/order_sending.py,sha256=0M5eK20nDO5KXJZV-yidC7HR_RHP3uJL9f-q9FF0BIs,3313
|
181
|
+
examples/orderflow_channel.py,sha256=L6W9aZS95Xmjl1IvrKA1Cp06r9-QOERsBETLOg3EImk,1891
|
182
|
+
examples/orderflow_streaming.py,sha256=BtVwCYWBCpytaAFN9u2WPgGCugyNMsGa6nA1dPWuVLs,1300
|
183
|
+
examples/stream_l1_marketdata.py,sha256=ZkXcm5XOpG6epPn3EhmqlVJyYBwh87I0QHtuOmKjRpg,728
|
184
|
+
examples/stream_l2_marketdata.py,sha256=AeVOBBLdg-0OQE0gouHiLaUfGAAmUoVxif9XBrRo1tQ,1091
|
185
|
+
examples/termutils.py,sha256=ZZrky5Ftn4UoLPKGffGvUl1Z8CtvDoNjEtUH4S1a_KY,1133
|
186
|
+
examples/trades.py,sha256=0OzWQVTuIrC0KlisY0Tc-3pmWNP0m0-eCSntCV6Qdh8,561
|
187
|
+
examples/tutorial_async.py,sha256=FNMjP2WmszRB0OXoMbshJ775LoPDzm55UZICa9ztr5w,2639
|
188
|
+
examples/tutorial_sync.py,sha256=w5Sqa0YFh0XnpoXuhD3WsKRKpR5cuTTNb7pCp-Aqnz0,2846
|
186
189
|
scripts/add_imports_to_inits.py,sha256=bryhz6RpKAJsSieVMnXnRyLp8evNkpOsNUkBUPkk1WQ,4518
|
187
190
|
scripts/correct_sync_interface.py,sha256=O8qxSqNSNIL8KrgZ4C8rjs_pUCdcA1WeqKAggM2DINw,4056
|
188
191
|
scripts/generate_functions_md.py,sha256=-rVRhbHlDodGH2a32UCsMLIpgXtDvOhBmkHa0RqDpCA,6232
|
@@ -191,7 +194,7 @@ scripts/preprocess_grpc_schema.py,sha256=p9LdoMZzixBSsVx7Dy3_8uJzOy_QwCoVMkAABQK
|
|
191
194
|
scripts/prune_graphql_schema.py,sha256=hmfw5FD_iKGKMFkq6H1neZiXXtljFFrOwi2fiusTWE4,6210
|
192
195
|
templates/exceptions.py,sha256=tIHbiO5Q114h9nPwJXsgHvW_bERLwxuNp9Oj41p6t3A,2379
|
193
196
|
templates/juniper_base_client.py,sha256=B8QF4IFSwqBK5UY2aFPbSdYnX9bcwnlxLK4ojPRaW0E,12705
|
194
|
-
architect_py-5.1.
|
195
|
-
architect_py-5.1.
|
196
|
-
architect_py-5.1.
|
197
|
-
architect_py-5.1.
|
197
|
+
architect_py-5.1.3.dist-info/METADATA,sha256=Ozka0r2vOt_iWe4muYQRt8dLA--nNXXUeQSQ1Oi2S14,2638
|
198
|
+
architect_py-5.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
199
|
+
architect_py-5.1.3.dist-info/top_level.txt,sha256=UjtO97OACFQ9z5MzS-X2wBlt5Ovk1vxakQPKfokI454,40
|
200
|
+
architect_py-5.1.3.dist-info/RECORD,,
|
examples/book_subscription.py
CHANGED
@@ -6,7 +6,7 @@ from pydantic import ValidationError
|
|
6
6
|
from architect_py import AsyncClient, TradableProduct
|
7
7
|
from architect_py.graphql_client.exceptions import GraphQLClientHttpError
|
8
8
|
|
9
|
-
from .
|
9
|
+
from .config import connect_async_client
|
10
10
|
|
11
11
|
buy_columns = "{:>15} {:>15} {:>15}"
|
12
12
|
sell_columns = "{:<15} {:<15} {:<15}"
|
examples/candles.py
CHANGED
@@ -3,7 +3,7 @@ import asyncio
|
|
3
3
|
from architect_py import AsyncClient, CandleWidth, TradableProduct
|
4
4
|
from architect_py.graphql_client.exceptions import GraphQLClientHttpError
|
5
5
|
|
6
|
-
from .
|
6
|
+
from .config import connect_async_client
|
7
7
|
|
8
8
|
|
9
9
|
async def main():
|
examples/{common.py → config.py}
RENAMED
@@ -16,15 +16,17 @@ class Config:
|
|
16
16
|
|
17
17
|
def load_config() -> Config:
|
18
18
|
loaded = load_dotenv()
|
19
|
+
|
19
20
|
if not loaded:
|
20
21
|
raise ValueError(
|
21
|
-
"⚠️ .env file not found or had no new variables\n"
|
22
|
-
"Please create a .env file with the following variables:\n"
|
22
|
+
"⚠️ .env file not found or had no new variables\n\n"
|
23
|
+
"Please create a .env file with the following variables:\n\n"
|
23
24
|
"ARCHITECT_ENDPOINT=your_endpoint (e.g. app.architect.co)\n"
|
24
25
|
"ARCHITECT_API_KEY=your_api_key (get from https://app.architect.co/user/account)\n"
|
25
26
|
"ARCHITECT_API_SECRET=your_api_secret\n"
|
26
27
|
"ARCHITECT_PAPER_TRADING=true/false\n"
|
27
28
|
)
|
29
|
+
|
28
30
|
endpoint = os.environ["ARCHITECT_ENDPOINT"]
|
29
31
|
api_key = os.getenv("ARCHITECT_API_KEY")
|
30
32
|
api_secret = os.getenv("ARCHITECT_API_SECRET")
|
@@ -49,7 +51,6 @@ def load_config() -> Config:
|
|
49
51
|
|
50
52
|
def connect_client():
|
51
53
|
config = load_config()
|
52
|
-
|
53
54
|
c = Client(
|
54
55
|
endpoint=config.endpoint,
|
55
56
|
api_key=config.api_key,
|
@@ -68,48 +69,3 @@ async def connect_async_client():
|
|
68
69
|
paper_trading=config.paper_trading,
|
69
70
|
)
|
70
71
|
return c
|
71
|
-
|
72
|
-
|
73
|
-
buy_columns = "{:>15} {:>15} {:>15}"
|
74
|
-
sell_columns = "{:<15} {:<15} {:<15}"
|
75
|
-
green = "\033[32m"
|
76
|
-
red = "\033[31m"
|
77
|
-
normal = "\033[0m"
|
78
|
-
|
79
|
-
|
80
|
-
def print_book(book):
|
81
|
-
print(
|
82
|
-
(buy_columns + " " + sell_columns).format(
|
83
|
-
"Total", "Size", "Bid", "Ask", "Size", "Total"
|
84
|
-
)
|
85
|
-
)
|
86
|
-
for i in range(min(20, len(book.bids), len(book.asks))):
|
87
|
-
b = book.bids[i]
|
88
|
-
s = book.asks[i]
|
89
|
-
print(
|
90
|
-
(green + buy_columns).format(b.total, b.amount, b.price),
|
91
|
-
(red + sell_columns).format(s.price, s.amount, s.total),
|
92
|
-
)
|
93
|
-
print(normal)
|
94
|
-
|
95
|
-
|
96
|
-
def print_open_orders(orders):
|
97
|
-
if len(orders) == 0:
|
98
|
-
print("No open orders")
|
99
|
-
else:
|
100
|
-
for o in orders:
|
101
|
-
print(
|
102
|
-
f" • {o.order.market.name} {o.order.dir} {o.order.quantity} {o.order.order_type.limit_price}"
|
103
|
-
)
|
104
|
-
|
105
|
-
|
106
|
-
def confirm(prompt: str):
|
107
|
-
"""
|
108
|
-
Ask user to enter Y or N (case-insensitive).
|
109
|
-
:return: True if the answer is Y.
|
110
|
-
:rtype: bool
|
111
|
-
"""
|
112
|
-
answer = ""
|
113
|
-
while answer not in ["y", "n"]:
|
114
|
-
answer = input(f"{prompt} [Y/N]? ").lower()
|
115
|
-
return answer == "y"
|
examples/order_sending.py
CHANGED
@@ -4,7 +4,7 @@ from datetime import datetime, timedelta, timezone
|
|
4
4
|
from decimal import Decimal
|
5
5
|
|
6
6
|
from architect_py import AsyncClient, OrderDir, OrderType, TimeInForce, TradableProduct
|
7
|
-
from examples.
|
7
|
+
from examples.config import connect_async_client
|
8
8
|
|
9
9
|
LOGGER = logging.getLogger(__name__)
|
10
10
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# """
|
2
|
+
# Example of using a bidirectional orderflow channel with the Architect OEMS.
|
3
|
+
|
4
|
+
# This connection style is ~equivalent to having a websocket.
|
5
|
+
|
6
|
+
# This code example sends a series of orders to Architect while concurrently
|
7
|
+
# listening to orderflow events. Compare to `examples/orderflow_streaming.py`,
|
8
|
+
# which accomplishes the same thing but using a separate asyncio task.
|
9
|
+
# """
|
10
|
+
|
11
|
+
# import asyncio
|
12
|
+
# from decimal import Decimal
|
13
|
+
|
14
|
+
# from architect_py import AsyncClient, OrderDir, PlaceOrderRequest
|
15
|
+
# from architect_py.grpc.models.Orderflow.OrderflowRequest import PlaceOrder
|
16
|
+
|
17
|
+
# from .config import connect_async_client
|
18
|
+
|
19
|
+
|
20
|
+
# async def send_orders(client: AsyncClient):
|
21
|
+
# symbol = await client.get_front_future("ES CME Futures")
|
22
|
+
# print(f"symbol={symbol}")
|
23
|
+
|
24
|
+
# while True:
|
25
|
+
# await asyncio.sleep(1)
|
26
|
+
# snap = await client.get_l1_book_snapshot(symbol, "CME")
|
27
|
+
# if snap.best_ask is not None:
|
28
|
+
# limit_price = snap.best_ask[0]
|
29
|
+
# print(f"\nPlacing buy order at {limit_price}\n")
|
30
|
+
# try:
|
31
|
+
# req = PlaceOrderRequest.new(
|
32
|
+
# symbol=symbol,
|
33
|
+
# execution_venue="CME",
|
34
|
+
# dir=OrderDir.BUY,
|
35
|
+
# quantity=Decimal(1),
|
36
|
+
# limit_price=limit_price,
|
37
|
+
# post_only=True,
|
38
|
+
# time_in_force="DAY",
|
39
|
+
# order_type="LIMIT",
|
40
|
+
# )
|
41
|
+
# print(f"req={req}")
|
42
|
+
# yield PlaceOrder(req)
|
43
|
+
# except Exception as e:
|
44
|
+
# print(f"Error placing order: {e}")
|
45
|
+
# else:
|
46
|
+
# print("\nNo ask price from snapshot, doing nothing\n")
|
47
|
+
|
48
|
+
|
49
|
+
# async def main():
|
50
|
+
# client = await connect_async_client()
|
51
|
+
|
52
|
+
# async for event in client.orderflow(send_orders(client)):
|
53
|
+
# print(f" --> {event}")
|
54
|
+
|
55
|
+
|
56
|
+
# asyncio.run(main())
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"""
|
2
|
+
Example of streaming orderflow events from the Architect OEMS.
|
3
|
+
|
4
|
+
This code example sends a series of orders to Architect in one asyncio
|
5
|
+
task, while concurrently listening to orderflow events in another.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import asyncio
|
9
|
+
from decimal import Decimal
|
10
|
+
|
11
|
+
from architect_py import AsyncClient, OrderDir
|
12
|
+
|
13
|
+
from .config import connect_async_client
|
14
|
+
|
15
|
+
|
16
|
+
async def send_orders(client: AsyncClient):
|
17
|
+
symbol = await client.get_front_future("ES CME Futures")
|
18
|
+
print(f"symbol={symbol}")
|
19
|
+
|
20
|
+
while True:
|
21
|
+
await asyncio.sleep(1)
|
22
|
+
snap = await client.get_l1_book_snapshot(symbol, "CME")
|
23
|
+
if snap.best_ask is not None:
|
24
|
+
limit_price = snap.best_ask[0]
|
25
|
+
print(f"\nPlacing buy order at {limit_price}\n")
|
26
|
+
await client.place_limit_order(
|
27
|
+
symbol=symbol,
|
28
|
+
execution_venue="CME",
|
29
|
+
dir=OrderDir.BUY,
|
30
|
+
quantity=Decimal(1),
|
31
|
+
limit_price=limit_price,
|
32
|
+
post_only=True,
|
33
|
+
)
|
34
|
+
else:
|
35
|
+
print("\nNo ask price from snapshot, doing nothing\n")
|
36
|
+
|
37
|
+
|
38
|
+
async def main():
|
39
|
+
client = await connect_async_client()
|
40
|
+
|
41
|
+
asyncio.create_task(send_orders(client))
|
42
|
+
|
43
|
+
async for event in client.stream_orderflow():
|
44
|
+
print(f" --> {event}")
|
45
|
+
|
46
|
+
|
47
|
+
asyncio.run(main())
|
examples/stream_l1_marketdata.py
CHANGED
examples/stream_l2_marketdata.py
CHANGED
examples/termutils.py
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
buy_columns = "{:>15} {:>15} {:>15}"
|
2
|
+
sell_columns = "{:<15} {:<15} {:<15}"
|
3
|
+
green = "\033[32m"
|
4
|
+
red = "\033[31m"
|
5
|
+
normal = "\033[0m"
|
6
|
+
|
7
|
+
|
8
|
+
def print_book(book):
|
9
|
+
print(
|
10
|
+
(buy_columns + " " + sell_columns).format(
|
11
|
+
"Total", "Size", "Bid", "Ask", "Size", "Total"
|
12
|
+
)
|
13
|
+
)
|
14
|
+
for i in range(min(20, len(book.bids), len(book.asks))):
|
15
|
+
b = book.bids[i]
|
16
|
+
s = book.asks[i]
|
17
|
+
print(
|
18
|
+
(green + buy_columns).format(b.total, b.amount, b.price),
|
19
|
+
(red + sell_columns).format(s.price, s.amount, s.total),
|
20
|
+
)
|
21
|
+
print(normal)
|
22
|
+
|
23
|
+
|
24
|
+
def print_open_orders(orders):
|
25
|
+
if len(orders) == 0:
|
26
|
+
print("No open orders")
|
27
|
+
else:
|
28
|
+
for o in orders:
|
29
|
+
print(
|
30
|
+
f" • {o.order.market.name} {o.order.dir} {o.order.quantity} {o.order.order_type.limit_price}"
|
31
|
+
)
|
32
|
+
|
33
|
+
|
34
|
+
def confirm(prompt: str):
|
35
|
+
"""
|
36
|
+
Ask user to enter Y or N (case-insensitive).
|
37
|
+
|
38
|
+
:return: True if the answer is Y.
|
39
|
+
:rtype: bool
|
40
|
+
"""
|
41
|
+
answer = ""
|
42
|
+
while answer not in ["y", "n"]:
|
43
|
+
answer = input(f"{prompt} [Y/N]? ").lower()
|
44
|
+
return answer == "y"
|
examples/trades.py
CHANGED
examples/tutorial_async.py
CHANGED
examples/tutorial_sync.py
CHANGED
@@ -5,7 +5,8 @@ from decimal import Decimal
|
|
5
5
|
from architect_py import OrderDir, OrderStatus
|
6
6
|
from architect_py.utils.nearest_tick import TickRoundMethod
|
7
7
|
|
8
|
-
from .
|
8
|
+
from .config import connect_client
|
9
|
+
from .termutils import confirm, print_book, print_open_orders
|
9
10
|
|
10
11
|
c = connect_client()
|
11
12
|
|
File without changes
|
File without changes
|
File without changes
|