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,248 @@
|
|
|
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 Any, TYPE_CHECKING
|
|
12
|
+
import csv
|
|
13
|
+
import six
|
|
14
|
+
|
|
15
|
+
from everysk.config import settings
|
|
16
|
+
from everysk.core.fields import ListField, StrField, FloatField, BoolField
|
|
17
|
+
from everysk.core.string import to_string
|
|
18
|
+
from everysk.sdk.entities.base import BaseEntity, ScriptMetaClass
|
|
19
|
+
from everysk.sdk.entities.fields import EntityNameField, EntityDescriptionField, EntityLinkUIDField, EntityWorkspaceField, EntityDateTimeField, EntityTagsField, CurrencyField
|
|
20
|
+
from everysk.sdk.entities.portfolio.securities import Securities
|
|
21
|
+
from everysk.sdk.entities.script import Script
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from io import StringIO
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
###############################################################################
|
|
28
|
+
# SecuritiesField Class Implementation
|
|
29
|
+
###############################################################################
|
|
30
|
+
class SecuritiesField(ListField):
|
|
31
|
+
attr_type = Securities
|
|
32
|
+
|
|
33
|
+
def __init__(self, default: Any = None, required_lazy: bool = True, **kwargs) -> None:
|
|
34
|
+
"""
|
|
35
|
+
This method initializes the field.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
default (Any): The default value of the field.
|
|
39
|
+
required_lazy (bool): True if the field is required, False otherwise.
|
|
40
|
+
**kwargs (dict): The keyword arguments of the field.
|
|
41
|
+
"""
|
|
42
|
+
super().__init__(default=default, required_lazy=required_lazy, **kwargs)
|
|
43
|
+
|
|
44
|
+
def clean_value(self, value: Any) -> Securities:
|
|
45
|
+
"""
|
|
46
|
+
This method cleans the value of the field.
|
|
47
|
+
|
|
48
|
+
Args:s
|
|
49
|
+
value (Any): The value to be cleaned.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Securities: The cleaned value.
|
|
53
|
+
"""
|
|
54
|
+
if isinstance(value, list):
|
|
55
|
+
value = self.attr_type(value)
|
|
56
|
+
return super().clean_value(value)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
###############################################################################
|
|
60
|
+
# Portfolio Class Implementation
|
|
61
|
+
###############################################################################
|
|
62
|
+
class Portfolio(BaseEntity, metaclass=ScriptMetaClass):
|
|
63
|
+
"""
|
|
64
|
+
This class represents a portfolio entity object and provides methods to validate
|
|
65
|
+
and convert the entity object to a dictionary or a CSV string representation.
|
|
66
|
+
|
|
67
|
+
Attributes:
|
|
68
|
+
script (Script): The script object associated to the entity.
|
|
69
|
+
id (StrField): The unique identifier of the portfolio.
|
|
70
|
+
workspace (EntityWorkspaceField): The workspace of the portfolio.
|
|
71
|
+
name (EntityNameField): The name of the portfolio.
|
|
72
|
+
tags (EntityTagsField): The tags of the portfolio.
|
|
73
|
+
link_uid (EntityLinkUIDField): The link uid of the portfolio.
|
|
74
|
+
description (EntityDescriptionField): The description of the portfolio.
|
|
75
|
+
nlv (FloatField): The nlv of the portfolio.
|
|
76
|
+
base_currency (CurrencyField): The base currency of the portfolio.
|
|
77
|
+
date (EntityDateTimeField): The date of the portfolio.
|
|
78
|
+
securities (SecuritiesField): The securities of the portfolio.
|
|
79
|
+
level (StrField): The level of the portfolio.
|
|
80
|
+
|
|
81
|
+
version (StrField): The version of the portfolio.
|
|
82
|
+
created_on (DateTimeField): The created on date of the portfolio.
|
|
83
|
+
updated_on (DateTimeField): The updated on date of the portfolio.
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
>>> from everysk.sdk.entities.portfolio.base import Portfolio
|
|
87
|
+
>>> portfolio = Portfolio()
|
|
88
|
+
>>> portfolio.workspace = 'my_workspace'
|
|
89
|
+
>>> portfolio.name = 'My Portfolio'
|
|
90
|
+
>>> portfolio.tags = ['tag1', 'tag2']
|
|
91
|
+
>>> portfolio.nlv = 1000.0
|
|
92
|
+
>>> portfolio.base_currency = 'USD'
|
|
93
|
+
>>> portfolio.date = '20210101'
|
|
94
|
+
>>> portfolio.securities = ['sec1', 'sec2', 'sec3']
|
|
95
|
+
>>> portfolio.save()
|
|
96
|
+
>>> print(portfolio)
|
|
97
|
+
{
|
|
98
|
+
'id': 'port_12345678',
|
|
99
|
+
'workspace': 'my_workspace',
|
|
100
|
+
'name': 'My Portfolio',
|
|
101
|
+
'tags': ['tag1', 'tag2'],
|
|
102
|
+
'nlv': 1000.0,
|
|
103
|
+
'base_currency': 'USD',
|
|
104
|
+
'date': '20210101',
|
|
105
|
+
'securities': ['sec1', 'sec2', 'sec3'],
|
|
106
|
+
'version': 'v1',
|
|
107
|
+
'created_on': '2021-01-01T00:00:00.000000Z',
|
|
108
|
+
'updated_on': '2021-01-01T00:00:00.000000Z',
|
|
109
|
+
'level': 'portfolio'
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
script: Script
|
|
114
|
+
_orderable_attributes = ListField(default=['date', 'created_on', 'updated_on', 'name'], readonly=True)
|
|
115
|
+
|
|
116
|
+
id = StrField(regex=settings.PORTFOLIO_ID_REGEX, max_size=settings.PORTFOLIO_ID_MAX_SIZE, required_lazy=True, empty_is_none=True)
|
|
117
|
+
|
|
118
|
+
name = EntityNameField()
|
|
119
|
+
description = EntityDescriptionField()
|
|
120
|
+
tags = EntityTagsField()
|
|
121
|
+
link_uid = EntityLinkUIDField()
|
|
122
|
+
workspace = EntityWorkspaceField()
|
|
123
|
+
|
|
124
|
+
nlv = FloatField(min_size=float('-inf'), max_size=float('inf'))
|
|
125
|
+
base_currency = CurrencyField()
|
|
126
|
+
date = EntityDateTimeField()
|
|
127
|
+
securities = SecuritiesField(min_size=0, max_size=settings.PORTFOLIO_MAX_SIZE, required_lazy=True)
|
|
128
|
+
level = StrField(min_size=1, max_size=settings.PORTFOLIO_LEVEL_MAX_LENGTH)
|
|
129
|
+
|
|
130
|
+
check_securities = BoolField(default=False)
|
|
131
|
+
|
|
132
|
+
###############################################################################
|
|
133
|
+
# Portfolio Basics Implementation
|
|
134
|
+
###############################################################################
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def get_id_prefix() -> str:
|
|
138
|
+
"""
|
|
139
|
+
Returns the prefix of the portfolio id field value.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
str: The prefix of the portfolio id field value.
|
|
143
|
+
|
|
144
|
+
Example:
|
|
145
|
+
>>> Portfolio.get_id_prefix()
|
|
146
|
+
'port_'
|
|
147
|
+
|
|
148
|
+
Notes:
|
|
149
|
+
The prefix is typically used to distinguish portfolio IDs from other types of IDs.
|
|
150
|
+
"""
|
|
151
|
+
return settings.PORTFOLIO_ID_PREFIX
|
|
152
|
+
|
|
153
|
+
def validate(self) -> bool:
|
|
154
|
+
"""
|
|
155
|
+
This method validates the entity object and raises an exception if it is not
|
|
156
|
+
valid. The validation is performed by calling the `validate` method of each field
|
|
157
|
+
of the entity.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
self (Self): The entity object to be validated.
|
|
161
|
+
|
|
162
|
+
Raises:
|
|
163
|
+
FieldValueError: If the entity object is not valid.
|
|
164
|
+
RequiredFieldError: If a required field is missing.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
bool: True if the entity object is valid, False otherwise.
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
>>> entity = Entity()
|
|
171
|
+
>>> entity.validate()
|
|
172
|
+
True
|
|
173
|
+
"""
|
|
174
|
+
return self.get_response(self_obj=self)
|
|
175
|
+
|
|
176
|
+
def to_csv(self) -> str:
|
|
177
|
+
"""
|
|
178
|
+
This method converts the entity object into a CSV string representation of the
|
|
179
|
+
entity object.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
str: A CSV string representation of the entity.
|
|
183
|
+
|
|
184
|
+
Example:
|
|
185
|
+
>>> entity = Entity()
|
|
186
|
+
>>> entity.to_csv()
|
|
187
|
+
"name,date,base_currency,nlv,description,tags,securities
|
|
188
|
+
My Portfolio,2021-01-01,USD,1000.0,My Portfolio Description,tag1 tag2,sec1,sec2,sec3"
|
|
189
|
+
"""
|
|
190
|
+
def write_row(csv_writer_: Any, line: list[str], length: int) -> None:
|
|
191
|
+
"""
|
|
192
|
+
Write a row to a CSV file
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
csv_writer_ (Any): CSV writer object to use for writing the row
|
|
196
|
+
line (list[str]): The list of values to write as a row
|
|
197
|
+
length (int): The desired length of the row
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
None
|
|
201
|
+
|
|
202
|
+
Example:
|
|
203
|
+
>>> from everysk.sdk.entities.portfolio.base import Portfolio
|
|
204
|
+
>>> import csv
|
|
205
|
+
>>> csv_file = open('output'.csv', 'w', newline='')
|
|
206
|
+
>>> write = csv.writer(csv_file)
|
|
207
|
+
>>> Portfolio.write_row(writer, ['value1', 'value2'], 5)
|
|
208
|
+
>>> csv_file.close()
|
|
209
|
+
|
|
210
|
+
Notes:
|
|
211
|
+
This function pads the row with empty strings to ensure the fixed length.
|
|
212
|
+
"""
|
|
213
|
+
out: list[str] = line + ([''] * (length - len(line)))
|
|
214
|
+
out = [to_string(s) if s is not None else None for s in out]
|
|
215
|
+
csv_writer_.writerow(out)
|
|
216
|
+
return None
|
|
217
|
+
|
|
218
|
+
csv_file: StringIO = six.StringIO()
|
|
219
|
+
csv_writer: Any = csv.writer(csv_file)
|
|
220
|
+
|
|
221
|
+
date_: str = self.date.strftime()
|
|
222
|
+
nlv_: str = '' if not self.nlv else to_string(self.nlv)
|
|
223
|
+
pre_headers: list[str] = [self.name, date_, self.base_currency, nlv_, self.description, ' '.join(self.tags)]
|
|
224
|
+
|
|
225
|
+
securities_as_lists: list[list[str]] = self.securities.to_lists()
|
|
226
|
+
|
|
227
|
+
headers: list[str] = securities_as_lists[0]
|
|
228
|
+
headers_len: int = len(headers)
|
|
229
|
+
write_row(csv_writer, pre_headers, headers_len)
|
|
230
|
+
write_row(csv_writer, headers, headers_len)
|
|
231
|
+
|
|
232
|
+
for sec_as_list in securities_as_lists[1:]:
|
|
233
|
+
write_row(csv_writer, sec_as_list, headers_len)
|
|
234
|
+
|
|
235
|
+
out: str = csv_file.getvalue()
|
|
236
|
+
csv_file.close()
|
|
237
|
+
return out
|
|
238
|
+
|
|
239
|
+
def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
|
|
240
|
+
"""
|
|
241
|
+
This method is used to convert the object to a dictionary.
|
|
242
|
+
"""
|
|
243
|
+
dct: dict = super().to_dict(add_class_path=add_class_path, recursion=recursion)
|
|
244
|
+
|
|
245
|
+
if isinstance(dct['securities'], Securities):
|
|
246
|
+
dct['securities'] = dct['securities'].to_list(add_class_path=add_class_path, recursion=recursion)
|
|
247
|
+
|
|
248
|
+
return dct
|
|
@@ -0,0 +1,241 @@
|
|
|
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 Any, Self
|
|
12
|
+
|
|
13
|
+
from everysk.core.exceptions import FieldValueError, HttpError, SDKError
|
|
14
|
+
from everysk.core.http import HttpSDKPOSTConnection
|
|
15
|
+
from everysk.core.object import BaseDict
|
|
16
|
+
from everysk.sdk.entities.base_list import EntityList
|
|
17
|
+
from everysk.sdk.entities.portfolio.security import Security
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
###############################################################################
|
|
21
|
+
# Securities Class Implementation
|
|
22
|
+
###############################################################################
|
|
23
|
+
class Securities(EntityList):
|
|
24
|
+
_attr_type: Security = Security
|
|
25
|
+
|
|
26
|
+
def _validate(self, value: dict) -> Security:
|
|
27
|
+
"""
|
|
28
|
+
Validates a dictionary value and converts it into a `Security` object.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
value (dict): A dictionary representing the security data.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Security: A `Security` object created from the provided dictionary.
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
FieldValueError: If the provided value is not a valid dictionary.
|
|
38
|
+
TypeError: If the provided value is not of dictionary type.
|
|
39
|
+
|
|
40
|
+
Example:
|
|
41
|
+
>>> from my_module import Security
|
|
42
|
+
>>> security_data = {'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 150.0}
|
|
43
|
+
>>> validated_security = self._validate(security_data)
|
|
44
|
+
>>> isinstance(validated_security, Security)
|
|
45
|
+
True
|
|
46
|
+
"""
|
|
47
|
+
if not isinstance(value, (dict, BaseDict)):
|
|
48
|
+
raise FieldValueError(f'Security: The value must be a dict or BaseDict. {type(value)}') from TypeError
|
|
49
|
+
return self._attr_type(**value)
|
|
50
|
+
|
|
51
|
+
def validate(self) -> bool:
|
|
52
|
+
"""
|
|
53
|
+
Validates the required fields of each security in the collection.
|
|
54
|
+
|
|
55
|
+
This method iterates through the collection of securities and calls the
|
|
56
|
+
`validate_required_fields` method for each security to ensure that all
|
|
57
|
+
required fields are present and have valid values.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
bool: True if validation succeeds for all securities, otherwise False.
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
FieldValueError: If the collection of securities is empty.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> from everysk.sdk.entities.portfolio.securities import Securities
|
|
67
|
+
>>> security_data = [{'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 150.0},
|
|
68
|
+
... {'symbol': 'GOOGL', 'name': 'Alphabet Inc.', 'price': 2800.0}]
|
|
69
|
+
>>> security_collection = Securities(security_data)
|
|
70
|
+
>>> security_collection.validate()
|
|
71
|
+
True
|
|
72
|
+
"""
|
|
73
|
+
if len(self) == 0:
|
|
74
|
+
raise FieldValueError('The quantity of securities cannot be zero.')
|
|
75
|
+
|
|
76
|
+
for security in self:
|
|
77
|
+
security.validate_required_fields()
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def from_lists(security_list: list[list[Any]]) -> Self:
|
|
82
|
+
"""
|
|
83
|
+
Create a Securities collection from a list of lists representing securities.
|
|
84
|
+
|
|
85
|
+
This static method takes a list of lists where each inner list represents a security.
|
|
86
|
+
The first inner list (header) is used to extract attribute names, and the subsequent
|
|
87
|
+
lists are used to create individual `Security` objects within a `Securities` collection.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
security_list (list[list[Any]]): A list of lists where each inner list represents a security.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Self: A `Securities` collection containing `Security` objects created from the provided data.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
>>> from everysk.sdk.entities.portfolio.securities import Securities
|
|
97
|
+
>>> security_data = [
|
|
98
|
+
... ['symbol', 'name', 'price'],
|
|
99
|
+
... ['AAPL', 'Apple Inc.', 150.0],
|
|
100
|
+
... ['GOOGL', 'Alphabet Inc.', 2800.0]
|
|
101
|
+
... ]
|
|
102
|
+
>>> securities_collection = Securities.from_lists(security_data)
|
|
103
|
+
>>> len(securities_collection)
|
|
104
|
+
2
|
|
105
|
+
"""
|
|
106
|
+
header: list[str] = security_list.pop(0)
|
|
107
|
+
return Securities([Securities._attr_type.from_list(sec_as_list, header) for sec_as_list in security_list])
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def diff(securities_a: list[dict], securities_b: list[dict], accessor: str = 'comparable') -> dict:
|
|
111
|
+
"""
|
|
112
|
+
Diff two securities list. The securities list are compared by the
|
|
113
|
+
accessor provided. The accessor is used to compare the securities
|
|
114
|
+
list. The accessor must be a key in the securities list.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
securities_a (Securities): Securities list to compare.
|
|
118
|
+
securities_b (Securities): Securities list to compare.
|
|
119
|
+
accessor (str): Accessor to compare.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
dict: Diff result.
|
|
123
|
+
Keys:
|
|
124
|
+
added_positions (Securities): Added positions.
|
|
125
|
+
removed_positions (Securities): Removed positions.
|
|
126
|
+
partial_positions (Securities): Partial positions.
|
|
127
|
+
equal_positions (Securities): Equal positions.
|
|
128
|
+
"""
|
|
129
|
+
try:
|
|
130
|
+
response: dict = HttpSDKPOSTConnection(
|
|
131
|
+
cls_name='Securities',
|
|
132
|
+
params={'securities_a': securities_a, 'securities_b': securities_b, 'accessor': accessor},
|
|
133
|
+
).get_response_decode()
|
|
134
|
+
except HttpError as error:
|
|
135
|
+
raise SDKError(error.msg) from error
|
|
136
|
+
|
|
137
|
+
return response
|
|
138
|
+
|
|
139
|
+
def consolidate(self, consolidation_keys) -> Self:
|
|
140
|
+
"""
|
|
141
|
+
Consolidate securities list. If no consolidation keys are provided,
|
|
142
|
+
the securities list is returned as is. Otherwise, the securities list
|
|
143
|
+
is consolidated by the provided keys.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
consolidation_keys (List[str]): List of keys to consolidate
|
|
147
|
+
by (e.g. ['symbol', 'instrument_class']). If no keys are provided,
|
|
148
|
+
the securities list is returned as is.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
Securities: Consolidated securities list.
|
|
152
|
+
"""
|
|
153
|
+
try:
|
|
154
|
+
response: dict = HttpSDKPOSTConnection(
|
|
155
|
+
cls_name='Securities', params={'consolidation_keys': consolidation_keys}
|
|
156
|
+
).get_response_decode()
|
|
157
|
+
except HttpError as error:
|
|
158
|
+
raise SDKError(error.msg) from error
|
|
159
|
+
|
|
160
|
+
return type(self)(**response)
|
|
161
|
+
|
|
162
|
+
def remove_errors(self) -> Self:
|
|
163
|
+
"""
|
|
164
|
+
Create a new Securities collection with securities having a status other than 'ERROR'.
|
|
165
|
+
|
|
166
|
+
This method filters the current Securities collection, creating a new collection that
|
|
167
|
+
includes only securities with a status attribute other than 'ERROR'.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Self: A new Securities collection containing securities without the 'ERROR' status.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
>>> from everysk.sdk.entities.portfolio.securities import Securities
|
|
174
|
+
>>> security_data = [{'symbol': 'AAPL', 'status': 'OK'},
|
|
175
|
+
... {'symbol': 'GOOGL', 'status': 'ERROR'},
|
|
176
|
+
... {'symbol': 'MSFT', 'status': 'OK'}]
|
|
177
|
+
>>> securities_collection = Securities(security_data)
|
|
178
|
+
>>> filtered_securities = securities_collection.remove_errors()
|
|
179
|
+
>>> len(filtered_securities)
|
|
180
|
+
2
|
|
181
|
+
"""
|
|
182
|
+
return Securities([security for security in self if security.status != 'ERROR'])
|
|
183
|
+
|
|
184
|
+
def to_lists(self, header: list[str] = None) -> list[list[Any]]:
|
|
185
|
+
"""
|
|
186
|
+
Convert the Securities collection to a list of lists.
|
|
187
|
+
|
|
188
|
+
This method converts each `Security` object in the collection to a list representation.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
header (list[str], optional): A list of strings representing the header row. If not provided,
|
|
192
|
+
the method will create a header based on the keys of the first security in the collection.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
list[list[Any]]: A list of lists representing the securities in the collection, including the header.
|
|
196
|
+
|
|
197
|
+
Example:
|
|
198
|
+
>>> from everysk.sdk.entities.portfolio.securities import Securities
|
|
199
|
+
>>> security_data = [{'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 150.0},
|
|
200
|
+
... {'symbol': 'GOOGL', 'name': 'Alphabet Inc.', 'price': 2800.0}]
|
|
201
|
+
>>> securities_collection = Securities(securities=security_data)
|
|
202
|
+
>>> securities_list = securities_collection.to_lists()
|
|
203
|
+
>>> len(securities_list)
|
|
204
|
+
3 # Including the header row
|
|
205
|
+
"""
|
|
206
|
+
if header is None:
|
|
207
|
+
first_security: Security = self[0]
|
|
208
|
+
extra_data: dict = first_security.get('extra_data') or {}
|
|
209
|
+
header = list(first_security.keys()) + list(extra_data.keys())
|
|
210
|
+
header = self._attr_type.sort_header(header)
|
|
211
|
+
|
|
212
|
+
security_list: list[list[Any]] = [security.to_list(header=header) for security in self]
|
|
213
|
+
security_list.insert(0, header)
|
|
214
|
+
|
|
215
|
+
return security_list
|
|
216
|
+
|
|
217
|
+
def to_list(self, add_class_path: bool = False, recursion: bool = False) -> list[dict]:
|
|
218
|
+
"""
|
|
219
|
+
This method converts each `Security` object in the collection to a dictionary representation.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
with_internals (bool, optional): Indicates whether to include internal attributes in the dictionaries.
|
|
223
|
+
Defaults to True.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
list[dict]: A list of dictionaries representing the securities in the collection.
|
|
227
|
+
|
|
228
|
+
Example:
|
|
229
|
+
>>> from everysk.sdk.entities.portfolio.securities import Securities
|
|
230
|
+
>>> security_data = [{'symbol': 'AAPL', 'name': 'Apple Inc.', 'price': 150.0},
|
|
231
|
+
... {'symbol': 'GOOGL', 'name': 'Alphabet Inc.', 'price': 2800.0}]
|
|
232
|
+
>>> securities_collection = Securities(security_data)
|
|
233
|
+
>>> securities_dict = securities_collection.to_list()
|
|
234
|
+
>>> len(securities_dict)
|
|
235
|
+
2
|
|
236
|
+
"""
|
|
237
|
+
return [
|
|
238
|
+
security.to_dict(add_class_path=add_class_path, recursion=recursion)
|
|
239
|
+
for security in self
|
|
240
|
+
if hasattr(security, 'to_dict')
|
|
241
|
+
]
|