crypticorn 2.6.0__py3-none-any.whl → 2.7.0__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.
- crypticorn/common/errors.py +10 -0
- crypticorn/hive/client/api/data_api.py +15 -12
- crypticorn/hive/main.py +43 -2
- crypticorn/hive/utils.py +65 -0
- {crypticorn-2.6.0.dist-info → crypticorn-2.7.0.dist-info}/METADATA +2 -2
- {crypticorn-2.6.0.dist-info → crypticorn-2.7.0.dist-info}/RECORD +9 -8
- {crypticorn-2.6.0.dist-info → crypticorn-2.7.0.dist-info}/WHEEL +0 -0
- {crypticorn-2.6.0.dist-info → crypticorn-2.7.0.dist-info}/entry_points.txt +0 -0
- {crypticorn-2.6.0.dist-info → crypticorn-2.7.0.dist-info}/top_level.txt +0 -0
crypticorn/common/errors.py
CHANGED
@@ -60,6 +60,7 @@ class ApiErrorIdentifier(ExcludeEnumMixin, StrEnum):
|
|
60
60
|
INVALID_PARAMETER = "invalid_parameter_provided"
|
61
61
|
LEVERAGE_EXCEEDED = "leverage_limit_exceeded"
|
62
62
|
LIQUIDATION_PRICE_VIOLATION = "order_violates_liquidation_price_constraints"
|
63
|
+
MODEL_NAME_NOT_UNIQUE = "model_name_not_unique"
|
63
64
|
NO_CREDENTIALS = "no_credentials"
|
64
65
|
NOW_API_DOWN = "now_api_down"
|
65
66
|
OBJECT_ALREADY_EXISTS = "object_already_exists"
|
@@ -318,6 +319,11 @@ class ApiError(ExcludeEnumMixin, Enum, metaclass=ApiErrorFallback):
|
|
318
319
|
ApiErrorType.SERVER_ERROR,
|
319
320
|
ApiErrorLevel.ERROR,
|
320
321
|
)
|
322
|
+
MODEL_NAME_NOT_UNIQUE = (
|
323
|
+
ApiErrorIdentifier.MODEL_NAME_NOT_UNIQUE,
|
324
|
+
ApiErrorType.USER_ERROR,
|
325
|
+
ApiErrorLevel.ERROR,
|
326
|
+
)
|
321
327
|
NO_CREDENTIALS = (
|
322
328
|
ApiErrorIdentifier.NO_CREDENTIALS,
|
323
329
|
ApiErrorType.USER_ERROR,
|
@@ -598,6 +604,10 @@ class StatusCodeMapper:
|
|
598
604
|
status.HTTP_409_CONFLICT,
|
599
605
|
status.WS_1008_POLICY_VIOLATION,
|
600
606
|
),
|
607
|
+
ApiError.MODEL_NAME_NOT_UNIQUE: (
|
608
|
+
status.HTTP_409_CONFLICT,
|
609
|
+
status.WS_1008_POLICY_VIOLATION,
|
610
|
+
),
|
601
611
|
# Invalid Content
|
602
612
|
ApiError.CONTENT_TYPE_ERROR: (
|
603
613
|
status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
|
@@ -48,9 +48,10 @@ class DataApi:
|
|
48
48
|
version: Annotated[
|
49
49
|
Optional[DataVersion],
|
50
50
|
Field(description="Data version. Default is the latest public version."),
|
51
|
-
],
|
51
|
+
] = None,
|
52
52
|
feature_size: Annotated[
|
53
|
-
Optional[FeatureSize],
|
53
|
+
Optional[FeatureSize],
|
54
|
+
Field(description="The number of features in the data. Default is LARGE."),
|
54
55
|
] = None,
|
55
56
|
_request_timeout: Union[
|
56
57
|
None,
|
@@ -70,9 +71,9 @@ class DataApi:
|
|
70
71
|
|
71
72
|
:param model_id: Model ID (required)
|
72
73
|
:type model_id: int
|
73
|
-
:param version: Data version. Default is the latest public version.
|
74
|
+
:param version: Data version. Default is the latest public version.
|
74
75
|
:type version: DataVersion
|
75
|
-
:param feature_size:
|
76
|
+
:param feature_size: The number of features in the data. Default is LARGE.
|
76
77
|
:type feature_size: FeatureSize
|
77
78
|
:param _request_timeout: timeout setting for this request. If one
|
78
79
|
number provided, it will be total request
|
@@ -125,9 +126,10 @@ class DataApi:
|
|
125
126
|
version: Annotated[
|
126
127
|
Optional[DataVersion],
|
127
128
|
Field(description="Data version. Default is the latest public version."),
|
128
|
-
],
|
129
|
+
] = None,
|
129
130
|
feature_size: Annotated[
|
130
|
-
Optional[FeatureSize],
|
131
|
+
Optional[FeatureSize],
|
132
|
+
Field(description="The number of features in the data. Default is LARGE."),
|
131
133
|
] = None,
|
132
134
|
_request_timeout: Union[
|
133
135
|
None,
|
@@ -147,9 +149,9 @@ class DataApi:
|
|
147
149
|
|
148
150
|
:param model_id: Model ID (required)
|
149
151
|
:type model_id: int
|
150
|
-
:param version: Data version. Default is the latest public version.
|
152
|
+
:param version: Data version. Default is the latest public version.
|
151
153
|
:type version: DataVersion
|
152
|
-
:param feature_size:
|
154
|
+
:param feature_size: The number of features in the data. Default is LARGE.
|
153
155
|
:type feature_size: FeatureSize
|
154
156
|
:param _request_timeout: timeout setting for this request. If one
|
155
157
|
number provided, it will be total request
|
@@ -202,9 +204,10 @@ class DataApi:
|
|
202
204
|
version: Annotated[
|
203
205
|
Optional[DataVersion],
|
204
206
|
Field(description="Data version. Default is the latest public version."),
|
205
|
-
],
|
207
|
+
] = None,
|
206
208
|
feature_size: Annotated[
|
207
|
-
Optional[FeatureSize],
|
209
|
+
Optional[FeatureSize],
|
210
|
+
Field(description="The number of features in the data. Default is LARGE."),
|
208
211
|
] = None,
|
209
212
|
_request_timeout: Union[
|
210
213
|
None,
|
@@ -224,9 +227,9 @@ class DataApi:
|
|
224
227
|
|
225
228
|
:param model_id: Model ID (required)
|
226
229
|
:type model_id: int
|
227
|
-
:param version: Data version. Default is the latest public version.
|
230
|
+
:param version: Data version. Default is the latest public version.
|
228
231
|
:type version: DataVersion
|
229
|
-
:param feature_size:
|
232
|
+
:param feature_size: The number of features in the data. Default is LARGE.
|
230
233
|
:type feature_size: FeatureSize
|
231
234
|
:param _request_timeout: timeout setting for this request. If one
|
232
235
|
number provided, it will be total request
|
crypticorn/hive/main.py
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
import asyncio
|
2
|
+
from pathlib import Path
|
3
|
+
import os
|
1
4
|
from crypticorn.hive import (
|
2
5
|
ApiClient,
|
3
6
|
Configuration,
|
@@ -6,7 +9,45 @@ from crypticorn.hive import (
|
|
6
9
|
StatusApi,
|
7
10
|
Configuration,
|
8
11
|
)
|
9
|
-
from crypticorn.
|
12
|
+
from crypticorn.hive.utils import download_file
|
13
|
+
import logging
|
14
|
+
|
15
|
+
|
16
|
+
class DataApiWrapper(DataApi):
|
17
|
+
"""
|
18
|
+
A wrapper for the DataApi class.
|
19
|
+
"""
|
20
|
+
|
21
|
+
async def download_data(self, folder: Path = "data", *args, **kwargs) -> list[Path]:
|
22
|
+
"""
|
23
|
+
Download data for model training. All three files (y_train, x_test, x_train) are downloaded and saved under e.g. FOLDER/v1/coin_1/*.feather.
|
24
|
+
The folder will be created if it doesn't exist.
|
25
|
+
|
26
|
+
:param model_id: Model ID (required) (type: int)
|
27
|
+
:param version: Data version. Default is the latest public version. (optional) (type: DataVersion)
|
28
|
+
:param feature_size: The number of features in the data. Default is LARGE. (optional) (type: FeatureSize)
|
29
|
+
:return: A list of paths to the downloaded files.
|
30
|
+
"""
|
31
|
+
response = await super().download_data(*args, **kwargs)
|
32
|
+
base_path = f"{folder}/v{response.version.value}/coin_{response.coin.value}/"
|
33
|
+
os.makedirs(base_path, exist_ok=True)
|
34
|
+
|
35
|
+
return await asyncio.gather(
|
36
|
+
*[
|
37
|
+
download_file(
|
38
|
+
url=response.links.y_train,
|
39
|
+
dest_path=base_path + "y_train_" + response.target + ".feather",
|
40
|
+
),
|
41
|
+
download_file(
|
42
|
+
url=response.links.x_test,
|
43
|
+
dest_path=base_path + "x_test_" + response.feature_size + ".feather",
|
44
|
+
),
|
45
|
+
download_file(
|
46
|
+
url=response.links.x_train,
|
47
|
+
dest_path=base_path + "x_train_" + response.feature_size + ".feather",
|
48
|
+
),
|
49
|
+
]
|
50
|
+
)
|
10
51
|
|
11
52
|
|
12
53
|
class HiveClient:
|
@@ -24,5 +65,5 @@ class HiveClient:
|
|
24
65
|
self.base_client = ApiClient(configuration=self.config)
|
25
66
|
# Instantiate all the endpoint clients
|
26
67
|
self.models = ModelsApi(self.base_client)
|
27
|
-
self.data =
|
68
|
+
self.data = DataApiWrapper(self.base_client)
|
28
69
|
self.status = StatusApi(self.base_client)
|
crypticorn/hive/utils.py
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
import requests
|
2
|
+
import os
|
3
|
+
import tqdm
|
4
|
+
import logging
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
logger.setLevel(logging.INFO)
|
8
|
+
|
9
|
+
|
10
|
+
async def download_file(url: str, dest_path: str, show_progress_bars: bool = True) -> str:
|
11
|
+
"""downloads a file and shows a progress bar. allow resuming a download"""
|
12
|
+
file_size = 0
|
13
|
+
req = requests.get(url, stream=True, timeout=600)
|
14
|
+
req.raise_for_status()
|
15
|
+
|
16
|
+
total_size = int(req.headers.get("content-length", 0))
|
17
|
+
temp_path = dest_path + ".temp"
|
18
|
+
|
19
|
+
if os.path.exists(dest_path):
|
20
|
+
logger.info(f" file already exists: {dest_path}")
|
21
|
+
file_size = os.stat(dest_path).st_size
|
22
|
+
if file_size == total_size:
|
23
|
+
return dest_path
|
24
|
+
|
25
|
+
if os.path.exists(temp_path):
|
26
|
+
file_size = os.stat(temp_path).st_size
|
27
|
+
|
28
|
+
if file_size < total_size:
|
29
|
+
# Download incomplete
|
30
|
+
logger.info(f" resuming download")
|
31
|
+
resume_header = {"Range": f"bytes={file_size}-"}
|
32
|
+
req = requests.get(
|
33
|
+
url,
|
34
|
+
headers=resume_header,
|
35
|
+
stream=True,
|
36
|
+
verify=False,
|
37
|
+
allow_redirects=True,
|
38
|
+
timeout=600,
|
39
|
+
)
|
40
|
+
else:
|
41
|
+
# Error, delete file and restart download
|
42
|
+
logger.error(f" deleting file {dest_path} and restarting")
|
43
|
+
os.remove(temp_path)
|
44
|
+
file_size = 0
|
45
|
+
else:
|
46
|
+
# File does not exist, starting download
|
47
|
+
logger.info(f" starting download")
|
48
|
+
|
49
|
+
# write dataset to file and show progress bar
|
50
|
+
pbar = tqdm.tqdm(
|
51
|
+
total=total_size,
|
52
|
+
unit="B",
|
53
|
+
unit_scale=True,
|
54
|
+
desc=dest_path,
|
55
|
+
disable=not show_progress_bars,
|
56
|
+
)
|
57
|
+
# Update progress bar to reflect how much of the file is already downloaded
|
58
|
+
pbar.update(file_size)
|
59
|
+
with open(temp_path, "ab") as dest_file:
|
60
|
+
for chunk in req.iter_content(1024):
|
61
|
+
dest_file.write(chunk)
|
62
|
+
pbar.update(1024)
|
63
|
+
# move temp file to target destination
|
64
|
+
os.replace(temp_path, dest_path)
|
65
|
+
return dest_path
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: crypticorn
|
3
|
-
Version: 2.
|
4
|
-
Summary: Maximise Your Crypto Trading Profits with
|
3
|
+
Version: 2.7.0
|
4
|
+
Summary: Maximise Your Crypto Trading Profits with Machine Learning
|
5
5
|
Author-email: Crypticorn <timon@crypticorn.com>
|
6
6
|
Project-URL: Homepage, https://crypticorn.com
|
7
7
|
Keywords: machine learning,data science,crypto,modelling
|
@@ -64,7 +64,7 @@ crypticorn/common/__init__.py,sha256=42ajAXlz0LDBb1AFyX8xvwpp1MB_YrvqutFDkLthUQM
|
|
64
64
|
crypticorn/common/auth.py,sha256=60SRXlW72VJO8rGzCiemWmzGu8tXDqWr0wt9EM6p8aI,8631
|
65
65
|
crypticorn/common/decorators.py,sha256=pmnGYCIrLv59wZkDbvPyK9NJmgPJWW74LXTdIWSjOkY,1063
|
66
66
|
crypticorn/common/enums.py,sha256=RitDVqlG_HTe6tHT6bWusZNFCeYk1eQvJVH-7x3_Zlg,668
|
67
|
-
crypticorn/common/errors.py,sha256=
|
67
|
+
crypticorn/common/errors.py,sha256=K1VSEKZro1I4cmi-sOhx24pTrvhbbD4RBRRqKodWpA8,27851
|
68
68
|
crypticorn/common/exceptions.py,sha256=Rrpk2ORou2F__cNUWmXs6tFZwIFBZppF4YapUSZLfOQ,5662
|
69
69
|
crypticorn/common/mixins.py,sha256=LKPcNTR8uREeDGWTlWozNx7rS1mYdQVx1RllLhxIAsE,1640
|
70
70
|
crypticorn/common/pagination.py,sha256=c07jrMNrBaNTmgx4sppdP7ND4RNT7NBqBXWvofazIlE,2251
|
@@ -73,7 +73,8 @@ crypticorn/common/status_router.py,sha256=s7LY3aNQPhtDUgNWHRszfCQMl0Uh13li_jR8je
|
|
73
73
|
crypticorn/common/urls.py,sha256=3Gf1NU1XQYcOTjcdztG3bDAE98FVbgTK2QXzUe7tFVQ,878
|
74
74
|
crypticorn/common/utils.py,sha256=Kz2-I96MKIGKM18PHQ77VbKHLMGUvZG_jjj7xpQed8k,2138
|
75
75
|
crypticorn/hive/__init__.py,sha256=hRfTlEzEql4msytdUC_04vfaHzVKG5CGZle1M-9QFgY,81
|
76
|
-
crypticorn/hive/main.py,sha256=
|
76
|
+
crypticorn/hive/main.py,sha256=8-MKEE9zjxjSk4QMD-PcezD5MS-A1BzCFAmdgunJqyg,2308
|
77
|
+
crypticorn/hive/utils.py,sha256=nQe_GLb2Xk9EsuYpHASb_Sik5VyNXEHewCgT1LN4woo,2060
|
77
78
|
crypticorn/hive/client/__init__.py,sha256=BZ7MlUhK1x5j73WRPTPJFbTSELv9urdbpPonq04m6Aw,2331
|
78
79
|
crypticorn/hive/client/api_client.py,sha256=fDFsACK7hxXw_sgt3ZJVH2RplEdUhR0YZd4tsZA9P5Q,26869
|
79
80
|
crypticorn/hive/client/api_response.py,sha256=WhxwYDSMm6wPixp9CegO8dJzjFxDz3JF1yCq9s0ZqKE,639
|
@@ -82,7 +83,7 @@ crypticorn/hive/client/exceptions.py,sha256=IKuM8sbMtr3T9z-fOuePTJmheUFahzmyZ8ia
|
|
82
83
|
crypticorn/hive/client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
83
84
|
crypticorn/hive/client/rest.py,sha256=VhXkE7R3y1RD0QmbvIwmsk-LP_DmOei_zd9YiIXer28,6975
|
84
85
|
crypticorn/hive/client/api/__init__.py,sha256=y0KYdyqWZTjlf6IKASYmLdUs9a2aiFMHrfQO_V_-ZUw,223
|
85
|
-
crypticorn/hive/client/api/data_api.py,sha256=
|
86
|
+
crypticorn/hive/client/api/data_api.py,sha256=GJlH2Qs1KmWCc4nv7y5byyyFDiidLdooG-WvbBv-Z-4,22624
|
86
87
|
crypticorn/hive/client/api/models_api.py,sha256=61r9uObh1puEGJOXi_v-LmEP1xNqfbEo5spEYzlAA44,74136
|
87
88
|
crypticorn/hive/client/api/status_api.py,sha256=3ZZ9e1duL9Oz8gWvQQMryUevuRY_ERMPpClW8gY2THE,28714
|
88
89
|
crypticorn/hive/client/models/__init__.py,sha256=C-SmdIMEQljgJaxgADRAgHQuknh0sCZiAELnHC4SuJI,1539
|
@@ -220,8 +221,8 @@ crypticorn/trade/client/models/strategy_model_input.py,sha256=ala19jARyfA5ysys5D
|
|
220
221
|
crypticorn/trade/client/models/strategy_model_output.py,sha256=2o2lhbgUSTznowpMLEHF1Ex9TG9oRmzlCIb-gXqo7_s,5643
|
221
222
|
crypticorn/trade/client/models/tpsl.py,sha256=C2KgTIZs-a8W4msdaXgBKJcwtA-o5wR4rBauRP-iQxU,4317
|
222
223
|
crypticorn/trade/client/models/trading_action_type.py,sha256=pGq_TFLMPfYFizYP-xKgEC1ZF4U3lGdJYoGa_ZH2x-Q,769
|
223
|
-
crypticorn-2.
|
224
|
-
crypticorn-2.
|
225
|
-
crypticorn-2.
|
226
|
-
crypticorn-2.
|
227
|
-
crypticorn-2.
|
224
|
+
crypticorn-2.7.0.dist-info/METADATA,sha256=WcIXa2urQyx79i-xY-v6Q6TicA9zaybXWNOcmg2euxo,6249
|
225
|
+
crypticorn-2.7.0.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
|
226
|
+
crypticorn-2.7.0.dist-info/entry_points.txt,sha256=d_xHsGvUTebPveVUK0SrpDFQ5ZRSjlI7lNCc11sn2PM,59
|
227
|
+
crypticorn-2.7.0.dist-info/top_level.txt,sha256=EP3NY216qIBYfmvGl0L2Zc9ItP0DjGSkiYqd9xJwGcM,11
|
228
|
+
crypticorn-2.7.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|