Entities
Entities are the main building blocks of the Everysk SDK. They are the objects that you will interact with to create, read, update, and delete data in the Everysk platform. The SDK provides a set of classes that represent the main entities in the platform, such as Portfolio, Security, Datastore, File, Report, CustomIndex, and PrivateSecurity.
Base Entity¶
The BaseEntity class is the foundation that all Everysk entities build upon. Every entity — Custom Index, Datastore, File, Portfolio, Private Security, Report, Secrets, Worker Execution, Workflow Execution, and Workspace — inherits from it, gaining a shared set of methods for creation, retrieval, modification, deletion, cloning, and querying.
Lets take a look a them below.
Create¶
Use create() to persist a new entity. Pass a dictionary with the entity's attributes and get back the created instance:
from everysk.sdk.entities import Portfolio
portfolio = Portfolio.create({
'name': 'My Portfolio',
'workspace': 'main',
'date': '20210622',
'securities': [
{'id': 'id1', 'symbol': 'AAPL', 'quantity': 1000.0},
{'id': 'id2', 'symbol': 'MSFT', 'quantity': 500.0},
],
})
portfolio.id
# 'port_V7xU8dwCMnJIuyUPHJPx2ynuz'
Retrieve¶
Use retrieve() to fetch an existing entity by its ID. Returns the entity instance, or None if not found:
portfolio = Portfolio.retrieve('port_V7xU8dwCMnJIuyUPHJPx2ynuz')
portfolio.name
# 'My Portfolio'
portfolio.date
# '20210622'
Modify¶
Use modify() to update an existing entity. Pass the entity ID and a dictionary of fields to overwrite. Returns the updated instance, or None if not found:
portfolio = Portfolio.modify(
'port_V7xU8dwCMnJIuyUPHJPx2ynuz',
{
'name': 'My Updated Portfolio',
'securities': [
{'id': 'id3', 'symbol': 'GOOGL', 'quantity': 300.0},
],
},
)
portfolio.name
# 'My Updated Portfolio'
Remove¶
Use remove() to permanently delete an entity by its ID. Returns the deleted instance, or None if not found:
deleted = Portfolio.remove('port_V7xU8dwCMnJIuyUPHJPx2ynuz')
deleted.id
# 'port_V7xU8dwCMnJIuyUPHJPx2ynuz'
Delete¶
Use delete() to permanently delete an entity instance directly, without needing its ID separately:
Remove Many¶
Use remove_many() to permanently delete multiple entities in bulk by passing a list of IDs:
Script API¶
The script interface provides lower-level methods used to fetch and persist entities within worker contexts. Each entity class exposes a script attribute with the following methods:
fetch¶
Fetches a single entity by query, variant, and workspace. Returns the entity instance or None if not found:
datastore = Datastore.script.fetch('dats_abc123', 'id', 'main')
# fetch by tag (latest)
datastore = Datastore.script.fetch('my-tag', 'tagLatest', 'main')
# fetch by link_uid (latest)
portfolio = Portfolio.script.fetch('my-link', 'linkLatest', 'main')
fetch_list¶
Fetches a list of entities by query, variant, and workspace:
fetch_multi¶
Fetches multiple entities at once using separate lists of queries, variants, and workspaces. Useful when each entity may come from a different workspace or use a different lookup variant:
datastores = Datastore.script.fetch_multi(
['dats_abc123', 'dats_def456'],
['id', 'id'],
['workspace_a', 'workspace_b'],
)
storage¶
Persists an entity according to the provided storage_settings. This is the standard way to save an entity inside a worker after building or modifying it:
storage_settings = BaseMapping(mode='create') # or 'update', 'transient'
datastore = Datastore.script.storage(datastore, storage_settings)
Now that we've seen the shared CRUD interface, let's take a closer look at each entity individually — their specific attributes, behaviors, and usage patterns.
Custom Index¶
A custom index is a proprietary vector of date-value tuples. It can represent a proprietary benchmark, a risk factor, a proxy or any other measure. Even when persisted to your account, it is only available to the account. Custom Indexes are not bind to a workspace, meaning that they can be used globally, no matter the workspace.
We can start using the Custom Index entity by running the following import statement:
-
symbol: Refers to the symbol of the custom index. Unique to the user account, starts with the prefix CUSTOM:. -
name: The name of the custom index. -
description: The description of the custom index. -
tags: The tags of the custom index. -
periodicity: The periodicity of the custom index. -
currency: The currency of the custom index. -
base_price: The base price of the custom index. -
data_type: The data type of the custom index.
Instantiating a Custom Index Entity¶
Below let's instantiate a Custom Index entity and set the most common attributes used:
custom_index = CustomIndex()
custom_index.symbol = 'CUSTOM:INDEX'
custom_index.name = 'Custom Index'
custom_index.description = 'Description'
custom_index.tags = ['tag1', 'tag2']
custom_index.version = '1.0'
custom_index.periodicity = 'M'
custom_index.currency = 'USD'
custom_index.base_price = 1000
custom_index.data_type = 'PRICE'
custom_index.data = [[1, 2, 3], [4, 5, 6]]
Convert Custom Index to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
custom_index = CustomIndex()
type(custom_index)
everysk.sdk.entities.custom_index.base.CustomIndex
to_dict = custom_index.to_dict()
type(to_dict)
dict
Validating a Custom Index Entity¶
For validating a Custom Index entity, we can make use of the validate() method, which will either return a boolean value or raise an exception in the case of an invalid entity, let's use our previous instantiated entity:
If somehow the entity were to be invalid, the validate() method would raise an exception along with the error message indicating the issue.
custom_index = CustomIndex()
custom_index.id = 'invalid id'
FieldValueError: The value 'invalid id' for field 'symbol' must match with this regex: ^CUSTOM:[A-Z0-9_]*$.
Datastore¶
Datastores are fully integrated repositories to manage and persist data. They can record data calculated by Everysk’s servers, proprietary data from the client or both. The most common usage is the storage of securities as rows and related properties as columns, but there are no constraints on the usage. They enable powerful data explorations and trend analysis to be performed.
The Datastore entity is kept under the following import statement:
Below we have the most common attributes used in the Datastore entity:
-
name: The name of the Datastore entity. -
tags: The tags of the datastore. -
description: The current description of the datastore. -
workspace: Which workspace will the Datastore entity reside. -
date: The date of the datastore. -
data: The data associated with the current datastore. -
level: The level of the datastore.
Instantiating a Datastore Entity and Passing Attributes¶
To instantiate a Datastore entity, we can use the following code snippet:
Now we can manually set the class attributes in order to properly configure our Datastore entity.
datastore.name = 'SampleDatastore'
datastore.tags = ['tag1', 'tag2']
datastore.description = 'Description'
datastore.workspace = 'SampleWorkspace'
datastore.date = DateTime(2023, 9, 9, 9, 9, 9, 9)
datastore.data = 'data'
datastore.level = 1
Convert Datastore to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
datastore = Datastore()
type(datastore)
everysk.sdk.entities.datastore.base.Datastore
to_dict = datastore.to_dict()
type(to_dict)
dict
Validating a Datastore Entity¶
The validate() method from the Datastore entity is used as a lazy validation method in order to check if the entity is valid or not by returning a boolean value:
In the case of an invalid entity, meaning that some field is missing or has an invalid value, the validate() method will raise a FieldValueError:
datastore = Datastore()
datastore.id = 'invalid_id'
FieldValueError: The value 'invalid_id' for field 'id' must match with this regex: ^dats_[a-zA-Z0-9].
File¶
A file is a collection of data stored in one unit, identified by a filename. It can be a document, picture, data library, binary data, or any other collection of data.
In order to work with the File entity we will be using the following import throughout the examples:
Below we have all the required attributes associated with the File Entity
-
name: The name of the File entity -
tags: The tags of the file. -
description: The current description of the file. -
workspace: Which workspace will the File entity reside. -
date: The date of the file. -
data: The data of the file in base64 format. -
content_type: Refers to the media type of the file. -
url: The URL which the file will reside.
Creating a File Entity¶
For creating a brand new File entity we can simply instantiate the class and passing our desired arguments:
file = File()
file.name = 'SampleFile'
file.tags = ['tag1', 'tag2']
file.description = 'Description'
file.workspace = 'SampleWorkspace'
file.date = '20230909'
file.data = 'data'
file.content_type = 'text/plain'
file.url = '/filehttps://example.com'
Convert File Entity to Dictionary¶
For converting a File entity to a python dictionary, we can make use of the to_dict() method, let's see that in practice by using our previously created File entity:
file = File()
type(file)
everysk.sdk.entities.file.base.File
to_dict = file.to_dict(file)
type(to_dict)
dict
Validate the File Entity¶
The validate() method from the File entity is used as a lazy validation method in order to check if the entity is valid or not by returning a boolean value:
In the case of an invalid entity, the validate() method will raise a FieldValueError in the case of an invalid entity or a RequiredFieldError in the case of a missing required field.
Portfolio¶
A portfolio is a collection of financial investments like stocks, bonds, derivatives, commodities, cash, and cash equivalents. Each security can be traded in a specific local currency. The portfolio has a base currency that is required to reflect each FX risk.
We can start using the Portfolio entity by running the following import statement:
Below we have the attributes used in the Portfolio entity
-
workspace: Refers to the workspace which the Portfolio entity will reside. -
name: The name of the portfolio. -
tags: The tags of the portfolio. Used for filtering and searching -
nlv: The NLV for the portfolio. -
base_currency: Which currency will be used as the standard. -
date: The current date of the portfolio. -
securities: The securities of the portfolio. Generally comes in a list format filled with dictionaries inside of typeSecurities.
Convert Portfolio to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
port = Portfolio()
type(port)
everysk.sdk.entities.portfolio.base.Portfolio
to_dict = port.to_dict()
type(to_dict)
dict
Convert Portfolio to a CSV¶
Another useful conversion for our Portfolio entity, is the ability to convert it to a CSV type using the to_csv() method:
For demonstration purposes let's grab some sample data for instantiating our Portfolio entity:
portfolio_data = {
'id': 'port_1234567891011211234567890',
'workspace': 'SampleWorkspace',
'name': 'SamplePortfolio',
'tags': ['tag1', 'tag2'],
'link_uid': 'ABC',
'description': 'Description',
'nlv': 1000.0,
'base_currency': 'USD',
'date': DateTime(2023, 9, 9, 9, 9, 9, 9),
'securities': Securities([{'symbol': 'AAPL'}]),
'version': '1.0',
'created_on': DateTime(2023, 9, 9, 9, 9, 9, 9),
'updated_on': DateTime(2023, 9, 9, 9, 9, 9, 9),
'level': 'v1',
'outstanding_shares': 1000,
'source_hash': 'XYZ',
'status': 'OK',
'portfolio_uid': 'UID123',
'check_securities': False
}
Now let's use the data above in our Portfolio:
port = Portfolio(**portfolio_data)
to_csv = port.to_csv()
type(to_csv)
to_csv
'SamplePortfolio,20230909 09:09:09,USD,1000.0,Description,tag1 tag2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\r\nstatus,id,symbol,quantity,instrument_class,ticker,label,name,isin '
As seen above we have our portfolio entity converted to a CSV format, ready to be used.
Validate the entity¶
Before actually using the entity we may want to validate its arguments using the validate() method, otherwise we might get unwanted behavior when using:
In the case of something going wrong, the method will point out the invalid field. Let's see how that works in practice by setting an invalid value for the securities attribute:
port = Portfolio()
port.securities = 'Invalid'
FieldValueError: Key securities mus be <class 'everysk.sdk.entities.portfolio.securities.Securities'>.
Private Security¶
The "Private Security" entity allows for the customized registration of fixed income instruments, covering data such as issue date, maturity, issue price, and the calculation method (SELIC, IPCA, Private). This enables the creation or simulation of private assets, adjusting various specific characteristics.
To start using the Private Security entity, run the following import statement:
Below we have the most common attributes used in the Private Security entity:
-
symbol: The symbol of the private security. The symbol attribute is prefixed with the stringPRIVATE:. -
name: The name of the private security. -
tags: The tags of the private security. Used for filtering and searching. -
description: The description of the private security. -
currency: The currency of the private security. -
data: The data contained inside the private security. -
instrument_type: The type of instrument of the private security.
Creating a Private Security Entity¶
To create a new Private Security entity, we can use the following code snippet, where we manually set the attributes:
private_security = PrivateSecurity()
private_security.symbol = 'PRIVATE:ABC'
private_security.name = 'ABC Private Security'
private_security.tags = ['tag1', 'tag2']
private_security.description = 'This is a private security'
private_security.currency = 'USD'
private_security.data = {'key1': 'value1', 'key2': 'value2'}
private_security.instrument_type = 'EQUITY'
Validate Private Security Entity¶
To validate the Private Security entity, we can use the validate() method, in the case of getting an invalid entity, the method will raise either a FieldValueError or a RequiredFieldError depending on the case.
Below we have an example of a FieldValueError exception:
private_security = PrivateSecurity()
private_security.symbol = '123'
The value "123" for field "symbol" must match this regex: ^PRIVATE:[A-Z0-9_]*$.
Convert Private Security to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
private_security = PrivateSecurity()
type(private_security)
everysk.sdk.entities.private_security.base.PrivateSecurity
to_dict = private_security.to_dict()
type(to_dict)
dict
Query¶
The Query class allows you to build and execute queries to retrieve entities from the data source based on specific conditions. A query can return a single entity, a list of entities, or a paginated set.
Every entity also exposes a .query shortcut that returns a pre-configured Query instance for that entity type:
Attributes¶
Below are the attributes available on a Query instance:
-
filters: The list of filter conditions added viawhere(). -
order: The list of properties by which to sort the results. -
projection: The list of properties to include or exclude in the result. -
distinct_on: The list of properties for which the resulting entities should be distinct. -
limit: The maximum number of entities to retrieve. -
offset: The number of initial entities to skip before starting retrieval. -
page_size: The number of entities to retrieve per page. -
page_token: The token representing the desired page of results.
Building a Query¶
Instantiate a Query by passing the entity class you want to query:
All builder methods return self, so they can be chained:
where¶
The where() method adds a filter condition to the query. It accepts either two arguments (property, value) — in which case = is assumed as the operator — or three arguments (property, operator, value):
query = Query(Portfolio)
query.where('name', 'My Portfolio')
# equivalent to:
query.where('name', '=', 'My Portfolio')
Supported operators are =, <, <=, >, >=, and IN.
Filtering by date — when the operator is =, a full-day range is created automatically:
query = Query(Portfolio)
query.where('date', '=', '2023-08-10')
# expands to: date >= 2023-08-10 00:00:00 AND date <= 2023-08-10 23:59:59
Filtering by tags — pass a single string or a list of strings:
Filtering by a list — use the IN operator with a list of values:
from everysk.sdk.entities import File
query = Query(File)
query.where('content_type', 'IN', ['text/csv', 'application/pdf'])
Filtering by link_uid — filter by a single value or multiple values using IN:
query = Query(Portfolio)
query.where('link_uid', 'my-link-uid')
# match any of several link UIDs
query = Query(Portfolio)
query.where('link_uid', 'IN', ['link-a', 'link-b'])
Passing an unsupported operator raises an SDKValueError:
sort_by¶
The sort_by() method adds a property to the sort order. Prefix the property name with - for descending order:
Adding a property that is not sortable or that has already been added raises a ValueError:
query.sort_by('invalid_property')
# ValueError: invalid_property is not sortable
query.sort_by('date')
# ValueError: Duplicated order property: date in ['date']
set_projection¶
The set_projection() method specifies which properties to include or exclude from the result. Pass a string or a list of strings. Prefix a property name with - to exclude it (inverse projection):
# Include only name and date
query = Query(Portfolio)
query.set_projection(['name', 'date'])
# Exclude date
query.set_projection(['-date'])
Mixing inclusion and exclusion in the same call raises a ValueError:
query.set_projection(['name', '-date'])
# ValueError: Projection and Inverse Projection should not be set in the same query
set_distinct_on¶
The set_distinct_on() method specifies the properties for which the resulting entities should be distinct. Pass a string or a list of strings:
set_limit¶
Sets the maximum number of entities the query should return:
The value must be an integer greater than or equal to 0, otherwise an SDKValueError is raised.
set_offset¶
Sets the number of initial entities to skip before retrieval begins:
The value must be an integer greater than or equal to 0, otherwise an SDKValueError is raised.
set_page_size¶
Sets the number of entities to retrieve per page in a paginated query:
The value must be an integer greater than or equal to 0, otherwise an SDKValueError is raised.
set_page_token¶
Sets the page token to resume from a specific page:
set_find_or_fail¶
When set to True, the query raises an error if no entity is found instead of returning None:
load¶
Fetches a single entity matching the query. Returns the entity instance or None if nothing is found. An optional offset can be passed to skip results:
portfolio = Query(Portfolio).where('name', 'My Portfolio').load()
portfolio.name
# 'My Portfolio'
# Skip the first result and return the second match
portfolio = Query(Portfolio).where('name', 'My Portfolio').load(offset=1)
loads¶
Fetches a list of entities matching the query. Returns an empty list if nothing is found. Optional limit and offset parameters control the result set:
portfolios = Query(Portfolio).where('tags', 'equity').loads()
# [<Portfolio ...>, <Portfolio ...>, ...]
# Fetch up to 2 results, skipping the first
portfolios = Query(Portfolio).where('tags', 'equity').loads(limit=2, offset=1)
page¶
Fetches a single page of entities. Returns a QueryPage dictionary with entities and next_page_token keys:
result = Query(Portfolio).page(page_size=10)
len(result['entities'])
# up to 10 — depends on available data
result['next_page_token']
# 'eyJvZmZzZXQiOiAxMH0=' (None if this is the last page)
Pass the token from the previous response to retrieve the next page:
pages¶
A generator that iterates over all pages automatically. Yields one list of entities per page until no more pages are available:
for page in Query(Portfolio).where('tags', 'equity').pages(page_size=10):
for portfolio in page:
print(portfolio.name)
fetch_ids¶
Fetches only the IDs of matching entities instead of full entity objects. Optional limit and offset parameters are supported:
ids = Query(Portfolio).where('tags', 'equity').fetch_ids()
# ['port_abc123', 'port_def456', ...]
ids = Query(Portfolio).fetch_ids(limit=5, offset=10)
fetch_id¶
Fetches the ID of a single matching entity. Returns the ID string or None if nothing is found. An optional offset can be provided:
entity_id = Query(Portfolio).where('name', 'My Portfolio').fetch_id()
# 'port_abc123'
entity_id = Query(Portfolio).where('name', 'My Portfolio').fetch_id(offset=1)
Report¶
Interactive dashboards that present portfolio analytics information in an intuitive and explorable way. Reports represent a specific portfolio and date so that they can be referenced in the future.
We can start using the Report entity by running the following import statement:
Below we have the most common class attributes used in the Report entity:
-
script: The script used to generate the report. -
name: The name of the report. -
description: The description of the report. -
tags: The tags associated with the report. -
workspace: The workspace where the report is stored. -
date: The date the report was created. -
widgets: The widgets associated with the report. -
url: The URL of the report. -
authorization: The type of authorization in the report. -
config_cascaded: The different configurations in the report. -
layout_content: How the layout of the content will be structured.
Instantiating a Report Entity¶
Below we have a code segment demonstrating how to instantiate a Report entity and set its class attributes:
report = Report()
report.script = 'my_script'
report.name = 'My Report'
report.description = 'This is a report'
report.tags = ['tag1', 'tag2']
report.workspace = 'my_workspace'
report.date = '20210101'
report.widgets = [{'type': 'chart', 'data': {...}}, {'type': 'table', 'data': {...}}]
report.url = '/my_report_url'
report.authorization = 'private'
report.config_cascaded = {'config1': 'value1', 'config2': 'value2'}
report.layout_content = {'section1': {...}, 'section2': {...}}
Converting Report to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
report = Report()
type(report)
everysk.sdk.entities.report.base.Report
to_dict = report.to_dict()
type(to_dict)
dict
Tags¶
You can start using the Tags entity by running the following import statement:
Below we have the most common attributes used in the Tags entity:
min_size: The minimum size of each individual tag. Default is 1.
max_size: The maximum size of each individual tag. Default is 252.
Creating a Tag instance¶
For creating a new Tag instance and starting using, we can use the following piece of code:
Min Size¶
The min_size attribute is used to set the minimum size of each individual tag. By default, the minimum size is 1. If we want to change it, we can do it as follows:
Let's try to add a tag with less than 2 characters:
Max Size¶
The max_size attribute is used to set the maximum size of each individual tag. By default, the maximum size is 252. If we want to change it, we can do it as follows:
Let's try to add a tag with more than 5 characters:
Now, let's understand below the append() method along with a few other methods that can be used to manipulate the tags.
Adding new tags¶
The append() method is used in order to add new tags to our tag instance:
Keep in mind that the append() method only accepts a single tag as an argument, which can be a string, integer, or float. If you want to add multiple tags at once, you can use the extend() method.
Extending tags¶
There is also the possibility of adding multiple tags at once on a list format by using the extend method:
Inserting a tag at some index¶
To add a specific tag at a certain index, we can make use of the insert method:
Lets continue with our previous tag instance, now let's say that we want to add a new tag at the beginning of our tags list:
Unifying Tags¶
The unify() static method merges two tag sources — typically an overwrite value and an existing entity's tags — into a single Tags instance. If the overwrite is provided it takes precedence; otherwise the existing tags are kept:
existing_tags = Tags(['equity', 'risk'])
overwrite_tags = Tags(['bond'])
Tags.unify(overwrite_tags, existing_tags)
# Tags(['bond'])
# When overwrite is empty, existing tags are preserved
Tags.unify(Tags(), existing_tags)
# Tags(['equity', 'risk'])
This is the standard pattern used by modifier workers when applying partial updates to an entity's tags.
Secrets Entity¶
The Secrets entity is kept under the following import statement:
Attributes¶
Below we have the most common attributes used in the Secrets entity:
-
id: The unique identifier of the Secrets entity. Follows the formatsec_<value>. -
name: The name of the secrets entity. -
description: The current description of the secrets entity. -
data: A dictionary containing the secret values. This field is required and must be a non-empty dictionary.
Instantiating a Secrets Entity and Passing Attributes¶
To instantiate a Secrets entity, we can use the following code snippet:
Now we can manually set the class attributes in order to properly configure our Secrets entity.
secrets.name = 'api-keys'
secrets.description = 'Third-party API credentials'
secrets.data = {'v1': {'openai': 'sk-abc123', 'stripe': 'sk-live-xyz'}}
Retrieving a Value by Path¶
The Secrets entity provides a class method value_from_path() that allows retrieving a specific value using a dot-notation path. The path must start with a valid secret id, followed by one or more keys separated by dots.
If the path format is invalid or the secret ID does not match the expected format, a ValueError is raised:
Secrets.value_from_path('invalid-path')
ValueError: Invalid path format. Expected format: "<secret_id>.<key1>.<key2>..."
Convert Secrets to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
secrets = Secrets()
type(secrets)
everysk.sdk.entities.secrets.base.Secrets
to_dict = secrets.to_dict()
type(to_dict)
dict
Validating a Secrets Entity¶
The validate() method from the Secrets entity is used as a lazy validation method in order to check if the entity is valid or not by returning a boolean value:
In the case of an invalid entity, meaning that some field is missing or has an invalid value, the validate() method will raise a FieldValueError:
Securities Entity¶
The Securities entity is a typed list of Security objects. It is the standard container used to hold a portfolio's positions and provides methods for validation, transformation, and comparison.
Creating a Securities Collection¶
Pass a list of dictionaries or Security objects:
securities = Securities([
{'symbol': 'AAPL', 'quantity': 100.0},
{'symbol': 'GOOGL', 'quantity': 50.0},
])
len(securities)
# 2
type(securities[0])
# <class 'everysk.sdk.entities.portfolio.security.Security'>
Validate¶
The validate() method checks that the collection is not empty and that every Security inside it has all required fields. It auto-generates the id field for any security that is missing one:
securities = Securities([
{'symbol': 'AAPL', 'quantity': 100.0},
{'symbol': 'GOOGL', 'quantity': 50.0},
])
securities.validate()
# True
Calling validate() on an empty collection raises a FieldValueError:
Remove Errors¶
The remove_errors() method returns a new Securities collection containing only positions whose status is not 'ERROR':
securities = Securities([
{'symbol': 'AAPL', 'quantity': 100.0, 'status': 'OK'},
{'symbol': 'GOOGL', 'quantity': 50.0, 'status': 'ERROR'},
{'symbol': 'MSFT', 'quantity': 75.0, 'status': 'OK'},
])
clean = securities.remove_errors()
len(clean)
# 2
Create from Lists¶
The from_lists() static method builds a Securities collection from a list-of-lists where the first row is the header:
data = [
['symbol', 'quantity', 'market_price'],
['AAPL', 100.0, 150.0],
['GOOGL', 50.0, 2800.0],
]
securities = Securities.from_lists(data)
len(securities)
# 2
securities[0].symbol
# 'AAPL'
Convert to Lists¶
The to_lists() method is the inverse of from_lists(). It returns a list-of-lists with the header as the first row:
securities = Securities([
{'symbol': 'AAPL', 'quantity': 100.0},
{'symbol': 'GOOGL', 'quantity': 50.0},
])
rows = securities.to_lists()
len(rows)
# 3 (header + 2 securities)
rows[0]
# ['symbol', 'quantity', ...] (header row, ordered by sort_header)
A custom header can be passed to control the column order:
rows = securities.to_lists(header=['symbol', 'quantity'])
rows[0]
# ['symbol', 'quantity']
rows[1]
# ['AAPL', 100.0]
Convert to a List of Dicts¶
The to_list() method converts each Security to a plain dictionary and returns them as a list:
securities = Securities([
{'symbol': 'AAPL', 'quantity': 100.0},
{'symbol': 'GOOGL', 'quantity': 50.0},
])
dicts = securities.to_list()
len(dicts)
# 2
dicts[0]['symbol']
# 'AAPL'
Diff¶
The diff() static method compares two securities lists and returns a breakdown of the changes. By default it uses the comparable field as the comparison key:
securities_a = [{'symbol': 'AAPL', 'quantity': 100.0, 'comparable': 'AAPL'}]
securities_b = [{'symbol': 'AAPL', 'quantity': 120.0, 'comparable': 'AAPL'},
{'symbol': 'MSFT', 'quantity': 50.0, 'comparable': 'MSFT'}]
result = Securities.diff(securities_a, securities_b)
# {
# 'added_positions': [...],
# 'removed_positions': [...],
# 'partial_positions': [...],
# 'equal_positions': [...],
# }
A custom accessor field can be specified:
Consolidate¶
The consolidate() method merges positions that share the same values for the given keys, summing their quantities:
securities = Securities([
{'symbol': 'AAPL', 'quantity': 100.0, 'exchange': 'NASDAQ'},
{'symbol': 'AAPL', 'quantity': 50.0, 'exchange': 'NASDAQ'},
{'symbol': 'GOOGL', 'quantity': 75.0, 'exchange': 'NASDAQ'},
])
consolidated = securities.consolidate(['symbol', 'exchange'])
# Returns a new Securities with AAPL consolidated into one position
Security Entity¶
The Security entity represents a single financial instrument inside a portfolio. It behaves both as a dictionary and as an SDK entity, meaning you can access its fields by attribute name or by key.
Attributes¶
Below are the main attributes of the Security entity:
status: The status of the security (e.g.'OK','DELISTED','ERROR').id: The unique identifier of the security. Auto-generated if not provided.symbol: The symbol of the security (e.g.'AAPL').quantity: The quantity held.instrument_class: The class of the instrument (e.g.'Equity').ticker: The ticker symbol.label: A short label for display purposes.name: The full name of the security (e.g.'Apple Inc.').isin: The ISIN (International Securities Identification Number).exchange: The exchange where the security is traded.currency: The currency of the security (e.g.'USD').fx_rate: The foreign exchange rate.market_price: The current market price.market_value: The market value (quantity × market_price).market_value_in_base: The market value in the portfolio base currency.instrument_type/instrument_subtype: Type and subtype of the instrument.asset_class/asset_subclass: Asset classification.maturity_date: The maturity date (stored as'YYYYMMDD'string).issue_date: The issue date (stored as'YYYYMMDD'string).return_date: The return date (stored as'YYYYMMDD'string).settlement: The settlement date (stored as'YYYYMMDD'string).cost_price: The cost price.unrealized_pl/unrealized_pl_in_base: Unrealized profit or loss.extra_data: A dictionary for any additional fields that do not map to standard attributes.
Unknown keyword arguments passed at construction time are automatically stored in extra_data.
Creating a Security¶
security = Security(
symbol='AAPL',
quantity=100.0,
market_price=150.0,
currency='USD',
name='Apple Inc.',
status='OK',
)
security.symbol
# 'AAPL'
security.quantity
# 100.0
Extra Data¶
Any attribute that does not correspond to a known field is automatically moved to extra_data:
security = Security(symbol='AAPL', quantity=50.0, industry='Technology')
security.extra_data
# {'industry': 'Technology'}
You can also provide extra data explicitly:
security = Security(
symbol='AAPL',
quantity=50.0,
extra_data={'industry': 'Technology', 'country': 'USA'},
)
security.extra_data
# {'industry': 'Technology', 'country': 'USA'}
Generate a Security ID¶
The generate_security_id() static method creates a unique security ID with a standard prefix:
Each call returns a different value. If a Security object is validated without an id, one is auto-generated.
Validate Required Fields¶
The validate_required_fields() method checks that all mandatory fields (symbol, quantity, id) are present. If id is missing it is auto-generated:
security = Security(symbol='AAPL', quantity=100.0)
security.validate_required_fields()
# True
security.id
# 'sec_p06No4' (auto-generated)
Get Attribute¶
The _get_attr() static method retrieves a value from a security dictionary, also looking inside extra_data when the key is not a top-level field. An optional fallback callable is called if the key is not found anywhere:
security = Security(symbol='AAPL', quantity=100.0, industry='Technology')
Security._get_attr(security, 'symbol')
# 'AAPL'
Security._get_attr(security, 'industry')
# 'Technology'
Security._get_attr(security, 'missing_key')
# None
Security._get_attr(security, 'missing_key', lambda: 'default_val')
# 'default_val'
Generate Consolidation Key¶
The generate_consolidation_key() method builds a single string key from one or more attribute values, used to group or deduplicate securities:
security = Security(symbol='AAPL', quantity=100.0, instrument_class='Equity')
security.generate_consolidation_key(['symbol', 'instrument_class'])
# 'AAPL_Equity'
If a specified attribute is missing, a new security ID is generated as a fallback to ensure uniqueness.
Sort Header¶
The sort_header() static method reorders a list of attribute names according to the platform's canonical column order. Unrecognised keys are appended alphabetically at the end:
Security.sort_header(['symbol', 'name', 'quantity', 'instrument_class'])
# ['symbol', 'quantity', 'instrument_class', 'name']
Create from a List¶
The from_list() static method constructs a Security from a flat list of values and a matching list of header names:
security = Security.from_list(
['AAPL', 100.0, 150.0],
['symbol', 'quantity', 'market_price'],
)
security.symbol
# 'AAPL'
security.market_price
# 150.0
Convert to a List¶
The to_list() method serializes the security back to a flat list of values. The column order follows sort_header() by default, or a custom header can be provided:
security = Security(symbol='AAPL', quantity=100.0, market_price=150.0)
security.to_list(header=['symbol', 'quantity', 'market_price'])
# ['AAPL', 100.0, 150.0]
Worker Execution Entity¶
The Worker Execution entity is kept under the following import statement:
Attributes¶
Below we have the most common attributes used in the Worker Execution entity:
-
id: The unique identifier of the Worker Execution entity. Follows the formatwkex_<value>. -
status: The current execution status of the worker. Possible values are defined by the platform (e.g.PREPARING,RUNNING,OK,ERROR). -
execution_type: How the worker was triggered (e.g. scheduled, manual). -
result: An object containing the outcome of the execution, with the following fields: status: Result status —OK,ERROR, orUNKNOW.data: The output data returned by the worker.-
log: A list of log entries produced during execution. -
input_params: An object containing the input parameters passed to the worker, including: worker_id: The ID of the worker.workflow_id: The ID of the parent workflow.workspace: The workspace in which the worker runs.script_inputs: A dictionary of script-level inputs.-
parallel_info: Parallel execution metadata (indexandlength). -
parallel_info: Metadata about parallel execution, withindex(current shard) andlength(total shards). -
start_time: When the worker execution started. -
end_time: When the worker execution ended. -
duration: Total wall-clock duration of the execution in seconds. -
cpu_time: CPU time consumed during execution. -
process_cpu_time: Process-level CPU time consumed. -
workflow_execution_id: The ID of the parent Workflow Execution. -
workflow_id: The ID of the workflow this worker belongs to. -
workflow_name: The name of the workflow. -
worker_id: The ID of the worker definition. -
worker_name: The name of the worker. -
worker_type: The template type of the worker.
Instantiating a Worker Execution Entity¶
To instantiate a Worker Execution entity, we can use the following code snippet:
worker_execution = WorkerExecution()
type(worker_execution)
everysk.sdk.entities.worker_execution.base.WorkerExecution
Retrieving a Worker Execution¶
To retrieve an existing Worker Execution by its ID:
worker_execution = WorkerExecution.retrieve('wkex_abc123')
print(worker_execution.status)
print(worker_execution.duration)
Retrieving Input Params¶
The Worker Execution entity provides a class method get_input_params() that retrieves the InputParams object of a worker execution by its ID.
params = WorkerExecution.get_input_params('wkex_abc123')
print(params.worker_id)
print(params.workflow_id)
If the ID is invalid or the entity is not found, a ValueError is raised:
Querying Worker Executions¶
Worker executions can be queried by their parent workflow execution:
worker_execution = WorkerExecution(workflow_execution_id='wfex_abc123')
results = worker_execution.query()
for execution in results:
print(execution.id, execution.status, execution.duration)
Convert Worker Execution to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
worker_execution = WorkerExecution()
type(worker_execution)
everysk.sdk.entities.worker_execution.base.WorkerExecution
to_dict = worker_execution.to_dict()
type(to_dict)
dict
Workflow Execution Entity¶
The Workflow Execution entity is kept under the following import statement:
Attributes¶
Below we have the most common attributes used in the Workflow Execution entity:
-
id: The unique identifier of the Workflow Execution entity. Follows the formatwfex_<value>. -
status: The overall status of the workflow execution. Possible values are defined by the platform (e.g.OK,ERROR). -
run_status: The current running status of the execution (e.g.PREPARING,RUNNING,OK,ERROR). -
execution_type: How the workflow was triggered (e.g. scheduled, manual). -
start_time: When the workflow execution started. -
end_time: When the workflow execution ended. -
duration: Total wall-clock duration of the execution in seconds. -
real_execution_time: The actual computation time of the execution. -
total_execution_time: The sum of all worker execution times within this workflow execution. -
workflow_id: The ID of the workflow definition being executed. -
workflow_name: The name of the workflow. -
workspace: The workspace in which the workflow runs. -
started_worker_id: The ID of the worker that started the execution. -
ender_worker_id: The ID of the worker that ended the execution. -
ender_worker_execution_id: The execution ID of the worker that ended the execution. -
worker_ids: A list of all worker IDs involved in this workflow execution. -
resume: A list of checkpoint data used to resume the workflow execution.
Instantiating a Workflow Execution Entity¶
To instantiate a Workflow Execution entity, we can use the following code snippet:
workflow_execution = WorkflowExecution()
type(workflow_execution)
everysk.sdk.entities.workflow_execution.base.WorkflowExecution
Retrieving a Workflow Execution¶
To retrieve an existing Workflow Execution by its ID:
workflow_execution = WorkflowExecution.retrieve('wfex_abc123')
print(workflow_execution.run_status)
print(workflow_execution.duration)
Querying Workflow Executions¶
Workflow executions can be queried by their parent workflow:
workflow_execution = WorkflowExecution(workflow_id='wf_abc123')
results = workflow_execution.query()
for execution in results:
print(execution.id, execution.run_status, execution.duration)
Convert Workflow Execution to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
workflow_execution = WorkflowExecution()
type(workflow_execution)
everysk.sdk.entities.workflow_execution.base.WorkflowExecution
to_dict = workflow_execution.to_dict()
type(to_dict)
dict
Workspace Entity¶
The Workspace entity is kept under the following import statement:
Attributes¶
Below we have the most common attributes used in the Workspace entity:
-
name: The name of the Workspace entity. Also serves as the unique identifier (idis an alias forname). -
description: The current description of the workspace. -
group: An optional group label used to organize workspaces together.
Instantiating a Workspace Entity and Passing Attributes¶
To instantiate a Workspace entity, we can use the following code snippet:
Now we can manually set the class attributes in order to properly configure our Workspace entity.
workspace.name = 'my-workspace'
workspace.description = 'Production workspace'
workspace.group = 'production'
Convert Workspace to a Dictionary¶
Most times when working with entities, there might be a point where we need to convert the entity to a dictionary, and to achieve this we simply use the to_dict() method:
workspace = Workspace()
type(workspace)
everysk.sdk.entities.workspace.base.Workspace
to_dict = workspace.to_dict()
type(to_dict)
dict
Validating a Workspace Entity¶
The validate() method from the Workspace entity is used as a lazy validation method in order to check if the entity is valid or not by returning a boolean value:
In the case of an invalid entity, meaning that some field is missing or has an invalid value, the validate() method will raise a FieldValueError: