crypticorn 2.5.0rc4__py3-none-any.whl → 2.5.1__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.
Files changed (83) hide show
  1. crypticorn/auth/main.py +2 -0
  2. crypticorn/client.py +60 -69
  3. crypticorn/common/__init__.py +2 -1
  4. crypticorn/common/auth.py +38 -20
  5. crypticorn/common/enums.py +5 -34
  6. crypticorn/common/errors.py +33 -14
  7. crypticorn/common/exceptions.py +42 -25
  8. crypticorn/common/mixins.py +36 -0
  9. crypticorn/common/urls.py +2 -1
  10. crypticorn/common/utils.py +4 -2
  11. crypticorn/hive/main.py +2 -0
  12. crypticorn/klines/client/__init__.py +14 -42
  13. crypticorn/klines/client/api/__init__.py +1 -1
  14. crypticorn/klines/client/api/change_in_timeframe_api.py +8 -22
  15. crypticorn/klines/client/api/funding_rates_api.py +8 -22
  16. crypticorn/klines/client/api/ohlcv_data_api.py +13 -33
  17. crypticorn/klines/client/api/status_api.py +260 -0
  18. crypticorn/klines/client/api/symbols_api.py +14 -29
  19. crypticorn/klines/client/api/udf_api.py +48 -59
  20. crypticorn/klines/client/api_client.py +1 -1
  21. crypticorn/klines/client/configuration.py +1 -1
  22. crypticorn/klines/client/exceptions.py +1 -1
  23. crypticorn/klines/client/models/__init__.py +13 -41
  24. crypticorn/klines/client/models/api_error_identifier.py +108 -0
  25. crypticorn/klines/client/models/api_error_level.py +37 -0
  26. crypticorn/klines/client/models/api_error_type.py +37 -0
  27. crypticorn/klines/client/models/change_in_timeframe.py +86 -0
  28. crypticorn/klines/client/models/exception_detail.py +117 -0
  29. crypticorn/klines/client/models/funding_rate.py +92 -0
  30. crypticorn/klines/client/models/internal_exchange.py +39 -0
  31. crypticorn/klines/client/models/market_type.py +1 -1
  32. crypticorn/klines/client/models/ohlcv_history.py +105 -0
  33. crypticorn/klines/client/models/resolution.py +1 -1
  34. crypticorn/klines/client/models/search_symbol.py +94 -0
  35. crypticorn/klines/client/models/sort_direction.py +1 -1
  36. crypticorn/klines/client/models/symbol_group.py +83 -0
  37. crypticorn/klines/client/models/symbol_info.py +131 -0
  38. crypticorn/klines/client/models/symbol_type.py +1 -1
  39. crypticorn/klines/client/models/timeframe.py +1 -1
  40. crypticorn/klines/client/models/udf_config.py +149 -0
  41. crypticorn/klines/client/rest.py +1 -1
  42. crypticorn/klines/main.py +40 -23
  43. crypticorn/metrics/client/__init__.py +7 -21
  44. crypticorn/metrics/client/api/__init__.py +1 -1
  45. crypticorn/metrics/client/api/exchanges_api.py +36 -78
  46. crypticorn/metrics/client/api/indicators_api.py +12 -37
  47. crypticorn/metrics/client/api/logs_api.py +8 -23
  48. crypticorn/metrics/client/api/marketcap_api.py +22 -73
  49. crypticorn/metrics/client/api/markets_api.py +12 -40
  50. crypticorn/metrics/client/api/status_api.py +260 -0
  51. crypticorn/metrics/client/api/tokens_api.py +7 -21
  52. crypticorn/metrics/client/api_client.py +1 -1
  53. crypticorn/metrics/client/configuration.py +5 -3
  54. crypticorn/metrics/client/exceptions.py +1 -1
  55. crypticorn/metrics/client/models/__init__.py +6 -20
  56. crypticorn/{trade → metrics}/client/models/api_error_identifier.py +6 -2
  57. crypticorn/{trade → metrics}/client/models/api_error_level.py +2 -2
  58. crypticorn/{trade → metrics}/client/models/api_error_type.py +2 -2
  59. crypticorn/metrics/client/models/exception_detail.py +117 -0
  60. crypticorn/metrics/client/models/internal_exchange.py +39 -0
  61. crypticorn/metrics/client/models/market_type.py +1 -1
  62. crypticorn/metrics/client/models/severity.py +1 -1
  63. crypticorn/metrics/client/models/time_interval.py +1 -1
  64. crypticorn/metrics/client/models/trading_status.py +1 -1
  65. crypticorn/metrics/client/rest.py +1 -1
  66. crypticorn/metrics/main.py +51 -43
  67. crypticorn/pay/main.py +2 -0
  68. crypticorn/trade/client/__init__.py +0 -3
  69. crypticorn/trade/client/configuration.py +2 -2
  70. crypticorn/trade/client/models/__init__.py +0 -3
  71. crypticorn/trade/client/models/bot_model.py +3 -7
  72. crypticorn/trade/client/models/execution_ids.py +1 -1
  73. crypticorn/trade/client/models/notification_model.py +3 -12
  74. crypticorn/trade/client/models/order_model.py +3 -7
  75. crypticorn/trade/client/models/spot_trading_action.py +231 -0
  76. crypticorn/trade/main.py +2 -0
  77. {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.1.dist-info}/METADATA +7 -5
  78. {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.1.dist-info}/RECORD +82 -65
  79. {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.1.dist-info}/WHEEL +1 -1
  80. crypticorn/common/sorter.py +0 -40
  81. /crypticorn/common/{pydantic.py → decorators.py} +0 -0
  82. {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.1.dist-info}/entry_points.txt +0 -0
  83. {crypticorn-2.5.0rc4.dist-info → crypticorn-2.5.1.dist-info}/top_level.txt +0 -0
@@ -19,7 +19,6 @@ import json
19
19
 
20
20
  from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr
21
21
  from typing import Any, ClassVar, Dict, List, Optional, Union
22
- from crypticorn.trade.client.models.api_error_identifier import ApiErrorIdentifier
23
22
  from crypticorn.trade.client.models.bot_status import BotStatus
24
23
  from typing import Optional, Set
25
24
  from typing_extensions import Self
@@ -40,7 +39,9 @@ class BotModel(BaseModel):
40
39
  api_key_id: StrictStr = Field(description="UID for the API key")
41
40
  allocation: StrictInt = Field(description="Initial allocation for the bot")
42
41
  status: BotStatus = Field(description="Status of the bot")
43
- status_code: Optional[ApiErrorIdentifier] = None
42
+ status_code: Optional[StrictStr] = Field(
43
+ default=None, description="API error identifiers"
44
+ )
44
45
  user_id: Optional[StrictStr] = None
45
46
  current_allocation: Optional[Union[StrictFloat, StrictInt]] = None
46
47
  current_exposure: Optional[Union[StrictFloat, StrictInt]] = None
@@ -111,11 +112,6 @@ class BotModel(BaseModel):
111
112
  if self.id is None and "id" in self.model_fields_set:
112
113
  _dict["id"] = None
113
114
 
114
- # set to None if status_code (nullable) is None
115
- # and model_fields_set contains the field
116
- if self.status_code is None and "status_code" in self.model_fields_set:
117
- _dict["status_code"] = None
118
-
119
115
  # set to None if user_id (nullable) is None
120
116
  # and model_fields_set contains the field
121
117
  if self.user_id is None and "user_id" in self.model_fields_set:
@@ -28,7 +28,7 @@ class ExecutionIds(BaseModel):
28
28
  ExecutionIds
