afp-sdk 0.5.2__py3-none-any.whl → 0.5.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.
- afp/api/trading.py +91 -4
- afp/enums.py +1 -0
- afp/exchange.py +25 -0
- afp/schemas.py +9 -0
- {afp_sdk-0.5.2.dist-info → afp_sdk-0.5.3.dist-info}/METADATA +1 -1
- {afp_sdk-0.5.2.dist-info → afp_sdk-0.5.3.dist-info}/RECORD +8 -8
- {afp_sdk-0.5.2.dist-info → afp_sdk-0.5.3.dist-info}/WHEEL +1 -1
- {afp_sdk-0.5.2.dist-info → afp_sdk-0.5.3.dist-info}/licenses/LICENSE +0 -0
afp/api/trading.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import secrets
|
|
2
2
|
import warnings
|
|
3
|
-
from datetime import datetime
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
4
|
from decimal import Decimal
|
|
5
5
|
from typing import Generator, Iterable
|
|
6
6
|
|
|
@@ -16,6 +16,7 @@ from ..schemas import (
|
|
|
16
16
|
Intent,
|
|
17
17
|
IntentData,
|
|
18
18
|
MarketDepthData,
|
|
19
|
+
OHLCVItem,
|
|
19
20
|
Order,
|
|
20
21
|
OrderFilter,
|
|
21
22
|
OrderCancellationData,
|
|
@@ -238,6 +239,7 @@ class Trading(ExchangeAPI):
|
|
|
238
239
|
self,
|
|
239
240
|
*,
|
|
240
241
|
product_id: str | None = None,
|
|
242
|
+
intent_account_id: str | None = None,
|
|
241
243
|
type_: str | None = None,
|
|
242
244
|
states: Iterable[str] = (),
|
|
243
245
|
side: str | None = None,
|
|
@@ -255,6 +257,8 @@ class Trading(ExchangeAPI):
|
|
|
255
257
|
Parameters
|
|
256
258
|
----------
|
|
257
259
|
product_id : str, optional
|
|
260
|
+
intent_account_id : str, optional
|
|
261
|
+
Defaults to the address of the authenticated account.
|
|
258
262
|
type_ : str, optional
|
|
259
263
|
One of `LIMIT_ORDER` and `CANCEL_ORDER`.
|
|
260
264
|
states : iterable of str
|
|
@@ -274,8 +278,11 @@ class Trading(ExchangeAPI):
|
|
|
274
278
|
-------
|
|
275
279
|
list of afp.schemas.OrderFill
|
|
276
280
|
"""
|
|
281
|
+
if intent_account_id is None:
|
|
282
|
+
intent_account_id = self._authenticator.address
|
|
283
|
+
|
|
277
284
|
filter = OrderFilter(
|
|
278
|
-
intent_account_id=
|
|
285
|
+
intent_account_id=intent_account_id,
|
|
279
286
|
product_id=product_id,
|
|
280
287
|
type=None if type_ is None else OrderType(type_.upper()),
|
|
281
288
|
states=[OrderState(state.upper()) for state in states],
|
|
@@ -306,6 +313,7 @@ class Trading(ExchangeAPI):
|
|
|
306
313
|
self,
|
|
307
314
|
*,
|
|
308
315
|
product_id: str | None = None,
|
|
316
|
+
intent_account_id: str | None = None,
|
|
309
317
|
intent_hash: str | None = None,
|
|
310
318
|
start: datetime | None = None,
|
|
311
319
|
end: datetime | None = None,
|
|
@@ -323,6 +331,8 @@ class Trading(ExchangeAPI):
|
|
|
323
331
|
Parameters
|
|
324
332
|
----------
|
|
325
333
|
product_id : str, optional
|
|
334
|
+
intent_account_id : str, optional
|
|
335
|
+
Defaults to the address of the authenticated account.
|
|
326
336
|
intent_hash : str, optional
|
|
327
337
|
start : datetime.datetime, optional
|
|
328
338
|
end : datetime.datetime, optional
|
|
@@ -339,8 +349,11 @@ class Trading(ExchangeAPI):
|
|
|
339
349
|
-------
|
|
340
350
|
list of afp.schemas.OrderFill
|
|
341
351
|
"""
|
|
352
|
+
if intent_account_id is None:
|
|
353
|
+
intent_account_id = self._authenticator.address
|
|
354
|
+
|
|
342
355
|
filter = OrderFillFilter(
|
|
343
|
-
intent_account_id=
|
|
356
|
+
intent_account_id=intent_account_id,
|
|
344
357
|
product_id=product_id,
|
|
345
358
|
intent_hash=intent_hash,
|
|
346
359
|
start=start,
|
|
@@ -357,6 +370,7 @@ class Trading(ExchangeAPI):
|
|
|
357
370
|
self,
|
|
358
371
|
*,
|
|
359
372
|
product_id: str | None = None,
|
|
373
|
+
intent_account_id: str | None = None,
|
|
360
374
|
intent_hash: str | None = None,
|
|
361
375
|
trade_states: Iterable[str] = ("PENDING",),
|
|
362
376
|
) -> Generator[OrderFill, None, None]:
|
|
@@ -376,6 +390,8 @@ class Trading(ExchangeAPI):
|
|
|
376
390
|
Parameters
|
|
377
391
|
----------
|
|
378
392
|
product_id : str, optional
|
|
393
|
+
intent_account_id : str, optional
|
|
394
|
+
Defaults to the address of the authenticated account.
|
|
379
395
|
intent_hash : str, optional
|
|
380
396
|
trade_states: iterable of str
|
|
381
397
|
Any of `PENDING`, `CLEARED` and `REJECTED`.
|
|
@@ -384,8 +400,11 @@ class Trading(ExchangeAPI):
|
|
|
384
400
|
-------
|
|
385
401
|
afp.schemas.OrderFill
|
|
386
402
|
"""
|
|
403
|
+
if intent_account_id is None:
|
|
404
|
+
intent_account_id = self._authenticator.address
|
|
405
|
+
|
|
387
406
|
filter = OrderFillFilter(
|
|
388
|
-
intent_account_id=
|
|
407
|
+
intent_account_id=intent_account_id,
|
|
389
408
|
product_id=product_id,
|
|
390
409
|
intent_hash=intent_hash,
|
|
391
410
|
start=None,
|
|
@@ -439,3 +458,71 @@ class Trading(ExchangeAPI):
|
|
|
439
458
|
"""
|
|
440
459
|
value = validators.validate_hexstr32(product_id)
|
|
441
460
|
yield from self._exchange.iter_market_depth_data(value)
|
|
461
|
+
|
|
462
|
+
def ohlcv(
|
|
463
|
+
self,
|
|
464
|
+
product_id: str,
|
|
465
|
+
start: datetime | None = None,
|
|
466
|
+
interval: timedelta = timedelta(minutes=5),
|
|
467
|
+
) -> list[OHLCVItem]:
|
|
468
|
+
"""Retrieves Open-High-Low-Close-Volume time series data for the given product.
|
|
469
|
+
|
|
470
|
+
Parameters
|
|
471
|
+
----------
|
|
472
|
+
product_id : str
|
|
473
|
+
start : datetime
|
|
474
|
+
Defaults to 1 day ago.
|
|
475
|
+
interval : timedelta
|
|
476
|
+
The distance between 2 data points. Gets rounded to a multiple of 5 seconds.
|
|
477
|
+
Defaults to 5 minutes.
|
|
478
|
+
|
|
479
|
+
Returns
|
|
480
|
+
-------
|
|
481
|
+
list of afp.schemas.OHLCVItem
|
|
482
|
+
|
|
483
|
+
Raises
|
|
484
|
+
------
|
|
485
|
+
afp.exceptions.NotFoundError
|
|
486
|
+
If no such product exists.
|
|
487
|
+
"""
|
|
488
|
+
if start is None:
|
|
489
|
+
start = datetime.now() - timedelta(days=1)
|
|
490
|
+
|
|
491
|
+
product_id = validators.validate_hexstr32(product_id)
|
|
492
|
+
start_timestamp = int(start.timestamp())
|
|
493
|
+
interval_secs = int(validators.validate_timedelta(interval).total_seconds())
|
|
494
|
+
return self._exchange.get_time_series_data(
|
|
495
|
+
product_id, start_timestamp, interval_secs
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
def iter_ohlcv(
|
|
499
|
+
self, product_id: str, interval: timedelta = timedelta(seconds=5)
|
|
500
|
+
) -> Generator[OHLCVItem, None, None]:
|
|
501
|
+
"""Subscribes to Open-High-Low-Close-Volume time series data updates for the
|
|
502
|
+
given product.
|
|
503
|
+
|
|
504
|
+
Returns a generator that yields OHLCV data points as they are published
|
|
505
|
+
by the exhange.
|
|
506
|
+
|
|
507
|
+
Parameters
|
|
508
|
+
----------
|
|
509
|
+
product_id : str
|
|
510
|
+
interval : timedelta
|
|
511
|
+
The distance between 2 data points. Gets rounded to a multiple of 5 seconds.
|
|
512
|
+
Defaults to 5 seconds.
|
|
513
|
+
|
|
514
|
+
Yields
|
|
515
|
+
-------
|
|
516
|
+
afp.schemas.OHLCVItem
|
|
517
|
+
|
|
518
|
+
Raises
|
|
519
|
+
------
|
|
520
|
+
afp.exceptions.NotFoundError
|
|
521
|
+
If no such product exists.
|
|
522
|
+
"""
|
|
523
|
+
product_id = validators.validate_hexstr32(product_id)
|
|
524
|
+
start_timestamp = int(datetime.now().timestamp())
|
|
525
|
+
interval_secs = int(validators.validate_timedelta(interval).total_seconds())
|
|
526
|
+
yield from self._exchange.iter_time_series_data(
|
|
527
|
+
product_id, start_timestamp, interval_secs
|
|
528
|
+
)
|
afp/enums.py
CHANGED
afp/exchange.py
CHANGED
|
@@ -21,6 +21,7 @@ from .schemas import (
|
|
|
21
21
|
ExchangeProductUpdateSubmission,
|
|
22
22
|
LoginSubmission,
|
|
23
23
|
MarketDepthData,
|
|
24
|
+
OHLCVItem,
|
|
24
25
|
Order,
|
|
25
26
|
OrderFilter,
|
|
26
27
|
OrderFill,
|
|
@@ -138,6 +139,30 @@ class ExchangeClient:
|
|
|
138
139
|
for line in response.iter_lines():
|
|
139
140
|
yield MarketDepthData.model_validate_json(line)
|
|
140
141
|
|
|
142
|
+
# GET /time-series/{product_id}
|
|
143
|
+
def get_time_series_data(
|
|
144
|
+
self, product_id: str, start: int, interval: int
|
|
145
|
+
) -> list[OHLCVItem]:
|
|
146
|
+
response = self._send_request(
|
|
147
|
+
"GET",
|
|
148
|
+
f"/time-series/{product_id}",
|
|
149
|
+
params=dict(start=start, interval=interval),
|
|
150
|
+
)
|
|
151
|
+
return [OHLCVItem(**item) for item in response.json()["data"]]
|
|
152
|
+
|
|
153
|
+
# GET /stream/time-series/{product_id}
|
|
154
|
+
def iter_time_series_data(
|
|
155
|
+
self, product_id: str, start: int, interval: int
|
|
156
|
+
) -> Generator[OHLCVItem, None, None]:
|
|
157
|
+
response = self._send_request(
|
|
158
|
+
"GET",
|
|
159
|
+
f"/stream/time-series/{product_id}",
|
|
160
|
+
params=dict(start=start, interval=interval),
|
|
161
|
+
stream=True,
|
|
162
|
+
)
|
|
163
|
+
for line in response.iter_lines():
|
|
164
|
+
yield OHLCVItem.model_validate_json(line)
|
|
165
|
+
|
|
141
166
|
def _send_request(
|
|
142
167
|
self,
|
|
143
168
|
method: str,
|
afp/schemas.py
CHANGED
|
@@ -209,6 +209,15 @@ class MarketDepthData(Model):
|
|
|
209
209
|
asks: list[MarketDepthItem]
|
|
210
210
|
|
|
211
211
|
|
|
212
|
+
class OHLCVItem(Model):
|
|
213
|
+
timestamp: Timestamp
|
|
214
|
+
open: Decimal
|
|
215
|
+
high: Decimal
|
|
216
|
+
low: Decimal
|
|
217
|
+
close: Decimal
|
|
218
|
+
volume: int
|
|
219
|
+
|
|
220
|
+
|
|
212
221
|
# Clearing API
|
|
213
222
|
|
|
214
223
|
|
|
@@ -5,7 +5,7 @@ afp/api/admin.py,sha256=6TiWCo0SB41CtXYTkTYYGQY7MrdB6OMTyU3-0J0V_7o,2170
|
|
|
5
5
|
afp/api/base.py,sha256=5X1joEwFX4gxYUDCSTvp_hSFCfLZCktnW-UtZFxDquk,4471
|
|
6
6
|
afp/api/margin_account.py,sha256=sC1DF7J3QTHR7cXcRjTG33oZswVy6qr9xnevQbrQ-ew,15256
|
|
7
7
|
afp/api/product.py,sha256=2N4bPBahuw19GcBbBL20oQ5RFRuUxa5LOZzmN7hs39U,10156
|
|
8
|
-
afp/api/trading.py,sha256=
|
|
8
|
+
afp/api/trading.py,sha256=y5Q2KApEpUau9R8G9KUqOdm4ymhw9Hbu9d2dkG80AsQ,17262
|
|
9
9
|
afp/auth.py,sha256=sV_9E6CgRWV1xYoppc4IdrnqNo5ZNDBIp6QF3fQbMWE,2055
|
|
10
10
|
afp/bindings/__init__.py,sha256=_n9xoogYi8AAlSx_PE-wjnwP1ujVyDUwoRM0BSm243U,1271
|
|
11
11
|
afp/bindings/auctioneer_facet.py,sha256=4p906zdU2lUsqpWlsiLE3dlxTPrlNpqk8DtjiQUWJ8M,23919
|
|
@@ -24,14 +24,14 @@ afp/bindings/trading_protocol.py,sha256=ZloF3REbjFq9v0UGVsM0_Lk0EhfWJKdeJ0PzVEny
|
|
|
24
24
|
afp/config.py,sha256=_WKywiuty8poE1A0v46uBe1JGpfCzRlxCPamKennfpE,699
|
|
25
25
|
afp/constants.py,sha256=EvDhLpKBOsc8OHGm1paiUAdAetPGD4nyi13coB8rd14,1930
|
|
26
26
|
afp/decorators.py,sha256=SEUQtbgPGc4iVPtBQV2eiCejcDAVImmXcI0uPXFhtJA,2774
|
|
27
|
-
afp/enums.py,sha256=
|
|
27
|
+
afp/enums.py,sha256=9JhwdLcTNhyKabKdrALAlCeL3C5XfeXYSSSXSCsuTzE,688
|
|
28
28
|
afp/exceptions.py,sha256=frdS-EH84K0fOf92RgRgNkTe3VII2m36XNCS8eyXLLM,390
|
|
29
|
-
afp/exchange.py,sha256
|
|
29
|
+
afp/exchange.py,sha256=QQAfglOzsxo_T0BUOFAkxI2wUbda1sKStMXUO9IcDbw,7498
|
|
30
30
|
afp/hashing.py,sha256=gBCWN93-ydRPlgnnorSvDQlylcnglrAypRDb-1K-20I,1949
|
|
31
31
|
afp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
-
afp/schemas.py,sha256=
|
|
32
|
+
afp/schemas.py,sha256=zyZOPvAdDnXp60kqYqX-OoWnKvRLPZT7at0A0MHlurc,6746
|
|
33
33
|
afp/validators.py,sha256=zQvPu3HDu6ADnEE72EJlS5hc1-xfru78Mzd74s1u_EM,1841
|
|
34
|
-
afp_sdk-0.5.
|
|
35
|
-
afp_sdk-0.5.
|
|
36
|
-
afp_sdk-0.5.
|
|
37
|
-
afp_sdk-0.5.
|
|
34
|
+
afp_sdk-0.5.3.dist-info/licenses/LICENSE,sha256=ZdaKItgc2ppfqta2OJV0oHpSJiK87PUxmUkUo-_0SB8,1065
|
|
35
|
+
afp_sdk-0.5.3.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
36
|
+
afp_sdk-0.5.3.dist-info/METADATA,sha256=__Jo9oroNSkI1O9-vAOSA2HrSEONWX95AB4nLKkrjg0,6354
|
|
37
|
+
afp_sdk-0.5.3.dist-info/RECORD,,
|
|
File without changes
|