everysk-lib 1.10.2__cp312-cp312-win_amd64.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.
- everysk/__init__.py +30 -0
- everysk/_version.py +683 -0
- everysk/api/__init__.py +61 -0
- everysk/api/api_requestor.py +167 -0
- everysk/api/api_resources/__init__.py +23 -0
- everysk/api/api_resources/api_resource.py +371 -0
- everysk/api/api_resources/calculation.py +779 -0
- everysk/api/api_resources/custom_index.py +42 -0
- everysk/api/api_resources/datastore.py +81 -0
- everysk/api/api_resources/file.py +42 -0
- everysk/api/api_resources/market_data.py +223 -0
- everysk/api/api_resources/parser.py +66 -0
- everysk/api/api_resources/portfolio.py +43 -0
- everysk/api/api_resources/private_security.py +42 -0
- everysk/api/api_resources/report.py +65 -0
- everysk/api/api_resources/report_template.py +39 -0
- everysk/api/api_resources/tests.py +115 -0
- everysk/api/api_resources/worker_execution.py +64 -0
- everysk/api/api_resources/workflow.py +65 -0
- everysk/api/api_resources/workflow_execution.py +93 -0
- everysk/api/api_resources/workspace.py +42 -0
- everysk/api/http_client.py +63 -0
- everysk/api/tests.py +32 -0
- everysk/api/utils.py +262 -0
- everysk/config.py +451 -0
- everysk/core/_tests/serialize/test_json.py +336 -0
- everysk/core/_tests/serialize/test_orjson.py +295 -0
- everysk/core/_tests/serialize/test_pickle.py +48 -0
- everysk/core/cloud_function/main.py +78 -0
- everysk/core/cloud_function/tests.py +86 -0
- everysk/core/compress.py +245 -0
- everysk/core/datetime/__init__.py +12 -0
- everysk/core/datetime/calendar.py +144 -0
- everysk/core/datetime/date.py +424 -0
- everysk/core/datetime/date_expression.py +299 -0
- everysk/core/datetime/date_mixin.py +1475 -0
- everysk/core/datetime/date_settings.py +30 -0
- everysk/core/datetime/datetime.py +713 -0
- everysk/core/exceptions.py +435 -0
- everysk/core/fields.py +1176 -0
- everysk/core/firestore.py +555 -0
- everysk/core/fixtures/_settings.py +29 -0
- everysk/core/fixtures/other/_settings.py +18 -0
- everysk/core/fixtures/user_agents.json +88 -0
- everysk/core/http.py +691 -0
- everysk/core/lists.py +92 -0
- everysk/core/log.py +709 -0
- everysk/core/number.py +37 -0
- everysk/core/object.py +1469 -0
- everysk/core/redis.py +1021 -0
- everysk/core/retry.py +51 -0
- everysk/core/serialize.py +674 -0
- everysk/core/sftp.py +414 -0
- everysk/core/signing.py +53 -0
- everysk/core/slack.py +127 -0
- everysk/core/string.py +199 -0
- everysk/core/tests.py +240 -0
- everysk/core/threads.py +199 -0
- everysk/core/undefined.py +70 -0
- everysk/core/unittests.py +73 -0
- everysk/core/workers.py +241 -0
- everysk/sdk/__init__.py +23 -0
- everysk/sdk/base.py +98 -0
- everysk/sdk/brutils/cnpj.py +391 -0
- everysk/sdk/brutils/cnpj_pd.py +129 -0
- everysk/sdk/engines/__init__.py +26 -0
- everysk/sdk/engines/cache.py +185 -0
- everysk/sdk/engines/compliance.py +37 -0
- everysk/sdk/engines/cryptography.py +69 -0
- everysk/sdk/engines/expression.cp312-win_amd64.pyd +0 -0
- everysk/sdk/engines/expression.pyi +55 -0
- everysk/sdk/engines/helpers.cp312-win_amd64.pyd +0 -0
- everysk/sdk/engines/helpers.pyi +26 -0
- everysk/sdk/engines/lock.py +120 -0
- everysk/sdk/engines/market_data.py +244 -0
- everysk/sdk/engines/settings.py +19 -0
- everysk/sdk/entities/__init__.py +23 -0
- everysk/sdk/entities/base.py +784 -0
- everysk/sdk/entities/base_list.py +131 -0
- everysk/sdk/entities/custom_index/base.py +209 -0
- everysk/sdk/entities/custom_index/settings.py +29 -0
- everysk/sdk/entities/datastore/base.py +160 -0
- everysk/sdk/entities/datastore/settings.py +17 -0
- everysk/sdk/entities/fields.py +375 -0
- everysk/sdk/entities/file/base.py +215 -0
- everysk/sdk/entities/file/settings.py +63 -0
- everysk/sdk/entities/portfolio/base.py +248 -0
- everysk/sdk/entities/portfolio/securities.py +241 -0
- everysk/sdk/entities/portfolio/security.py +580 -0
- everysk/sdk/entities/portfolio/settings.py +97 -0
- everysk/sdk/entities/private_security/base.py +226 -0
- everysk/sdk/entities/private_security/settings.py +17 -0
- everysk/sdk/entities/query.py +603 -0
- everysk/sdk/entities/report/base.py +214 -0
- everysk/sdk/entities/report/settings.py +23 -0
- everysk/sdk/entities/script.py +310 -0
- everysk/sdk/entities/secrets/base.py +128 -0
- everysk/sdk/entities/secrets/script.py +119 -0
- everysk/sdk/entities/secrets/settings.py +17 -0
- everysk/sdk/entities/settings.py +48 -0
- everysk/sdk/entities/tags.py +174 -0
- everysk/sdk/entities/worker_execution/base.py +307 -0
- everysk/sdk/entities/worker_execution/settings.py +63 -0
- everysk/sdk/entities/workflow_execution/base.py +113 -0
- everysk/sdk/entities/workflow_execution/settings.py +32 -0
- everysk/sdk/entities/workspace/base.py +99 -0
- everysk/sdk/entities/workspace/settings.py +27 -0
- everysk/sdk/settings.py +67 -0
- everysk/sdk/tests.py +105 -0
- everysk/sdk/worker_base.py +47 -0
- everysk/server/__init__.py +9 -0
- everysk/server/applications.py +63 -0
- everysk/server/endpoints.py +516 -0
- everysk/server/example_api.py +69 -0
- everysk/server/middlewares.py +80 -0
- everysk/server/requests.py +62 -0
- everysk/server/responses.py +119 -0
- everysk/server/routing.py +64 -0
- everysk/server/settings.py +36 -0
- everysk/server/tests.py +36 -0
- everysk/settings.py +98 -0
- everysk/sql/__init__.py +9 -0
- everysk/sql/connection.py +232 -0
- everysk/sql/model.py +376 -0
- everysk/sql/query.py +417 -0
- everysk/sql/row_factory.py +63 -0
- everysk/sql/settings.py +49 -0
- everysk/sql/utils.py +129 -0
- everysk/tests.py +23 -0
- everysk/utils.py +81 -0
- everysk/version.py +15 -0
- everysk_lib-1.10.2.dist-info/.gitignore +5 -0
- everysk_lib-1.10.2.dist-info/METADATA +326 -0
- everysk_lib-1.10.2.dist-info/RECORD +137 -0
- everysk_lib-1.10.2.dist-info/WHEEL +5 -0
- everysk_lib-1.10.2.dist-info/licenses/LICENSE.txt +9 -0
- everysk_lib-1.10.2.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
# -*- coding: utf_8 -*-
|
|
2
|
+
###############################################################################
|
|
3
|
+
#
|
|
4
|
+
# (C) Copyright 2023 EVERYSK TECHNOLOGIES
|
|
5
|
+
#
|
|
6
|
+
# This is an unpublished work containing confidential and proprietary
|
|
7
|
+
# information of EVERYSK TECHNOLOGIES. Disclosure, use, or reproduction
|
|
8
|
+
# without authorization of EVERYSK TECHNOLOGIES is prohibited.
|
|
9
|
+
#
|
|
10
|
+
###############################################################################
|
|
11
|
+
from typing import Callable, Any, Self
|
|
12
|
+
|
|
13
|
+
from everysk.config import settings
|
|
14
|
+
from everysk.core.datetime import Date, DateTime
|
|
15
|
+
from everysk.core.fields import DateField, DictField, FloatField, ListField, StrField
|
|
16
|
+
from everysk.core.object import BaseDict, BaseDictConfig, CLASS_KEY
|
|
17
|
+
from everysk.core.exceptions import FieldValueError
|
|
18
|
+
from everysk.sdk.engines import cryptography
|
|
19
|
+
from everysk.sdk.entities.base import BaseSDK
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
###############################################################################
|
|
23
|
+
# ExtraDataField Class Implementation
|
|
24
|
+
###############################################################################
|
|
25
|
+
class ExtraDataField(DictField):
|
|
26
|
+
|
|
27
|
+
def clean_value(self, value: Any) -> Any:
|
|
28
|
+
"""
|
|
29
|
+
This function is used to clean the value before it is assigned to the field.
|
|
30
|
+
It can be used to ensure consistency in the data.
|
|
31
|
+
"""
|
|
32
|
+
if isinstance(value, dict):
|
|
33
|
+
value = BaseDict(**value)
|
|
34
|
+
|
|
35
|
+
return super().clean_value(value)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
###############################################################################
|
|
39
|
+
# Security Class Implementation
|
|
40
|
+
###############################################################################
|
|
41
|
+
class Security(BaseDict, BaseSDK):
|
|
42
|
+
"""
|
|
43
|
+
This class represents a security entity and its attributes.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
status (StrField): The status of the security.
|
|
47
|
+
id (StrField): The unique identifier of the security.
|
|
48
|
+
symbol (StrField): The symbol of the security.
|
|
49
|
+
quantity (FloatField): The quantity of the security.
|
|
50
|
+
instrument_class (StrField): The class of the instrument.
|
|
51
|
+
ticker (StrField): The ticker symbol of the security.
|
|
52
|
+
label (StrField): The label of the security.
|
|
53
|
+
name (StrField): The name of the security.
|
|
54
|
+
isin (StrField): The ISIN (International Securities Identification Number) of the security.
|
|
55
|
+
exchange (StrField): The exchange where the security is traded.
|
|
56
|
+
currency (StrField): The currency of the security.
|
|
57
|
+
fx_rate (FloatField): The foreign exchange rate of the security.
|
|
58
|
+
market_price (FloatField): The market price of the security.
|
|
59
|
+
premium (FloatField): The premium associated with the security.
|
|
60
|
+
market_value (FloatField): The market value of the security.
|
|
61
|
+
market_value_in_base (FloatField): The market value of the security in the base currency.
|
|
62
|
+
instrument_type (StrField): The type of instrument.
|
|
63
|
+
instrument_subtype (StrField): The subtype of the instrument.
|
|
64
|
+
asset_class (StrField): The asset class of the security.
|
|
65
|
+
asset_subclass (StrField): The asset subclass of the security.
|
|
66
|
+
error_type (StrField): The type of error associated with the security.
|
|
67
|
+
error_message (StrField): The error message associated with the security.
|
|
68
|
+
maturity_date (DateField): The maturity date of the security.
|
|
69
|
+
indexer (StrField): The indexer used for the security.
|
|
70
|
+
percent_index (FloatField): The percentage index value.
|
|
71
|
+
rate (FloatField): The rate value.
|
|
72
|
+
coupon (FloatField): The coupon value.
|
|
73
|
+
multiplier (FloatField): The multiplier value.
|
|
74
|
+
underlying (StrField): The underlying asset of the security.
|
|
75
|
+
series (StrField): The series of the security.
|
|
76
|
+
option_type (StrField): The type of option (if applicable).
|
|
77
|
+
strike (FloatField): The strike price (if applicable).
|
|
78
|
+
issue_price (FloatField): The issue price of the security.
|
|
79
|
+
issue_date (DateField): The issue date of the security.
|
|
80
|
+
issuer (StrField): The issuer of the security.
|
|
81
|
+
issuer_type (StrField): The type of issuer.
|
|
82
|
+
cost_price (FloatField): The cost price of the security.
|
|
83
|
+
unrealized_pl (FloatField): The unrealized profit or loss of the security.
|
|
84
|
+
unrealized_pl_in_base (FloatField): The unrealized profit or loss of the security in the base currency.
|
|
85
|
+
book (StrField): The book associated with the security.
|
|
86
|
+
trader (StrField): The trader responsible for the security.
|
|
87
|
+
trade_id (StrField): The trade identifier of the security.
|
|
88
|
+
operation (StrField): The operation related to the security.
|
|
89
|
+
accounting (StrField): The accounting information of the security.
|
|
90
|
+
warranty (FloatField): The warranty associated with the security.
|
|
91
|
+
return_date (DateField): The return date of the security.
|
|
92
|
+
settlement (DateField): The settlement date of the security.
|
|
93
|
+
look_through_reference (StrField): The look-through reference of the security.
|
|
94
|
+
extra_data (DictField): Additional data associated with the security.
|
|
95
|
+
hash (StrField): The hash value of the security.
|
|
96
|
+
display (StrField): The display information of the security.
|
|
97
|
+
comparable (StrField): The comparable information of the security.
|
|
98
|
+
previous_quantity (FloatField): The previous quantity of the security (not sure about its use).
|
|
99
|
+
|
|
100
|
+
Example:
|
|
101
|
+
>>> security = Security()
|
|
102
|
+
>>> security.symbol = 'AAPL'
|
|
103
|
+
>>> security.quantity = 100
|
|
104
|
+
>>> security.market_price = 150.0
|
|
105
|
+
>>> security.currency = 'USD'
|
|
106
|
+
>>> security.name = 'Apple Inc.'
|
|
107
|
+
>>> security.status = 'OK'
|
|
108
|
+
>>> security
|
|
109
|
+
{
|
|
110
|
+
'status': 'OK',
|
|
111
|
+
'id': None,
|
|
112
|
+
'symbol': 'AAPL',
|
|
113
|
+
'quantity': 100.0,
|
|
114
|
+
'instrument_class': None,
|
|
115
|
+
'ticker': None,
|
|
116
|
+
'label': None,
|
|
117
|
+
'name': 'Apple Inc.',
|
|
118
|
+
'isin': None,
|
|
119
|
+
'exchange': None,
|
|
120
|
+
'currency': 'USD',
|
|
121
|
+
'fx_rate': None,
|
|
122
|
+
'market_price': 150.0,
|
|
123
|
+
'premium': None,
|
|
124
|
+
'market_value': None,
|
|
125
|
+
'market_value_in_base': None,
|
|
126
|
+
'instrument_type': None,
|
|
127
|
+
'instrument_subtype': None,
|
|
128
|
+
'asset_class': None,
|
|
129
|
+
'asset_subclass': None,
|
|
130
|
+
'error_type': None,
|
|
131
|
+
'error_message': None,
|
|
132
|
+
'maturity_date': None,
|
|
133
|
+
'indexer': None,
|
|
134
|
+
'percent_index': None,
|
|
135
|
+
'rate': None,
|
|
136
|
+
'coupon': None,
|
|
137
|
+
'multiplier': None,
|
|
138
|
+
'underlying': None,
|
|
139
|
+
'series': None,
|
|
140
|
+
'option_type': None,
|
|
141
|
+
'strike': None,
|
|
142
|
+
'issue_price': None,
|
|
143
|
+
'issue_date': None,
|
|
144
|
+
'issuer': None,
|
|
145
|
+
'issuer_type': None,
|
|
146
|
+
'cost_price': None,
|
|
147
|
+
'unrealized_pl': None,
|
|
148
|
+
'unrealized_pl_in_base': None,
|
|
149
|
+
'book': None,
|
|
150
|
+
'trader': None,
|
|
151
|
+
'trade_id': None,
|
|
152
|
+
'operation': None,
|
|
153
|
+
'accounting': None,
|
|
154
|
+
'warranty': None,
|
|
155
|
+
'return_date': None,
|
|
156
|
+
'settlement': None,
|
|
157
|
+
'look_through_reference': None,
|
|
158
|
+
'extra_data': None,
|
|
159
|
+
'hash': None,
|
|
160
|
+
'display': None,
|
|
161
|
+
'comparable': None,
|
|
162
|
+
'previous_quantity': None
|
|
163
|
+
}
|
|
164
|
+
"""
|
|
165
|
+
class Config(BaseDictConfig):
|
|
166
|
+
default_status = StrField(default=settings.SECURITY_STATUS_OK, readonly=True)
|
|
167
|
+
valid_status = ListField(default=[settings.SECURITY_STATUS_OK, settings.SECURITY_STATUS_DELISTED], readonly=True)
|
|
168
|
+
exclude_keys: frozenset[str] = frozenset(['_is_frozen', '_silent', '_errors', '_orderable_attributes'])
|
|
169
|
+
|
|
170
|
+
_config: Config = None
|
|
171
|
+
status = StrField()
|
|
172
|
+
id = StrField(required_lazy=True, min_size=1, max_size=settings.SYMBOL_ID_MAX_LEN)
|
|
173
|
+
|
|
174
|
+
symbol = StrField(required_lazy=True, max_size=settings.SYMBOL_MAX_LENGTH)
|
|
175
|
+
quantity = FloatField(required_lazy=True, min_size=settings.QUANTITY_MIN_VALUE, max_size=settings.QUANTITY_MAX_VALUE)
|
|
176
|
+
instrument_class = StrField()
|
|
177
|
+
|
|
178
|
+
ticker = StrField()
|
|
179
|
+
label = StrField(min_size=0, max_size=settings.LABEL_MAX_LENGTH)
|
|
180
|
+
name = StrField()
|
|
181
|
+
isin = StrField(min_size=0, max_size=settings.SYMBOL_MAX_LENGTH)
|
|
182
|
+
exchange = StrField()
|
|
183
|
+
currency = StrField()
|
|
184
|
+
fx_rate = FloatField(min_size=settings.FX_RATE_MIN_VALUE, max_size=settings.FX_RATE_MAX_VALUE)
|
|
185
|
+
market_price = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
186
|
+
premium = FloatField()
|
|
187
|
+
market_value = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
188
|
+
market_value_in_base = FloatField()
|
|
189
|
+
|
|
190
|
+
instrument_type = StrField()
|
|
191
|
+
instrument_subtype = StrField()
|
|
192
|
+
asset_class = StrField()
|
|
193
|
+
asset_subclass = StrField()
|
|
194
|
+
|
|
195
|
+
error_type = StrField(min_size=0, max_size=settings.PORTFOLIO_SECURITY_ERROR_TYPE_MAX_LEN)
|
|
196
|
+
error_message = StrField(min_size=0, max_size=settings.PORTFOLIO_SECURITY_ERROR_MESSAGE_MAX_LEN)
|
|
197
|
+
|
|
198
|
+
maturity_date = DateField(empty_is_none=True)
|
|
199
|
+
indexer = StrField()
|
|
200
|
+
percent_index = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
201
|
+
rate = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
202
|
+
coupon = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
203
|
+
|
|
204
|
+
multiplier = FloatField(min_size=settings.MULTIPLIER_MIN_VALUE, max_size=settings.MULTIPLIER_MAX_VALUE)
|
|
205
|
+
underlying = StrField()
|
|
206
|
+
series = StrField()
|
|
207
|
+
option_type = StrField()
|
|
208
|
+
strike = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
209
|
+
|
|
210
|
+
issue_price = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
211
|
+
issue_date = DateField(empty_is_none=True)
|
|
212
|
+
issuer = StrField()
|
|
213
|
+
issuer_type = StrField()
|
|
214
|
+
|
|
215
|
+
cost_price = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
216
|
+
unrealized_pl = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
217
|
+
unrealized_pl_in_base = FloatField(min_size=settings.PRICE_MIN_VALUE, max_size=settings.PRICE_MAX_VALUE)
|
|
218
|
+
|
|
219
|
+
book = StrField()
|
|
220
|
+
trader = StrField(min_size=0, max_size=settings.PORTFOLIO_SECURITY_TYPE_MAX_LEN)
|
|
221
|
+
trade_id = StrField()
|
|
222
|
+
|
|
223
|
+
operation = StrField()
|
|
224
|
+
accounting = StrField()
|
|
225
|
+
warranty = FloatField(min_size=settings.QUANTITY_MIN_VALUE, max_size=settings.QUANTITY_MAX_VALUE)
|
|
226
|
+
|
|
227
|
+
return_date = DateField(empty_is_none=True)
|
|
228
|
+
settlement = DateField(empty_is_none=True)
|
|
229
|
+
|
|
230
|
+
look_through_reference = StrField()
|
|
231
|
+
|
|
232
|
+
extra_data = ExtraDataField(default=None)
|
|
233
|
+
|
|
234
|
+
hash = StrField()
|
|
235
|
+
display = StrField()
|
|
236
|
+
comparable = StrField()
|
|
237
|
+
|
|
238
|
+
#NOT SURE ABOUT IT
|
|
239
|
+
previous_quantity = FloatField(min_size=settings.QUANTITY_MIN_VALUE, max_size=settings.QUANTITY_MAX_VALUE)
|
|
240
|
+
|
|
241
|
+
def __init__(self, **kwargs):
|
|
242
|
+
kwargs.pop('id_', None)
|
|
243
|
+
kwargs.pop('mic', None)
|
|
244
|
+
kwargs.pop(CLASS_KEY, None)
|
|
245
|
+
|
|
246
|
+
# This creates the Security with all default attributes
|
|
247
|
+
super().__init__()
|
|
248
|
+
|
|
249
|
+
# We check if the extra_data is not initialized
|
|
250
|
+
_extra_data = kwargs.pop('extra_data', None) or BaseDict()
|
|
251
|
+
if not isinstance(_extra_data, (BaseDict, dict)):
|
|
252
|
+
raise FieldValueError(f'attribute extra_data must be a dictionary. {type(_extra_data)}')
|
|
253
|
+
|
|
254
|
+
self.extra_data = BaseDict()
|
|
255
|
+
if _extra_data is not None:
|
|
256
|
+
for extra_key, extra_value in _extra_data.items():
|
|
257
|
+
self._add_extra_data(extra_key, extra_value)
|
|
258
|
+
|
|
259
|
+
for key, value in kwargs.items():
|
|
260
|
+
# If the key already exists in the class we just store it
|
|
261
|
+
if key in self:
|
|
262
|
+
self[key] = value
|
|
263
|
+
# otherwise we store it inside the extra_data key.
|
|
264
|
+
else:
|
|
265
|
+
self._add_extra_data(key, value)
|
|
266
|
+
|
|
267
|
+
# If for some reason the extra_data is empty we convert it to None
|
|
268
|
+
if not self.extra_data:
|
|
269
|
+
self.extra_data = None
|
|
270
|
+
|
|
271
|
+
def _add_extra_data(self, key: str, value: Any) -> None:
|
|
272
|
+
"""
|
|
273
|
+
Add an extra data attribute to the security.
|
|
274
|
+
|
|
275
|
+
This method adds an extra data attribute to the security object by storing it in the 'extra_data' dictionary.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
key (str): The key for the extra data attribute.
|
|
279
|
+
value (Any): The value of the extra data attribute.
|
|
280
|
+
|
|
281
|
+
Example:
|
|
282
|
+
>>> security = Security()
|
|
283
|
+
>>> security._add_extra_data('industry', 'Technology')
|
|
284
|
+
>>> security.extra_data
|
|
285
|
+
{'industry': 'Technology'}
|
|
286
|
+
"""
|
|
287
|
+
if value is None or isinstance(value, (int, str, bool, float, Date, DateTime)):
|
|
288
|
+
self.extra_data[key] = value
|
|
289
|
+
|
|
290
|
+
def _process_maturity_date(self, value: Date) -> str:
|
|
291
|
+
"""
|
|
292
|
+
Converts a Date object to a string.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
value (Date): The Date object to be converted.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
str: The converted Date, now represented as a string.
|
|
299
|
+
|
|
300
|
+
Example:
|
|
301
|
+
>>> _process_maturity_date(Date(2023, 9, 9))
|
|
302
|
+
'20230909'
|
|
303
|
+
"""
|
|
304
|
+
return Date.strftime_or_null(value)
|
|
305
|
+
|
|
306
|
+
def _process_issue_date(self, value: Date) -> str:
|
|
307
|
+
"""
|
|
308
|
+
Converts a Date object to a string.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
value (Date): The Date object to be converted.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
str: The converted Date, now represented as a string.
|
|
315
|
+
|
|
316
|
+
Example:
|
|
317
|
+
>>> _process_issue_date(Date(2023, 9, 9))
|
|
318
|
+
'20230909'
|
|
319
|
+
"""
|
|
320
|
+
return Date.strftime_or_null(value)
|
|
321
|
+
|
|
322
|
+
def _process_return_date(self, value: Date) -> str:
|
|
323
|
+
"""
|
|
324
|
+
Converts a Date object to a string.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
value (Date): The Date object to be converted.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
str: The converted Date, now represented as a string.
|
|
331
|
+
|
|
332
|
+
Example:
|
|
333
|
+
>>> _process_return_date(Date(2023, 9, 9))
|
|
334
|
+
'20230909'
|
|
335
|
+
"""
|
|
336
|
+
return Date.strftime_or_null(value)
|
|
337
|
+
|
|
338
|
+
def _process_settlement(self, value: Date) -> str:
|
|
339
|
+
"""
|
|
340
|
+
Converts a Date object to a string.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
value (Date): The Date object to be converted.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
str: The converted Data, now represented as a string.
|
|
347
|
+
|
|
348
|
+
Example:
|
|
349
|
+
>>> _process_settlement(Date(2023, 9, 9))
|
|
350
|
+
'20230909'
|
|
351
|
+
"""
|
|
352
|
+
return Date.strftime_or_null(value)
|
|
353
|
+
|
|
354
|
+
@staticmethod
|
|
355
|
+
def _get_attr(security: dict, key: str, fallback_func: Callable | None = None) -> Any:
|
|
356
|
+
"""
|
|
357
|
+
Get an attribute value from a security dictionary with optional fallback.
|
|
358
|
+
|
|
359
|
+
This static method attempts to retrieve a value associated with a given key from a security dictionary.
|
|
360
|
+
If the key is not found in the main dictionary, it checks if the key exists in the 'extra_data' dictionary
|
|
361
|
+
within the security dictionary. If the key is still not found and a fallback function is provided, the
|
|
362
|
+
fallback function is called to provide a default value.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
security (dict): A dictionary representing a security and its attributes.
|
|
366
|
+
key (str): The key for the attribute value to retrieve.
|
|
367
|
+
fallback_func (Callable | None, optional): A fallback function to call if the key is not found in
|
|
368
|
+
the main or 'extra_data' dictionaries. Defaults to None.
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
Any: The attribute value if found, or the result of the fallback function (if provided), or None.
|
|
372
|
+
|
|
373
|
+
Example:
|
|
374
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
375
|
+
>>> security_data = {
|
|
376
|
+
... 'symbol': 'AAPL',
|
|
377
|
+
... 'name': 'Apple Inc.',
|
|
378
|
+
... 'extra_data': {'industry': 'Technology'},
|
|
379
|
+
... }
|
|
380
|
+
>>> symbol = Security._get_attr(security_data, 'symbol')
|
|
381
|
+
>>> industry = Security._get_attr(security_data, 'industry')
|
|
382
|
+
>>> missing_attr = Security._get_attr(security_data, 'missing_attribute', lambda: 'Unknown')
|
|
383
|
+
>>> symbol
|
|
384
|
+
'AAPL'
|
|
385
|
+
>>> industry
|
|
386
|
+
'Technology'
|
|
387
|
+
>>> missing_attr
|
|
388
|
+
'Unknown'
|
|
389
|
+
"""
|
|
390
|
+
if key in security:
|
|
391
|
+
return security[key]
|
|
392
|
+
|
|
393
|
+
extra_data: dict = security['extra_data'] or {}
|
|
394
|
+
if key in extra_data:
|
|
395
|
+
return extra_data[key]
|
|
396
|
+
|
|
397
|
+
if fallback_func is not None:
|
|
398
|
+
return fallback_func()
|
|
399
|
+
|
|
400
|
+
return None
|
|
401
|
+
|
|
402
|
+
@staticmethod
|
|
403
|
+
def generate_security_id() -> str:
|
|
404
|
+
"""
|
|
405
|
+
Generate a unique security ID.
|
|
406
|
+
|
|
407
|
+
This static method generates a unique security ID by combining a prefix specified in
|
|
408
|
+
'settings.SECURITY_ID_PREFIX' with a unique identifier of a specified length
|
|
409
|
+
using the 'cryptography.generate_unique_id' function.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
str: A unique security ID.
|
|
413
|
+
|
|
414
|
+
Example:
|
|
415
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
416
|
+
>>> unique_id = Security.generate_security_id()
|
|
417
|
+
>>> unique_id
|
|
418
|
+
'SEC123456789'
|
|
419
|
+
"""
|
|
420
|
+
return f'{settings.SECURITY_ID_PREFIX}{cryptography.generate_random_id(length=settings.SECURITY_ID_LENGTH)}'
|
|
421
|
+
|
|
422
|
+
@staticmethod
|
|
423
|
+
def sort_header(header: list[str]) -> list[str]:
|
|
424
|
+
"""
|
|
425
|
+
Sort a header list based on a predefined order of properties.
|
|
426
|
+
|
|
427
|
+
This static method takes a list of header strings and sorts them based on a predefined order
|
|
428
|
+
specified in `settings.PORTFOLIO_PROPERTIES_ORDER`. Properties that are not found in the predefined
|
|
429
|
+
order are sorted alphabetically at the end.
|
|
430
|
+
|
|
431
|
+
Args:
|
|
432
|
+
header (list[str]): A list of header strings to be sorted.
|
|
433
|
+
|
|
434
|
+
Returns:
|
|
435
|
+
list[str]: A sorted list of header strings.
|
|
436
|
+
|
|
437
|
+
Example:
|
|
438
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
439
|
+
>>> header = ['symbol', 'name', 'price', 'quantity']
|
|
440
|
+
>>> sorted_header = Security.sort_header(header)
|
|
441
|
+
>>> sorted_header
|
|
442
|
+
['quantity', 'name', 'price', 'symbol']
|
|
443
|
+
"""
|
|
444
|
+
|
|
445
|
+
def sorting_key(element: str) -> tuple[int, str]:
|
|
446
|
+
try:
|
|
447
|
+
return (settings.PORTFOLIO_PROPERTIES_ORDER.index(element), '')
|
|
448
|
+
except ValueError:
|
|
449
|
+
return (len(settings.PORTFOLIO_PROPERTIES_ORDER), element)
|
|
450
|
+
|
|
451
|
+
return sorted(header, key=sorting_key)
|
|
452
|
+
|
|
453
|
+
def generate_consolidation_key(self, consolidation_keys: str) -> str:
|
|
454
|
+
"""
|
|
455
|
+
Generate a consolidation key based on specified attributes.
|
|
456
|
+
|
|
457
|
+
This method generates a consolidation key by extracting values from the security object
|
|
458
|
+
based on the provided consolidation keys. It uses the `_get_attr` method to retrieve
|
|
459
|
+
attribute values, and if a value is missing, it falls back to generating a security ID.
|
|
460
|
+
|
|
461
|
+
Args:
|
|
462
|
+
consolidation_keys (str): A string containing comma-separated attribute keys used for consolidation.
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
str: The consolidation key generated from the specified attributes.
|
|
466
|
+
|
|
467
|
+
Example:
|
|
468
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
469
|
+
>>> security_data = {
|
|
470
|
+
... 'symbol': 'AAPL',
|
|
471
|
+
... 'name': 'Apple Inc.',
|
|
472
|
+
... 'industry': 'Technology',
|
|
473
|
+
... 'extra_data': {'country': 'USA'}
|
|
474
|
+
... }
|
|
475
|
+
>>> security = Security(security_data)
|
|
476
|
+
>>> consolidation_keys = 'symbol,name,industry,country'
|
|
477
|
+
>>> consolidation_key = security.generate_consolidation_key(consolidation_keys)
|
|
478
|
+
>>> consolidation_key
|
|
479
|
+
'AAPL_Apple Inc._Technology_USA'
|
|
480
|
+
"""
|
|
481
|
+
key_: list[Any] = [Security._get_attr(self, key, fallback_func=self.generate_security_id) for key in consolidation_keys]
|
|
482
|
+
key: str = "_".join(str(v) for v in key_)
|
|
483
|
+
|
|
484
|
+
return key
|
|
485
|
+
|
|
486
|
+
@staticmethod
|
|
487
|
+
def from_list(sec_as_list: list[Any], headers: list[str]) -> Self:
|
|
488
|
+
"""
|
|
489
|
+
Create a Security object from a list of values and corresponding headers.
|
|
490
|
+
|
|
491
|
+
This static method takes a list of values representing a security's attributes and a list
|
|
492
|
+
of headers specifying the order of attributes. It constructs a Security object using the
|
|
493
|
+
provided values and headers.
|
|
494
|
+
|
|
495
|
+
Args:
|
|
496
|
+
sec_as_list (list[Any]): A list of attribute values for the security.
|
|
497
|
+
headers (list[str]): A list of headers specifying the order of attributes.
|
|
498
|
+
|
|
499
|
+
Returns:
|
|
500
|
+
Self: A new Security object initialized with the provided attribute values.
|
|
501
|
+
|
|
502
|
+
Example:
|
|
503
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
504
|
+
>>> sec_as_list = ['AAPL', 'Apple Inc.', 150.0, 100]
|
|
505
|
+
>>> headers = ['symbol', 'name', 'market_price', 'quantity']
|
|
506
|
+
>>> security = Security.from_list(sec_as_list, headers)
|
|
507
|
+
>>> security
|
|
508
|
+
{
|
|
509
|
+
'symbol': 'AAPL',
|
|
510
|
+
'name': 'Apple Inc.',
|
|
511
|
+
'market_price': 150.0,
|
|
512
|
+
'quantity': 100
|
|
513
|
+
}
|
|
514
|
+
"""
|
|
515
|
+
return Security(**dict(zip(headers, sec_as_list)))
|
|
516
|
+
|
|
517
|
+
def validate_required_fields(self) -> bool:
|
|
518
|
+
"""
|
|
519
|
+
Validate the required fields of the Security object.
|
|
520
|
+
|
|
521
|
+
This method checks if the 'id' attribute is present in the Security object. If not, it generates
|
|
522
|
+
a security ID using the 'generate_security_id' method and assigns it to the 'id' attribute.
|
|
523
|
+
Then, it calls the superclass method to validate other required fields.
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
bool: True if all required fields are valid, False otherwise.
|
|
527
|
+
|
|
528
|
+
Example:
|
|
529
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
530
|
+
>>> security = Security()
|
|
531
|
+
>>> security.name = 'Apple Inc.'
|
|
532
|
+
>>> security.quantity = 100
|
|
533
|
+
>>> security.market_price = 150.0
|
|
534
|
+
>>> security.validate_required_fields()
|
|
535
|
+
True
|
|
536
|
+
"""
|
|
537
|
+
if self.get('id', None) is None:
|
|
538
|
+
self.id = self.generate_security_id()
|
|
539
|
+
|
|
540
|
+
return super().validate_required_fields()
|
|
541
|
+
|
|
542
|
+
def to_list(self, header: list[str] | None = None) -> list[Any]:
|
|
543
|
+
"""
|
|
544
|
+
Convert the Security object to a list of attribute values.
|
|
545
|
+
|
|
546
|
+
This method converts the Security object and its attributes to a list of values.
|
|
547
|
+
The order of attributes in the list is determined by the 'header' parameter.
|
|
548
|
+
If 'header' is not provided, it defaults to the sorted order specified by the
|
|
549
|
+
'Security.sort_header' method.
|
|
550
|
+
|
|
551
|
+
Args:
|
|
552
|
+
header (list[str] | None, optional): A list of attribute keys specifying the order of attributes.
|
|
553
|
+
Defaults to None.
|
|
554
|
+
|
|
555
|
+
Returns:
|
|
556
|
+
list[Any]: A list of attribute values for the Security object.
|
|
557
|
+
|
|
558
|
+
Example:
|
|
559
|
+
>>> from everysk.sdk.entities.portfolio.security import Security
|
|
560
|
+
>>> security = Security()
|
|
561
|
+
>>> security.symbol = 'AAPL'
|
|
562
|
+
>>> security.quantity = 100
|
|
563
|
+
>>> security.market_price = 150.0
|
|
564
|
+
>>> security.name = 'Apple Inc.'
|
|
565
|
+
>>> attribute_list = security.to_list()
|
|
566
|
+
>>> attribute_list
|
|
567
|
+
['AAPL', 100, 150.0, 'Apple Inc.', # ... (other attributes)]
|
|
568
|
+
"""
|
|
569
|
+
if header is None:
|
|
570
|
+
header = Security.sort_header(self.keys())
|
|
571
|
+
|
|
572
|
+
security: dict = self.to_dict(add_class_path=False)
|
|
573
|
+
|
|
574
|
+
return [Security._get_attr(security, key) for key in header]
|
|
575
|
+
|
|
576
|
+
def _process_extra_data(self, value: dict | BaseDict | None) -> dict:
|
|
577
|
+
"""
|
|
578
|
+
Process the extra data attribute.
|
|
579
|
+
"""
|
|
580
|
+
return value.to_dict() if hasattr(value, 'to_dict') else value
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# (C) Copyright 2023 EVERYSK TECHNOLOGIES
|
|
4
|
+
#
|
|
5
|
+
# This is an unpublished work containing confidential and proprietary
|
|
6
|
+
# information of EVERYSK TECHNOLOGIES. Disclosure, use, or reproduction
|
|
7
|
+
# without authorization of EVERYSK TECHNOLOGIES is prohibited.
|
|
8
|
+
#
|
|
9
|
+
###############################################################################
|
|
10
|
+
from everysk.core.fields import FloatField, IntField, ListField, RegexField, StrField
|
|
11
|
+
|
|
12
|
+
PORTFOLIO_ID_REGEX = RegexField(default=r'^port_[a-zA-Z0-9]', readonly=True)
|
|
13
|
+
PORTFOLIO_ID_PREFIX = StrField(default='port_', readonly=True)
|
|
14
|
+
PORTFOLIO_ID_MAX_SIZE = IntField(default=30, readonly=True) # len(PORTFOLIO_ID_PREFIX) + ENTITY_ID_LENGTH
|
|
15
|
+
|
|
16
|
+
PORTFOLIO_MAX_SIZE = IntField(default=40000, readonly=True)
|
|
17
|
+
PORTFOLIO_LEVEL_MAX_LENGTH = IntField(default=32, readonly=True)
|
|
18
|
+
|
|
19
|
+
SECURITY_STATUS_OK = StrField(default='OK', readonly=True)
|
|
20
|
+
SECURITY_STATUS_ERROR = StrField(default='ERROR', readonly=True)
|
|
21
|
+
SECURITY_STATUS_DELISTED = StrField(default='DELISTED', readonly=True)
|
|
22
|
+
SECURITY_ID_LENGTH = IntField(default=6, readonly=True)
|
|
23
|
+
SECURITY_ID_PREFIX = StrField(default='sec_', readonly=True)
|
|
24
|
+
SYMBOL_ID_MAX_LEN = IntField(default=100, readonly=True)
|
|
25
|
+
|
|
26
|
+
PRICE_MIN_VALUE = FloatField(default=-9999999999999.99, readonly=True)
|
|
27
|
+
PRICE_MAX_VALUE = FloatField(default=+9999999999999.99, readonly=True)
|
|
28
|
+
|
|
29
|
+
FX_RATE_MIN_VALUE = FloatField(default=0.0, readonly=True)
|
|
30
|
+
FX_RATE_MAX_VALUE = FloatField(default=+9999999999999.99, readonly=True)
|
|
31
|
+
|
|
32
|
+
MULTIPLIER_MIN_VALUE = FloatField(default=0.0, readonly=True)
|
|
33
|
+
MULTIPLIER_MAX_VALUE = FloatField(default=+9999999999999.99, readonly=True)
|
|
34
|
+
|
|
35
|
+
QUANTITY_MIN_VALUE = FloatField(default=-9999999999999.99, readonly=True)
|
|
36
|
+
QUANTITY_MAX_VALUE = FloatField(default=+9999999999999.99, readonly=True)
|
|
37
|
+
|
|
38
|
+
SYMBOL_MAX_LENGTH = IntField(default=100, readonly=True)
|
|
39
|
+
LABEL_MAX_LENGTH = IntField(default=100, readonly=True)
|
|
40
|
+
|
|
41
|
+
PORTFOLIO_SECURITY_ERROR_TYPE_MAX_LEN = IntField(default=100, readonly=True)
|
|
42
|
+
PORTFOLIO_SECURITY_ERROR_MESSAGE_MAX_LEN = IntField(default=500, readonly=True)
|
|
43
|
+
PORTFOLIO_SECURITY_TYPE_MAX_LEN = IntField(default=100, readonly=True)
|
|
44
|
+
|
|
45
|
+
PORTFOLIO_PROPERTIES_ORDER = ListField(
|
|
46
|
+
default=[
|
|
47
|
+
'status',
|
|
48
|
+
'id',
|
|
49
|
+
'symbol',
|
|
50
|
+
'quantity',
|
|
51
|
+
'instrument_class',
|
|
52
|
+
'ticker',
|
|
53
|
+
'label',
|
|
54
|
+
'name',
|
|
55
|
+
'isin',
|
|
56
|
+
'exchange',
|
|
57
|
+
'currency',
|
|
58
|
+
'fx_rate',
|
|
59
|
+
'market_price',
|
|
60
|
+
'market_value',
|
|
61
|
+
'instrument_type',
|
|
62
|
+
'instrument_subtype',
|
|
63
|
+
'asset_class',
|
|
64
|
+
'asset_subclass',
|
|
65
|
+
'error_type',
|
|
66
|
+
'error_message',
|
|
67
|
+
'maturity_date',
|
|
68
|
+
'indexer',
|
|
69
|
+
'percent_index',
|
|
70
|
+
'rate',
|
|
71
|
+
'coupon',
|
|
72
|
+
'multiplier',
|
|
73
|
+
'underlying',
|
|
74
|
+
'series',
|
|
75
|
+
'option_type',
|
|
76
|
+
'strike',
|
|
77
|
+
'issue_price',
|
|
78
|
+
'issue_date',
|
|
79
|
+
'issuer',
|
|
80
|
+
'issuer_type',
|
|
81
|
+
'cost_price',
|
|
82
|
+
'unrealized_pl',
|
|
83
|
+
'unrealized_pl_in_base',
|
|
84
|
+
'book',
|
|
85
|
+
'trader',
|
|
86
|
+
'trade_id',
|
|
87
|
+
'operation',
|
|
88
|
+
'accounting',
|
|
89
|
+
'warranty',
|
|
90
|
+
'return_date',
|
|
91
|
+
'settlement',
|
|
92
|
+
'look_through_reference',
|
|
93
|
+
'extra_data',
|
|
94
|
+
'hash',
|
|
95
|
+
],
|
|
96
|
+
readonly=True,
|
|
97
|
+
)
|