29
29
  """ # noqa: E501
30
30
 
31
- main: List[StrictStr] = Field(description="Main execution ID. List with one item.")
31
+ main: StrictStr = Field(description="Main execution ID.")
32
32
  sl: List[StrictStr] = Field(
33
33
  description="Stop loss execution IDs. List with multiple items ordered by the next stop loss, e.g. price = 10000 => SLs: ['900', '700', '500']."
34
34
  )
@@ -19,9 +19,6 @@ import json
19
19
 
20
20
  from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
21
21
  from typing import Any, ClassVar, Dict, List, Optional
22
- from crypticorn.trade.client.models.api_error_identifier import ApiErrorIdentifier
23
- from crypticorn.trade.client.models.api_error_level import ApiErrorLevel
24
- from crypticorn.trade.client.models.api_error_type import ApiErrorType
25
22
  from typing import Optional, Set
26
23
  from typing_extensions import Self
27
24
 
@@ -34,15 +31,9 @@ class NotificationModel(BaseModel):
34
31
  created_at: Optional[StrictInt] = None
35
32
  updated_at: Optional[StrictInt] = None
36
33
  id: Optional[StrictStr] = None
37
- identifier: ApiErrorIdentifier = Field(
38
- description="Identifier string. Must match the mapping key in the frontend."
39
- )
40
- level: ApiErrorLevel = Field(
41
- description="Level of the notification. Of type ApiErrorLevel"
42
- )
43
- type: ApiErrorType = Field(
44
- description="Type of the notification. Of type ApiErrorType"
45
- )
34
+ identifier: StrictStr = Field(description="API error identifiers")
35
+ level: StrictStr = Field(description="API error levels")
36
+ type: StrictStr = Field(description="Type of API error")
46
37
  user_id: Optional[StrictStr] = None
47
38
  viewed: Optional[StrictBool] = Field(
48
39
  default=False, description="Whether the notification has been marked as seen"
@@ -19,7 +19,6 @@ import json
19
19
 
20
20
  from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr
21
21
  from typing import Any, ClassVar, Dict, List, Optional, Union
22
- from crypticorn.trade.client.models.api_error_identifier import ApiErrorIdentifier
23
22
  from crypticorn.trade.client.models.exchange import Exchange
24
23
  from crypticorn.trade.client.models.margin_mode import MarginMode
25
24
  from crypticorn.trade.client.models.market_type import MarketType
@@ -52,7 +51,9 @@ class OrderModel(BaseModel):
52
51
  action_type: Optional[TradingActionType] = None
53
52
  market_type: Optional[MarketType] = None
54
53
  margin_mode: Optional[MarginMode] = None
55
- status_code: Optional[ApiErrorIdentifier] = None
54
+ status_code: Optional[StrictStr] = Field(
55
+ default=None, description="API error identifiers"
56
+ )
56
57
  status: Optional[OrderStatus] = None
57
58
  filled_perc: Optional[Union[StrictFloat, StrictInt]] = None
58
59
  filled_qty: Optional[Union[StrictFloat, StrictInt]] = None
@@ -229,11 +230,6 @@ class OrderModel(BaseModel):
229
230
  if self.margin_mode is None and "margin_mode" in self.model_fields_set:
230
231
  _dict["margin_mode"] = None
231
232
 
232
- # set to None if status_code (nullable) is None
233
- # and model_fields_set contains the field
234
- if self.status_code is None and "status_code" in self.model_fields_set:
235
- _dict["status_code"] = None
236
-
237
233
  # set to None if status (nullable) is None
238
234
  # and model_fields_set contains the field
239
235
  if self.status is None and "status" in self.model_fields_set:
@@ -0,0 +1,231 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Trading API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import (
21
+ BaseModel,
22
+ ConfigDict,
23
+ Field,
24
+ StrictBool,
25
+ StrictFloat,
26
+ StrictInt,
27
+ StrictStr,
28
+ )
29
+ from typing import Any, ClassVar, Dict, List, Optional, Union
30
+ from typing_extensions import Annotated
31
+ from crypticorn.trade.client.models.market_type import MarketType
32
+ from crypticorn.trade.client.models.tpsl import TPSL
33
+ from crypticorn.trade.client.models.trading_action_type import TradingActionType
34
+ from typing import Optional, Set
35
+ from typing_extensions import Self
36
+
37
+
38
+ class SpotTradingAction(BaseModel):
39
+ """
40
+ Model for spot trading actions
41
+ """ # noqa: E501
42
+
43
+ id: Optional[StrictStr] = None
44
+ execution_id: Optional[StrictStr] = None
45
+ open_order_execution_id: Optional[StrictStr] = None
46
+ client_order_id: Optional[StrictStr] = None
47
+ action_type: TradingActionType = Field(description="The type of action.")
48
+ market_type: MarketType = Field(description="The type of market the action is for.")
49
+ strategy_id: StrictStr = Field(description="UID for the strategy.")
50
+ symbol: StrictStr = Field(
51
+ description="Trading symbol or asset pair in format: 'symbol/quote_currency' (see market service for valid symbols)"
52
+ )
53
+ is_limit: Optional[StrictBool] = None
54
+ limit_price: Optional[Union[StrictFloat, StrictInt]] = None
55
+ allocation: Optional[
56
+ Union[
57
+ Annotated[float, Field(le=1.0, strict=True)],
58
+ Annotated[int, Field(le=1, strict=True)],
59
+ ]
60
+ ] = Field(
61
+ default=None,
62
+ description="How much of bot's balance to use for the order (for open actions). How much of the reference open order (open_order_execution_id) to close (for close actions). 0=0%, 1=100%.",
63
+ )
64
+ take_profit: Optional[List[TPSL]] = None
65
+ stop_loss: Optional[List[TPSL]] = None
66
+ expiry_timestamp: Optional[StrictInt] = None
67
+ position_id: Optional[StrictStr] = None
68
+ __properties: ClassVar[List[str]] = [
69
+ "id",
70
+ "execution_id",
71
+ "open_order_execution_id",
72
+ "client_order_id",
73
+ "action_type",
74
+ "market_type",
75
+ "strategy_id",
76
+ "symbol",
77
+ "is_limit",
78
+ "limit_price",
79
+ "allocation",
80
+ "take_profit",
81
+ "stop_loss",
82
+ "expiry_timestamp",
83
+ "position_id",
84
+ ]
85
+
86
+ model_config = ConfigDict(
87
+ populate_by_name=True,
88
+ validate_assignment=True,
89
+ protected_namespaces=(),
90
+ )
91
+
92
+ def to_str(self) -> str:
93
+ """Returns the string representation of the model using alias"""
94
+ return pprint.pformat(self.model_dump(by_alias=True))
95
+
96
+ def to_json(self) -> str:
97
+ """Returns the JSON representation of the model using alias"""
98
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
99
+ return json.dumps(self.to_dict())
100
+
101
+ @classmethod
102
+ def from_json(cls, json_str: str) -> Optional[Self]:
103
+ """Create an instance of SpotTradingAction from a JSON string"""
104
+ return cls.from_dict(json.loads(json_str))
105
+
106
+ def to_dict(self) -> Dict[str, Any]:
107
+ """Return the dictionary representation of the model using alias.
108
+
109
+ This has the following differences from calling pydantic's
110
+ `self.model_dump(by_alias=True)`:
111
+
112
+ * `None` is only added to the output dict for nullable fields that
113
+ were set at model initialization. Other fields with value `None`
114
+ are ignored.
115
+ """
116
+ excluded_fields: Set[str] = set([])
117
+
118
+ _dict = self.model_dump(
119
+ by_alias=True,
120
+ exclude=excluded_fields,
121
+ exclude_none=True,
122
+ )
123
+ # override the default output from pydantic by calling `to_dict()` of each item in take_profit (list)
124
+ _items = []
125
+ if self.take_profit:
126
+ for _item_take_profit in self.take_profit:
127
+ if _item_take_profit:
128
+ _items.append(_item_take_profit.to_dict())
129
+ _dict["take_profit"] = _items
130
+ # override the default output from pydantic by calling `to_dict()` of each item in stop_loss (list)
131
+ _items = []
132
+ if self.stop_loss:
133
+ for _item_stop_loss in self.stop_loss:
134
+ if _item_stop_loss:
135
+ _items.append(_item_stop_loss.to_dict())
136
+ _dict["stop_loss"] = _items
137
+ # set to None if id (nullable) is None
138
+ # and model_fields_set contains the field
139
+ if self.id is None and "id" in self.model_fields_set:
140
+ _dict["id"] = None
141
+
142
+ # set to None if execution_id (nullable) is None
143
+ # and model_fields_set contains the field
144
+ if self.execution_id is None and "execution_id" in self.model_fields_set:
145
+ _dict["execution_id"] = None
146
+
147
+ # set to None if open_order_execution_id (nullable) is None
148
+ # and model_fields_set contains the field
149
+ if (
150
+ self.open_order_execution_id is None
151
+ and "open_order_execution_id" in self.model_fields_set
152
+ ):
153
+ _dict["open_order_execution_id"] = None
154
+
155
+ # set to None if client_order_id (nullable) is None
156
+ # and model_fields_set contains the field
157
+ if self.client_order_id is None and "client_order_id" in self.model_fields_set:
158
+ _dict["client_order_id"] = None
159
+
160
+ # set to None if is_limit (nullable) is None
161
+ # and model_fields_set contains the field
162
+ if self.is_limit is None and "is_limit" in self.model_fields_set:
163
+ _dict["is_limit"] = None
164
+
165
+ # set to None if limit_price (nullable) is None
166
+ # and model_fields_set contains the field
167
+ if self.limit_price is None and "limit_price" in self.model_fields_set:
168
+ _dict["limit_price"] = None
169
+
170
+ # set to None if take_profit (nullable) is None
171
+ # and model_fields_set contains the field
172
+ if self.take_profit is None and "take_profit" in self.model_fields_set:
173
+ _dict["take_profit"] = None
174
+
175
+ # set to None if stop_loss (nullable) is None
176
+ # and model_fields_set contains the field
177
+ if self.stop_loss is None and "stop_loss" in self.model_fields_set:
178
+ _dict["stop_loss"] = None
179
+
180
+ # set to None if expiry_timestamp (nullable) is None
181
+ # and model_fields_set contains the field
182
+ if (
183
+ self.expiry_timestamp is None
184
+ and "expiry_timestamp" in self.model_fields_set
185
+ ):
186
+ _dict["expiry_timestamp"] = None
187
+
188
+ # set to None if position_id (nullable) is None
189
+ # and model_fields_set contains the field
190
+ if self.position_id is None and "position_id" in self.model_fields_set:
191
+ _dict["position_id"] = None
192
+
193
+ return _dict
194
+
195
+ @classmethod
196
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
197
+ """Create an instance of SpotTradingAction from a dict"""
198
+ if obj is None:
199
+ return None
200
+
201
+ if not isinstance(obj, dict):
202
+ return cls.model_validate(obj)
203
+
204
+ _obj = cls.model_validate(
205
+ {
206
+ "id": obj.get("id"),
207
+ "execution_id": obj.get("execution_id"),
208
+ "open_order_execution_id": obj.get("open_order_execution_id"),
209
+ "client_order_id": obj.get("client_order_id"),
210
+ "action_type": obj.get("action_type"),
211
+ "market_type": obj.get("market_type"),
212
+ "strategy_id": obj.get("strategy_id"),
213
+ "symbol": obj.get("symbol"),
214
+ "is_limit": obj.get("is_limit"),
215
+ "limit_price": obj.get("limit_price"),
216
+ "allocation": obj.get("allocation"),
217
+ "take_profit": (
218
+ [TPSL.from_dict(_item) for _item in obj["take_profit"]]
219
+ if obj.get("take_profit") is not None
220
+ else None
221
+ ),
222
+ "stop_loss": (
223
+ [TPSL.from_dict(_item) for _item in obj["stop_loss"]]
224
+ if obj.get("stop_loss") is not None
225
+ else None
226
+ ),
227
+ "expiry_timestamp": obj.get("expiry_timestamp"),
228
+ "position_id": obj.get("position_id"),
229
+ }
230
+ )
231
+ return _obj
crypticorn/trade/main.py CHANGED
@@ -18,6 +18,8 @@ class TradeClient:
18
18
  A client for interacting with the Crypticorn Trade API.
19
19
  """
20
20
 
21
+ config_class = Configuration
22
+
21
23
  def __init__(
22
24
  self,
23
25
  config: Configuration,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crypticorn
3
- Version: 2.5.0rc4
3
+ Version: 2.5.1
4
4
  Summary: Maximise Your Crypto Trading Profits with AI Predictions
5
5
  Author-email: Crypticorn <timon@crypticorn.com>
6
6
  Project-URL: Homepage, https://crypticorn.com
@@ -36,6 +36,7 @@ Requires-Dist: pytest==8.3.5; extra == "test"
36
36
  Requires-Dist: pytest-asyncio==0.26.0; extra == "test"
37
37
  Requires-Dist: pytest-cov==6.1.1; extra == "test"
38
38
  Requires-Dist: python-dotenv==1.0.1; extra == "test"
39
+ Requires-Dist: PyJWT==2.10.0; extra == "test"
39
40
  Provides-Extra: extra
40
41
  Requires-Dist: pandas<3.0.0,>=2.2.0; extra == "extra"
41
42
 
@@ -86,7 +87,7 @@ The `common` submodule contains shared classes not bound to a specific API.
86
87
  from crypticorn.common import Scope, Exchange
87
88
  ```
88
89
 
89
- ## Usage
90
+ ## Basic Usage
90
91
 
91
92
  ### With Async Context Protocol
92
93
  ```python
@@ -107,6 +108,7 @@ async def main():
107
108
 
108
109
  asyncio.run(main())
109
110
  asyncio.run(client.close())
111
+
110
112
  ## Response Types
111
113
 
112
114
  There are three different available output formats you can choose from:
@@ -155,12 +157,12 @@ The output would look like this:
155
157
 
156
158
  ## Advanced Usage
157
159
 
158
- You can override some configuration for specific sub clients. If you just want to use the API as is, you don't need to configure anything.
160
+ You can override some configuration for specific services. If you just want to use the API as is, you don't need to configure anything.
159
161
  This might be of use if you are testing a specific API locally.
160
162
 
161
- To override e.g. the host for the Hive client to connect to http://localhost:8000 instead of the default caddy proxy, you would do:
163
+ To override e.g. the host for the Hive client to connect to http://localhost:8000 instead of the default proxy, you would do:
162
164
  ```python
163
165
  from crypticorn.hive import Configuration as Hiveconfig
164
166
  async with ApiClient(base_url=BaseUrl.DEV) as client:
165
- client.configure(config=HiveConfig(host="http://localhost:8000"), sub_client=client.hive)
167
+ client.configure(config=HiveConfig(host="http://localhost:8000"), client=client.hive)
166
168
  ```