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.
@@ -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], Field(description="Feature size")
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. (required)
74
+ :param version: Data version. Default is the latest public version.
74
75
  :type version: DataVersion
75
- :param feature_size: 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], Field(description="Feature size")
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. (required)
152
+ :param version: Data version. Default is the latest public version.
151
153
  :type version: DataVersion
152
- :param feature_size: 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], Field(description="Feature size")
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. (required)
230
+ :param version: Data version. Default is the latest public version.
228
231
  :type version: DataVersion
229
- :param feature_size: 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.common import apikey_header as aph
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 = DataApi(self.base_client)
68
+ self.data = DataApiWrapper(self.base_client)
28
69
  self.status = StatusApi(self.base_client)
@@ -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.6.0
4
- Summary: Maximise Your Crypto Trading Profits with AI Predictions
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=I1wuD8ZaMqlhJDk-SE1yS41KyjPEhNQ4r4LpLXwcSBw,27515
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=WUgsjs9p9zZ5NgPuD54m1u8dLnM8yaYCYHF51AH2IaE,665
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=9WpN0R1eI6Bq7KfJwm7R_fJ0IYIDoBIehQiUG3sb4kE,22351
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.6.0.dist-info/METADATA,sha256=bDu5aD7J0MfUC_bMe6FL57Z8niFcOTBWWG_WTu1tEro,6247
224
- crypticorn-2.6.0.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
225
- crypticorn-2.6.0.dist-info/entry_points.txt,sha256=d_xHsGvUTebPveVUK0SrpDFQ5ZRSjlI7lNCc11sn2PM,59
226
- crypticorn-2.6.0.dist-info/top_level.txt,sha256=EP3NY216qIBYfmvGl0L2Zc9ItP0DjGSkiYqd9xJwGcM,11
227
- crypticorn-2.6.0.dist-info/RECORD,,
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,,