qtsurfer.api.client.models
Re-export of every generated model plus public scalar aliases.
All request/response dataclasses live in
qtsurfer.api.client._generated.models; importing this module makes
them available at the shorter qtsurfer.api.client.models path.
1"""Re-export of every generated model plus public scalar aliases. 2 3All request/response dataclasses live in 4``qtsurfer.api.client._generated.models``; importing this module makes 5them available at the shorter ``qtsurfer.api.client.models`` path. 6""" 7 8from typing import TypeAlias 9 10from qtsurfer.api.client._generated.models import * # noqa: F401,F403 11from qtsurfer.api.client._generated.models import __all__ as _generated_all 12 13# The generator flattens a named primitive-only `oneOf` schema while it builds 14# map values. Keep the spec name available to consumers at the public facade. 15ScalarStrategyParamValue: TypeAlias = bool | float | str 16 17__all__ = (*_generated_all, "ScalarStrategyParamValue")
13@_attrs_define 14class AcceptedJob: 15 """Response returned by async endpoints (`202 Accepted`). The `jobId` is deterministic for the 16 same input parameters — repeated calls with identical params return the same id. 17 18 Example: 19 {'jobId': '13RBLGQlPnfDjO6wyKSX8i'} 20 21 Attributes: 22 job_id (str): Unique job identifier; use this to poll for completion. For a sweep, pass this same value as the 23 `requestId` path parameter to `executeSweep` — same identifier, different name at that call site. Example: 24 13RBLGQlPnfDjO6wyKSX8i. 25 """ 26 27 job_id: str 28 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 29 30 def to_dict(self) -> dict[str, Any]: 31 job_id = self.job_id 32 33 field_dict: dict[str, Any] = {} 34 field_dict.update(self.additional_properties) 35 field_dict.update( 36 { 37 "jobId": job_id, 38 } 39 ) 40 41 return field_dict 42 43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 d = dict(src_dict) 46 job_id = d.pop("jobId") 47 48 accepted_job = cls( 49 job_id=job_id, 50 ) 51 52 accepted_job.additional_properties = d 53 return accepted_job 54 55 @property 56 def additional_keys(self) -> list[str]: 57 return list(self.additional_properties.keys()) 58 59 def __getitem__(self, key: str) -> Any: 60 return self.additional_properties[key] 61 62 def __setitem__(self, key: str, value: Any) -> None: 63 self.additional_properties[key] = value 64 65 def __delitem__(self, key: str) -> None: 66 del self.additional_properties[key] 67 68 def __contains__(self, key: str) -> bool: 69 return key in self.additional_properties
Response returned by async endpoints (202 Accepted). The jobId is deterministic for the
same input parameters — repeated calls with identical params return the same id.
Example:
{'jobId': '13RBLGQlPnfDjO6wyKSX8i'}
Attributes:
job_id (str): Unique job identifier; use this to poll for completion. For a sweep, pass this same value as the
`requestId` path parameter to `executeSweep` — same identifier, different name at that call site. Example:
13RBLGQlPnfDjO6wyKSX8i.
24def __init__(self, job_id): 25 self.job_id = job_id 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class AcceptedJob.
17@_attrs_define 18class Account: 19 """Your identity and tier limits. No database call behind this one — safe to fetch on every 20 page load. Live usage against these limits is a separate resource, `GET /account/usage`, 21 deliberately: usage changes on every upload/execution and costs a query to compute, this 22 one doesn't. 23 24 Attributes: 25 user_id (str): Your account id — the JWT `sub` claim. Example: 00000000-0000-0000-0000-000000000000. 26 tier (str): Your current subscription tier. Example: free. 27 max_execute (int): Maximum number of strategy executions (and sweeps) you can have running at the same time 28 through the API. Starting one past this number is answered with `429`, whose message 29 carries the same number. The value already includes any API allowance your plan has. 30 Example: 10. 31 max_range_days (int): Maximum length, in days, of the time range of a backtest on one of your own datasets. 32 Example: 7. 33 max_sweep_cartesian (int): Largest full grid, in parameter combinations, a sweep may run with the `grid` 34 sampler. 35 A grid with more combinations is refused with `400`; the `random` and `lhs` samplers run 36 only their `samples` and are not held to it. 37 Example: 100. 38 max_import_range_hours (int): Maximum length, in hours, of the time range of one dataset import from an 39 exchange. Example: 6. 40 max_datasets (int): Maximum number of active datasets your tier allows. Example: 3. 41 max_dataset_bytes (int): Maximum size, in bytes, of a single dataset version as stored, that is the `bytes` of 42 its ready version. For a CSV upload that is the converted file, not the file you upload, so estimate from the 43 number of rows. The Datasets guide has the details. Example: 52428800. 44 max_total_storage_bytes (int): Maximum combined storage, in bytes, across every dataset, strategy-execution 45 signal, 46 and registered strategy on your account — one shared pool, not a separate cap per 47 resource type, since they all compete for the same underlying storage. See `GET 48 /account/usage`'s `storageBytesUsed` for your current usage against this number. 49 Example: 104857600. 50 field_links (AccountLinks): HAL `_links` for `GET /account` 51 """ 52 53 user_id: str 54 tier: str 55 max_execute: int 56 max_range_days: int 57 max_sweep_cartesian: int 58 max_import_range_hours: int 59 max_datasets: int 60 max_dataset_bytes: int 61 max_total_storage_bytes: int 62 field_links: AccountLinks 63 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 64 65 def to_dict(self) -> dict[str, Any]: 66 user_id = self.user_id 67 68 tier = self.tier 69 70 max_execute = self.max_execute 71 72 max_range_days = self.max_range_days 73 74 max_sweep_cartesian = self.max_sweep_cartesian 75 76 max_import_range_hours = self.max_import_range_hours 77 78 max_datasets = self.max_datasets 79 80 max_dataset_bytes = self.max_dataset_bytes 81 82 max_total_storage_bytes = self.max_total_storage_bytes 83 84 field_links = self.field_links.to_dict() 85 86 field_dict: dict[str, Any] = {} 87 field_dict.update(self.additional_properties) 88 field_dict.update( 89 { 90 "userId": user_id, 91 "tier": tier, 92 "maxExecute": max_execute, 93 "maxRangeDays": max_range_days, 94 "maxSweepCartesian": max_sweep_cartesian, 95 "maxImportRangeHours": max_import_range_hours, 96 "maxDatasets": max_datasets, 97 "maxDatasetBytes": max_dataset_bytes, 98 "maxTotalStorageBytes": max_total_storage_bytes, 99 "_links": field_links, 100 } 101 ) 102 103 return field_dict 104 105 @classmethod 106 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 107 from ..models.account_links import AccountLinks 108 109 d = dict(src_dict) 110 user_id = d.pop("userId") 111 112 tier = d.pop("tier") 113 114 max_execute = d.pop("maxExecute") 115 116 max_range_days = d.pop("maxRangeDays") 117 118 max_sweep_cartesian = d.pop("maxSweepCartesian") 119 120 max_import_range_hours = d.pop("maxImportRangeHours") 121 122 max_datasets = d.pop("maxDatasets") 123 124 max_dataset_bytes = d.pop("maxDatasetBytes") 125 126 max_total_storage_bytes = d.pop("maxTotalStorageBytes") 127 128 field_links = AccountLinks.from_dict(d.pop("_links")) 129 130 account = cls( 131 user_id=user_id, 132 tier=tier, 133 max_execute=max_execute, 134 max_range_days=max_range_days, 135 max_sweep_cartesian=max_sweep_cartesian, 136 max_import_range_hours=max_import_range_hours, 137 max_datasets=max_datasets, 138 max_dataset_bytes=max_dataset_bytes, 139 max_total_storage_bytes=max_total_storage_bytes, 140 field_links=field_links, 141 ) 142 143 account.additional_properties = d 144 return account 145 146 @property 147 def additional_keys(self) -> list[str]: 148 return list(self.additional_properties.keys()) 149 150 def __getitem__(self, key: str) -> Any: 151 return self.additional_properties[key] 152 153 def __setitem__(self, key: str, value: Any) -> None: 154 self.additional_properties[key] = value 155 156 def __delitem__(self, key: str) -> None: 157 del self.additional_properties[key] 158 159 def __contains__(self, key: str) -> bool: 160 return key in self.additional_properties
Your identity and tier limits. No database call behind this one — safe to fetch on every
page load. Live usage against these limits is a separate resource, GET /account/usage,
deliberately: usage changes on every upload/execution and costs a query to compute, this
one doesn't.
Attributes:
user_id (str): Your account id — the JWT `sub` claim. Example: 00000000-0000-0000-0000-000000000000.
tier (str): Your current subscription tier. Example: free.
max_execute (int): Maximum number of strategy executions (and sweeps) you can have running at the same time
through the API. Starting one past this number is answered with `429`, whose message
carries the same number. The value already includes any API allowance your plan has.
Example: 10.
max_range_days (int): Maximum length, in days, of the time range of a backtest on one of your own datasets.
Example: 7.
max_sweep_cartesian (int): Largest full grid, in parameter combinations, a sweep may run with the `grid`
sampler.
A grid with more combinations is refused with `400`; the `random` and `lhs` samplers run
only their `samples` and are not held to it.
Example: 100.
max_import_range_hours (int): Maximum length, in hours, of the time range of one dataset import from an
exchange. Example: 6.
max_datasets (int): Maximum number of active datasets your tier allows. Example: 3.
max_dataset_bytes (int): Maximum size, in bytes, of a single dataset version as stored, that is the `bytes` of
its ready version. For a CSV upload that is the converted file, not the file you upload, so estimate from the
number of rows. The Datasets guide has the details. Example: 52428800.
max_total_storage_bytes (int): Maximum combined storage, in bytes, across every dataset, strategy-execution
signal,
and registered strategy on your account — one shared pool, not a separate cap per
resource type, since they all compete for the same underlying storage. See `GET
/account/usage`'s `storageBytesUsed` for your current usage against this number.
Example: 104857600.
field_links (AccountLinks): HAL `_links` for `GET /account`
33def __init__(self, user_id, tier, max_execute, max_range_days, max_sweep_cartesian, max_import_range_hours, max_datasets, max_dataset_bytes, max_total_storage_bytes, field_links): 34 self.user_id = user_id 35 self.tier = tier 36 self.max_execute = max_execute 37 self.max_range_days = max_range_days 38 self.max_sweep_cartesian = max_sweep_cartesian 39 self.max_import_range_hours = max_import_range_hours 40 self.max_datasets = max_datasets 41 self.max_dataset_bytes = max_dataset_bytes 42 self.max_total_storage_bytes = max_total_storage_bytes 43 self.field_links = field_links 44 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class Account.
65 def to_dict(self) -> dict[str, Any]: 66 user_id = self.user_id 67 68 tier = self.tier 69 70 max_execute = self.max_execute 71 72 max_range_days = self.max_range_days 73 74 max_sweep_cartesian = self.max_sweep_cartesian 75 76 max_import_range_hours = self.max_import_range_hours 77 78 max_datasets = self.max_datasets 79 80 max_dataset_bytes = self.max_dataset_bytes 81 82 max_total_storage_bytes = self.max_total_storage_bytes 83 84 field_links = self.field_links.to_dict() 85 86 field_dict: dict[str, Any] = {} 87 field_dict.update(self.additional_properties) 88 field_dict.update( 89 { 90 "userId": user_id, 91 "tier": tier, 92 "maxExecute": max_execute, 93 "maxRangeDays": max_range_days, 94 "maxSweepCartesian": max_sweep_cartesian, 95 "maxImportRangeHours": max_import_range_hours, 96 "maxDatasets": max_datasets, 97 "maxDatasetBytes": max_dataset_bytes, 98 "maxTotalStorageBytes": max_total_storage_bytes, 99 "_links": field_links, 100 } 101 ) 102 103 return field_dict
105 @classmethod 106 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 107 from ..models.account_links import AccountLinks 108 109 d = dict(src_dict) 110 user_id = d.pop("userId") 111 112 tier = d.pop("tier") 113 114 max_execute = d.pop("maxExecute") 115 116 max_range_days = d.pop("maxRangeDays") 117 118 max_sweep_cartesian = d.pop("maxSweepCartesian") 119 120 max_import_range_hours = d.pop("maxImportRangeHours") 121 122 max_datasets = d.pop("maxDatasets") 123 124 max_dataset_bytes = d.pop("maxDatasetBytes") 125 126 max_total_storage_bytes = d.pop("maxTotalStorageBytes") 127 128 field_links = AccountLinks.from_dict(d.pop("_links")) 129 130 account = cls( 131 user_id=user_id, 132 tier=tier, 133 max_execute=max_execute, 134 max_range_days=max_range_days, 135 max_sweep_cartesian=max_sweep_cartesian, 136 max_import_range_hours=max_import_range_hours, 137 max_datasets=max_datasets, 138 max_dataset_bytes=max_dataset_bytes, 139 max_total_storage_bytes=max_total_storage_bytes, 140 field_links=field_links, 141 ) 142 143 account.additional_properties = d 144 return account
17@_attrs_define 18class AccountLinks: 19 """HAL `_links` for `GET /account` 20 21 Attributes: 22 self_ (HalLink): A HAL link object (Hypertext Application Language) 23 usage (HalLink): A HAL link object (Hypertext Application Language) 24 """ 25 26 self_: HalLink 27 usage: HalLink 28 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 29 30 def to_dict(self) -> dict[str, Any]: 31 self_ = self.self_.to_dict() 32 33 usage = self.usage.to_dict() 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update( 38 { 39 "self": self_, 40 "usage": usage, 41 } 42 ) 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 from ..models.hal_link import HalLink 49 50 d = dict(src_dict) 51 self_ = HalLink.from_dict(d.pop("self")) 52 53 usage = HalLink.from_dict(d.pop("usage")) 54 55 account_links = cls( 56 self_=self_, 57 usage=usage, 58 ) 59 60 account_links.additional_properties = d 61 return account_links 62 63 @property 64 def additional_keys(self) -> list[str]: 65 return list(self.additional_properties.keys()) 66 67 def __getitem__(self, key: str) -> Any: 68 return self.additional_properties[key] 69 70 def __setitem__(self, key: str, value: Any) -> None: 71 self.additional_properties[key] = value 72 73 def __delitem__(self, key: str) -> None: 74 del self.additional_properties[key] 75 76 def __contains__(self, key: str) -> bool: 77 return key in self.additional_properties
HAL _links for GET /account
Attributes: self_ (HalLink): A HAL link object (Hypertext Application Language) usage (HalLink): A HAL link object (Hypertext Application Language)
25def __init__(self, self_, usage): 26 self.self_ = self_ 27 self.usage = usage 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class AccountLinks.
46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 from ..models.hal_link import HalLink 49 50 d = dict(src_dict) 51 self_ = HalLink.from_dict(d.pop("self")) 52 53 usage = HalLink.from_dict(d.pop("usage")) 54 55 account_links = cls( 56 self_=self_, 57 usage=usage, 58 ) 59 60 account_links.additional_properties = d 61 return account_links
17@_attrs_define 18class AccountUsage: 19 """Your live usage of the shared storage pool `GET /account`'s `maxTotalStorageBytes` caps. 20 Not guaranteed real-time — a just-completed upload or strategy execution may take a short 21 moment to be reflected here. 22 23 Attributes: 24 datasets_used (int): Active datasets counted — the same set `GET /account`'s `maxDatasets` limits. Example: 2. 25 dataset_bytes_used (int): Combined bytes of every active dataset's current version. Example: 15728640. 26 signals_used (int): Recorded strategy-execution signal uploads. Example: 1. 27 signal_bytes_used (int): Combined bytes of every recorded signal upload. Example: 524288. 28 strategies_used (int): Registered strategies (see `GET /strategies`). Example: 4. 29 strategy_bytes_used (int): Combined bytes of each registered strategy's source plus its latest compiled 30 bytecode. Superseded (non-latest) compilations aren't counted. 31 Example: 40960. 32 storage_bytes_used (int): `datasetBytesUsed + signalBytesUsed + strategyBytesUsed` — the number checked 33 against `GET /account`'s `maxTotalStorageBytes`. 34 Example: 16293888. 35 field_links (AccountUsageLinks): HAL `_links` for `GET /account/usage` 36 """ 37 38 datasets_used: int 39 dataset_bytes_used: int 40 signals_used: int 41 signal_bytes_used: int 42 strategies_used: int 43 strategy_bytes_used: int 44 storage_bytes_used: int 45 field_links: AccountUsageLinks 46 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 47 48 def to_dict(self) -> dict[str, Any]: 49 datasets_used = self.datasets_used 50 51 dataset_bytes_used = self.dataset_bytes_used 52 53 signals_used = self.signals_used 54 55 signal_bytes_used = self.signal_bytes_used 56 57 strategies_used = self.strategies_used 58 59 strategy_bytes_used = self.strategy_bytes_used 60 61 storage_bytes_used = self.storage_bytes_used 62 63 field_links = self.field_links.to_dict() 64 65 field_dict: dict[str, Any] = {} 66 field_dict.update(self.additional_properties) 67 field_dict.update( 68 { 69 "datasetsUsed": datasets_used, 70 "datasetBytesUsed": dataset_bytes_used, 71 "signalsUsed": signals_used, 72 "signalBytesUsed": signal_bytes_used, 73 "strategiesUsed": strategies_used, 74 "strategyBytesUsed": strategy_bytes_used, 75 "storageBytesUsed": storage_bytes_used, 76 "_links": field_links, 77 } 78 ) 79 80 return field_dict 81 82 @classmethod 83 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 84 from ..models.account_usage_links import AccountUsageLinks 85 86 d = dict(src_dict) 87 datasets_used = d.pop("datasetsUsed") 88 89 dataset_bytes_used = d.pop("datasetBytesUsed") 90 91 signals_used = d.pop("signalsUsed") 92 93 signal_bytes_used = d.pop("signalBytesUsed") 94 95 strategies_used = d.pop("strategiesUsed") 96 97 strategy_bytes_used = d.pop("strategyBytesUsed") 98 99 storage_bytes_used = d.pop("storageBytesUsed") 100 101 field_links = AccountUsageLinks.from_dict(d.pop("_links")) 102 103 account_usage = cls( 104 datasets_used=datasets_used, 105 dataset_bytes_used=dataset_bytes_used, 106 signals_used=signals_used, 107 signal_bytes_used=signal_bytes_used, 108 strategies_used=strategies_used, 109 strategy_bytes_used=strategy_bytes_used, 110 storage_bytes_used=storage_bytes_used, 111 field_links=field_links, 112 ) 113 114 account_usage.additional_properties = d 115 return account_usage 116 117 @property 118 def additional_keys(self) -> list[str]: 119 return list(self.additional_properties.keys()) 120 121 def __getitem__(self, key: str) -> Any: 122 return self.additional_properties[key] 123 124 def __setitem__(self, key: str, value: Any) -> None: 125 self.additional_properties[key] = value 126 127 def __delitem__(self, key: str) -> None: 128 del self.additional_properties[key] 129 130 def __contains__(self, key: str) -> bool: 131 return key in self.additional_properties
Your live usage of the shared storage pool GET /account's maxTotalStorageBytes caps.
Not guaranteed real-time — a just-completed upload or strategy execution may take a short
moment to be reflected here.
Attributes:
datasets_used (int): Active datasets counted — the same set `GET /account`'s `maxDatasets` limits. Example: 2.
dataset_bytes_used (int): Combined bytes of every active dataset's current version. Example: 15728640.
signals_used (int): Recorded strategy-execution signal uploads. Example: 1.
signal_bytes_used (int): Combined bytes of every recorded signal upload. Example: 524288.
strategies_used (int): Registered strategies (see `GET /strategies`). Example: 4.
strategy_bytes_used (int): Combined bytes of each registered strategy's source plus its latest compiled
bytecode. Superseded (non-latest) compilations aren't counted.
Example: 40960.
storage_bytes_used (int): `datasetBytesUsed + signalBytesUsed + strategyBytesUsed` — the number checked
against `GET /account`'s `maxTotalStorageBytes`.
Example: 16293888.
field_links (AccountUsageLinks): HAL `_links` for `GET /account/usage`
31def __init__(self, datasets_used, dataset_bytes_used, signals_used, signal_bytes_used, strategies_used, strategy_bytes_used, storage_bytes_used, field_links): 32 self.datasets_used = datasets_used 33 self.dataset_bytes_used = dataset_bytes_used 34 self.signals_used = signals_used 35 self.signal_bytes_used = signal_bytes_used 36 self.strategies_used = strategies_used 37 self.strategy_bytes_used = strategy_bytes_used 38 self.storage_bytes_used = storage_bytes_used 39 self.field_links = field_links 40 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class AccountUsage.
48 def to_dict(self) -> dict[str, Any]: 49 datasets_used = self.datasets_used 50 51 dataset_bytes_used = self.dataset_bytes_used 52 53 signals_used = self.signals_used 54 55 signal_bytes_used = self.signal_bytes_used 56 57 strategies_used = self.strategies_used 58 59 strategy_bytes_used = self.strategy_bytes_used 60 61 storage_bytes_used = self.storage_bytes_used 62 63 field_links = self.field_links.to_dict() 64 65 field_dict: dict[str, Any] = {} 66 field_dict.update(self.additional_properties) 67 field_dict.update( 68 { 69 "datasetsUsed": datasets_used, 70 "datasetBytesUsed": dataset_bytes_used, 71 "signalsUsed": signals_used, 72 "signalBytesUsed": signal_bytes_used, 73 "strategiesUsed": strategies_used, 74 "strategyBytesUsed": strategy_bytes_used, 75 "storageBytesUsed": storage_bytes_used, 76 "_links": field_links, 77 } 78 ) 79 80 return field_dict
82 @classmethod 83 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 84 from ..models.account_usage_links import AccountUsageLinks 85 86 d = dict(src_dict) 87 datasets_used = d.pop("datasetsUsed") 88 89 dataset_bytes_used = d.pop("datasetBytesUsed") 90 91 signals_used = d.pop("signalsUsed") 92 93 signal_bytes_used = d.pop("signalBytesUsed") 94 95 strategies_used = d.pop("strategiesUsed") 96 97 strategy_bytes_used = d.pop("strategyBytesUsed") 98 99 storage_bytes_used = d.pop("storageBytesUsed") 100 101 field_links = AccountUsageLinks.from_dict(d.pop("_links")) 102 103 account_usage = cls( 104 datasets_used=datasets_used, 105 dataset_bytes_used=dataset_bytes_used, 106 signals_used=signals_used, 107 signal_bytes_used=signal_bytes_used, 108 strategies_used=strategies_used, 109 strategy_bytes_used=strategy_bytes_used, 110 storage_bytes_used=storage_bytes_used, 111 field_links=field_links, 112 ) 113 114 account_usage.additional_properties = d 115 return account_usage
17@_attrs_define 18class AccountUsageLinks: 19 """HAL `_links` for `GET /account/usage` 20 21 Attributes: 22 self_ (HalLink): A HAL link object (Hypertext Application Language) 23 account (HalLink): A HAL link object (Hypertext Application Language) 24 """ 25 26 self_: HalLink 27 account: HalLink 28 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 29 30 def to_dict(self) -> dict[str, Any]: 31 self_ = self.self_.to_dict() 32 33 account = self.account.to_dict() 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update( 38 { 39 "self": self_, 40 "account": account, 41 } 42 ) 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 from ..models.hal_link import HalLink 49 50 d = dict(src_dict) 51 self_ = HalLink.from_dict(d.pop("self")) 52 53 account = HalLink.from_dict(d.pop("account")) 54 55 account_usage_links = cls( 56 self_=self_, 57 account=account, 58 ) 59 60 account_usage_links.additional_properties = d 61 return account_usage_links 62 63 @property 64 def additional_keys(self) -> list[str]: 65 return list(self.additional_properties.keys()) 66 67 def __getitem__(self, key: str) -> Any: 68 return self.additional_properties[key] 69 70 def __setitem__(self, key: str, value: Any) -> None: 71 self.additional_properties[key] = value 72 73 def __delitem__(self, key: str) -> None: 74 del self.additional_properties[key] 75 76 def __contains__(self, key: str) -> bool: 77 return key in self.additional_properties
HAL _links for GET /account/usage
Attributes: self_ (HalLink): A HAL link object (Hypertext Application Language) account (HalLink): A HAL link object (Hypertext Application Language)
25def __init__(self, self_, account): 26 self.self_ = self_ 27 self.account = account 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class AccountUsageLinks.
46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 from ..models.hal_link import HalLink 49 50 d = dict(src_dict) 51 self_ = HalLink.from_dict(d.pop("self")) 52 53 account = HalLink.from_dict(d.pop("account")) 54 55 account_usage_links = cls( 56 self_=self_, 57 account=account, 58 ) 59 60 account_usage_links.additional_properties = d 61 return account_usage_links
15@_attrs_define 16class AuthTokenError: 17 """Error envelope returned by `POST /auth/token` when the API key is rejected. 18 19 Attributes: 20 code (AuthTokenErrorCode): Machine-readable error reason. 21 message (str): Human-readable description of the failure. 22 """ 23 24 code: AuthTokenErrorCode 25 message: str 26 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 27 28 def to_dict(self) -> dict[str, Any]: 29 code = self.code.value 30 31 message = self.message 32 33 field_dict: dict[str, Any] = {} 34 field_dict.update(self.additional_properties) 35 field_dict.update( 36 { 37 "code": code, 38 "message": message, 39 } 40 ) 41 42 return field_dict 43 44 @classmethod 45 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 46 d = dict(src_dict) 47 code = AuthTokenErrorCode(d.pop("code")) 48 49 message = d.pop("message") 50 51 auth_token_error = cls( 52 code=code, 53 message=message, 54 ) 55 56 auth_token_error.additional_properties = d 57 return auth_token_error 58 59 @property 60 def additional_keys(self) -> list[str]: 61 return list(self.additional_properties.keys()) 62 63 def __getitem__(self, key: str) -> Any: 64 return self.additional_properties[key] 65 66 def __setitem__(self, key: str, value: Any) -> None: 67 self.additional_properties[key] = value 68 69 def __delitem__(self, key: str) -> None: 70 del self.additional_properties[key] 71 72 def __contains__(self, key: str) -> bool: 73 return key in self.additional_properties
Error envelope returned by POST /auth/token when the API key is rejected.
Attributes: code (AuthTokenErrorCode): Machine-readable error reason. message (str): Human-readable description of the failure.
25def __init__(self, code, message): 26 self.code = code 27 self.message = message 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class AuthTokenError.
44 @classmethod 45 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 46 d = dict(src_dict) 47 code = AuthTokenErrorCode(d.pop("code")) 48 49 message = d.pop("message") 50 51 auth_token_error = cls( 52 code=code, 53 message=message, 54 ) 55 56 auth_token_error.additional_properties = d 57 return auth_token_error
5class AuthTokenErrorCode(str, Enum): 6 APIKEY_EXPIRED = "apikey_expired" 7 APIKEY_REVOKED = "apikey_revoked" 8 INVALID_APIKEY = "invalid_apikey" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class AuthTokenResponse: 19 """ 20 Attributes: 21 access_token (str): Short-lived HS256 JWT. Send as `Authorization: Bearer <token>` on all other endpoints. 22 token_type (AuthTokenResponseTokenType): Always `Bearer`. 23 expires_in (int): Seconds until the JWT expires (typically 3600). Example: 3600. 24 tier (AuthTokenResponseTier): Subscription tier this token was issued for. Drives rate limits and feature flags 25 on downstream endpoints. Example: free. 26 scopes (list[str] | Unset): Scopes granted to this token. Reserved for future use; currently always empty. 27 """ 28 29 access_token: str 30 token_type: AuthTokenResponseTokenType 31 expires_in: int 32 tier: AuthTokenResponseTier 33 scopes: list[str] | Unset = UNSET 34 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 35 36 def to_dict(self) -> dict[str, Any]: 37 access_token = self.access_token 38 39 token_type = self.token_type.value 40 41 expires_in = self.expires_in 42 43 tier = self.tier.value 44 45 scopes: list[str] | Unset = UNSET 46 if not isinstance(self.scopes, Unset): 47 scopes = self.scopes 48 49 field_dict: dict[str, Any] = {} 50 field_dict.update(self.additional_properties) 51 field_dict.update( 52 { 53 "access_token": access_token, 54 "token_type": token_type, 55 "expires_in": expires_in, 56 "tier": tier, 57 } 58 ) 59 if scopes is not UNSET: 60 field_dict["scopes"] = scopes 61 62 return field_dict 63 64 @classmethod 65 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 66 d = dict(src_dict) 67 access_token = d.pop("access_token") 68 69 token_type = AuthTokenResponseTokenType(d.pop("token_type")) 70 71 expires_in = d.pop("expires_in") 72 73 tier = AuthTokenResponseTier(d.pop("tier")) 74 75 scopes = cast(list[str], d.pop("scopes", UNSET)) 76 77 auth_token_response = cls( 78 access_token=access_token, 79 token_type=token_type, 80 expires_in=expires_in, 81 tier=tier, 82 scopes=scopes, 83 ) 84 85 auth_token_response.additional_properties = d 86 return auth_token_response 87 88 @property 89 def additional_keys(self) -> list[str]: 90 return list(self.additional_properties.keys()) 91 92 def __getitem__(self, key: str) -> Any: 93 return self.additional_properties[key] 94 95 def __setitem__(self, key: str, value: Any) -> None: 96 self.additional_properties[key] = value 97 98 def __delitem__(self, key: str) -> None: 99 del self.additional_properties[key] 100 101 def __contains__(self, key: str) -> bool: 102 return key in self.additional_properties
Attributes:
access_token (str): Short-lived HS256 JWT. Send as Authorization: Bearer <token> on all other endpoints.
token_type (AuthTokenResponseTokenType): Always Bearer.
expires_in (int): Seconds until the JWT expires (typically 3600). Example: 3600.
tier (AuthTokenResponseTier): Subscription tier this token was issued for. Drives rate limits and feature flags
on downstream endpoints. Example: free.
scopes (list[str] | Unset): Scopes granted to this token. Reserved for future use; currently always empty.
28def __init__(self, access_token, token_type, expires_in, tier, scopes=attr_dict['scopes'].default): 29 self.access_token = access_token 30 self.token_type = token_type 31 self.expires_in = expires_in 32 self.tier = tier 33 self.scopes = scopes 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class AuthTokenResponse.
36 def to_dict(self) -> dict[str, Any]: 37 access_token = self.access_token 38 39 token_type = self.token_type.value 40 41 expires_in = self.expires_in 42 43 tier = self.tier.value 44 45 scopes: list[str] | Unset = UNSET 46 if not isinstance(self.scopes, Unset): 47 scopes = self.scopes 48 49 field_dict: dict[str, Any] = {} 50 field_dict.update(self.additional_properties) 51 field_dict.update( 52 { 53 "access_token": access_token, 54 "token_type": token_type, 55 "expires_in": expires_in, 56 "tier": tier, 57 } 58 ) 59 if scopes is not UNSET: 60 field_dict["scopes"] = scopes 61 62 return field_dict
64 @classmethod 65 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 66 d = dict(src_dict) 67 access_token = d.pop("access_token") 68 69 token_type = AuthTokenResponseTokenType(d.pop("token_type")) 70 71 expires_in = d.pop("expires_in") 72 73 tier = AuthTokenResponseTier(d.pop("tier")) 74 75 scopes = cast(list[str], d.pop("scopes", UNSET)) 76 77 auth_token_response = cls( 78 access_token=access_token, 79 token_type=token_type, 80 expires_in=expires_in, 81 tier=tier, 82 scopes=scopes, 83 ) 84 85 auth_token_response.additional_properties = d 86 return auth_token_response
5class AuthTokenResponseTier(str, Enum): 6 BASIC = "basic" 7 ELITE = "elite" 8 FREE = "free" 9 PRO = "pro" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class AuthTokenResponseTokenType(str, Enum): 6 BEARER = "Bearer" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
18@_attrs_define 19class BacktestJobResult: 20 """Backtest job result. 21 22 Attributes: 23 results (ResultMap): Execution result map. Always includes core fields (hostName, iops, strategyId, instrument). 24 Yield metrics (pnlTotal, pnlTotalPercent, totalTrades, winRate, equityCurve, etc.) are present when the strategy 25 emitted at least one trade. When signal storage is enabled, includes signal fields described below. `notices` 26 carries what the run had to say about itself, and is absent when it had nothing. 27 state (JobState): Information about a single job 28 """ 29 30 results: ResultMap 31 state: JobState 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 results = self.results.to_dict() 36 37 state = self.state.to_dict() 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update( 42 { 43 "results": results, 44 "state": state, 45 } 46 ) 47 48 return field_dict 49 50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 from ..models.job_state import JobState 53 from ..models.result_map import ResultMap 54 55 d = dict(src_dict) 56 results = ResultMap.from_dict(d.pop("results")) 57 58 state = JobState.from_dict(d.pop("state")) 59 60 backtest_job_result = cls( 61 results=results, 62 state=state, 63 ) 64 65 backtest_job_result.additional_properties = d 66 return backtest_job_result 67 68 @property 69 def additional_keys(self) -> list[str]: 70 return list(self.additional_properties.keys()) 71 72 def __getitem__(self, key: str) -> Any: 73 return self.additional_properties[key] 74 75 def __setitem__(self, key: str, value: Any) -> None: 76 self.additional_properties[key] = value 77 78 def __delitem__(self, key: str) -> None: 79 del self.additional_properties[key] 80 81 def __contains__(self, key: str) -> bool: 82 return key in self.additional_properties
Backtest job result.
Attributes:
results (ResultMap): Execution result map. Always includes core fields (hostName, iops, strategyId, instrument).
Yield metrics (pnlTotal, pnlTotalPercent, totalTrades, winRate, equityCurve, etc.) are present when the strategy
emitted at least one trade. When signal storage is enabled, includes signal fields described below. notices
carries what the run had to say about itself, and is absent when it had nothing.
state (JobState): Information about a single job
25def __init__(self, results, state): 26 self.results = results 27 self.state = state 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class BacktestJobResult.
34 def to_dict(self) -> dict[str, Any]: 35 results = self.results.to_dict() 36 37 state = self.state.to_dict() 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update( 42 { 43 "results": results, 44 "state": state, 45 } 46 ) 47 48 return field_dict
50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 from ..models.job_state import JobState 53 from ..models.result_map import ResultMap 54 55 d = dict(src_dict) 56 results = ResultMap.from_dict(d.pop("results")) 57 58 state = JobState.from_dict(d.pop("state")) 59 60 backtest_job_result = cls( 61 results=results, 62 state=state, 63 ) 64 65 backtest_job_result.additional_properties = d 66 return backtest_job_result
16@_attrs_define 17class CancelBacktestResponse200: 18 """ 19 Attributes: 20 status (CancelBacktestResponse200Status | Unset): Example: cancelling. 21 job_id (str | Unset): Example: 13RBLGQlPnfDjO6wyKSX8i. 22 """ 23 24 status: CancelBacktestResponse200Status | Unset = UNSET 25 job_id: str | Unset = UNSET 26 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 27 28 def to_dict(self) -> dict[str, Any]: 29 status: str | Unset = UNSET 30 if not isinstance(self.status, Unset): 31 status = self.status.value 32 33 job_id = self.job_id 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update({}) 38 if status is not UNSET: 39 field_dict["status"] = status 40 if job_id is not UNSET: 41 field_dict["jobId"] = job_id 42 43 return field_dict 44 45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 _status = d.pop("status", UNSET) 49 status: CancelBacktestResponse200Status | Unset 50 if isinstance(_status, Unset): 51 status = UNSET 52 else: 53 status = CancelBacktestResponse200Status(_status) 54 55 job_id = d.pop("jobId", UNSET) 56 57 cancel_backtest_response_200 = cls( 58 status=status, 59 job_id=job_id, 60 ) 61 62 cancel_backtest_response_200.additional_properties = d 63 return cancel_backtest_response_200 64 65 @property 66 def additional_keys(self) -> list[str]: 67 return list(self.additional_properties.keys()) 68 69 def __getitem__(self, key: str) -> Any: 70 return self.additional_properties[key] 71 72 def __setitem__(self, key: str, value: Any) -> None: 73 self.additional_properties[key] = value 74 75 def __delitem__(self, key: str) -> None: 76 del self.additional_properties[key] 77 78 def __contains__(self, key: str) -> bool: 79 return key in self.additional_properties
Attributes: status (CancelBacktestResponse200Status | Unset): Example: cancelling. job_id (str | Unset): Example: 13RBLGQlPnfDjO6wyKSX8i.
25def __init__(self, status=attr_dict['status'].default, job_id=attr_dict['job_id'].default): 26 self.status = status 27 self.job_id = job_id 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class CancelBacktestResponse200.
28 def to_dict(self) -> dict[str, Any]: 29 status: str | Unset = UNSET 30 if not isinstance(self.status, Unset): 31 status = self.status.value 32 33 job_id = self.job_id 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update({}) 38 if status is not UNSET: 39 field_dict["status"] = status 40 if job_id is not UNSET: 41 field_dict["jobId"] = job_id 42 43 return field_dict
45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 _status = d.pop("status", UNSET) 49 status: CancelBacktestResponse200Status | Unset 50 if isinstance(_status, Unset): 51 status = UNSET 52 else: 53 status = CancelBacktestResponse200Status(_status) 54 55 job_id = d.pop("jobId", UNSET) 56 57 cancel_backtest_response_200 = cls( 58 status=status, 59 job_id=job_id, 60 ) 61 62 cancel_backtest_response_200.additional_properties = d 63 return cancel_backtest_response_200
5class CancelBacktestResponse200Status(str, Enum): 6 CANCELLING = "cancelling" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class CancelSweepResponse200: 17 """ 18 Attributes: 19 status (CancelSweepResponse200Status): 20 sweep_id (str): 21 """ 22 23 status: CancelSweepResponse200Status 24 sweep_id: str 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 status = self.status.value 29 30 sweep_id = self.sweep_id 31 32 field_dict: dict[str, Any] = {} 33 field_dict.update(self.additional_properties) 34 field_dict.update( 35 { 36 "status": status, 37 "sweepId": sweep_id, 38 } 39 ) 40 41 return field_dict 42 43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 d = dict(src_dict) 46 status = CancelSweepResponse200Status(d.pop("status")) 47 48 sweep_id = d.pop("sweepId") 49 50 cancel_sweep_response_200 = cls( 51 status=status, 52 sweep_id=sweep_id, 53 ) 54 55 cancel_sweep_response_200.additional_properties = d 56 return cancel_sweep_response_200 57 58 @property 59 def additional_keys(self) -> list[str]: 60 return list(self.additional_properties.keys()) 61 62 def __getitem__(self, key: str) -> Any: 63 return self.additional_properties[key] 64 65 def __setitem__(self, key: str, value: Any) -> None: 66 self.additional_properties[key] = value 67 68 def __delitem__(self, key: str) -> None: 69 del self.additional_properties[key] 70 71 def __contains__(self, key: str) -> bool: 72 return key in self.additional_properties
Attributes: status (CancelSweepResponse200Status): sweep_id (str):
25def __init__(self, status, sweep_id): 26 self.status = status 27 self.sweep_id = sweep_id 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class CancelSweepResponse200.
43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 d = dict(src_dict) 46 status = CancelSweepResponse200Status(d.pop("status")) 47 48 sweep_id = d.pop("sweepId") 49 50 cancel_sweep_response_200 = cls( 51 status=status, 52 sweep_id=sweep_id, 53 ) 54 55 cancel_sweep_response_200.additional_properties = d 56 return cancel_sweep_response_200
5class CancelSweepResponse200Status(str, Enum): 6 CANCELLING = "cancelling" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
19@_attrs_define 20class CompileStrategyResponse200: 21 """ 22 Attributes: 23 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 24 always yields the same id, for every caller. How much formatting the id ignores depends on 25 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 26 not. 27 Example: 6bsh31ikwkuivhtgcoa6s4. 28 declared_properties (list[DeclaredProperty] | Unset): What could be established about this strategy's sweep-key 29 vocabulary without 30 constructing it. See `DeclaredProperty` — best-effort, not exhaustive. 31 """ 32 33 strategy_id: str 34 declared_properties: list[DeclaredProperty] | Unset = UNSET 35 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 36 37 def to_dict(self) -> dict[str, Any]: 38 strategy_id = self.strategy_id 39 40 declared_properties: list[dict[str, Any]] | Unset = UNSET 41 if not isinstance(self.declared_properties, Unset): 42 declared_properties = [] 43 for declared_properties_item_data in self.declared_properties: 44 declared_properties_item = declared_properties_item_data.to_dict() 45 declared_properties.append(declared_properties_item) 46 47 field_dict: dict[str, Any] = {} 48 field_dict.update(self.additional_properties) 49 field_dict.update( 50 { 51 "strategyId": strategy_id, 52 } 53 ) 54 if declared_properties is not UNSET: 55 field_dict["declaredProperties"] = declared_properties 56 57 return field_dict 58 59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 from ..models.declared_property import DeclaredProperty 62 63 d = dict(src_dict) 64 strategy_id = d.pop("strategyId") 65 66 _declared_properties = d.pop("declaredProperties", UNSET) 67 declared_properties: list[DeclaredProperty] | Unset = UNSET 68 if _declared_properties is not UNSET: 69 declared_properties = [] 70 for declared_properties_item_data in _declared_properties: 71 declared_properties_item = DeclaredProperty.from_dict(declared_properties_item_data) 72 73 declared_properties.append(declared_properties_item) 74 75 compile_strategy_response_200 = cls( 76 strategy_id=strategy_id, 77 declared_properties=declared_properties, 78 ) 79 80 compile_strategy_response_200.additional_properties = d 81 return compile_strategy_response_200 82 83 @property 84 def additional_keys(self) -> list[str]: 85 return list(self.additional_properties.keys()) 86 87 def __getitem__(self, key: str) -> Any: 88 return self.additional_properties[key] 89 90 def __setitem__(self, key: str, value: Any) -> None: 91 self.additional_properties[key] = value 92 93 def __delitem__(self, key: str) -> None: 94 del self.additional_properties[key] 95 96 def __contains__(self, key: str) -> bool: 97 return key in self.additional_properties
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see POST /strategy for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
declared_properties (list[DeclaredProperty] | Unset): What could be established about this strategy's sweep-key
vocabulary without
constructing it. See DeclaredProperty — best-effort, not exhaustive.
25def __init__(self, strategy_id, declared_properties=attr_dict['declared_properties'].default): 26 self.strategy_id = strategy_id 27 self.declared_properties = declared_properties 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class CompileStrategyResponse200.
37 def to_dict(self) -> dict[str, Any]: 38 strategy_id = self.strategy_id 39 40 declared_properties: list[dict[str, Any]] | Unset = UNSET 41 if not isinstance(self.declared_properties, Unset): 42 declared_properties = [] 43 for declared_properties_item_data in self.declared_properties: 44 declared_properties_item = declared_properties_item_data.to_dict() 45 declared_properties.append(declared_properties_item) 46 47 field_dict: dict[str, Any] = {} 48 field_dict.update(self.additional_properties) 49 field_dict.update( 50 { 51 "strategyId": strategy_id, 52 } 53 ) 54 if declared_properties is not UNSET: 55 field_dict["declaredProperties"] = declared_properties 56 57 return field_dict
59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 from ..models.declared_property import DeclaredProperty 62 63 d = dict(src_dict) 64 strategy_id = d.pop("strategyId") 65 66 _declared_properties = d.pop("declaredProperties", UNSET) 67 declared_properties: list[DeclaredProperty] | Unset = UNSET 68 if _declared_properties is not UNSET: 69 declared_properties = [] 70 for declared_properties_item_data in _declared_properties: 71 declared_properties_item = DeclaredProperty.from_dict(declared_properties_item_data) 72 73 declared_properties.append(declared_properties_item) 74 75 compile_strategy_response_200 = cls( 76 strategy_id=strategy_id, 77 declared_properties=declared_properties, 78 ) 79 80 compile_strategy_response_200.additional_properties = d 81 return compile_strategy_response_200
17@_attrs_define 18class CoverageWindow: 19 """The time range of available data for a single data type 20 21 Attributes: 22 from_ (datetime.datetime | Unset): Earliest timestamp with data available Example: 2026-04-10T21:00:00Z. 23 to (datetime.datetime | Unset): Latest timestamp with data available Example: 2026-07-09T20:31:08Z. 24 inactive_since (datetime.datetime | Unset): If the instrument stopped producing this data type 25 (delisted/inactive), the timestamp it went inactive. Optional — omitted while the instrument is active. Example: 26 2026-06-30T12:00:00Z. 27 """ 28 29 from_: datetime.datetime | Unset = UNSET 30 to: datetime.datetime | Unset = UNSET 31 inactive_since: datetime.datetime | Unset = UNSET 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 from_: str | Unset = UNSET 36 if not isinstance(self.from_, Unset): 37 from_ = self.from_.isoformat() 38 39 to: str | Unset = UNSET 40 if not isinstance(self.to, Unset): 41 to = self.to.isoformat() 42 43 inactive_since: str | Unset = UNSET 44 if not isinstance(self.inactive_since, Unset): 45 inactive_since = self.inactive_since.isoformat() 46 47 field_dict: dict[str, Any] = {} 48 field_dict.update(self.additional_properties) 49 field_dict.update({}) 50 if from_ is not UNSET: 51 field_dict["from"] = from_ 52 if to is not UNSET: 53 field_dict["to"] = to 54 if inactive_since is not UNSET: 55 field_dict["inactiveSince"] = inactive_since 56 57 return field_dict 58 59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 d = dict(src_dict) 62 _from_ = d.pop("from", UNSET) 63 from_: datetime.datetime | Unset 64 if isinstance(_from_, Unset): 65 from_ = UNSET 66 else: 67 from_ = isoparse(_from_) 68 69 _to = d.pop("to", UNSET) 70 to: datetime.datetime | Unset 71 if isinstance(_to, Unset): 72 to = UNSET 73 else: 74 to = isoparse(_to) 75 76 _inactive_since = d.pop("inactiveSince", UNSET) 77 inactive_since: datetime.datetime | Unset 78 if isinstance(_inactive_since, Unset): 79 inactive_since = UNSET 80 else: 81 inactive_since = isoparse(_inactive_since) 82 83 coverage_window = cls( 84 from_=from_, 85 to=to, 86 inactive_since=inactive_since, 87 ) 88 89 coverage_window.additional_properties = d 90 return coverage_window 91 92 @property 93 def additional_keys(self) -> list[str]: 94 return list(self.additional_properties.keys()) 95 96 def __getitem__(self, key: str) -> Any: 97 return self.additional_properties[key] 98 99 def __setitem__(self, key: str, value: Any) -> None: 100 self.additional_properties[key] = value 101 102 def __delitem__(self, key: str) -> None: 103 del self.additional_properties[key] 104 105 def __contains__(self, key: str) -> bool: 106 return key in self.additional_properties
The time range of available data for a single data type
Attributes: from_ (datetime.datetime | Unset): Earliest timestamp with data available Example: 2026-04-10T21:00:00Z. to (datetime.datetime | Unset): Latest timestamp with data available Example: 2026-07-09T20:31:08Z. inactive_since (datetime.datetime | Unset): If the instrument stopped producing this data type (delisted/inactive), the timestamp it went inactive. Optional — omitted while the instrument is active. Example: 2026-06-30T12:00:00Z.
26def __init__(self, from_=attr_dict['from_'].default, to=attr_dict['to'].default, inactive_since=attr_dict['inactive_since'].default): 27 self.from_ = from_ 28 self.to = to 29 self.inactive_since = inactive_since 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class CoverageWindow.
34 def to_dict(self) -> dict[str, Any]: 35 from_: str | Unset = UNSET 36 if not isinstance(self.from_, Unset): 37 from_ = self.from_.isoformat() 38 39 to: str | Unset = UNSET 40 if not isinstance(self.to, Unset): 41 to = self.to.isoformat() 42 43 inactive_since: str | Unset = UNSET 44 if not isinstance(self.inactive_since, Unset): 45 inactive_since = self.inactive_since.isoformat() 46 47 field_dict: dict[str, Any] = {} 48 field_dict.update(self.additional_properties) 49 field_dict.update({}) 50 if from_ is not UNSET: 51 field_dict["from"] = from_ 52 if to is not UNSET: 53 field_dict["to"] = to 54 if inactive_since is not UNSET: 55 field_dict["inactiveSince"] = inactive_since 56 57 return field_dict
59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 d = dict(src_dict) 62 _from_ = d.pop("from", UNSET) 63 from_: datetime.datetime | Unset 64 if isinstance(_from_, Unset): 65 from_ = UNSET 66 else: 67 from_ = isoparse(_from_) 68 69 _to = d.pop("to", UNSET) 70 to: datetime.datetime | Unset 71 if isinstance(_to, Unset): 72 to = UNSET 73 else: 74 to = isoparse(_to) 75 76 _inactive_since = d.pop("inactiveSince", UNSET) 77 inactive_since: datetime.datetime | Unset 78 if isinstance(_inactive_since, Unset): 79 inactive_since = UNSET 80 else: 81 inactive_since = isoparse(_inactive_since) 82 83 coverage_window = cls( 84 from_=from_, 85 to=to, 86 inactive_since=inactive_since, 87 ) 88 89 coverage_window.additional_properties = d 90 return coverage_window
13@_attrs_define 14class CreateDatasetBody: 15 """ 16 Attributes: 17 name (str): A name unique among your datasets. `409` if already taken. Example: My BTC ticks. 18 instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT. 19 """ 20 21 name: str 22 instrument: str 23 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 24 25 def to_dict(self) -> dict[str, Any]: 26 name = self.name 27 28 instrument = self.instrument 29 30 field_dict: dict[str, Any] = {} 31 field_dict.update(self.additional_properties) 32 field_dict.update( 33 { 34 "name": name, 35 "instrument": instrument, 36 } 37 ) 38 39 return field_dict 40 41 @classmethod 42 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 43 d = dict(src_dict) 44 name = d.pop("name") 45 46 instrument = d.pop("instrument") 47 48 create_dataset_body = cls( 49 name=name, 50 instrument=instrument, 51 ) 52 53 create_dataset_body.additional_properties = d 54 return create_dataset_body 55 56 @property 57 def additional_keys(self) -> list[str]: 58 return list(self.additional_properties.keys()) 59 60 def __getitem__(self, key: str) -> Any: 61 return self.additional_properties[key] 62 63 def __setitem__(self, key: str, value: Any) -> None: 64 self.additional_properties[key] = value 65 66 def __delitem__(self, key: str) -> None: 67 del self.additional_properties[key] 68 69 def __contains__(self, key: str) -> bool: 70 return key in self.additional_properties
Attributes:
name (str): A name unique among your datasets. 409 if already taken. Example: My BTC ticks.
instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT.
25def __init__(self, name, instrument): 26 self.name = name 27 self.instrument = instrument 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class CreateDatasetBody.
41 @classmethod 42 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 43 d = dict(src_dict) 44 name = d.pop("name") 45 46 instrument = d.pop("instrument") 47 48 create_dataset_body = cls( 49 name=name, 50 instrument=instrument, 51 ) 52 53 create_dataset_body.additional_properties = d 54 return create_dataset_body
20@_attrs_define 21class Dataset: 22 """A dataset's own metadata — not its data. `currentVersionId` is what a prepare against 23 `exchangeId: user` reads by default; see `DatasetVersion` for what a version carries. 24 25 `from`/`to`/`cadence`/`timestampUnit`/`bytes`/`rows`/`gaps`/`largestGapSteps` mirror that 26 current version's own discovered range, cadence, timestamp unit and metrics, so you don't 27 need a second call to `GET /datasets/{datasetId}/uploads/{uploadId}` just to see what a 28 dataset covers. 29 30 Attributes: 31 dataset_id (str): Opaque id, returned by `POST /datasets`. Example: ds_3f9a1c2e7b0d4a5f. 32 name (str): Unique among your datasets. Example: My BTC ticks. 33 type_ (DatasetType): `ticker` for an upload or a `dex` import with no `cadence` requested (native per-trade 34 data). `klines` for a `dex` import that requested a candle `cadence` — pre-aggregated 35 bars rather than raw ticks. Purely informational; both shapes are read the same way. 36 Example: ticker. 37 instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT. 38 created_at (datetime.datetime): When the dataset was created. Example: 2026-08-20T09:00:00Z. 39 status (DatasetStatus): * `ready` — `currentVersionId` is set; `from`/`to`/`cadence`/`bytes`/`rows`/`gaps`/ 40 `largestGapSteps` describe it. 41 * `failed` — the most recent upload/import attempt failed. `currentVersionId` and the 42 fields above are absent — there is nothing to read yet. See `error`. 43 * `pending` — nothing has ever been attempted (just created, or an upload was never 44 finalized). 45 Example: ready. 46 current_version_id (str | Unset): The id of the most recently finalized, successfully ingested version. Absent 47 until at 48 least one upload has finished ingesting. 49 Example: dsv_8e2b4f19c6a03d7e. 50 deleted_at (datetime.datetime | Unset): When you deleted this dataset. Only ever present in `GET 51 /datasets?includeDeleted=true`, 52 and only on datasets you have deleted. 53 updated_at (datetime.datetime | Unset): When `currentVersionId` last changed. Absent until it has a value. 54 Example: 2026-08-20T09:04:12Z. 55 from_ (datetime.datetime | Unset): Start of `currentVersionId`'s own data range, as discovered at ingest time. 56 Absent 57 until a version exists. 58 Example: 2026-03-01T00:00:00Z. 59 to (datetime.datetime | Unset): End of `currentVersionId`'s own data range, as discovered at ingest time. Absent 60 until 61 a version exists. 62 Example: 2026-03-08T00:00:00Z. 63 cadence (str | Unset): `currentVersionId`'s own discovered cadence — a fixed grid (e.g. `1s`, `1m`, `1h`) or 64 `rt` (see `DatasetVersion.cadence`). Absent until a version exists. 65 Example: 1m. 66 timestamp_unit (DatasetTimestampUnit | Unset): `currentVersionId`'s own timestamp unit (see 67 `DatasetVersion.timestampUnit`) — decode 68 the `timestamp` column of `dataUrl`'s file accordingly. Present only when `status` is 69 `ready`. 70 Example: iso. 71 bytes_ (int | Unset): Size of `currentVersionId`'s own stored file. Present only when `status` is `ready` — 72 see `DatasetVersion.bytes` for what it measures exactly. 73 Example: 4831022. 74 rows (int | Unset): `currentVersionId`'s own row count. Present only when `status` is `ready`. Example: 86400. 75 gaps (int | Unset): `currentVersionId`'s own gap count at its discovered cadence. Present only when `status` is 76 `ready`. 77 largest_gap_steps (int | Unset): `currentVersionId`'s own largest gap, in units of its discovered cadence step. 78 Present only when `status` is `ready`. 79 error (str | Unset): A human-readable reason the most recent upload/import attempt failed. Present only 80 when `status` is `failed`. 81 Example: line 3: column 'close' is not a number: not-a-number. 82 """ 83 84 dataset_id: str 85 name: str 86 type_: DatasetType 87 instrument: str 88 created_at: datetime.datetime 89 status: DatasetStatus 90 current_version_id: str | Unset = UNSET 91 deleted_at: datetime.datetime | Unset = UNSET 92 updated_at: datetime.datetime | Unset = UNSET 93 from_: datetime.datetime | Unset = UNSET 94 to: datetime.datetime | Unset = UNSET 95 cadence: str | Unset = UNSET 96 timestamp_unit: DatasetTimestampUnit | Unset = UNSET 97 bytes_: int | Unset = UNSET 98 rows: int | Unset = UNSET 99 gaps: int | Unset = UNSET 100 largest_gap_steps: int | Unset = UNSET 101 error: str | Unset = UNSET 102 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 103 104 def to_dict(self) -> dict[str, Any]: 105 dataset_id = self.dataset_id 106 107 name = self.name 108 109 type_ = self.type_.value 110 111 instrument = self.instrument 112 113 created_at = self.created_at.isoformat() 114 115 status = self.status.value 116 117 current_version_id = self.current_version_id 118 119 deleted_at: str | Unset = UNSET 120 if not isinstance(self.deleted_at, Unset): 121 deleted_at = self.deleted_at.isoformat() 122 123 updated_at: str | Unset = UNSET 124 if not isinstance(self.updated_at, Unset): 125 updated_at = self.updated_at.isoformat() 126 127 from_: str | Unset = UNSET 128 if not isinstance(self.from_, Unset): 129 from_ = self.from_.isoformat() 130 131 to: str | Unset = UNSET 132 if not isinstance(self.to, Unset): 133 to = self.to.isoformat() 134 135 cadence = self.cadence 136 137 timestamp_unit: str | Unset = UNSET 138 if not isinstance(self.timestamp_unit, Unset): 139 timestamp_unit = self.timestamp_unit.value 140 141 bytes_ = self.bytes_ 142 143 rows = self.rows 144 145 gaps = self.gaps 146 147 largest_gap_steps = self.largest_gap_steps 148 149 error = self.error 150 151 field_dict: dict[str, Any] = {} 152 field_dict.update(self.additional_properties) 153 field_dict.update( 154 { 155 "datasetId": dataset_id, 156 "name": name, 157 "type": type_, 158 "instrument": instrument, 159 "createdAt": created_at, 160 "status": status, 161 } 162 ) 163 if current_version_id is not UNSET: 164 field_dict["currentVersionId"] = current_version_id 165 if deleted_at is not UNSET: 166 field_dict["deletedAt"] = deleted_at 167 if updated_at is not UNSET: 168 field_dict["updatedAt"] = updated_at 169 if from_ is not UNSET: 170 field_dict["from"] = from_ 171 if to is not UNSET: 172 field_dict["to"] = to 173 if cadence is not UNSET: 174 field_dict["cadence"] = cadence 175 if timestamp_unit is not UNSET: 176 field_dict["timestampUnit"] = timestamp_unit 177 if bytes_ is not UNSET: 178 field_dict["bytes"] = bytes_ 179 if rows is not UNSET: 180 field_dict["rows"] = rows 181 if gaps is not UNSET: 182 field_dict["gaps"] = gaps 183 if largest_gap_steps is not UNSET: 184 field_dict["largestGapSteps"] = largest_gap_steps 185 if error is not UNSET: 186 field_dict["error"] = error 187 188 return field_dict 189 190 @classmethod 191 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 192 d = dict(src_dict) 193 dataset_id = d.pop("datasetId") 194 195 name = d.pop("name") 196 197 type_ = DatasetType(d.pop("type")) 198 199 instrument = d.pop("instrument") 200 201 created_at = isoparse(d.pop("createdAt")) 202 203 status = DatasetStatus(d.pop("status")) 204 205 current_version_id = d.pop("currentVersionId", UNSET) 206 207 _deleted_at = d.pop("deletedAt", UNSET) 208 deleted_at: datetime.datetime | Unset 209 if isinstance(_deleted_at, Unset): 210 deleted_at = UNSET 211 else: 212 deleted_at = isoparse(_deleted_at) 213 214 _updated_at = d.pop("updatedAt", UNSET) 215 updated_at: datetime.datetime | Unset 216 if isinstance(_updated_at, Unset): 217 updated_at = UNSET 218 else: 219 updated_at = isoparse(_updated_at) 220 221 _from_ = d.pop("from", UNSET) 222 from_: datetime.datetime | Unset 223 if isinstance(_from_, Unset): 224 from_ = UNSET 225 else: 226 from_ = isoparse(_from_) 227 228 _to = d.pop("to", UNSET) 229 to: datetime.datetime | Unset 230 if isinstance(_to, Unset): 231 to = UNSET 232 else: 233 to = isoparse(_to) 234 235 cadence = d.pop("cadence", UNSET) 236 237 _timestamp_unit = d.pop("timestampUnit", UNSET) 238 timestamp_unit: DatasetTimestampUnit | Unset 239 if isinstance(_timestamp_unit, Unset): 240 timestamp_unit = UNSET 241 else: 242 timestamp_unit = DatasetTimestampUnit(_timestamp_unit) 243 244 bytes_ = d.pop("bytes", UNSET) 245 246 rows = d.pop("rows", UNSET) 247 248 gaps = d.pop("gaps", UNSET) 249 250 largest_gap_steps = d.pop("largestGapSteps", UNSET) 251 252 error = d.pop("error", UNSET) 253 254 dataset = cls( 255 dataset_id=dataset_id, 256 name=name, 257 type_=type_, 258 instrument=instrument, 259 created_at=created_at, 260 status=status, 261 current_version_id=current_version_id, 262 deleted_at=deleted_at, 263 updated_at=updated_at, 264 from_=from_, 265 to=to, 266 cadence=cadence, 267 timestamp_unit=timestamp_unit, 268 bytes_=bytes_, 269 rows=rows, 270 gaps=gaps, 271 largest_gap_steps=largest_gap_steps, 272 error=error, 273 ) 274 275 dataset.additional_properties = d 276 return dataset 277 278 @property 279 def additional_keys(self) -> list[str]: 280 return list(self.additional_properties.keys()) 281 282 def __getitem__(self, key: str) -> Any: 283 return self.additional_properties[key] 284 285 def __setitem__(self, key: str, value: Any) -> None: 286 self.additional_properties[key] = value 287 288 def __delitem__(self, key: str) -> None: 289 del self.additional_properties[key] 290 291 def __contains__(self, key: str) -> bool: 292 return key in self.additional_properties
A dataset's own metadata — not its data. currentVersionId is what a prepare against
exchangeId: user reads by default; see DatasetVersion for what a version carries.
from/to/cadence/timestampUnit/bytes/rows/gaps/largestGapSteps mirror that
current version's own discovered range, cadence, timestamp unit and metrics, so you don't
need a second call to GET /datasets/{datasetId}/uploads/{uploadId} just to see what a
dataset covers.
Attributes:
dataset_id (str): Opaque id, returned by `POST /datasets`. Example: ds_3f9a1c2e7b0d4a5f.
name (str): Unique among your datasets. Example: My BTC ticks.
type_ (DatasetType): `ticker` for an upload or a `dex` import with no `cadence` requested (native per-trade
data). `klines` for a `dex` import that requested a candle `cadence` — pre-aggregated
bars rather than raw ticks. Purely informational; both shapes are read the same way.
Example: ticker.
instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT.
created_at (datetime.datetime): When the dataset was created. Example: 2026-08-20T09:00:00Z.
status (DatasetStatus): * `ready` — `currentVersionId` is set; `from`/`to`/`cadence`/`bytes`/`rows`/`gaps`/
`largestGapSteps` describe it.
* `failed` — the most recent upload/import attempt failed. `currentVersionId` and the
fields above are absent — there is nothing to read yet. See `error`.
* `pending` — nothing has ever been attempted (just created, or an upload was never
finalized).
Example: ready.
current_version_id (str | Unset): The id of the most recently finalized, successfully ingested version. Absent
until at
least one upload has finished ingesting.
Example: dsv_8e2b4f19c6a03d7e.
deleted_at (datetime.datetime | Unset): When you deleted this dataset. Only ever present in `GET
/datasets?includeDeleted=true`,
and only on datasets you have deleted.
updated_at (datetime.datetime | Unset): When `currentVersionId` last changed. Absent until it has a value.
Example: 2026-08-20T09:04:12Z.
from_ (datetime.datetime | Unset): Start of `currentVersionId`'s own data range, as discovered at ingest time.
Absent
until a version exists.
Example: 2026-03-01T00:00:00Z.
to (datetime.datetime | Unset): End of `currentVersionId`'s own data range, as discovered at ingest time. Absent
until
a version exists.
Example: 2026-03-08T00:00:00Z.
cadence (str | Unset): `currentVersionId`'s own discovered cadence — a fixed grid (e.g. `1s`, `1m`, `1h`) or
`rt` (see `DatasetVersion.cadence`). Absent until a version exists.
Example: 1m.
timestamp_unit (DatasetTimestampUnit | Unset): `currentVersionId`'s own timestamp unit (see
`DatasetVersion.timestampUnit`) — decode
the `timestamp` column of `dataUrl`'s file accordingly. Present only when `status` is
`ready`.
Example: iso.
bytes_ (int | Unset): Size of `currentVersionId`'s own stored file. Present only when `status` is `ready` —
see `DatasetVersion.bytes` for what it measures exactly.
Example: 4831022.
rows (int | Unset): `currentVersionId`'s own row count. Present only when `status` is `ready`. Example: 86400.
gaps (int | Unset): `currentVersionId`'s own gap count at its discovered cadence. Present only when `status` is
`ready`.
largest_gap_steps (int | Unset): `currentVersionId`'s own largest gap, in units of its discovered cadence step.
Present only when `status` is `ready`.
error (str | Unset): A human-readable reason the most recent upload/import attempt failed. Present only
when `status` is `failed`.
Example: line 3: column 'close' is not a number: not-a-number.
41def __init__(self, dataset_id, name, type_, instrument, created_at, status, current_version_id=attr_dict['current_version_id'].default, deleted_at=attr_dict['deleted_at'].default, updated_at=attr_dict['updated_at'].default, from_=attr_dict['from_'].default, to=attr_dict['to'].default, cadence=attr_dict['cadence'].default, timestamp_unit=attr_dict['timestamp_unit'].default, bytes_=attr_dict['bytes_'].default, rows=attr_dict['rows'].default, gaps=attr_dict['gaps'].default, largest_gap_steps=attr_dict['largest_gap_steps'].default, error=attr_dict['error'].default): 42 self.dataset_id = dataset_id 43 self.name = name 44 self.type_ = type_ 45 self.instrument = instrument 46 self.created_at = created_at 47 self.status = status 48 self.current_version_id = current_version_id 49 self.deleted_at = deleted_at 50 self.updated_at = updated_at 51 self.from_ = from_ 52 self.to = to 53 self.cadence = cadence 54 self.timestamp_unit = timestamp_unit 55 self.bytes_ = bytes_ 56 self.rows = rows 57 self.gaps = gaps 58 self.largest_gap_steps = largest_gap_steps 59 self.error = error 60 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class Dataset.
104 def to_dict(self) -> dict[str, Any]: 105 dataset_id = self.dataset_id 106 107 name = self.name 108 109 type_ = self.type_.value 110 111 instrument = self.instrument 112 113 created_at = self.created_at.isoformat() 114 115 status = self.status.value 116 117 current_version_id = self.current_version_id 118 119 deleted_at: str | Unset = UNSET 120 if not isinstance(self.deleted_at, Unset): 121 deleted_at = self.deleted_at.isoformat() 122 123 updated_at: str | Unset = UNSET 124 if not isinstance(self.updated_at, Unset): 125 updated_at = self.updated_at.isoformat() 126 127 from_: str | Unset = UNSET 128 if not isinstance(self.from_, Unset): 129 from_ = self.from_.isoformat() 130 131 to: str | Unset = UNSET 132 if not isinstance(self.to, Unset): 133 to = self.to.isoformat() 134 135 cadence = self.cadence 136 137 timestamp_unit: str | Unset = UNSET 138 if not isinstance(self.timestamp_unit, Unset): 139 timestamp_unit = self.timestamp_unit.value 140 141 bytes_ = self.bytes_ 142 143 rows = self.rows 144 145 gaps = self.gaps 146 147 largest_gap_steps = self.largest_gap_steps 148 149 error = self.error 150 151 field_dict: dict[str, Any] = {} 152 field_dict.update(self.additional_properties) 153 field_dict.update( 154 { 155 "datasetId": dataset_id, 156 "name": name, 157 "type": type_, 158 "instrument": instrument, 159 "createdAt": created_at, 160 "status": status, 161 } 162 ) 163 if current_version_id is not UNSET: 164 field_dict["currentVersionId"] = current_version_id 165 if deleted_at is not UNSET: 166 field_dict["deletedAt"] = deleted_at 167 if updated_at is not UNSET: 168 field_dict["updatedAt"] = updated_at 169 if from_ is not UNSET: 170 field_dict["from"] = from_ 171 if to is not UNSET: 172 field_dict["to"] = to 173 if cadence is not UNSET: 174 field_dict["cadence"] = cadence 175 if timestamp_unit is not UNSET: 176 field_dict["timestampUnit"] = timestamp_unit 177 if bytes_ is not UNSET: 178 field_dict["bytes"] = bytes_ 179 if rows is not UNSET: 180 field_dict["rows"] = rows 181 if gaps is not UNSET: 182 field_dict["gaps"] = gaps 183 if largest_gap_steps is not UNSET: 184 field_dict["largestGapSteps"] = largest_gap_steps 185 if error is not UNSET: 186 field_dict["error"] = error 187 188 return field_dict
190 @classmethod 191 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 192 d = dict(src_dict) 193 dataset_id = d.pop("datasetId") 194 195 name = d.pop("name") 196 197 type_ = DatasetType(d.pop("type")) 198 199 instrument = d.pop("instrument") 200 201 created_at = isoparse(d.pop("createdAt")) 202 203 status = DatasetStatus(d.pop("status")) 204 205 current_version_id = d.pop("currentVersionId", UNSET) 206 207 _deleted_at = d.pop("deletedAt", UNSET) 208 deleted_at: datetime.datetime | Unset 209 if isinstance(_deleted_at, Unset): 210 deleted_at = UNSET 211 else: 212 deleted_at = isoparse(_deleted_at) 213 214 _updated_at = d.pop("updatedAt", UNSET) 215 updated_at: datetime.datetime | Unset 216 if isinstance(_updated_at, Unset): 217 updated_at = UNSET 218 else: 219 updated_at = isoparse(_updated_at) 220 221 _from_ = d.pop("from", UNSET) 222 from_: datetime.datetime | Unset 223 if isinstance(_from_, Unset): 224 from_ = UNSET 225 else: 226 from_ = isoparse(_from_) 227 228 _to = d.pop("to", UNSET) 229 to: datetime.datetime | Unset 230 if isinstance(_to, Unset): 231 to = UNSET 232 else: 233 to = isoparse(_to) 234 235 cadence = d.pop("cadence", UNSET) 236 237 _timestamp_unit = d.pop("timestampUnit", UNSET) 238 timestamp_unit: DatasetTimestampUnit | Unset 239 if isinstance(_timestamp_unit, Unset): 240 timestamp_unit = UNSET 241 else: 242 timestamp_unit = DatasetTimestampUnit(_timestamp_unit) 243 244 bytes_ = d.pop("bytes", UNSET) 245 246 rows = d.pop("rows", UNSET) 247 248 gaps = d.pop("gaps", UNSET) 249 250 largest_gap_steps = d.pop("largestGapSteps", UNSET) 251 252 error = d.pop("error", UNSET) 253 254 dataset = cls( 255 dataset_id=dataset_id, 256 name=name, 257 type_=type_, 258 instrument=instrument, 259 created_at=created_at, 260 status=status, 261 current_version_id=current_version_id, 262 deleted_at=deleted_at, 263 updated_at=updated_at, 264 from_=from_, 265 to=to, 266 cadence=cadence, 267 timestamp_unit=timestamp_unit, 268 bytes_=bytes_, 269 rows=rows, 270 gaps=gaps, 271 largest_gap_steps=largest_gap_steps, 272 error=error, 273 ) 274 275 dataset.additional_properties = d 276 return dataset
19@_attrs_define 20class DatasetCreated: 21 """The metadata available immediately after creating a dataset, plus its first upload 22 session — the presigned URL to PUT the file to. Version-derived fields such as 23 `createdAt`, `currentVersionId`, range, and cadence are available from `GET /datasets/{datasetId}` 24 after the relevant lifecycle stages, not in this creation response. 25 26 Attributes: 27 upload_id (str): Identifies this upload session. Pass to 28 `POST /datasets/{datasetId}/uploads/{uploadId}/finalize` once the PUT completes. 29 Example: up_1a2b3c4d5e6f7a8b. 30 upload (DatasetUploadTarget): A presigned destination for uploading a raw dataset file directly to storage. 31 dataset_id (str): Opaque id of the newly created dataset. Example: ds_3f9a1c2e7b0d4a5f. 32 name (str): Unique name of the newly created dataset. Example: My BTC ticks. 33 type_ (DatasetCreatedType): Always `ticker` in v1. Example: ticker. 34 instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT. 35 """ 36 37 upload_id: str 38 upload: DatasetUploadTarget 39 dataset_id: str 40 name: str 41 type_: DatasetCreatedType 42 instrument: str 43 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 44 45 def to_dict(self) -> dict[str, Any]: 46 upload_id = self.upload_id 47 48 upload = self.upload.to_dict() 49 50 dataset_id = self.dataset_id 51 52 name = self.name 53 54 type_ = self.type_.value 55 56 instrument = self.instrument 57 58 field_dict: dict[str, Any] = {} 59 field_dict.update(self.additional_properties) 60 field_dict.update( 61 { 62 "uploadId": upload_id, 63 "upload": upload, 64 "datasetId": dataset_id, 65 "name": name, 66 "type": type_, 67 "instrument": instrument, 68 } 69 ) 70 71 return field_dict 72 73 @classmethod 74 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 75 from ..models.dataset_upload_target import DatasetUploadTarget 76 77 d = dict(src_dict) 78 upload_id = d.pop("uploadId") 79 80 upload = DatasetUploadTarget.from_dict(d.pop("upload")) 81 82 dataset_id = d.pop("datasetId") 83 84 name = d.pop("name") 85 86 type_ = DatasetCreatedType(d.pop("type")) 87 88 instrument = d.pop("instrument") 89 90 dataset_created = cls( 91 upload_id=upload_id, 92 upload=upload, 93 dataset_id=dataset_id, 94 name=name, 95 type_=type_, 96 instrument=instrument, 97 ) 98 99 dataset_created.additional_properties = d 100 return dataset_created 101 102 @property 103 def additional_keys(self) -> list[str]: 104 return list(self.additional_properties.keys()) 105 106 def __getitem__(self, key: str) -> Any: 107 return self.additional_properties[key] 108 109 def __setitem__(self, key: str, value: Any) -> None: 110 self.additional_properties[key] = value 111 112 def __delitem__(self, key: str) -> None: 113 del self.additional_properties[key] 114 115 def __contains__(self, key: str) -> bool: 116 return key in self.additional_properties
The metadata available immediately after creating a dataset, plus its first upload
session — the presigned URL to PUT the file to. Version-derived fields such as
createdAt, currentVersionId, range, and cadence are available from GET /datasets/{datasetId}
after the relevant lifecycle stages, not in this creation response.
Attributes:
upload_id (str): Identifies this upload session. Pass to
`POST /datasets/{datasetId}/uploads/{uploadId}/finalize` once the PUT completes.
Example: up_1a2b3c4d5e6f7a8b.
upload (DatasetUploadTarget): A presigned destination for uploading a raw dataset file directly to storage.
dataset_id (str): Opaque id of the newly created dataset. Example: ds_3f9a1c2e7b0d4a5f.
name (str): Unique name of the newly created dataset. Example: My BTC ticks.
type_ (DatasetCreatedType): Always `ticker` in v1. Example: ticker.
instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT.
29def __init__(self, upload_id, upload, dataset_id, name, type_, instrument): 30 self.upload_id = upload_id 31 self.upload = upload 32 self.dataset_id = dataset_id 33 self.name = name 34 self.type_ = type_ 35 self.instrument = instrument 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetCreated.
45 def to_dict(self) -> dict[str, Any]: 46 upload_id = self.upload_id 47 48 upload = self.upload.to_dict() 49 50 dataset_id = self.dataset_id 51 52 name = self.name 53 54 type_ = self.type_.value 55 56 instrument = self.instrument 57 58 field_dict: dict[str, Any] = {} 59 field_dict.update(self.additional_properties) 60 field_dict.update( 61 { 62 "uploadId": upload_id, 63 "upload": upload, 64 "datasetId": dataset_id, 65 "name": name, 66 "type": type_, 67 "instrument": instrument, 68 } 69 ) 70 71 return field_dict
73 @classmethod 74 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 75 from ..models.dataset_upload_target import DatasetUploadTarget 76 77 d = dict(src_dict) 78 upload_id = d.pop("uploadId") 79 80 upload = DatasetUploadTarget.from_dict(d.pop("upload")) 81 82 dataset_id = d.pop("datasetId") 83 84 name = d.pop("name") 85 86 type_ = DatasetCreatedType(d.pop("type")) 87 88 instrument = d.pop("instrument") 89 90 dataset_created = cls( 91 upload_id=upload_id, 92 upload=upload, 93 dataset_id=dataset_id, 94 name=name, 95 type_=type_, 96 instrument=instrument, 97 ) 98 99 dataset_created.additional_properties = d 100 return dataset_created
5class DatasetCreatedType(str, Enum): 6 TICKER = "ticker" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class DatasetImportCreated: 17 """The response to `POST /datasets/imports` — the dataset now exists, and its fetch has started. 18 19 Attributes: 20 dataset_id (str): Opaque id of the newly created dataset — same id space as `POST /datasets`. Example: 21 ds_3f9a1c2e7b0d4a5f. 22 import_id (str): Identifies this import. Pass to `GET /datasets/{datasetId}/imports/{importId}` to poll 23 it — there is no separate "finalize" step the way an upload has. 24 Example: imp_01j9z1x2y3z4a5b6c7d8e9f0g1. 25 job_id (str): The fetch/ingest job id. Example: dataset- 26 import:00000000-.../ds_3f9a1c2e7b0d4a5f:imp_01j9z1x2y3z4a5b6c7d8e9f0g1. 27 status (DatasetImportCreatedStatus): Always `fetching` in this response — the fetch has only just started. 28 Example: fetching. 29 """ 30 31 dataset_id: str 32 import_id: str 33 job_id: str 34 status: DatasetImportCreatedStatus 35 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 36 37 def to_dict(self) -> dict[str, Any]: 38 dataset_id = self.dataset_id 39 40 import_id = self.import_id 41 42 job_id = self.job_id 43 44 status = self.status.value 45 46 field_dict: dict[str, Any] = {} 47 field_dict.update(self.additional_properties) 48 field_dict.update( 49 { 50 "datasetId": dataset_id, 51 "importId": import_id, 52 "jobId": job_id, 53 "status": status, 54 } 55 ) 56 57 return field_dict 58 59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 d = dict(src_dict) 62 dataset_id = d.pop("datasetId") 63 64 import_id = d.pop("importId") 65 66 job_id = d.pop("jobId") 67 68 status = DatasetImportCreatedStatus(d.pop("status")) 69 70 dataset_import_created = cls( 71 dataset_id=dataset_id, 72 import_id=import_id, 73 job_id=job_id, 74 status=status, 75 ) 76 77 dataset_import_created.additional_properties = d 78 return dataset_import_created 79 80 @property 81 def additional_keys(self) -> list[str]: 82 return list(self.additional_properties.keys()) 83 84 def __getitem__(self, key: str) -> Any: 85 return self.additional_properties[key] 86 87 def __setitem__(self, key: str, value: Any) -> None: 88 self.additional_properties[key] = value 89 90 def __delitem__(self, key: str) -> None: 91 del self.additional_properties[key] 92 93 def __contains__(self, key: str) -> bool: 94 return key in self.additional_properties
The response to POST /datasets/imports — the dataset now exists, and its fetch has started.
Attributes:
dataset_id (str): Opaque id of the newly created dataset — same id space as POST /datasets. Example:
ds_3f9a1c2e7b0d4a5f.
import_id (str): Identifies this import. Pass to GET /datasets/{datasetId}/imports/{importId} to poll
it — there is no separate "finalize" step the way an upload has.
Example: imp_01j9z1x2y3z4a5b6c7d8e9f0g1.
job_id (str): The fetch/ingest job id. Example: dataset-
import:00000000-.../ds_3f9a1c2e7b0d4a5f:imp_01j9z1x2y3z4a5b6c7d8e9f0g1.
status (DatasetImportCreatedStatus): Always fetching in this response — the fetch has only just started.
Example: fetching.
27def __init__(self, dataset_id, import_id, job_id, status): 28 self.dataset_id = dataset_id 29 self.import_id = import_id 30 self.job_id = job_id 31 self.status = status 32 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetImportCreated.
37 def to_dict(self) -> dict[str, Any]: 38 dataset_id = self.dataset_id 39 40 import_id = self.import_id 41 42 job_id = self.job_id 43 44 status = self.status.value 45 46 field_dict: dict[str, Any] = {} 47 field_dict.update(self.additional_properties) 48 field_dict.update( 49 { 50 "datasetId": dataset_id, 51 "importId": import_id, 52 "jobId": job_id, 53 "status": status, 54 } 55 ) 56 57 return field_dict
59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 d = dict(src_dict) 62 dataset_id = d.pop("datasetId") 63 64 import_id = d.pop("importId") 65 66 job_id = d.pop("jobId") 67 68 status = DatasetImportCreatedStatus(d.pop("status")) 69 70 dataset_import_created = cls( 71 dataset_id=dataset_id, 72 import_id=import_id, 73 job_id=job_id, 74 status=status, 75 ) 76 77 dataset_import_created.additional_properties = d 78 return dataset_import_created
5class DatasetImportCreatedStatus(str, Enum): 6 FETCHING = "fetching" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
18@_attrs_define 19class DatasetImportDexRequest: 20 """The `dex` source's own fields — required when `type` is `dex`. `id`/`version` are required 21 for a plain (native-cadence) import; both are ignored if the top-level `cadence` requested 22 pre-aggregated candles instead, since that path needs neither a protocol nor a version 23 distinction. 24 25 Example: 26 {'network': 'ethereum', 'id': 'uniswap', 'version': 'v3', 'contract': 27 '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640'} 28 29 Attributes: 30 network (DatasetImportDexRequestNetwork): Which chain the pool/pair lives on. Example: ethereum. 31 contract (str): The pool (v3) or pair (v2) contract address. Example: 32 0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640. 33 id (DatasetImportDexRequestId | Unset): Which on-chain DEX protocol `contract` implements. Required unless the 34 top-level 35 `cadence` requested pre-aggregated candles, in which case it's ignored. 36 Example: uniswap. 37 version (DatasetImportDexRequestVersion | Unset): Uniswap version the pool/pair contract implements. Required 38 unless the top-level 39 `cadence` requested pre-aggregated candles, in which case it's ignored. 40 Example: v3. 41 factory (str | Unset): The factory that deployed `contract`. Optional — when omitted, it is discovered 42 on-chain from `contract` itself at fetch time. Supply it explicitly only if you 43 already know it, or the pool/pair belongs to a factory other than the canonical one 44 for `network`/`version`. Either way, the pool/pair is validated against whichever 45 factory is used before anything is fetched — a wrong or unrelated factory fails the 46 import rather than silently fetching from the wrong pool. Ignored if the top-level 47 `cadence` requested pre-aggregated candles. 48 """ 49 50 network: DatasetImportDexRequestNetwork 51 contract: str 52 id: DatasetImportDexRequestId | Unset = UNSET 53 version: DatasetImportDexRequestVersion | Unset = UNSET 54 factory: str | Unset = UNSET 55 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 56 57 def to_dict(self) -> dict[str, Any]: 58 network = self.network.value 59 60 contract = self.contract 61 62 id: str | Unset = UNSET 63 if not isinstance(self.id, Unset): 64 id = self.id.value 65 66 version: str | Unset = UNSET 67 if not isinstance(self.version, Unset): 68 version = self.version.value 69 70 factory = self.factory 71 72 field_dict: dict[str, Any] = {} 73 field_dict.update(self.additional_properties) 74 field_dict.update( 75 { 76 "network": network, 77 "contract": contract, 78 } 79 ) 80 if id is not UNSET: 81 field_dict["id"] = id 82 if version is not UNSET: 83 field_dict["version"] = version 84 if factory is not UNSET: 85 field_dict["factory"] = factory 86 87 return field_dict 88 89 @classmethod 90 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 91 d = dict(src_dict) 92 network = DatasetImportDexRequestNetwork(d.pop("network")) 93 94 contract = d.pop("contract") 95 96 _id = d.pop("id", UNSET) 97 id: DatasetImportDexRequestId | Unset 98 if isinstance(_id, Unset): 99 id = UNSET 100 else: 101 id = DatasetImportDexRequestId(_id) 102 103 _version = d.pop("version", UNSET) 104 version: DatasetImportDexRequestVersion | Unset 105 if isinstance(_version, Unset): 106 version = UNSET 107 else: 108 version = DatasetImportDexRequestVersion(_version) 109 110 factory = d.pop("factory", UNSET) 111 112 dataset_import_dex_request = cls( 113 network=network, 114 contract=contract, 115 id=id, 116 version=version, 117 factory=factory, 118 ) 119 120 dataset_import_dex_request.additional_properties = d 121 return dataset_import_dex_request 122 123 @property 124 def additional_keys(self) -> list[str]: 125 return list(self.additional_properties.keys()) 126 127 def __getitem__(self, key: str) -> Any: 128 return self.additional_properties[key] 129 130 def __setitem__(self, key: str, value: Any) -> None: 131 self.additional_properties[key] = value 132 133 def __delitem__(self, key: str) -> None: 134 del self.additional_properties[key] 135 136 def __contains__(self, key: str) -> bool: 137 return key in self.additional_properties
The dex source's own fields — required when type is dex. id/version are required
for a plain (native-cadence) import; both are ignored if the top-level cadence requested
pre-aggregated candles instead, since that path needs neither a protocol nor a version
distinction.
Example:
{'network': 'ethereum', 'id': 'uniswap', 'version': 'v3', 'contract':
'0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640'}
Attributes:
network (DatasetImportDexRequestNetwork): Which chain the pool/pair lives on. Example: ethereum.
contract (str): The pool (v3) or pair (v2) contract address. Example:
0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640.
id (DatasetImportDexRequestId | Unset): Which on-chain DEX protocol `contract` implements. Required unless the
top-level
`cadence` requested pre-aggregated candles, in which case it's ignored.
Example: uniswap.
version (DatasetImportDexRequestVersion | Unset): Uniswap version the pool/pair contract implements. Required
unless the top-level
`cadence` requested pre-aggregated candles, in which case it's ignored.
Example: v3.
factory (str | Unset): The factory that deployed `contract`. Optional — when omitted, it is discovered
on-chain from `contract` itself at fetch time. Supply it explicitly only if you
already know it, or the pool/pair belongs to a factory other than the canonical one
for `network`/`version`. Either way, the pool/pair is validated against whichever
factory is used before anything is fetched — a wrong or unrelated factory fails the
import rather than silently fetching from the wrong pool. Ignored if the top-level
`cadence` requested pre-aggregated candles.
28def __init__(self, network, contract, id=attr_dict['id'].default, version=attr_dict['version'].default, factory=attr_dict['factory'].default): 29 self.network = network 30 self.contract = contract 31 self.id = id 32 self.version = version 33 self.factory = factory 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetImportDexRequest.
57 def to_dict(self) -> dict[str, Any]: 58 network = self.network.value 59 60 contract = self.contract 61 62 id: str | Unset = UNSET 63 if not isinstance(self.id, Unset): 64 id = self.id.value 65 66 version: str | Unset = UNSET 67 if not isinstance(self.version, Unset): 68 version = self.version.value 69 70 factory = self.factory 71 72 field_dict: dict[str, Any] = {} 73 field_dict.update(self.additional_properties) 74 field_dict.update( 75 { 76 "network": network, 77 "contract": contract, 78 } 79 ) 80 if id is not UNSET: 81 field_dict["id"] = id 82 if version is not UNSET: 83 field_dict["version"] = version 84 if factory is not UNSET: 85 field_dict["factory"] = factory 86 87 return field_dict
89 @classmethod 90 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 91 d = dict(src_dict) 92 network = DatasetImportDexRequestNetwork(d.pop("network")) 93 94 contract = d.pop("contract") 95 96 _id = d.pop("id", UNSET) 97 id: DatasetImportDexRequestId | Unset 98 if isinstance(_id, Unset): 99 id = UNSET 100 else: 101 id = DatasetImportDexRequestId(_id) 102 103 _version = d.pop("version", UNSET) 104 version: DatasetImportDexRequestVersion | Unset 105 if isinstance(_version, Unset): 106 version = UNSET 107 else: 108 version = DatasetImportDexRequestVersion(_version) 109 110 factory = d.pop("factory", UNSET) 111 112 dataset_import_dex_request = cls( 113 network=network, 114 contract=contract, 115 id=id, 116 version=version, 117 factory=factory, 118 ) 119 120 dataset_import_dex_request.additional_properties = d 121 return dataset_import_dex_request
5class DatasetImportDexRequestId(str, Enum): 6 UNISWAP = "uniswap" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetImportDexRequestNetwork(str, Enum): 6 ETHEREUM = "ethereum" 7 ROBINHOOD = "robinhood" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetImportDexRequestVersion(str, Enum): 6 V2 = "v2" 7 V3 = "v3" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
23@_attrs_define 24class DatasetImportRequest: 25 """`POST /datasets/imports`'s request body. A common block plus one type-specific block, 26 selected by `type` — `dex` is the only value today. 27 28 Attributes: 29 name (str): A name unique among your datasets. `409` if already taken. Example: weth-usdc-week. 30 instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT. 31 from_ (datetime.datetime): Start of the range to fetch, inclusive. Must be before `to`. Example: 32 2026-08-01T00:00:00Z. 33 to (datetime.datetime): End of the range to fetch, exclusive. The total span is capped by your tier — a 34 request wider than that ceiling is `400`, regardless of source type. 35 Example: 2026-08-08T00:00:00Z. 36 type_ (DatasetImportRequestType): The source to fetch from. `dex` is the only value today. Example: dex. 37 cadence (DatasetImportRequestCadence | Unset): Optional. Omitted/blank keeps native per-trade event cadence — 38 each swap at its own 39 timestamp, so the resulting version's `cadence` is `rt` unless the swaps happen to sit 40 on a fixed grid (see `DatasetVersion.cadence`). Set to `1s`, `1m` or 41 `5m` instead to get pre-aggregated candles at that width rather than raw trades (the 42 resulting dataset's `type` becomes `klines`); any other value is `400`. Not every 43 network supports every cadence — an unsupported combination fails asynchronously, not 44 at request time (see `DatasetImportState.error`). 45 dex (DatasetImportDexRequest | Unset): The `dex` source's own fields — required when `type` is `dex`. 46 `id`/`version` are required 47 for a plain (native-cadence) import; both are ignored if the top-level `cadence` requested 48 pre-aggregated candles instead, since that path needs neither a protocol nor a version 49 distinction. 50 Example: {'network': 'ethereum', 'id': 'uniswap', 'version': 'v3', 'contract': 51 '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640'}. 52 """ 53 54 name: str 55 instrument: str 56 from_: datetime.datetime 57 to: datetime.datetime 58 type_: DatasetImportRequestType 59 cadence: DatasetImportRequestCadence | Unset = UNSET 60 dex: DatasetImportDexRequest | Unset = UNSET 61 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 62 63 def to_dict(self) -> dict[str, Any]: 64 name = self.name 65 66 instrument = self.instrument 67 68 from_ = self.from_.isoformat() 69 70 to = self.to.isoformat() 71 72 type_ = self.type_.value 73 74 cadence: str | Unset = UNSET 75 if not isinstance(self.cadence, Unset): 76 cadence = self.cadence.value 77 78 dex: dict[str, Any] | Unset = UNSET 79 if not isinstance(self.dex, Unset): 80 dex = self.dex.to_dict() 81 82 field_dict: dict[str, Any] = {} 83 field_dict.update(self.additional_properties) 84 field_dict.update( 85 { 86 "name": name, 87 "instrument": instrument, 88 "from": from_, 89 "to": to, 90 "type": type_, 91 } 92 ) 93 if cadence is not UNSET: 94 field_dict["cadence"] = cadence 95 if dex is not UNSET: 96 field_dict["dex"] = dex 97 98 return field_dict 99 100 @classmethod 101 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 102 from ..models.dataset_import_dex_request import DatasetImportDexRequest 103 104 d = dict(src_dict) 105 name = d.pop("name") 106 107 instrument = d.pop("instrument") 108 109 from_ = isoparse(d.pop("from")) 110 111 to = isoparse(d.pop("to")) 112 113 type_ = DatasetImportRequestType(d.pop("type")) 114 115 _cadence = d.pop("cadence", UNSET) 116 cadence: DatasetImportRequestCadence | Unset 117 if isinstance(_cadence, Unset): 118 cadence = UNSET 119 else: 120 cadence = DatasetImportRequestCadence(_cadence) 121 122 _dex = d.pop("dex", UNSET) 123 dex: DatasetImportDexRequest | Unset 124 if isinstance(_dex, Unset): 125 dex = UNSET 126 else: 127 dex = DatasetImportDexRequest.from_dict(_dex) 128 129 dataset_import_request = cls( 130 name=name, 131 instrument=instrument, 132 from_=from_, 133 to=to, 134 type_=type_, 135 cadence=cadence, 136 dex=dex, 137 ) 138 139 dataset_import_request.additional_properties = d 140 return dataset_import_request 141 142 @property 143 def additional_keys(self) -> list[str]: 144 return list(self.additional_properties.keys()) 145 146 def __getitem__(self, key: str) -> Any: 147 return self.additional_properties[key] 148 149 def __setitem__(self, key: str, value: Any) -> None: 150 self.additional_properties[key] = value 151 152 def __delitem__(self, key: str) -> None: 153 del self.additional_properties[key] 154 155 def __contains__(self, key: str) -> bool: 156 return key in self.additional_properties
POST /datasets/imports's request body. A common block plus one type-specific block,
selected by type — dex is the only value today.
Attributes:
name (str): A name unique among your datasets. `409` if already taken. Example: weth-usdc-week.
instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT.
from_ (datetime.datetime): Start of the range to fetch, inclusive. Must be before `to`. Example:
2026-08-01T00:00:00Z.
to (datetime.datetime): End of the range to fetch, exclusive. The total span is capped by your tier — a
request wider than that ceiling is `400`, regardless of source type.
Example: 2026-08-08T00:00:00Z.
type_ (DatasetImportRequestType): The source to fetch from. `dex` is the only value today. Example: dex.
cadence (DatasetImportRequestCadence | Unset): Optional. Omitted/blank keeps native per-trade event cadence —
each swap at its own
timestamp, so the resulting version's `cadence` is `rt` unless the swaps happen to sit
on a fixed grid (see `DatasetVersion.cadence`). Set to `1s`, `1m` or
`5m` instead to get pre-aggregated candles at that width rather than raw trades (the
resulting dataset's `type` becomes `klines`); any other value is `400`. Not every
network supports every cadence — an unsupported combination fails asynchronously, not
at request time (see `DatasetImportState.error`).
dex (DatasetImportDexRequest | Unset): The `dex` source's own fields — required when `type` is `dex`.
`id`/`version` are required
for a plain (native-cadence) import; both are ignored if the top-level `cadence` requested
pre-aggregated candles instead, since that path needs neither a protocol nor a version
distinction.
Example: {'network': 'ethereum', 'id': 'uniswap', 'version': 'v3', 'contract':
'0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640'}.
30def __init__(self, name, instrument, from_, to, type_, cadence=attr_dict['cadence'].default, dex=attr_dict['dex'].default): 31 self.name = name 32 self.instrument = instrument 33 self.from_ = from_ 34 self.to = to 35 self.type_ = type_ 36 self.cadence = cadence 37 self.dex = dex 38 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetImportRequest.
63 def to_dict(self) -> dict[str, Any]: 64 name = self.name 65 66 instrument = self.instrument 67 68 from_ = self.from_.isoformat() 69 70 to = self.to.isoformat() 71 72 type_ = self.type_.value 73 74 cadence: str | Unset = UNSET 75 if not isinstance(self.cadence, Unset): 76 cadence = self.cadence.value 77 78 dex: dict[str, Any] | Unset = UNSET 79 if not isinstance(self.dex, Unset): 80 dex = self.dex.to_dict() 81 82 field_dict: dict[str, Any] = {} 83 field_dict.update(self.additional_properties) 84 field_dict.update( 85 { 86 "name": name, 87 "instrument": instrument, 88 "from": from_, 89 "to": to, 90 "type": type_, 91 } 92 ) 93 if cadence is not UNSET: 94 field_dict["cadence"] = cadence 95 if dex is not UNSET: 96 field_dict["dex"] = dex 97 98 return field_dict
100 @classmethod 101 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 102 from ..models.dataset_import_dex_request import DatasetImportDexRequest 103 104 d = dict(src_dict) 105 name = d.pop("name") 106 107 instrument = d.pop("instrument") 108 109 from_ = isoparse(d.pop("from")) 110 111 to = isoparse(d.pop("to")) 112 113 type_ = DatasetImportRequestType(d.pop("type")) 114 115 _cadence = d.pop("cadence", UNSET) 116 cadence: DatasetImportRequestCadence | Unset 117 if isinstance(_cadence, Unset): 118 cadence = UNSET 119 else: 120 cadence = DatasetImportRequestCadence(_cadence) 121 122 _dex = d.pop("dex", UNSET) 123 dex: DatasetImportDexRequest | Unset 124 if isinstance(_dex, Unset): 125 dex = UNSET 126 else: 127 dex = DatasetImportDexRequest.from_dict(_dex) 128 129 dataset_import_request = cls( 130 name=name, 131 instrument=instrument, 132 from_=from_, 133 to=to, 134 type_=type_, 135 cadence=cadence, 136 dex=dex, 137 ) 138 139 dataset_import_request.additional_properties = d 140 return dataset_import_request
5class DatasetImportRequestCadence(str, Enum): 6 VALUE_0 = "1s" 7 VALUE_1 = "1m" 8 VALUE_2 = "5m" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetImportRequestType(str, Enum): 6 DEX = "dex" 7 8 def __str__(self) -> str: 9 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
20@_attrs_define 21class DatasetImportState: 22 """Progress of one import, from fetching through ingest. `fetching` is the one status only an 23 import ever reports — an upload's file already exists by the time you can poll it; an 24 import's doesn't, until this source finishes fetching it. 25 26 Attributes: 27 import_id (str): Example: imp_01j9z1x2y3z4a5b6c7d8e9f0g1. 28 status (DatasetImportStateStatus): * `fetching` — reading from the source; nothing staged yet. 29 * `ingesting` — fetch complete, staged, and re-entered the same ingest chain an 30 upload uses; the worker is parsing and validating it. 31 * `ready` — ingested successfully. `version` carries the result. 32 * `failed` — the fetch or the ingest that followed it was rejected. `error` names why. 33 Example: ready. 34 job_id (str | Unset): The fetch/ingest job id, while `status` is `fetching` or `ingesting`. 35 error (str | Unset): A human-readable reason, present when `status` is `failed` — an unresolvable 36 pool/pair, no data in the requested range, a range older than the configured source 37 retains, the fetch exceeding your tier's time ceiling, or any of 38 `DatasetUploadState.error`'s own ingest-side reasons once fetching hands off to it. 39 Durably recorded, same as on the upload path. 40 Example: Import exceeded the tier's 12 minute ceiling. 41 version (DatasetVersion | Unset): One successfully ingested upload. Cadence and timestamp unit are discovered 42 from the file, 43 not declared by the caller. 44 """ 45 46 import_id: str 47 status: DatasetImportStateStatus 48 job_id: str | Unset = UNSET 49 error: str | Unset = UNSET 50 version: DatasetVersion | Unset = UNSET 51 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 52 53 def to_dict(self) -> dict[str, Any]: 54 import_id = self.import_id 55 56 status = self.status.value 57 58 job_id = self.job_id 59 60 error = self.error 61 62 version: dict[str, Any] | Unset = UNSET 63 if not isinstance(self.version, Unset): 64 version = self.version.to_dict() 65 66 field_dict: dict[str, Any] = {} 67 field_dict.update(self.additional_properties) 68 field_dict.update( 69 { 70 "importId": import_id, 71 "status": status, 72 } 73 ) 74 if job_id is not UNSET: 75 field_dict["jobId"] = job_id 76 if error is not UNSET: 77 field_dict["error"] = error 78 if version is not UNSET: 79 field_dict["version"] = version 80 81 return field_dict 82 83 @classmethod 84 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 85 from ..models.dataset_version import DatasetVersion 86 87 d = dict(src_dict) 88 import_id = d.pop("importId") 89 90 status = DatasetImportStateStatus(d.pop("status")) 91 92 job_id = d.pop("jobId", UNSET) 93 94 error = d.pop("error", UNSET) 95 96 _version = d.pop("version", UNSET) 97 version: DatasetVersion | Unset 98 if isinstance(_version, Unset): 99 version = UNSET 100 else: 101 version = DatasetVersion.from_dict(_version) 102 103 dataset_import_state = cls( 104 import_id=import_id, 105 status=status, 106 job_id=job_id, 107 error=error, 108 version=version, 109 ) 110 111 dataset_import_state.additional_properties = d 112 return dataset_import_state 113 114 @property 115 def additional_keys(self) -> list[str]: 116 return list(self.additional_properties.keys()) 117 118 def __getitem__(self, key: str) -> Any: 119 return self.additional_properties[key] 120 121 def __setitem__(self, key: str, value: Any) -> None: 122 self.additional_properties[key] = value 123 124 def __delitem__(self, key: str) -> None: 125 del self.additional_properties[key] 126 127 def __contains__(self, key: str) -> bool: 128 return key in self.additional_properties
Progress of one import, from fetching through ingest. fetching is the one status only an
import ever reports — an upload's file already exists by the time you can poll it; an
import's doesn't, until this source finishes fetching it.
Attributes:
import_id (str): Example: imp_01j9z1x2y3z4a5b6c7d8e9f0g1.
status (DatasetImportStateStatus): * `fetching` — reading from the source; nothing staged yet.
* `ingesting` — fetch complete, staged, and re-entered the same ingest chain an
upload uses; the worker is parsing and validating it.
* `ready` — ingested successfully. `version` carries the result.
* `failed` — the fetch or the ingest that followed it was rejected. `error` names why.
Example: ready.
job_id (str | Unset): The fetch/ingest job id, while `status` is `fetching` or `ingesting`.
error (str | Unset): A human-readable reason, present when `status` is `failed` — an unresolvable
pool/pair, no data in the requested range, a range older than the configured source
retains, the fetch exceeding your tier's time ceiling, or any of
`DatasetUploadState.error`'s own ingest-side reasons once fetching hands off to it.
Durably recorded, same as on the upload path.
Example: Import exceeded the tier's 12 minute ceiling.
version (DatasetVersion | Unset): One successfully ingested upload. Cadence and timestamp unit are discovered
from the file,
not declared by the caller.
28def __init__(self, import_id, status, job_id=attr_dict['job_id'].default, error=attr_dict['error'].default, version=attr_dict['version'].default): 29 self.import_id = import_id 30 self.status = status 31 self.job_id = job_id 32 self.error = error 33 self.version = version 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetImportState.
53 def to_dict(self) -> dict[str, Any]: 54 import_id = self.import_id 55 56 status = self.status.value 57 58 job_id = self.job_id 59 60 error = self.error 61 62 version: dict[str, Any] | Unset = UNSET 63 if not isinstance(self.version, Unset): 64 version = self.version.to_dict() 65 66 field_dict: dict[str, Any] = {} 67 field_dict.update(self.additional_properties) 68 field_dict.update( 69 { 70 "importId": import_id, 71 "status": status, 72 } 73 ) 74 if job_id is not UNSET: 75 field_dict["jobId"] = job_id 76 if error is not UNSET: 77 field_dict["error"] = error 78 if version is not UNSET: 79 field_dict["version"] = version 80 81 return field_dict
83 @classmethod 84 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 85 from ..models.dataset_version import DatasetVersion 86 87 d = dict(src_dict) 88 import_id = d.pop("importId") 89 90 status = DatasetImportStateStatus(d.pop("status")) 91 92 job_id = d.pop("jobId", UNSET) 93 94 error = d.pop("error", UNSET) 95 96 _version = d.pop("version", UNSET) 97 version: DatasetVersion | Unset 98 if isinstance(_version, Unset): 99 version = UNSET 100 else: 101 version = DatasetVersion.from_dict(_version) 102 103 dataset_import_state = cls( 104 import_id=import_id, 105 status=status, 106 job_id=job_id, 107 error=error, 108 version=version, 109 ) 110 111 dataset_import_state.additional_properties = d 112 return dataset_import_state
5class DatasetImportStateStatus(str, Enum): 6 FAILED = "failed" 7 FETCHING = "fetching" 8 INGESTING = "ingesting" 9 READY = "ready" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetStatus(str, Enum): 6 FAILED = "failed" 7 PENDING = "pending" 8 READY = "ready" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetTimestampUnit(str, Enum): 6 ISO = "iso" 7 MS = "ms" 8 S = "s" 9 US = "us" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetType(str, Enum): 6 KLINES = "klines" 7 TICKER = "ticker" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class DatasetUploadSession: 19 """An upload session — an id plus the presigned URL to PUT the raw file to. Returned both by 20 `POST /datasets` (as part of the new dataset) and by `POST /datasets/{datasetId}/uploads` 21 (on its own, for an existing one). 22 23 Attributes: 24 upload_id (str): Identifies this upload session. Pass to 25 `POST /datasets/{datasetId}/uploads/{uploadId}/finalize` once the PUT completes. 26 Example: up_1a2b3c4d5e6f7a8b. 27 upload (DatasetUploadTarget): A presigned destination for uploading a raw dataset file directly to storage. 28 """ 29 30 upload_id: str 31 upload: DatasetUploadTarget 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 upload_id = self.upload_id 36 37 upload = self.upload.to_dict() 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update( 42 { 43 "uploadId": upload_id, 44 "upload": upload, 45 } 46 ) 47 48 return field_dict 49 50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 from ..models.dataset_upload_target import DatasetUploadTarget 53 54 d = dict(src_dict) 55 upload_id = d.pop("uploadId") 56 57 upload = DatasetUploadTarget.from_dict(d.pop("upload")) 58 59 dataset_upload_session = cls( 60 upload_id=upload_id, 61 upload=upload, 62 ) 63 64 dataset_upload_session.additional_properties = d 65 return dataset_upload_session 66 67 @property 68 def additional_keys(self) -> list[str]: 69 return list(self.additional_properties.keys()) 70 71 def __getitem__(self, key: str) -> Any: 72 return self.additional_properties[key] 73 74 def __setitem__(self, key: str, value: Any) -> None: 75 self.additional_properties[key] = value 76 77 def __delitem__(self, key: str) -> None: 78 del self.additional_properties[key] 79 80 def __contains__(self, key: str) -> bool: 81 return key in self.additional_properties
An upload session — an id plus the presigned URL to PUT the raw file to. Returned both by
POST /datasets (as part of the new dataset) and by POST /datasets/{datasetId}/uploads
(on its own, for an existing one).
Attributes:
upload_id (str): Identifies this upload session. Pass to
`POST /datasets/{datasetId}/uploads/{uploadId}/finalize` once the PUT completes.
Example: up_1a2b3c4d5e6f7a8b.
upload (DatasetUploadTarget): A presigned destination for uploading a raw dataset file directly to storage.
25def __init__(self, upload_id, upload): 26 self.upload_id = upload_id 27 self.upload = upload 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetUploadSession.
34 def to_dict(self) -> dict[str, Any]: 35 upload_id = self.upload_id 36 37 upload = self.upload.to_dict() 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update( 42 { 43 "uploadId": upload_id, 44 "upload": upload, 45 } 46 ) 47 48 return field_dict
50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 from ..models.dataset_upload_target import DatasetUploadTarget 53 54 d = dict(src_dict) 55 upload_id = d.pop("uploadId") 56 57 upload = DatasetUploadTarget.from_dict(d.pop("upload")) 58 59 dataset_upload_session = cls( 60 upload_id=upload_id, 61 upload=upload, 62 ) 63 64 dataset_upload_session.additional_properties = d 65 return dataset_upload_session
20@_attrs_define 21class DatasetUploadState: 22 """Progress of one upload, from staged through ingest. Durably recorded once a version exists, 23 so `ready`/`failed` are permanent answers; `uploading`/`ingesting` reflect in-flight state 24 that can itself age out — see the `404` case on `GET .../uploads/{uploadId}`. 25 26 Attributes: 27 upload_id (str): Example: up_1a2b3c4d5e6f7a8b. 28 status (DatasetUploadStateStatus): * `uploading` — the file was PUT to the presigned URL, but `finalize` has not 29 been 30 called yet. 31 * `ingesting` — `finalize` was called; the worker is parsing and validating the file. 32 * `ready` — ingested successfully. `version` carries the result. 33 * `failed` — ingest rejected the file (e.g. bad CSV contract, mixed timestamp units, a 34 `.zip` with no file inside or more than one). 35 Example: ready. 36 job_id (str | Unset): The ingest job id, while `status` is `ingesting`. 37 error (str | Unset): A human-readable reason, present when `status` is `failed` (e.g. bad CSV contract, 38 mixed timestamp units, a `.zip` with no file inside or more than one). Durably 39 recorded alongside the failure itself, so it stays available however long after the 40 fact you poll — not tied to how recently the failure happened. 41 Example: line 3: column 'close' is not a number: not-a-number. 42 version (DatasetVersion | Unset): One successfully ingested upload. Cadence and timestamp unit are discovered 43 from the file, 44 not declared by the caller. 45 """ 46 47 upload_id: str 48 status: DatasetUploadStateStatus 49 job_id: str | Unset = UNSET 50 error: str | Unset = UNSET 51 version: DatasetVersion | Unset = UNSET 52 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 53 54 def to_dict(self) -> dict[str, Any]: 55 upload_id = self.upload_id 56 57 status = self.status.value 58 59 job_id = self.job_id 60 61 error = self.error 62 63 version: dict[str, Any] | Unset = UNSET 64 if not isinstance(self.version, Unset): 65 version = self.version.to_dict() 66 67 field_dict: dict[str, Any] = {} 68 field_dict.update(self.additional_properties) 69 field_dict.update( 70 { 71 "uploadId": upload_id, 72 "status": status, 73 } 74 ) 75 if job_id is not UNSET: 76 field_dict["jobId"] = job_id 77 if error is not UNSET: 78 field_dict["error"] = error 79 if version is not UNSET: 80 field_dict["version"] = version 81 82 return field_dict 83 84 @classmethod 85 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 86 from ..models.dataset_version import DatasetVersion 87 88 d = dict(src_dict) 89 upload_id = d.pop("uploadId") 90 91 status = DatasetUploadStateStatus(d.pop("status")) 92 93 job_id = d.pop("jobId", UNSET) 94 95 error = d.pop("error", UNSET) 96 97 _version = d.pop("version", UNSET) 98 version: DatasetVersion | Unset 99 if isinstance(_version, Unset): 100 version = UNSET 101 else: 102 version = DatasetVersion.from_dict(_version) 103 104 dataset_upload_state = cls( 105 upload_id=upload_id, 106 status=status, 107 job_id=job_id, 108 error=error, 109 version=version, 110 ) 111 112 dataset_upload_state.additional_properties = d 113 return dataset_upload_state 114 115 @property 116 def additional_keys(self) -> list[str]: 117 return list(self.additional_properties.keys()) 118 119 def __getitem__(self, key: str) -> Any: 120 return self.additional_properties[key] 121 122 def __setitem__(self, key: str, value: Any) -> None: 123 self.additional_properties[key] = value 124 125 def __delitem__(self, key: str) -> None: 126 del self.additional_properties[key] 127 128 def __contains__(self, key: str) -> bool: 129 return key in self.additional_properties
Progress of one upload, from staged through ingest. Durably recorded once a version exists,
so ready/failed are permanent answers; uploading/ingesting reflect in-flight state
that can itself age out — see the 404 case on GET .../uploads/{uploadId}.
Attributes:
upload_id (str): Example: up_1a2b3c4d5e6f7a8b.
status (DatasetUploadStateStatus): * `uploading` — the file was PUT to the presigned URL, but `finalize` has not
been
called yet.
* `ingesting` — `finalize` was called; the worker is parsing and validating the file.
* `ready` — ingested successfully. `version` carries the result.
* `failed` — ingest rejected the file (e.g. bad CSV contract, mixed timestamp units, a
`.zip` with no file inside or more than one).
Example: ready.
job_id (str | Unset): The ingest job id, while `status` is `ingesting`.
error (str | Unset): A human-readable reason, present when `status` is `failed` (e.g. bad CSV contract,
mixed timestamp units, a `.zip` with no file inside or more than one). Durably
recorded alongside the failure itself, so it stays available however long after the
fact you poll — not tied to how recently the failure happened.
Example: line 3: column 'close' is not a number: not-a-number.
version (DatasetVersion | Unset): One successfully ingested upload. Cadence and timestamp unit are discovered
from the file,
not declared by the caller.
28def __init__(self, upload_id, status, job_id=attr_dict['job_id'].default, error=attr_dict['error'].default, version=attr_dict['version'].default): 29 self.upload_id = upload_id 30 self.status = status 31 self.job_id = job_id 32 self.error = error 33 self.version = version 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetUploadState.
54 def to_dict(self) -> dict[str, Any]: 55 upload_id = self.upload_id 56 57 status = self.status.value 58 59 job_id = self.job_id 60 61 error = self.error 62 63 version: dict[str, Any] | Unset = UNSET 64 if not isinstance(self.version, Unset): 65 version = self.version.to_dict() 66 67 field_dict: dict[str, Any] = {} 68 field_dict.update(self.additional_properties) 69 field_dict.update( 70 { 71 "uploadId": upload_id, 72 "status": status, 73 } 74 ) 75 if job_id is not UNSET: 76 field_dict["jobId"] = job_id 77 if error is not UNSET: 78 field_dict["error"] = error 79 if version is not UNSET: 80 field_dict["version"] = version 81 82 return field_dict
84 @classmethod 85 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 86 from ..models.dataset_version import DatasetVersion 87 88 d = dict(src_dict) 89 upload_id = d.pop("uploadId") 90 91 status = DatasetUploadStateStatus(d.pop("status")) 92 93 job_id = d.pop("jobId", UNSET) 94 95 error = d.pop("error", UNSET) 96 97 _version = d.pop("version", UNSET) 98 version: DatasetVersion | Unset 99 if isinstance(_version, Unset): 100 version = UNSET 101 else: 102 version = DatasetVersion.from_dict(_version) 103 104 dataset_upload_state = cls( 105 upload_id=upload_id, 106 status=status, 107 job_id=job_id, 108 error=error, 109 version=version, 110 ) 111 112 dataset_upload_state.additional_properties = d 113 return dataset_upload_state
5class DatasetUploadStateStatus(str, Enum): 6 FAILED = "failed" 7 INGESTING = "ingesting" 8 READY = "ready" 9 UPLOADING = "uploading" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
13@_attrs_define 14class DatasetUploadTarget: 15 """A presigned destination for uploading a raw dataset file directly to storage. 16 17 Attributes: 18 url (str): Presigned URL. `PUT` the file here directly — the CSV or parquet itself, or a `.gz`/`.zip` of it 19 (see `createDataset`'s own description) — no `Authorization` header, no other API 20 credentials. 21 Example: https://storage.qtsurfer.com/uploads/00000000-.../up_1a2b3c4d5e6f7a8b/raw.csv?X-Amz-.... 22 expires_in_minutes (int): How long `url` stays valid. Example: 15. 23 """ 24 25 url: str 26 expires_in_minutes: int 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 url = self.url 31 32 expires_in_minutes = self.expires_in_minutes 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "url": url, 39 "expiresInMinutes": expires_in_minutes, 40 } 41 ) 42 43 return field_dict 44 45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 url = d.pop("url") 49 50 expires_in_minutes = d.pop("expiresInMinutes") 51 52 dataset_upload_target = cls( 53 url=url, 54 expires_in_minutes=expires_in_minutes, 55 ) 56 57 dataset_upload_target.additional_properties = d 58 return dataset_upload_target 59 60 @property 61 def additional_keys(self) -> list[str]: 62 return list(self.additional_properties.keys()) 63 64 def __getitem__(self, key: str) -> Any: 65 return self.additional_properties[key] 66 67 def __setitem__(self, key: str, value: Any) -> None: 68 self.additional_properties[key] = value 69 70 def __delitem__(self, key: str) -> None: 71 del self.additional_properties[key] 72 73 def __contains__(self, key: str) -> bool: 74 return key in self.additional_properties
A presigned destination for uploading a raw dataset file directly to storage.
Attributes:
url (str): Presigned URL. PUT the file here directly — the CSV or parquet itself, or a .gz/.zip of it
(see createDataset's own description) — no Authorization header, no other API
credentials.
Example: https://storage.qtsurfer.com/uploads/00000000-.../up_1a2b3c4d5e6f7a8b/raw.csv?X-Amz-....
expires_in_minutes (int): How long url stays valid. Example: 15.
25def __init__(self, url, expires_in_minutes): 26 self.url = url 27 self.expires_in_minutes = expires_in_minutes 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetUploadTarget.
29 def to_dict(self) -> dict[str, Any]: 30 url = self.url 31 32 expires_in_minutes = self.expires_in_minutes 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "url": url, 39 "expiresInMinutes": expires_in_minutes, 40 } 41 ) 42 43 return field_dict
45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 url = d.pop("url") 49 50 expires_in_minutes = d.pop("expiresInMinutes") 51 52 dataset_upload_target = cls( 53 url=url, 54 expires_in_minutes=expires_in_minutes, 55 ) 56 57 dataset_upload_target.additional_properties = d 58 return dataset_upload_target
17@_attrs_define 18class DatasetVersion: 19 """One successfully ingested upload. Cadence and timestamp unit are discovered from the file, 20 not declared by the caller. 21 22 Attributes: 23 dataset_id (str): Example: ds_3f9a1c2e7b0d4a5f. 24 id (str | Unset): The version id. Pass as `datasetVersionId` on `POST .../prepare` to pin it. Example: 25 dsv_8e2b4f19c6a03d7e. 26 bytes_ (int | Unset): Size of the stored file `dataUrl` points at — a converted `lastra` for a CSV/gzip/zip 27 upload, or the parquet file itself, unconverted, for a parquet upload. Not the size of the bytes originally PUT 28 to storage; see `dataFormat`. Example: 4831022. 29 rows (int | Unset): Number of data rows. Example: 86400. 30 cadence (str | Unset): The cadence discovered from the data's own timestamps. Either a fixed grid — `1s`, 31 `5s`, `15s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d` — when at least half the 32 intervals between consecutive rows fall on that step (small clock jitter tolerated), or 33 `rt`: native data at the rate it was captured, each row at its own timestamp with no 34 fixed step — per-trade on-chain swaps, block-spaced or sub-second ticks, irregular 35 intervals. An `rt` dataset can be resampled to any fixed cadence at prepare time. 36 Example: 1s. 37 timestamp_unit (DatasetVersionTimestampUnit | Unset): The unit the `timestamp` column was uploaded in — 38 ISO-8601, or the epoch band its 39 numeric values fell in (seconds, millis, or micros). 40 Example: iso. 41 gaps (int | Unset): Number of gaps at the discovered cadence. Always `0` for `rt`. 42 largest_gap_steps (int | Unset): The largest gap, in units of the discovered cadence step. Always `0` for `rt`. 43 data_url (str | Unset): Presigned GET URL to the stored file — see `dataFormat` for which format it's in. 44 Present once the version is `ready`. Long-lived (day-scale, not permanent): a 45 DuckDB-WASM/`lastra-ts`-style reader issues HTTP range requests against it lazily over 46 an extended viewing session, not in one shot like a browser upload. 47 Example: https://storage.qtsurfer.com/00000000- 48 .../ds_3f9a1c2e7b0d4a5f/dsv_8e2b4f19c6a03d7e/ticker_BTC_USDT_1700000000000_1700086400000_1m.lastra?X-Amz-.... 49 data_format (DatasetVersionDataFormat | Unset): Which format `dataUrl` is actually in — check this rather than 50 assuming it matches 51 how you uploaded it. `lastra` — our native columnar format — for a CSV (or gzip/zip 52 of one) upload, always converted on ingest, or for a lastra upload, stored as-is 53 (the value alone doesn't tell you which). `parquet` for a parquet upload, also 54 stored as-is today. 55 Example: lastra. 56 """ 57 58 dataset_id: str 59 id: str | Unset = UNSET 60 bytes_: int | Unset = UNSET 61 rows: int | Unset = UNSET 62 cadence: str | Unset = UNSET 63 timestamp_unit: DatasetVersionTimestampUnit | Unset = UNSET 64 gaps: int | Unset = UNSET 65 largest_gap_steps: int | Unset = UNSET 66 data_url: str | Unset = UNSET 67 data_format: DatasetVersionDataFormat | Unset = UNSET 68 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 69 70 def to_dict(self) -> dict[str, Any]: 71 dataset_id = self.dataset_id 72 73 id = self.id 74 75 bytes_ = self.bytes_ 76 77 rows = self.rows 78 79 cadence = self.cadence 80 81 timestamp_unit: str | Unset = UNSET 82 if not isinstance(self.timestamp_unit, Unset): 83 timestamp_unit = self.timestamp_unit.value 84 85 gaps = self.gaps 86 87 largest_gap_steps = self.largest_gap_steps 88 89 data_url = self.data_url 90 91 data_format: str | Unset = UNSET 92 if not isinstance(self.data_format, Unset): 93 data_format = self.data_format.value 94 95 field_dict: dict[str, Any] = {} 96 field_dict.update(self.additional_properties) 97 field_dict.update( 98 { 99 "datasetId": dataset_id, 100 } 101 ) 102 if id is not UNSET: 103 field_dict["id"] = id 104 if bytes_ is not UNSET: 105 field_dict["bytes"] = bytes_ 106 if rows is not UNSET: 107 field_dict["rows"] = rows 108 if cadence is not UNSET: 109 field_dict["cadence"] = cadence 110 if timestamp_unit is not UNSET: 111 field_dict["timestampUnit"] = timestamp_unit 112 if gaps is not UNSET: 113 field_dict["gaps"] = gaps 114 if largest_gap_steps is not UNSET: 115 field_dict["largestGapSteps"] = largest_gap_steps 116 if data_url is not UNSET: 117 field_dict["dataUrl"] = data_url 118 if data_format is not UNSET: 119 field_dict["dataFormat"] = data_format 120 121 return field_dict 122 123 @classmethod 124 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 125 d = dict(src_dict) 126 dataset_id = d.pop("datasetId") 127 128 id = d.pop("id", UNSET) 129 130 bytes_ = d.pop("bytes", UNSET) 131 132 rows = d.pop("rows", UNSET) 133 134 cadence = d.pop("cadence", UNSET) 135 136 _timestamp_unit = d.pop("timestampUnit", UNSET) 137 timestamp_unit: DatasetVersionTimestampUnit | Unset 138 if isinstance(_timestamp_unit, Unset): 139 timestamp_unit = UNSET 140 else: 141 timestamp_unit = DatasetVersionTimestampUnit(_timestamp_unit) 142 143 gaps = d.pop("gaps", UNSET) 144 145 largest_gap_steps = d.pop("largestGapSteps", UNSET) 146 147 data_url = d.pop("dataUrl", UNSET) 148 149 _data_format = d.pop("dataFormat", UNSET) 150 data_format: DatasetVersionDataFormat | Unset 151 if isinstance(_data_format, Unset): 152 data_format = UNSET 153 else: 154 data_format = DatasetVersionDataFormat(_data_format) 155 156 dataset_version = cls( 157 dataset_id=dataset_id, 158 id=id, 159 bytes_=bytes_, 160 rows=rows, 161 cadence=cadence, 162 timestamp_unit=timestamp_unit, 163 gaps=gaps, 164 largest_gap_steps=largest_gap_steps, 165 data_url=data_url, 166 data_format=data_format, 167 ) 168 169 dataset_version.additional_properties = d 170 return dataset_version 171 172 @property 173 def additional_keys(self) -> list[str]: 174 return list(self.additional_properties.keys()) 175 176 def __getitem__(self, key: str) -> Any: 177 return self.additional_properties[key] 178 179 def __setitem__(self, key: str, value: Any) -> None: 180 self.additional_properties[key] = value 181 182 def __delitem__(self, key: str) -> None: 183 del self.additional_properties[key] 184 185 def __contains__(self, key: str) -> bool: 186 return key in self.additional_properties
One successfully ingested upload. Cadence and timestamp unit are discovered from the file, not declared by the caller.
Attributes:
dataset_id (str): Example: ds_3f9a1c2e7b0d4a5f.
id (str | Unset): The version id. Pass as `datasetVersionId` on `POST .../prepare` to pin it. Example:
dsv_8e2b4f19c6a03d7e.
bytes_ (int | Unset): Size of the stored file `dataUrl` points at — a converted `lastra` for a CSV/gzip/zip
upload, or the parquet file itself, unconverted, for a parquet upload. Not the size of the bytes originally PUT
to storage; see `dataFormat`. Example: 4831022.
rows (int | Unset): Number of data rows. Example: 86400.
cadence (str | Unset): The cadence discovered from the data's own timestamps. Either a fixed grid — `1s`,
`5s`, `15s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d` — when at least half the
intervals between consecutive rows fall on that step (small clock jitter tolerated), or
`rt`: native data at the rate it was captured, each row at its own timestamp with no
fixed step — per-trade on-chain swaps, block-spaced or sub-second ticks, irregular
intervals. An `rt` dataset can be resampled to any fixed cadence at prepare time.
Example: 1s.
timestamp_unit (DatasetVersionTimestampUnit | Unset): The unit the `timestamp` column was uploaded in —
ISO-8601, or the epoch band its
numeric values fell in (seconds, millis, or micros).
Example: iso.
gaps (int | Unset): Number of gaps at the discovered cadence. Always `0` for `rt`.
largest_gap_steps (int | Unset): The largest gap, in units of the discovered cadence step. Always `0` for `rt`.
data_url (str | Unset): Presigned GET URL to the stored file — see `dataFormat` for which format it's in.
Present once the version is `ready`. Long-lived (day-scale, not permanent): a
DuckDB-WASM/`lastra-ts`-style reader issues HTTP range requests against it lazily over
an extended viewing session, not in one shot like a browser upload.
Example: https://storage.qtsurfer.com/00000000-
.../ds_3f9a1c2e7b0d4a5f/dsv_8e2b4f19c6a03d7e/ticker_BTC_USDT_1700000000000_1700086400000_1m.lastra?X-Amz-....
data_format (DatasetVersionDataFormat | Unset): Which format `dataUrl` is actually in — check this rather than
assuming it matches
how you uploaded it. `lastra` — our native columnar format — for a CSV (or gzip/zip
of one) upload, always converted on ingest, or for a lastra upload, stored as-is
(the value alone doesn't tell you which). `parquet` for a parquet upload, also
stored as-is today.
Example: lastra.
33def __init__(self, dataset_id, id=attr_dict['id'].default, bytes_=attr_dict['bytes_'].default, rows=attr_dict['rows'].default, cadence=attr_dict['cadence'].default, timestamp_unit=attr_dict['timestamp_unit'].default, gaps=attr_dict['gaps'].default, largest_gap_steps=attr_dict['largest_gap_steps'].default, data_url=attr_dict['data_url'].default, data_format=attr_dict['data_format'].default): 34 self.dataset_id = dataset_id 35 self.id = id 36 self.bytes_ = bytes_ 37 self.rows = rows 38 self.cadence = cadence 39 self.timestamp_unit = timestamp_unit 40 self.gaps = gaps 41 self.largest_gap_steps = largest_gap_steps 42 self.data_url = data_url 43 self.data_format = data_format 44 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetVersion.
70 def to_dict(self) -> dict[str, Any]: 71 dataset_id = self.dataset_id 72 73 id = self.id 74 75 bytes_ = self.bytes_ 76 77 rows = self.rows 78 79 cadence = self.cadence 80 81 timestamp_unit: str | Unset = UNSET 82 if not isinstance(self.timestamp_unit, Unset): 83 timestamp_unit = self.timestamp_unit.value 84 85 gaps = self.gaps 86 87 largest_gap_steps = self.largest_gap_steps 88 89 data_url = self.data_url 90 91 data_format: str | Unset = UNSET 92 if not isinstance(self.data_format, Unset): 93 data_format = self.data_format.value 94 95 field_dict: dict[str, Any] = {} 96 field_dict.update(self.additional_properties) 97 field_dict.update( 98 { 99 "datasetId": dataset_id, 100 } 101 ) 102 if id is not UNSET: 103 field_dict["id"] = id 104 if bytes_ is not UNSET: 105 field_dict["bytes"] = bytes_ 106 if rows is not UNSET: 107 field_dict["rows"] = rows 108 if cadence is not UNSET: 109 field_dict["cadence"] = cadence 110 if timestamp_unit is not UNSET: 111 field_dict["timestampUnit"] = timestamp_unit 112 if gaps is not UNSET: 113 field_dict["gaps"] = gaps 114 if largest_gap_steps is not UNSET: 115 field_dict["largestGapSteps"] = largest_gap_steps 116 if data_url is not UNSET: 117 field_dict["dataUrl"] = data_url 118 if data_format is not UNSET: 119 field_dict["dataFormat"] = data_format 120 121 return field_dict
123 @classmethod 124 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 125 d = dict(src_dict) 126 dataset_id = d.pop("datasetId") 127 128 id = d.pop("id", UNSET) 129 130 bytes_ = d.pop("bytes", UNSET) 131 132 rows = d.pop("rows", UNSET) 133 134 cadence = d.pop("cadence", UNSET) 135 136 _timestamp_unit = d.pop("timestampUnit", UNSET) 137 timestamp_unit: DatasetVersionTimestampUnit | Unset 138 if isinstance(_timestamp_unit, Unset): 139 timestamp_unit = UNSET 140 else: 141 timestamp_unit = DatasetVersionTimestampUnit(_timestamp_unit) 142 143 gaps = d.pop("gaps", UNSET) 144 145 largest_gap_steps = d.pop("largestGapSteps", UNSET) 146 147 data_url = d.pop("dataUrl", UNSET) 148 149 _data_format = d.pop("dataFormat", UNSET) 150 data_format: DatasetVersionDataFormat | Unset 151 if isinstance(_data_format, Unset): 152 data_format = UNSET 153 else: 154 data_format = DatasetVersionDataFormat(_data_format) 155 156 dataset_version = cls( 157 dataset_id=dataset_id, 158 id=id, 159 bytes_=bytes_, 160 rows=rows, 161 cadence=cadence, 162 timestamp_unit=timestamp_unit, 163 gaps=gaps, 164 largest_gap_steps=largest_gap_steps, 165 data_url=data_url, 166 data_format=data_format, 167 ) 168 169 dataset_version.additional_properties = d 170 return dataset_version
5class DatasetVersionDataFormat(str, Enum): 6 LASTRA = "lastra" 7 PARQUET = "parquet" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DatasetVersionTimestampUnit(str, Enum): 6 ISO = "iso" 7 MS = "ms" 8 S = "s" 9 US = "us" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
25@_attrs_define 26class DatasetWithLinks: 27 """A `Dataset` plus a self link. Returned by `GET /datasets/{datasetId}`. 28 29 Attributes: 30 dataset_id (str): Opaque id, returned by `POST /datasets`. Example: ds_3f9a1c2e7b0d4a5f. 31 name (str): Unique among your datasets. Example: My BTC ticks. 32 type_ (DatasetType): `ticker` for an upload or a `dex` import with no `cadence` requested (native per-trade 33 data). `klines` for a `dex` import that requested a candle `cadence` — pre-aggregated 34 bars rather than raw ticks. Purely informational; both shapes are read the same way. 35 Example: ticker. 36 instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT. 37 created_at (datetime.datetime): When the dataset was created. Example: 2026-08-20T09:00:00Z. 38 status (DatasetStatus): * `ready` — `currentVersionId` is set; `from`/`to`/`cadence`/`bytes`/`rows`/`gaps`/ 39 `largestGapSteps` describe it. 40 * `failed` — the most recent upload/import attempt failed. `currentVersionId` and the 41 fields above are absent — there is nothing to read yet. See `error`. 42 * `pending` — nothing has ever been attempted (just created, or an upload was never 43 finalized). 44 Example: ready. 45 current_version_id (str | Unset): The id of the most recently finalized, successfully ingested version. Absent 46 until at 47 least one upload has finished ingesting. 48 Example: dsv_8e2b4f19c6a03d7e. 49 deleted_at (datetime.datetime | Unset): When you deleted this dataset. Only ever present in `GET 50 /datasets?includeDeleted=true`, 51 and only on datasets you have deleted. 52 updated_at (datetime.datetime | Unset): When `currentVersionId` last changed. Absent until it has a value. 53 Example: 2026-08-20T09:04:12Z. 54 from_ (datetime.datetime | Unset): Start of `currentVersionId`'s own data range, as discovered at ingest time. 55 Absent 56 until a version exists. 57 Example: 2026-03-01T00:00:00Z. 58 to (datetime.datetime | Unset): End of `currentVersionId`'s own data range, as discovered at ingest time. Absent 59 until 60 a version exists. 61 Example: 2026-03-08T00:00:00Z. 62 cadence (str | Unset): `currentVersionId`'s own discovered cadence — a fixed grid (e.g. `1s`, `1m`, `1h`) or 63 `rt` (see `DatasetVersion.cadence`). Absent until a version exists. 64 Example: 1m. 65 timestamp_unit (DatasetTimestampUnit | Unset): `currentVersionId`'s own timestamp unit (see 66 `DatasetVersion.timestampUnit`) — decode 67 the `timestamp` column of `dataUrl`'s file accordingly. Present only when `status` is 68 `ready`. 69 Example: iso. 70 bytes_ (int | Unset): Size of `currentVersionId`'s own stored file. Present only when `status` is `ready` — 71 see `DatasetVersion.bytes` for what it measures exactly. 72 Example: 4831022. 73 rows (int | Unset): `currentVersionId`'s own row count. Present only when `status` is `ready`. Example: 86400. 74 gaps (int | Unset): `currentVersionId`'s own gap count at its discovered cadence. Present only when `status` is 75 `ready`. 76 largest_gap_steps (int | Unset): `currentVersionId`'s own largest gap, in units of its discovered cadence step. 77 Present only when `status` is `ready`. 78 error (str | Unset): A human-readable reason the most recent upload/import attempt failed. Present only 79 when `status` is `failed`. 80 Example: line 3: column 'close' is not a number: not-a-number. 81 data_url (str | Unset): Presigned GET URL to the current version's stored file — see `dataFormat` for 82 which format it's actually in. Present only once the current version's status is 83 `ready`. Long-lived (day-scale, not permanent): a DuckDB-WASM/`lastra-ts`-style 84 reader issues HTTP range requests against it lazily over an extended viewing 85 session, not in one shot like a browser upload. 86 Example: https://storage.qtsurfer.com/00000000- 87 .../ds_3f9a1c2e7b0d4a5f/dsv_8e2b4f19c6a03d7e/ticker_BTC_USDT_1700000000000_1700086400000_1m.lastra?X-Amz-.... 88 data_format (DatasetWithLinksDataFormat | Unset): Which format `dataUrl` is actually in — check this rather than 89 assuming it 90 matches how you uploaded it. `lastra` — our native columnar format — for a CSV (or 91 gzip/zip of one) upload, always converted on ingest, or for a lastra upload, 92 stored as-is (the value alone doesn't tell you which). `parquet` for a parquet 93 upload, also stored as-is today. 94 Example: lastra. 95 field_links (DatasetWithLinksLinks | Unset): 96 """ 97 98 dataset_id: str 99 name: str 100 type_: DatasetType 101 instrument: str 102 created_at: datetime.datetime 103 status: DatasetStatus 104 current_version_id: str | Unset = UNSET 105 deleted_at: datetime.datetime | Unset = UNSET 106 updated_at: datetime.datetime | Unset = UNSET 107 from_: datetime.datetime | Unset = UNSET 108 to: datetime.datetime | Unset = UNSET 109 cadence: str | Unset = UNSET 110 timestamp_unit: DatasetTimestampUnit | Unset = UNSET 111 bytes_: int | Unset = UNSET 112 rows: int | Unset = UNSET 113 gaps: int | Unset = UNSET 114 largest_gap_steps: int | Unset = UNSET 115 error: str | Unset = UNSET 116 data_url: str | Unset = UNSET 117 data_format: DatasetWithLinksDataFormat | Unset = UNSET 118 field_links: DatasetWithLinksLinks | Unset = UNSET 119 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 120 121 def to_dict(self) -> dict[str, Any]: 122 dataset_id = self.dataset_id 123 124 name = self.name 125 126 type_ = self.type_.value 127 128 instrument = self.instrument 129 130 created_at = self.created_at.isoformat() 131 132 status = self.status.value 133 134 current_version_id = self.current_version_id 135 136 deleted_at: str | Unset = UNSET 137 if not isinstance(self.deleted_at, Unset): 138 deleted_at = self.deleted_at.isoformat() 139 140 updated_at: str | Unset = UNSET 141 if not isinstance(self.updated_at, Unset): 142 updated_at = self.updated_at.isoformat() 143 144 from_: str | Unset = UNSET 145 if not isinstance(self.from_, Unset): 146 from_ = self.from_.isoformat() 147 148 to: str | Unset = UNSET 149 if not isinstance(self.to, Unset): 150 to = self.to.isoformat() 151 152 cadence = self.cadence 153 154 timestamp_unit: str | Unset = UNSET 155 if not isinstance(self.timestamp_unit, Unset): 156 timestamp_unit = self.timestamp_unit.value 157 158 bytes_ = self.bytes_ 159 160 rows = self.rows 161 162 gaps = self.gaps 163 164 largest_gap_steps = self.largest_gap_steps 165 166 error = self.error 167 168 data_url = self.data_url 169 170 data_format: str | Unset = UNSET 171 if not isinstance(self.data_format, Unset): 172 data_format = self.data_format.value 173 174 field_links: dict[str, Any] | Unset = UNSET 175 if not isinstance(self.field_links, Unset): 176 field_links = self.field_links.to_dict() 177 178 field_dict: dict[str, Any] = {} 179 field_dict.update(self.additional_properties) 180 field_dict.update( 181 { 182 "datasetId": dataset_id, 183 "name": name, 184 "type": type_, 185 "instrument": instrument, 186 "createdAt": created_at, 187 "status": status, 188 } 189 ) 190 if current_version_id is not UNSET: 191 field_dict["currentVersionId"] = current_version_id 192 if deleted_at is not UNSET: 193 field_dict["deletedAt"] = deleted_at 194 if updated_at is not UNSET: 195 field_dict["updatedAt"] = updated_at 196 if from_ is not UNSET: 197 field_dict["from"] = from_ 198 if to is not UNSET: 199 field_dict["to"] = to 200 if cadence is not UNSET: 201 field_dict["cadence"] = cadence 202 if timestamp_unit is not UNSET: 203 field_dict["timestampUnit"] = timestamp_unit 204 if bytes_ is not UNSET: 205 field_dict["bytes"] = bytes_ 206 if rows is not UNSET: 207 field_dict["rows"] = rows 208 if gaps is not UNSET: 209 field_dict["gaps"] = gaps 210 if largest_gap_steps is not UNSET: 211 field_dict["largestGapSteps"] = largest_gap_steps 212 if error is not UNSET: 213 field_dict["error"] = error 214 if data_url is not UNSET: 215 field_dict["dataUrl"] = data_url 216 if data_format is not UNSET: 217 field_dict["dataFormat"] = data_format 218 if field_links is not UNSET: 219 field_dict["_links"] = field_links 220 221 return field_dict 222 223 @classmethod 224 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 225 from ..models.dataset_with_links_links import DatasetWithLinksLinks 226 227 d = dict(src_dict) 228 dataset_id = d.pop("datasetId") 229 230 name = d.pop("name") 231 232 type_ = DatasetType(d.pop("type")) 233 234 instrument = d.pop("instrument") 235 236 created_at = isoparse(d.pop("createdAt")) 237 238 status = DatasetStatus(d.pop("status")) 239 240 current_version_id = d.pop("currentVersionId", UNSET) 241 242 _deleted_at = d.pop("deletedAt", UNSET) 243 deleted_at: datetime.datetime | Unset 244 if isinstance(_deleted_at, Unset): 245 deleted_at = UNSET 246 else: 247 deleted_at = isoparse(_deleted_at) 248 249 _updated_at = d.pop("updatedAt", UNSET) 250 updated_at: datetime.datetime | Unset 251 if isinstance(_updated_at, Unset): 252 updated_at = UNSET 253 else: 254 updated_at = isoparse(_updated_at) 255 256 _from_ = d.pop("from", UNSET) 257 from_: datetime.datetime | Unset 258 if isinstance(_from_, Unset): 259 from_ = UNSET 260 else: 261 from_ = isoparse(_from_) 262 263 _to = d.pop("to", UNSET) 264 to: datetime.datetime | Unset 265 if isinstance(_to, Unset): 266 to = UNSET 267 else: 268 to = isoparse(_to) 269 270 cadence = d.pop("cadence", UNSET) 271 272 _timestamp_unit = d.pop("timestampUnit", UNSET) 273 timestamp_unit: DatasetTimestampUnit | Unset 274 if isinstance(_timestamp_unit, Unset): 275 timestamp_unit = UNSET 276 else: 277 timestamp_unit = DatasetTimestampUnit(_timestamp_unit) 278 279 bytes_ = d.pop("bytes", UNSET) 280 281 rows = d.pop("rows", UNSET) 282 283 gaps = d.pop("gaps", UNSET) 284 285 largest_gap_steps = d.pop("largestGapSteps", UNSET) 286 287 error = d.pop("error", UNSET) 288 289 data_url = d.pop("dataUrl", UNSET) 290 291 _data_format = d.pop("dataFormat", UNSET) 292 data_format: DatasetWithLinksDataFormat | Unset 293 if isinstance(_data_format, Unset): 294 data_format = UNSET 295 else: 296 data_format = DatasetWithLinksDataFormat(_data_format) 297 298 _field_links = d.pop("_links", UNSET) 299 field_links: DatasetWithLinksLinks | Unset 300 if isinstance(_field_links, Unset): 301 field_links = UNSET 302 else: 303 field_links = DatasetWithLinksLinks.from_dict(_field_links) 304 305 dataset_with_links = cls( 306 dataset_id=dataset_id, 307 name=name, 308 type_=type_, 309 instrument=instrument, 310 created_at=created_at, 311 status=status, 312 current_version_id=current_version_id, 313 deleted_at=deleted_at, 314 updated_at=updated_at, 315 from_=from_, 316 to=to, 317 cadence=cadence, 318 timestamp_unit=timestamp_unit, 319 bytes_=bytes_, 320 rows=rows, 321 gaps=gaps, 322 largest_gap_steps=largest_gap_steps, 323 error=error, 324 data_url=data_url, 325 data_format=data_format, 326 field_links=field_links, 327 ) 328 329 dataset_with_links.additional_properties = d 330 return dataset_with_links 331 332 @property 333 def additional_keys(self) -> list[str]: 334 return list(self.additional_properties.keys()) 335 336 def __getitem__(self, key: str) -> Any: 337 return self.additional_properties[key] 338 339 def __setitem__(self, key: str, value: Any) -> None: 340 self.additional_properties[key] = value 341 342 def __delitem__(self, key: str) -> None: 343 del self.additional_properties[key] 344 345 def __contains__(self, key: str) -> bool: 346 return key in self.additional_properties
A Dataset plus a self link. Returned by GET /datasets/{datasetId}.
Attributes:
dataset_id (str): Opaque id, returned by POST /datasets. Example: ds_3f9a1c2e7b0d4a5f.
name (str): Unique among your datasets. Example: My BTC ticks.
type_ (DatasetType): ticker for an upload or a dex import with no cadence requested (native per-trade
data). klines for a dex import that requested a candle cadence — pre-aggregated
bars rather than raw ticks. Purely informational; both shapes are read the same way.
Example: ticker.
instrument (str): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT.
created_at (datetime.datetime): When the dataset was created. Example: 2026-08-20T09:00:00Z.
status (DatasetStatus): * ready — currentVersionId is set; from/to/cadence/bytes/rows/gaps/
largestGapSteps describe it.
* failed — the most recent upload/import attempt failed. currentVersionId and the
fields above are absent — there is nothing to read yet. See error.
* pending — nothing has ever been attempted (just created, or an upload was never
finalized).
Example: ready.
current_version_id (str | Unset): The id of the most recently finalized, successfully ingested version. Absent
until at
least one upload has finished ingesting.
Example: dsv_8e2b4f19c6a03d7e.
deleted_at (datetime.datetime | Unset): When you deleted this dataset. Only ever present in GET
/datasets?includeDeleted=true,
and only on datasets you have deleted.
updated_at (datetime.datetime | Unset): When currentVersionId last changed. Absent until it has a value.
Example: 2026-08-20T09:04:12Z.
from_ (datetime.datetime | Unset): Start of currentVersionId's own data range, as discovered at ingest time.
Absent
until a version exists.
Example: 2026-03-01T00:00:00Z.
to (datetime.datetime | Unset): End of currentVersionId's own data range, as discovered at ingest time. Absent
until
a version exists.
Example: 2026-03-08T00:00:00Z.
cadence (str | Unset): currentVersionId's own discovered cadence — a fixed grid (e.g. 1s, 1m, 1h) or
rt (see DatasetVersion.cadence). Absent until a version exists.
Example: 1m.
timestamp_unit (DatasetTimestampUnit | Unset): currentVersionId's own timestamp unit (see
DatasetVersion.timestampUnit) — decode
the timestamp column of dataUrl's file accordingly. Present only when status is
ready.
Example: iso.
bytes_ (int | Unset): Size of currentVersionId's own stored file. Present only when status is ready —
see DatasetVersion.bytes for what it measures exactly.
Example: 4831022.
rows (int | Unset): currentVersionId's own row count. Present only when status is ready. Example: 86400.
gaps (int | Unset): currentVersionId's own gap count at its discovered cadence. Present only when status is
ready.
largest_gap_steps (int | Unset): currentVersionId's own largest gap, in units of its discovered cadence step.
Present only when status is ready.
error (str | Unset): A human-readable reason the most recent upload/import attempt failed. Present only
when status is failed.
Example: line 3: column 'close' is not a number: not-a-number.
data_url (str | Unset): Presigned GET URL to the current version's stored file — see dataFormat for
which format it's actually in. Present only once the current version's status is
ready. Long-lived (day-scale, not permanent): a DuckDB-WASM/lastra-ts-style
reader issues HTTP range requests against it lazily over an extended viewing
session, not in one shot like a browser upload.
Example: https://storage.qtsurfer.com/00000000-
.../ds_3f9a1c2e7b0d4a5f/dsv_8e2b4f19c6a03d7e/ticker_BTC_USDT_1700000000000_1700086400000_1m.lastra?X-Amz-....
data_format (DatasetWithLinksDataFormat | Unset): Which format dataUrl is actually in — check this rather than
assuming it
matches how you uploaded it. lastra — our native columnar format — for a CSV (or
gzip/zip of one) upload, always converted on ingest, or for a lastra upload,
stored as-is (the value alone doesn't tell you which). parquet for a parquet
upload, also stored as-is today.
Example: lastra.
field_links (DatasetWithLinksLinks | Unset):
44def __init__(self, dataset_id, name, type_, instrument, created_at, status, current_version_id=attr_dict['current_version_id'].default, deleted_at=attr_dict['deleted_at'].default, updated_at=attr_dict['updated_at'].default, from_=attr_dict['from_'].default, to=attr_dict['to'].default, cadence=attr_dict['cadence'].default, timestamp_unit=attr_dict['timestamp_unit'].default, bytes_=attr_dict['bytes_'].default, rows=attr_dict['rows'].default, gaps=attr_dict['gaps'].default, largest_gap_steps=attr_dict['largest_gap_steps'].default, error=attr_dict['error'].default, data_url=attr_dict['data_url'].default, data_format=attr_dict['data_format'].default, field_links=attr_dict['field_links'].default): 45 self.dataset_id = dataset_id 46 self.name = name 47 self.type_ = type_ 48 self.instrument = instrument 49 self.created_at = created_at 50 self.status = status 51 self.current_version_id = current_version_id 52 self.deleted_at = deleted_at 53 self.updated_at = updated_at 54 self.from_ = from_ 55 self.to = to 56 self.cadence = cadence 57 self.timestamp_unit = timestamp_unit 58 self.bytes_ = bytes_ 59 self.rows = rows 60 self.gaps = gaps 61 self.largest_gap_steps = largest_gap_steps 62 self.error = error 63 self.data_url = data_url 64 self.data_format = data_format 65 self.field_links = field_links 66 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetWithLinks.
121 def to_dict(self) -> dict[str, Any]: 122 dataset_id = self.dataset_id 123 124 name = self.name 125 126 type_ = self.type_.value 127 128 instrument = self.instrument 129 130 created_at = self.created_at.isoformat() 131 132 status = self.status.value 133 134 current_version_id = self.current_version_id 135 136 deleted_at: str | Unset = UNSET 137 if not isinstance(self.deleted_at, Unset): 138 deleted_at = self.deleted_at.isoformat() 139 140 updated_at: str | Unset = UNSET 141 if not isinstance(self.updated_at, Unset): 142 updated_at = self.updated_at.isoformat() 143 144 from_: str | Unset = UNSET 145 if not isinstance(self.from_, Unset): 146 from_ = self.from_.isoformat() 147 148 to: str | Unset = UNSET 149 if not isinstance(self.to, Unset): 150 to = self.to.isoformat() 151 152 cadence = self.cadence 153 154 timestamp_unit: str | Unset = UNSET 155 if not isinstance(self.timestamp_unit, Unset): 156 timestamp_unit = self.timestamp_unit.value 157 158 bytes_ = self.bytes_ 159 160 rows = self.rows 161 162 gaps = self.gaps 163 164 largest_gap_steps = self.largest_gap_steps 165 166 error = self.error 167 168 data_url = self.data_url 169 170 data_format: str | Unset = UNSET 171 if not isinstance(self.data_format, Unset): 172 data_format = self.data_format.value 173 174 field_links: dict[str, Any] | Unset = UNSET 175 if not isinstance(self.field_links, Unset): 176 field_links = self.field_links.to_dict() 177 178 field_dict: dict[str, Any] = {} 179 field_dict.update(self.additional_properties) 180 field_dict.update( 181 { 182 "datasetId": dataset_id, 183 "name": name, 184 "type": type_, 185 "instrument": instrument, 186 "createdAt": created_at, 187 "status": status, 188 } 189 ) 190 if current_version_id is not UNSET: 191 field_dict["currentVersionId"] = current_version_id 192 if deleted_at is not UNSET: 193 field_dict["deletedAt"] = deleted_at 194 if updated_at is not UNSET: 195 field_dict["updatedAt"] = updated_at 196 if from_ is not UNSET: 197 field_dict["from"] = from_ 198 if to is not UNSET: 199 field_dict["to"] = to 200 if cadence is not UNSET: 201 field_dict["cadence"] = cadence 202 if timestamp_unit is not UNSET: 203 field_dict["timestampUnit"] = timestamp_unit 204 if bytes_ is not UNSET: 205 field_dict["bytes"] = bytes_ 206 if rows is not UNSET: 207 field_dict["rows"] = rows 208 if gaps is not UNSET: 209 field_dict["gaps"] = gaps 210 if largest_gap_steps is not UNSET: 211 field_dict["largestGapSteps"] = largest_gap_steps 212 if error is not UNSET: 213 field_dict["error"] = error 214 if data_url is not UNSET: 215 field_dict["dataUrl"] = data_url 216 if data_format is not UNSET: 217 field_dict["dataFormat"] = data_format 218 if field_links is not UNSET: 219 field_dict["_links"] = field_links 220 221 return field_dict
223 @classmethod 224 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 225 from ..models.dataset_with_links_links import DatasetWithLinksLinks 226 227 d = dict(src_dict) 228 dataset_id = d.pop("datasetId") 229 230 name = d.pop("name") 231 232 type_ = DatasetType(d.pop("type")) 233 234 instrument = d.pop("instrument") 235 236 created_at = isoparse(d.pop("createdAt")) 237 238 status = DatasetStatus(d.pop("status")) 239 240 current_version_id = d.pop("currentVersionId", UNSET) 241 242 _deleted_at = d.pop("deletedAt", UNSET) 243 deleted_at: datetime.datetime | Unset 244 if isinstance(_deleted_at, Unset): 245 deleted_at = UNSET 246 else: 247 deleted_at = isoparse(_deleted_at) 248 249 _updated_at = d.pop("updatedAt", UNSET) 250 updated_at: datetime.datetime | Unset 251 if isinstance(_updated_at, Unset): 252 updated_at = UNSET 253 else: 254 updated_at = isoparse(_updated_at) 255 256 _from_ = d.pop("from", UNSET) 257 from_: datetime.datetime | Unset 258 if isinstance(_from_, Unset): 259 from_ = UNSET 260 else: 261 from_ = isoparse(_from_) 262 263 _to = d.pop("to", UNSET) 264 to: datetime.datetime | Unset 265 if isinstance(_to, Unset): 266 to = UNSET 267 else: 268 to = isoparse(_to) 269 270 cadence = d.pop("cadence", UNSET) 271 272 _timestamp_unit = d.pop("timestampUnit", UNSET) 273 timestamp_unit: DatasetTimestampUnit | Unset 274 if isinstance(_timestamp_unit, Unset): 275 timestamp_unit = UNSET 276 else: 277 timestamp_unit = DatasetTimestampUnit(_timestamp_unit) 278 279 bytes_ = d.pop("bytes", UNSET) 280 281 rows = d.pop("rows", UNSET) 282 283 gaps = d.pop("gaps", UNSET) 284 285 largest_gap_steps = d.pop("largestGapSteps", UNSET) 286 287 error = d.pop("error", UNSET) 288 289 data_url = d.pop("dataUrl", UNSET) 290 291 _data_format = d.pop("dataFormat", UNSET) 292 data_format: DatasetWithLinksDataFormat | Unset 293 if isinstance(_data_format, Unset): 294 data_format = UNSET 295 else: 296 data_format = DatasetWithLinksDataFormat(_data_format) 297 298 _field_links = d.pop("_links", UNSET) 299 field_links: DatasetWithLinksLinks | Unset 300 if isinstance(_field_links, Unset): 301 field_links = UNSET 302 else: 303 field_links = DatasetWithLinksLinks.from_dict(_field_links) 304 305 dataset_with_links = cls( 306 dataset_id=dataset_id, 307 name=name, 308 type_=type_, 309 instrument=instrument, 310 created_at=created_at, 311 status=status, 312 current_version_id=current_version_id, 313 deleted_at=deleted_at, 314 updated_at=updated_at, 315 from_=from_, 316 to=to, 317 cadence=cadence, 318 timestamp_unit=timestamp_unit, 319 bytes_=bytes_, 320 rows=rows, 321 gaps=gaps, 322 largest_gap_steps=largest_gap_steps, 323 error=error, 324 data_url=data_url, 325 data_format=data_format, 326 field_links=field_links, 327 ) 328 329 dataset_with_links.additional_properties = d 330 return dataset_with_links
5class DatasetWithLinksDataFormat(str, Enum): 6 LASTRA = "lastra" 7 PARQUET = "parquet" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
19@_attrs_define 20class DatasetWithLinksLinks: 21 """ 22 Attributes: 23 self_ (DatasetWithLinksLinksSelf | Unset): 24 """ 25 26 self_: DatasetWithLinksLinksSelf | Unset = UNSET 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 self_: dict[str, Any] | Unset = UNSET 31 if not isinstance(self.self_, Unset): 32 self_ = self.self_.to_dict() 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update({}) 37 if self_ is not UNSET: 38 field_dict["self"] = self_ 39 40 return field_dict 41 42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 from ..models.dataset_with_links_links_self import DatasetWithLinksLinksSelf 45 46 d = dict(src_dict) 47 _self_ = d.pop("self", UNSET) 48 self_: DatasetWithLinksLinksSelf | Unset 49 if isinstance(_self_, Unset): 50 self_ = UNSET 51 else: 52 self_ = DatasetWithLinksLinksSelf.from_dict(_self_) 53 54 dataset_with_links_links = cls( 55 self_=self_, 56 ) 57 58 dataset_with_links_links.additional_properties = d 59 return dataset_with_links_links 60 61 @property 62 def additional_keys(self) -> list[str]: 63 return list(self.additional_properties.keys()) 64 65 def __getitem__(self, key: str) -> Any: 66 return self.additional_properties[key] 67 68 def __setitem__(self, key: str, value: Any) -> None: 69 self.additional_properties[key] = value 70 71 def __delitem__(self, key: str) -> None: 72 del self.additional_properties[key] 73 74 def __contains__(self, key: str) -> bool: 75 return key in self.additional_properties
Attributes: self_ (DatasetWithLinksLinksSelf | Unset):
24def __init__(self, self_=attr_dict['self_'].default): 25 self.self_ = self_ 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetWithLinksLinks.
29 def to_dict(self) -> dict[str, Any]: 30 self_: dict[str, Any] | Unset = UNSET 31 if not isinstance(self.self_, Unset): 32 self_ = self.self_.to_dict() 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update({}) 37 if self_ is not UNSET: 38 field_dict["self"] = self_ 39 40 return field_dict
42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 from ..models.dataset_with_links_links_self import DatasetWithLinksLinksSelf 45 46 d = dict(src_dict) 47 _self_ = d.pop("self", UNSET) 48 self_: DatasetWithLinksLinksSelf | Unset 49 if isinstance(_self_, Unset): 50 self_ = UNSET 51 else: 52 self_ = DatasetWithLinksLinksSelf.from_dict(_self_) 53 54 dataset_with_links_links = cls( 55 self_=self_, 56 ) 57 58 dataset_with_links_links.additional_properties = d 59 return dataset_with_links_links
15@_attrs_define 16class DatasetWithLinksLinksSelf: 17 """ 18 Attributes: 19 href (str | Unset): Example: /v1/datasets/ds_3f9a1c2e7b0d4a5f. 20 """ 21 22 href: str | Unset = UNSET 23 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 24 25 def to_dict(self) -> dict[str, Any]: 26 href = self.href 27 28 field_dict: dict[str, Any] = {} 29 field_dict.update(self.additional_properties) 30 field_dict.update({}) 31 if href is not UNSET: 32 field_dict["href"] = href 33 34 return field_dict 35 36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 d = dict(src_dict) 39 href = d.pop("href", UNSET) 40 41 dataset_with_links_links_self = cls( 42 href=href, 43 ) 44 45 dataset_with_links_links_self.additional_properties = d 46 return dataset_with_links_links_self 47 48 @property 49 def additional_keys(self) -> list[str]: 50 return list(self.additional_properties.keys()) 51 52 def __getitem__(self, key: str) -> Any: 53 return self.additional_properties[key] 54 55 def __setitem__(self, key: str, value: Any) -> None: 56 self.additional_properties[key] = value 57 58 def __delitem__(self, key: str) -> None: 59 del self.additional_properties[key] 60 61 def __contains__(self, key: str) -> bool: 62 return key in self.additional_properties
Attributes: href (str | Unset): Example: /v1/datasets/ds_3f9a1c2e7b0d4a5f.
24def __init__(self, href=attr_dict['href'].default): 25 self.href = href 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DatasetWithLinksLinksSelf.
5class DataSourceType(str, Enum): 6 FUNDING = "funding" 7 KLINE = "kline" 8 TICKER = "ticker" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class DeclaredProperty: 17 """One property name `POST /strategy` could establish without constructing the strategy — 18 either declared with `@StrategyProperty` on the compiled source, or one of the small set of 19 base properties every strategy carries (`amnt`, `enabled`, `multiEntry`, ...). 20 21 **Best-effort, not exhaustive.** A property registered through an attached risk/backtest 22 config needs a live instance to discover and is not listed here. Use this to catch a typo'd 23 sweep key before submitting, not as the definitive list of what a sweep will accept — a 24 name absent from this list may still be valid. 25 26 Attributes: 27 name (str): The key a sweep or execute param map uses for this property. Example: rsi.period. 28 description (str | Unset): Human-readable label, as declared. Example: RSI period. 29 default_value (str | Unset): The declared default, as a string, if one was given. Absent, not null, when none 30 was 31 declared. 32 Example: 14. 33 reflected (bool | Unset): Whether a value for this key is injected into the strategy's field (`true`) or only 34 available through the property map (`false`). 35 Example: True. 36 min_ (float | Unset): Suggested sweep/range minimum, if declared. Advisory only, never validated. Example: 2. 37 max_ (float | Unset): Suggested sweep/range maximum, if declared. Advisory only, never validated. Example: 50. 38 step (float | Unset): Suggested sweep/range step, if declared. Advisory only, never validated. Example: 1. 39 """ 40 41 name: str 42 description: str | Unset = UNSET 43 default_value: str | Unset = UNSET 44 reflected: bool | Unset = UNSET 45 min_: float | Unset = UNSET 46 max_: float | Unset = UNSET 47 step: float | Unset = UNSET 48 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 49 50 def to_dict(self) -> dict[str, Any]: 51 name = self.name 52 53 description = self.description 54 55 default_value = self.default_value 56 57 reflected = self.reflected 58 59 min_ = self.min_ 60 61 max_ = self.max_ 62 63 step = self.step 64 65 field_dict: dict[str, Any] = {} 66 field_dict.update(self.additional_properties) 67 field_dict.update( 68 { 69 "name": name, 70 } 71 ) 72 if description is not UNSET: 73 field_dict["description"] = description 74 if default_value is not UNSET: 75 field_dict["defaultValue"] = default_value 76 if reflected is not UNSET: 77 field_dict["reflected"] = reflected 78 if min_ is not UNSET: 79 field_dict["min"] = min_ 80 if max_ is not UNSET: 81 field_dict["max"] = max_ 82 if step is not UNSET: 83 field_dict["step"] = step 84 85 return field_dict 86 87 @classmethod 88 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 89 d = dict(src_dict) 90 name = d.pop("name") 91 92 description = d.pop("description", UNSET) 93 94 default_value = d.pop("defaultValue", UNSET) 95 96 reflected = d.pop("reflected", UNSET) 97 98 min_ = d.pop("min", UNSET) 99 100 max_ = d.pop("max", UNSET) 101 102 step = d.pop("step", UNSET) 103 104 declared_property = cls( 105 name=name, 106 description=description, 107 default_value=default_value, 108 reflected=reflected, 109 min_=min_, 110 max_=max_, 111 step=step, 112 ) 113 114 declared_property.additional_properties = d 115 return declared_property 116 117 @property 118 def additional_keys(self) -> list[str]: 119 return list(self.additional_properties.keys()) 120 121 def __getitem__(self, key: str) -> Any: 122 return self.additional_properties[key] 123 124 def __setitem__(self, key: str, value: Any) -> None: 125 self.additional_properties[key] = value 126 127 def __delitem__(self, key: str) -> None: 128 del self.additional_properties[key] 129 130 def __contains__(self, key: str) -> bool: 131 return key in self.additional_properties
One property name POST /strategy could establish without constructing the strategy —
either declared with @StrategyProperty on the compiled source, or one of the small set of
base properties every strategy carries (amnt, enabled, multiEntry, ...).
Best-effort, not exhaustive. A property registered through an attached risk/backtest config needs a live instance to discover and is not listed here. Use this to catch a typo'd sweep key before submitting, not as the definitive list of what a sweep will accept — a name absent from this list may still be valid.
Attributes:
name (str): The key a sweep or execute param map uses for this property. Example: rsi.period.
description (str | Unset): Human-readable label, as declared. Example: RSI period.
default_value (str | Unset): The declared default, as a string, if one was given. Absent, not null, when none
was
declared.
Example: 14.
reflected (bool | Unset): Whether a value for this key is injected into the strategy's field (`true`) or only
available through the property map (`false`).
Example: True.
min_ (float | Unset): Suggested sweep/range minimum, if declared. Advisory only, never validated. Example: 2.
max_ (float | Unset): Suggested sweep/range maximum, if declared. Advisory only, never validated. Example: 50.
step (float | Unset): Suggested sweep/range step, if declared. Advisory only, never validated. Example: 1.
30def __init__(self, name, description=attr_dict['description'].default, default_value=attr_dict['default_value'].default, reflected=attr_dict['reflected'].default, min_=attr_dict['min_'].default, max_=attr_dict['max_'].default, step=attr_dict['step'].default): 31 self.name = name 32 self.description = description 33 self.default_value = default_value 34 self.reflected = reflected 35 self.min_ = min_ 36 self.max_ = max_ 37 self.step = step 38 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DeclaredProperty.
50 def to_dict(self) -> dict[str, Any]: 51 name = self.name 52 53 description = self.description 54 55 default_value = self.default_value 56 57 reflected = self.reflected 58 59 min_ = self.min_ 60 61 max_ = self.max_ 62 63 step = self.step 64 65 field_dict: dict[str, Any] = {} 66 field_dict.update(self.additional_properties) 67 field_dict.update( 68 { 69 "name": name, 70 } 71 ) 72 if description is not UNSET: 73 field_dict["description"] = description 74 if default_value is not UNSET: 75 field_dict["defaultValue"] = default_value 76 if reflected is not UNSET: 77 field_dict["reflected"] = reflected 78 if min_ is not UNSET: 79 field_dict["min"] = min_ 80 if max_ is not UNSET: 81 field_dict["max"] = max_ 82 if step is not UNSET: 83 field_dict["step"] = step 84 85 return field_dict
87 @classmethod 88 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 89 d = dict(src_dict) 90 name = d.pop("name") 91 92 description = d.pop("description", UNSET) 93 94 default_value = d.pop("defaultValue", UNSET) 95 96 reflected = d.pop("reflected", UNSET) 97 98 min_ = d.pop("min", UNSET) 99 100 max_ = d.pop("max", UNSET) 101 102 step = d.pop("step", UNSET) 103 104 declared_property = cls( 105 name=name, 106 description=description, 107 default_value=default_value, 108 reflected=reflected, 109 min_=min_, 110 max_=max_, 111 step=step, 112 ) 113 114 declared_property.additional_properties = d 115 return declared_property
13@_attrs_define 14class DeleteDatasetResponse200: 15 """ 16 Attributes: 17 dataset_id (str): 18 deleted (bool): 19 """ 20 21 dataset_id: str 22 deleted: bool 23 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 24 25 def to_dict(self) -> dict[str, Any]: 26 dataset_id = self.dataset_id 27 28 deleted = self.deleted 29 30 field_dict: dict[str, Any] = {} 31 field_dict.update(self.additional_properties) 32 field_dict.update( 33 { 34 "datasetId": dataset_id, 35 "deleted": deleted, 36 } 37 ) 38 39 return field_dict 40 41 @classmethod 42 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 43 d = dict(src_dict) 44 dataset_id = d.pop("datasetId") 45 46 deleted = d.pop("deleted") 47 48 delete_dataset_response_200 = cls( 49 dataset_id=dataset_id, 50 deleted=deleted, 51 ) 52 53 delete_dataset_response_200.additional_properties = d 54 return delete_dataset_response_200 55 56 @property 57 def additional_keys(self) -> list[str]: 58 return list(self.additional_properties.keys()) 59 60 def __getitem__(self, key: str) -> Any: 61 return self.additional_properties[key] 62 63 def __setitem__(self, key: str, value: Any) -> None: 64 self.additional_properties[key] = value 65 66 def __delitem__(self, key: str) -> None: 67 del self.additional_properties[key] 68 69 def __contains__(self, key: str) -> bool: 70 return key in self.additional_properties
Attributes: dataset_id (str): deleted (bool):
25def __init__(self, dataset_id, deleted): 26 self.dataset_id = dataset_id 27 self.deleted = deleted 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DeleteDatasetResponse200.
41 @classmethod 42 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 43 d = dict(src_dict) 44 dataset_id = d.pop("datasetId") 45 46 deleted = d.pop("deleted") 47 48 delete_dataset_response_200 = cls( 49 dataset_id=dataset_id, 50 deleted=deleted, 51 ) 52 53 delete_dataset_response_200.additional_properties = d 54 return delete_dataset_response_200
13@_attrs_define 14class DeleteStrategyResponse200: 15 """ 16 Attributes: 17 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 18 always yields the same id, for every caller. How much formatting the id ignores depends on 19 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 20 not. 21 Example: 6bsh31ikwkuivhtgcoa6s4. 22 deleted (bool): 23 """ 24 25 strategy_id: str 26 deleted: bool 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 strategy_id = self.strategy_id 31 32 deleted = self.deleted 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "strategyId": strategy_id, 39 "deleted": deleted, 40 } 41 ) 42 43 return field_dict 44 45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 strategy_id = d.pop("strategyId") 49 50 deleted = d.pop("deleted") 51 52 delete_strategy_response_200 = cls( 53 strategy_id=strategy_id, 54 deleted=deleted, 55 ) 56 57 delete_strategy_response_200.additional_properties = d 58 return delete_strategy_response_200 59 60 @property 61 def additional_keys(self) -> list[str]: 62 return list(self.additional_properties.keys()) 63 64 def __getitem__(self, key: str) -> Any: 65 return self.additional_properties[key] 66 67 def __setitem__(self, key: str, value: Any) -> None: 68 self.additional_properties[key] = value 69 70 def __delitem__(self, key: str) -> None: 71 del self.additional_properties[key] 72 73 def __contains__(self, key: str) -> bool: 74 return key in self.additional_properties
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see POST /strategy for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
deleted (bool):
25def __init__(self, strategy_id, deleted): 26 self.strategy_id = strategy_id 27 self.deleted = deleted 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class DeleteStrategyResponse200.
29 def to_dict(self) -> dict[str, Any]: 30 strategy_id = self.strategy_id 31 32 deleted = self.deleted 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "strategyId": strategy_id, 39 "deleted": deleted, 40 } 41 ) 42 43 return field_dict
45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 strategy_id = d.pop("strategyId") 49 50 deleted = d.pop("deleted") 51 52 delete_strategy_response_200 = cls( 53 strategy_id=strategy_id, 54 deleted=deleted, 55 ) 56 57 delete_strategy_response_200.additional_properties = d 58 return delete_strategy_response_200
5class DownloadKlinesFormat(str, Enum): 6 LASTRA = "lastra" 7 PARQUET = "parquet" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class DownloadTickersFormat(str, Enum): 6 LASTRA = "lastra" 7 PARQUET = "parquet" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class EquityCurveMeta: 17 """What the transform pipeline actually did, computed from the observed outcome — never a copy of what was requested. 18 Lets a caller detect a forced or no-op transform (e.g. a `resample` ceiling already above the curve's size is a 19 legal no-op, reported honestly as `resampled: false`). 20 21 Attributes: 22 input_point_count (int): Size of the curve the transform pipeline received. Example: 100000. 23 output_point_count (int): Size after the full pipeline (resample, then differential, then outMode). Example: 24 100. 25 resampled (bool): True only if the resample stage actually changed the point count. 26 differential (bool): True only if delta-encoding actually ran. Requesting it on a curve of 0 or 1 points has 27 nothing to encode, so it does not run even if asked. 28 out_mode (EquityCurveOutMode): JSON shape for an equity curve's points. `ARRAY` is `[{timestamp, equity}, ...]`; 29 `SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The one schema shared 30 by every place `outMode` appears, request or response, so the two cannot drift to different value sets. 31 """ 32 33 input_point_count: int 34 output_point_count: int 35 resampled: bool 36 differential: bool 37 out_mode: EquityCurveOutMode 38 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 39 40 def to_dict(self) -> dict[str, Any]: 41 input_point_count = self.input_point_count 42 43 output_point_count = self.output_point_count 44 45 resampled = self.resampled 46 47 differential = self.differential 48 49 out_mode = self.out_mode.value 50 51 field_dict: dict[str, Any] = {} 52 field_dict.update(self.additional_properties) 53 field_dict.update( 54 { 55 "inputPointCount": input_point_count, 56 "outputPointCount": output_point_count, 57 "resampled": resampled, 58 "differential": differential, 59 "outMode": out_mode, 60 } 61 ) 62 63 return field_dict 64 65 @classmethod 66 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 67 d = dict(src_dict) 68 input_point_count = d.pop("inputPointCount") 69 70 output_point_count = d.pop("outputPointCount") 71 72 resampled = d.pop("resampled") 73 74 differential = d.pop("differential") 75 76 out_mode = EquityCurveOutMode(d.pop("outMode")) 77 78 equity_curve_meta = cls( 79 input_point_count=input_point_count, 80 output_point_count=output_point_count, 81 resampled=resampled, 82 differential=differential, 83 out_mode=out_mode, 84 ) 85 86 equity_curve_meta.additional_properties = d 87 return equity_curve_meta 88 89 @property 90 def additional_keys(self) -> list[str]: 91 return list(self.additional_properties.keys()) 92 93 def __getitem__(self, key: str) -> Any: 94 return self.additional_properties[key] 95 96 def __setitem__(self, key: str, value: Any) -> None: 97 self.additional_properties[key] = value 98 99 def __delitem__(self, key: str) -> None: 100 del self.additional_properties[key] 101 102 def __contains__(self, key: str) -> bool: 103 return key in self.additional_properties
What the transform pipeline actually did, computed from the observed outcome — never a copy of what was requested.
Lets a caller detect a forced or no-op transform (e.g. a resample ceiling already above the curve's size is a
legal no-op, reported honestly as resampled: false).
Attributes:
input_point_count (int): Size of the curve the transform pipeline received. Example: 100000.
output_point_count (int): Size after the full pipeline (resample, then differential, then outMode). Example:
100.
resampled (bool): True only if the resample stage actually changed the point count.
differential (bool): True only if delta-encoding actually ran. Requesting it on a curve of 0 or 1 points has
nothing to encode, so it does not run even if asked.
out_mode (EquityCurveOutMode): JSON shape for an equity curve's points. `ARRAY` is `[{timestamp, equity}, ...]`;
`SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The one schema shared
by every place `outMode` appears, request or response, so the two cannot drift to different value sets.
28def __init__(self, input_point_count, output_point_count, resampled, differential, out_mode): 29 self.input_point_count = input_point_count 30 self.output_point_count = output_point_count 31 self.resampled = resampled 32 self.differential = differential 33 self.out_mode = out_mode 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class EquityCurveMeta.
40 def to_dict(self) -> dict[str, Any]: 41 input_point_count = self.input_point_count 42 43 output_point_count = self.output_point_count 44 45 resampled = self.resampled 46 47 differential = self.differential 48 49 out_mode = self.out_mode.value 50 51 field_dict: dict[str, Any] = {} 52 field_dict.update(self.additional_properties) 53 field_dict.update( 54 { 55 "inputPointCount": input_point_count, 56 "outputPointCount": output_point_count, 57 "resampled": resampled, 58 "differential": differential, 59 "outMode": out_mode, 60 } 61 ) 62 63 return field_dict
65 @classmethod 66 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 67 d = dict(src_dict) 68 input_point_count = d.pop("inputPointCount") 69 70 output_point_count = d.pop("outputPointCount") 71 72 resampled = d.pop("resampled") 73 74 differential = d.pop("differential") 75 76 out_mode = EquityCurveOutMode(d.pop("outMode")) 77 78 equity_curve_meta = cls( 79 input_point_count=input_point_count, 80 output_point_count=output_point_count, 81 resampled=resampled, 82 differential=differential, 83 out_mode=out_mode, 84 ) 85 86 equity_curve_meta.additional_properties = d 87 return equity_curve_meta
16@_attrs_define 17class EquityCurveOptions: 18 """Requested equity-curve transform, applied server-side in a fixed pipeline order: `resample` (point count) then 19 `differential` (encoding) then `outMode` (JSON shape) — each stage assumes the previous one already ran. A server- 20 side size guard can still force a smaller/deflated shape above its thresholds regardless of what is requested here — 21 see `EquityCurveMeta` for what actually happened. 22 23 Attributes: 24 resample (int | Unset): Downsample to at most this many points (extrema-preserving — the global max/min and the 25 exact first/last point are always kept). Omit for no downsampling. 26 differential (bool | Unset): Delta-encode both fields from the second (post-resample) point onward. Default: 27 False. 28 out_mode (EquityCurveOutMode | Unset): JSON shape for an equity curve's points. `ARRAY` is `[{timestamp, 29 equity}, ...]`; `SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The 30 one schema shared by every place `outMode` appears, request or response, so the two cannot drift to different 31 value sets. Default: EquityCurveOutMode.ARRAY. 32 """ 33 34 resample: int | Unset = UNSET 35 differential: bool | Unset = False 36 out_mode: EquityCurveOutMode | Unset = EquityCurveOutMode.ARRAY 37 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 38 39 def to_dict(self) -> dict[str, Any]: 40 resample = self.resample 41 42 differential = self.differential 43 44 out_mode: str | Unset = UNSET 45 if not isinstance(self.out_mode, Unset): 46 out_mode = self.out_mode.value 47 48 field_dict: dict[str, Any] = {} 49 field_dict.update(self.additional_properties) 50 field_dict.update({}) 51 if resample is not UNSET: 52 field_dict["resample"] = resample 53 if differential is not UNSET: 54 field_dict["differential"] = differential 55 if out_mode is not UNSET: 56 field_dict["outMode"] = out_mode 57 58 return field_dict 59 60 @classmethod 61 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 62 d = dict(src_dict) 63 resample = d.pop("resample", UNSET) 64 65 differential = d.pop("differential", UNSET) 66 67 _out_mode = d.pop("outMode", UNSET) 68 out_mode: EquityCurveOutMode | Unset 69 if isinstance(_out_mode, Unset): 70 out_mode = UNSET 71 else: 72 out_mode = EquityCurveOutMode(_out_mode) 73 74 equity_curve_options = cls( 75 resample=resample, 76 differential=differential, 77 out_mode=out_mode, 78 ) 79 80 equity_curve_options.additional_properties = d 81 return equity_curve_options 82 83 @property 84 def additional_keys(self) -> list[str]: 85 return list(self.additional_properties.keys()) 86 87 def __getitem__(self, key: str) -> Any: 88 return self.additional_properties[key] 89 90 def __setitem__(self, key: str, value: Any) -> None: 91 self.additional_properties[key] = value 92 93 def __delitem__(self, key: str) -> None: 94 del self.additional_properties[key] 95 96 def __contains__(self, key: str) -> bool: 97 return key in self.additional_properties
Requested equity-curve transform, applied server-side in a fixed pipeline order: resample (point count) then
differential (encoding) then outMode (JSON shape) — each stage assumes the previous one already ran. A server-
side size guard can still force a smaller/deflated shape above its thresholds regardless of what is requested here —
see EquityCurveMeta for what actually happened.
Attributes:
resample (int | Unset): Downsample to at most this many points (extrema-preserving — the global max/min and the
exact first/last point are always kept). Omit for no downsampling.
differential (bool | Unset): Delta-encode both fields from the second (post-resample) point onward. Default:
False.
out_mode (EquityCurveOutMode | Unset): JSON shape for an equity curve's points. `ARRAY` is `[{timestamp,
equity}, ...]`; `SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The
one schema shared by every place `outMode` appears, request or response, so the two cannot drift to different
value sets. Default: EquityCurveOutMode.ARRAY.
26def __init__(self, resample=attr_dict['resample'].default, differential=attr_dict['differential'].default, out_mode=attr_dict['out_mode'].default): 27 self.resample = resample 28 self.differential = differential 29 self.out_mode = out_mode 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class EquityCurveOptions.
39 def to_dict(self) -> dict[str, Any]: 40 resample = self.resample 41 42 differential = self.differential 43 44 out_mode: str | Unset = UNSET 45 if not isinstance(self.out_mode, Unset): 46 out_mode = self.out_mode.value 47 48 field_dict: dict[str, Any] = {} 49 field_dict.update(self.additional_properties) 50 field_dict.update({}) 51 if resample is not UNSET: 52 field_dict["resample"] = resample 53 if differential is not UNSET: 54 field_dict["differential"] = differential 55 if out_mode is not UNSET: 56 field_dict["outMode"] = out_mode 57 58 return field_dict
60 @classmethod 61 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 62 d = dict(src_dict) 63 resample = d.pop("resample", UNSET) 64 65 differential = d.pop("differential", UNSET) 66 67 _out_mode = d.pop("outMode", UNSET) 68 out_mode: EquityCurveOutMode | Unset 69 if isinstance(_out_mode, Unset): 70 out_mode = UNSET 71 else: 72 out_mode = EquityCurveOutMode(_out_mode) 73 74 equity_curve_options = cls( 75 resample=resample, 76 differential=differential, 77 out_mode=out_mode, 78 ) 79 80 equity_curve_options.additional_properties = d 81 return equity_curve_options
5class EquityCurveOutMode(str, Enum): 6 ARRAY = "ARRAY" 7 SHORT = "SHORT" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class EquityCurveRequest: 19 """Selection (`mode`/`n`/`maxPct`) plus the transform preference (`resample`/`differential`/`outMode`) applied by `GET 20 .../equityCurve` whenever ITS OWN query params are absent, for a curve this sweep retained. The transform half never 21 affects retention or `sweepId` — a caller can always override it per-request at read time regardless of what was 22 submitted here. 23 24 Attributes: 25 resample (int | Unset): Downsample to at most this many points (extrema-preserving — the global max/min and the 26 exact first/last point are always kept). Omit for no downsampling. 27 differential (bool | Unset): Delta-encode both fields from the second (post-resample) point onward. Default: 28 False. 29 out_mode (EquityCurveOutMode | Unset): JSON shape for an equity curve's points. `ARRAY` is `[{timestamp, 30 equity}, ...]`; `SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The 31 one schema shared by every place `outMode` appears, request or response, so the two cannot drift to different 32 value sets. Default: EquityCurveOutMode.ARRAY. 33 mode (EquityCurveRequestMode | Unset): Which trials keep their per-point equity curve. `auto` retains curves 34 only while the accumulated size stays within server limits; `topN`/`topPct` retain curves for the best-ranked 35 trials explicitly; `none` retains no curves. Default: EquityCurveRequestMode.AUTO. 36 n (int | Unset): Trial count to retain when mode is topN. 37 max_pct (float | Unset): Top percentage of trials to retain when mode is topPct. 38 """ 39 40 resample: int | Unset = UNSET 41 differential: bool | Unset = False 42 out_mode: EquityCurveOutMode | Unset = EquityCurveOutMode.ARRAY 43 mode: EquityCurveRequestMode | Unset = EquityCurveRequestMode.AUTO 44 n: int | Unset = UNSET 45 max_pct: float | Unset = UNSET 46 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 47 48 def to_dict(self) -> dict[str, Any]: 49 resample = self.resample 50 51 differential = self.differential 52 53 out_mode: str | Unset = UNSET 54 if not isinstance(self.out_mode, Unset): 55 out_mode = self.out_mode.value 56 57 mode: str | Unset = UNSET 58 if not isinstance(self.mode, Unset): 59 mode = self.mode.value 60 61 n = self.n 62 63 max_pct = self.max_pct 64 65 field_dict: dict[str, Any] = {} 66 field_dict.update(self.additional_properties) 67 field_dict.update({}) 68 if resample is not UNSET: 69 field_dict["resample"] = resample 70 if differential is not UNSET: 71 field_dict["differential"] = differential 72 if out_mode is not UNSET: 73 field_dict["outMode"] = out_mode 74 if mode is not UNSET: 75 field_dict["mode"] = mode 76 if n is not UNSET: 77 field_dict["n"] = n 78 if max_pct is not UNSET: 79 field_dict["maxPct"] = max_pct 80 81 return field_dict 82 83 @classmethod 84 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 85 d = dict(src_dict) 86 resample = d.pop("resample", UNSET) 87 88 differential = d.pop("differential", UNSET) 89 90 _out_mode = d.pop("outMode", UNSET) 91 out_mode: EquityCurveOutMode | Unset 92 if isinstance(_out_mode, Unset): 93 out_mode = UNSET 94 else: 95 out_mode = EquityCurveOutMode(_out_mode) 96 97 _mode = d.pop("mode", UNSET) 98 mode: EquityCurveRequestMode | Unset 99 if isinstance(_mode, Unset): 100 mode = UNSET 101 else: 102 mode = EquityCurveRequestMode(_mode) 103 104 n = d.pop("n", UNSET) 105 106 max_pct = d.pop("maxPct", UNSET) 107 108 equity_curve_request = cls( 109 resample=resample, 110 differential=differential, 111 out_mode=out_mode, 112 mode=mode, 113 n=n, 114 max_pct=max_pct, 115 ) 116 117 equity_curve_request.additional_properties = d 118 return equity_curve_request 119 120 @property 121 def additional_keys(self) -> list[str]: 122 return list(self.additional_properties.keys()) 123 124 def __getitem__(self, key: str) -> Any: 125 return self.additional_properties[key] 126 127 def __setitem__(self, key: str, value: Any) -> None: 128 self.additional_properties[key] = value 129 130 def __delitem__(self, key: str) -> None: 131 del self.additional_properties[key] 132 133 def __contains__(self, key: str) -> bool: 134 return key in self.additional_properties
Selection (mode/n/maxPct) plus the transform preference (resample/differential/outMode) applied by GET
.../equityCurve whenever ITS OWN query params are absent, for a curve this sweep retained. The transform half never
affects retention or sweepId — a caller can always override it per-request at read time regardless of what was
submitted here.
Attributes:
resample (int | Unset): Downsample to at most this many points (extrema-preserving — the global max/min and the
exact first/last point are always kept). Omit for no downsampling.
differential (bool | Unset): Delta-encode both fields from the second (post-resample) point onward. Default:
False.
out_mode (EquityCurveOutMode | Unset): JSON shape for an equity curve's points. `ARRAY` is `[{timestamp,
equity}, ...]`; `SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The
one schema shared by every place `outMode` appears, request or response, so the two cannot drift to different
value sets. Default: EquityCurveOutMode.ARRAY.
mode (EquityCurveRequestMode | Unset): Which trials keep their per-point equity curve. `auto` retains curves
only while the accumulated size stays within server limits; `topN`/`topPct` retain curves for the best-ranked
trials explicitly; `none` retains no curves. Default: EquityCurveRequestMode.AUTO.
n (int | Unset): Trial count to retain when mode is topN.
max_pct (float | Unset): Top percentage of trials to retain when mode is topPct.
29def __init__(self, resample=attr_dict['resample'].default, differential=attr_dict['differential'].default, out_mode=attr_dict['out_mode'].default, mode=attr_dict['mode'].default, n=attr_dict['n'].default, max_pct=attr_dict['max_pct'].default): 30 self.resample = resample 31 self.differential = differential 32 self.out_mode = out_mode 33 self.mode = mode 34 self.n = n 35 self.max_pct = max_pct 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class EquityCurveRequest.
48 def to_dict(self) -> dict[str, Any]: 49 resample = self.resample 50 51 differential = self.differential 52 53 out_mode: str | Unset = UNSET 54 if not isinstance(self.out_mode, Unset): 55 out_mode = self.out_mode.value 56 57 mode: str | Unset = UNSET 58 if not isinstance(self.mode, Unset): 59 mode = self.mode.value 60 61 n = self.n 62 63 max_pct = self.max_pct 64 65 field_dict: dict[str, Any] = {} 66 field_dict.update(self.additional_properties) 67 field_dict.update({}) 68 if resample is not UNSET: 69 field_dict["resample"] = resample 70 if differential is not UNSET: 71 field_dict["differential"] = differential 72 if out_mode is not UNSET: 73 field_dict["outMode"] = out_mode 74 if mode is not UNSET: 75 field_dict["mode"] = mode 76 if n is not UNSET: 77 field_dict["n"] = n 78 if max_pct is not UNSET: 79 field_dict["maxPct"] = max_pct 80 81 return field_dict
83 @classmethod 84 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 85 d = dict(src_dict) 86 resample = d.pop("resample", UNSET) 87 88 differential = d.pop("differential", UNSET) 89 90 _out_mode = d.pop("outMode", UNSET) 91 out_mode: EquityCurveOutMode | Unset 92 if isinstance(_out_mode, Unset): 93 out_mode = UNSET 94 else: 95 out_mode = EquityCurveOutMode(_out_mode) 96 97 _mode = d.pop("mode", UNSET) 98 mode: EquityCurveRequestMode | Unset 99 if isinstance(_mode, Unset): 100 mode = UNSET 101 else: 102 mode = EquityCurveRequestMode(_mode) 103 104 n = d.pop("n", UNSET) 105 106 max_pct = d.pop("maxPct", UNSET) 107 108 equity_curve_request = cls( 109 resample=resample, 110 differential=differential, 111 out_mode=out_mode, 112 mode=mode, 113 n=n, 114 max_pct=max_pct, 115 ) 116 117 equity_curve_request.additional_properties = d 118 return equity_curve_request
5class EquityCurveRequestMode(str, Enum): 6 AUTO = "auto" 7 NONE = "none" 8 TOPN = "topN" 9 TOPPCT = "topPct" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
20@_attrs_define 21class EquityCurveResult: 22 """An equity curve, shaped per `meta.outMode`: `points` when `ARRAY`, `timestamps` + `equities` (parallel arrays) when 23 `SHORT`. Used identically wherever a curve is returned — a plain backtest's inline `equityCurve` and a sweep row's 24 `equityCurve` are the same type. `url` is present *instead of* any points when the curve is served by pointer rather 25 than inline (a sweep row's top-N winners only): `GET` it separately to fetch this exact same shape with the points 26 populated. 27 28 Attributes: 29 meta (EquityCurveMeta): What the transform pipeline actually did, computed from the observed outcome — never a 30 copy of what was requested. Lets a caller detect a forced or no-op transform (e.g. a `resample` ceiling already 31 above the curve's size is a legal no-op, reported honestly as `resampled: false`). 32 points (list[EquityPoint] | Unset): Present when `meta.outMode` is `ARRAY` and the curve is inline (not a 33 pointer). 34 timestamps (list[int] | Unset): Present when `meta.outMode` is `SHORT` and the curve is inline (not a pointer). 35 equities (list[float] | Unset): Present when `meta.outMode` is `SHORT` and the curve is inline (not a pointer), 36 parallel to `timestamps` (same index, same point). 37 url (str | Unset): Present only for a sweep row's pointer curve. `GET` this to fetch the curve itself, in this 38 exact `{points|timestamps+equities, meta}` shape — `meta` there is the real, possibly size-guarded outcome; this 39 outer `meta` is a raw, untransformed preview from the moment the sweep selected this trial's curve, and the two 40 can legitimately differ. Example: /v1/backtest/binance/ticker/executeSweep/req-1/swp_test/runs/3/equityCurve. 41 """ 42 43 meta: EquityCurveMeta 44 points: list[EquityPoint] | Unset = UNSET 45 timestamps: list[int] | Unset = UNSET 46 equities: list[float] | Unset = UNSET 47 url: str | Unset = UNSET 48 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 49 50 def to_dict(self) -> dict[str, Any]: 51 meta = self.meta.to_dict() 52 53 points: list[dict[str, Any]] | Unset = UNSET 54 if not isinstance(self.points, Unset): 55 points = [] 56 for points_item_data in self.points: 57 points_item = points_item_data.to_dict() 58 points.append(points_item) 59 60 timestamps: list[int] | Unset = UNSET 61 if not isinstance(self.timestamps, Unset): 62 timestamps = self.timestamps 63 64 equities: list[float] | Unset = UNSET 65 if not isinstance(self.equities, Unset): 66 equities = self.equities 67 68 url = self.url 69 70 field_dict: dict[str, Any] = {} 71 field_dict.update(self.additional_properties) 72 field_dict.update( 73 { 74 "meta": meta, 75 } 76 ) 77 if points is not UNSET: 78 field_dict["points"] = points 79 if timestamps is not UNSET: 80 field_dict["timestamps"] = timestamps 81 if equities is not UNSET: 82 field_dict["equities"] = equities 83 if url is not UNSET: 84 field_dict["url"] = url 85 86 return field_dict 87 88 @classmethod 89 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 90 from ..models.equity_curve_meta import EquityCurveMeta 91 from ..models.equity_point import EquityPoint 92 93 d = dict(src_dict) 94 meta = EquityCurveMeta.from_dict(d.pop("meta")) 95 96 _points = d.pop("points", UNSET) 97 points: list[EquityPoint] | Unset = UNSET 98 if _points is not UNSET: 99 points = [] 100 for points_item_data in _points: 101 points_item = EquityPoint.from_dict(points_item_data) 102 103 points.append(points_item) 104 105 timestamps = cast(list[int], d.pop("timestamps", UNSET)) 106 107 equities = cast(list[float], d.pop("equities", UNSET)) 108 109 url = d.pop("url", UNSET) 110 111 equity_curve_result = cls( 112 meta=meta, 113 points=points, 114 timestamps=timestamps, 115 equities=equities, 116 url=url, 117 ) 118 119 equity_curve_result.additional_properties = d 120 return equity_curve_result 121 122 @property 123 def additional_keys(self) -> list[str]: 124 return list(self.additional_properties.keys()) 125 126 def __getitem__(self, key: str) -> Any: 127 return self.additional_properties[key] 128 129 def __setitem__(self, key: str, value: Any) -> None: 130 self.additional_properties[key] = value 131 132 def __delitem__(self, key: str) -> None: 133 del self.additional_properties[key] 134 135 def __contains__(self, key: str) -> bool: 136 return key in self.additional_properties
An equity curve, shaped per meta.outMode: points when ARRAY, timestamps + equities (parallel arrays) when
SHORT. Used identically wherever a curve is returned — a plain backtest's inline equityCurve and a sweep row's
equityCurve are the same type. url is present instead of any points when the curve is served by pointer rather
than inline (a sweep row's top-N winners only): GET it separately to fetch this exact same shape with the points
populated.
Attributes:
meta (EquityCurveMeta): What the transform pipeline actually did, computed from the observed outcome — never a
copy of what was requested. Lets a caller detect a forced or no-op transform (e.g. a `resample` ceiling already
above the curve's size is a legal no-op, reported honestly as `resampled: false`).
points (list[EquityPoint] | Unset): Present when `meta.outMode` is `ARRAY` and the curve is inline (not a
pointer).
timestamps (list[int] | Unset): Present when `meta.outMode` is `SHORT` and the curve is inline (not a pointer).
equities (list[float] | Unset): Present when `meta.outMode` is `SHORT` and the curve is inline (not a pointer),
parallel to `timestamps` (same index, same point).
url (str | Unset): Present only for a sweep row's pointer curve. `GET` this to fetch the curve itself, in this
exact `{points|timestamps+equities, meta}` shape — `meta` there is the real, possibly size-guarded outcome; this
outer `meta` is a raw, untransformed preview from the moment the sweep selected this trial's curve, and the two
can legitimately differ. Example: /v1/backtest/binance/ticker/executeSweep/req-1/swp_test/runs/3/equityCurve.
28def __init__(self, meta, points=attr_dict['points'].default, timestamps=attr_dict['timestamps'].default, equities=attr_dict['equities'].default, url=attr_dict['url'].default): 29 self.meta = meta 30 self.points = points 31 self.timestamps = timestamps 32 self.equities = equities 33 self.url = url 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class EquityCurveResult.
50 def to_dict(self) -> dict[str, Any]: 51 meta = self.meta.to_dict() 52 53 points: list[dict[str, Any]] | Unset = UNSET 54 if not isinstance(self.points, Unset): 55 points = [] 56 for points_item_data in self.points: 57 points_item = points_item_data.to_dict() 58 points.append(points_item) 59 60 timestamps: list[int] | Unset = UNSET 61 if not isinstance(self.timestamps, Unset): 62 timestamps = self.timestamps 63 64 equities: list[float] | Unset = UNSET 65 if not isinstance(self.equities, Unset): 66 equities = self.equities 67 68 url = self.url 69 70 field_dict: dict[str, Any] = {} 71 field_dict.update(self.additional_properties) 72 field_dict.update( 73 { 74 "meta": meta, 75 } 76 ) 77 if points is not UNSET: 78 field_dict["points"] = points 79 if timestamps is not UNSET: 80 field_dict["timestamps"] = timestamps 81 if equities is not UNSET: 82 field_dict["equities"] = equities 83 if url is not UNSET: 84 field_dict["url"] = url 85 86 return field_dict
88 @classmethod 89 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 90 from ..models.equity_curve_meta import EquityCurveMeta 91 from ..models.equity_point import EquityPoint 92 93 d = dict(src_dict) 94 meta = EquityCurveMeta.from_dict(d.pop("meta")) 95 96 _points = d.pop("points", UNSET) 97 points: list[EquityPoint] | Unset = UNSET 98 if _points is not UNSET: 99 points = [] 100 for points_item_data in _points: 101 points_item = EquityPoint.from_dict(points_item_data) 102 103 points.append(points_item) 104 105 timestamps = cast(list[int], d.pop("timestamps", UNSET)) 106 107 equities = cast(list[float], d.pop("equities", UNSET)) 108 109 url = d.pop("url", UNSET) 110 111 equity_curve_result = cls( 112 meta=meta, 113 points=points, 114 timestamps=timestamps, 115 equities=equities, 116 url=url, 117 ) 118 119 equity_curve_result.additional_properties = d 120 return equity_curve_result
13@_attrs_define 14class EquityPoint: 15 """Single sample of the running equity at a yield event. 16 17 Attributes: 18 timestamp (int): Epoch milliseconds. The first point in an equity curve is anchored at the backtest `from`; 19 subsequent points carry the timestamp of each emitted yield. Example: 1700000000000. 20 equity (float): Running equity at this point (`initialCapital + cumulativePnl`). Example: 110.5. 21 """ 22 23 timestamp: int 24 equity: float 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 timestamp = self.timestamp 29 30 equity = self.equity 31 32 field_dict: dict[str, Any] = {} 33 field_dict.update(self.additional_properties) 34 field_dict.update( 35 { 36 "timestamp": timestamp, 37 "equity": equity, 38 } 39 ) 40 41 return field_dict 42 43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 d = dict(src_dict) 46 timestamp = d.pop("timestamp") 47 48 equity = d.pop("equity") 49 50 equity_point = cls( 51 timestamp=timestamp, 52 equity=equity, 53 ) 54 55 equity_point.additional_properties = d 56 return equity_point 57 58 @property 59 def additional_keys(self) -> list[str]: 60 return list(self.additional_properties.keys()) 61 62 def __getitem__(self, key: str) -> Any: 63 return self.additional_properties[key] 64 65 def __setitem__(self, key: str, value: Any) -> None: 66 self.additional_properties[key] = value 67 68 def __delitem__(self, key: str) -> None: 69 del self.additional_properties[key] 70 71 def __contains__(self, key: str) -> bool: 72 return key in self.additional_properties
Single sample of the running equity at a yield event.
Attributes:
timestamp (int): Epoch milliseconds. The first point in an equity curve is anchored at the backtest from;
subsequent points carry the timestamp of each emitted yield. Example: 1700000000000.
equity (float): Running equity at this point (initialCapital + cumulativePnl). Example: 110.5.
25def __init__(self, timestamp, equity): 26 self.timestamp = timestamp 27 self.equity = equity 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class EquityPoint.
43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 d = dict(src_dict) 46 timestamp = d.pop("timestamp") 47 48 equity = d.pop("equity") 49 50 equity_point = cls( 51 timestamp=timestamp, 52 equity=equity, 53 ) 54 55 equity_point.additional_properties = d 56 return equity_point
15@_attrs_define 16class Exchange: 17 """Exchange service provider 18 19 Attributes: 20 id (str): Unique identifier for the exchange Example: binance. 21 name (str): Name of the exchange Example: Binance. 22 description (str | Unset): Description of the exchange Example: Binance cryptocurrency exchange. 23 """ 24 25 id: str 26 name: str 27 description: str | Unset = UNSET 28 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 29 30 def to_dict(self) -> dict[str, Any]: 31 id = self.id 32 33 name = self.name 34 35 description = self.description 36 37 field_dict: dict[str, Any] = {} 38 field_dict.update(self.additional_properties) 39 field_dict.update( 40 { 41 "id": id, 42 "name": name, 43 } 44 ) 45 if description is not UNSET: 46 field_dict["description"] = description 47 48 return field_dict 49 50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 d = dict(src_dict) 53 id = d.pop("id") 54 55 name = d.pop("name") 56 57 description = d.pop("description", UNSET) 58 59 exchange = cls( 60 id=id, 61 name=name, 62 description=description, 63 ) 64 65 exchange.additional_properties = d 66 return exchange 67 68 @property 69 def additional_keys(self) -> list[str]: 70 return list(self.additional_properties.keys()) 71 72 def __getitem__(self, key: str) -> Any: 73 return self.additional_properties[key] 74 75 def __setitem__(self, key: str, value: Any) -> None: 76 self.additional_properties[key] = value 77 78 def __delitem__(self, key: str) -> None: 79 del self.additional_properties[key] 80 81 def __contains__(self, key: str) -> bool: 82 return key in self.additional_properties
Exchange service provider
Attributes: id (str): Unique identifier for the exchange Example: binance. name (str): Name of the exchange Example: Binance. description (str | Unset): Description of the exchange Example: Binance cryptocurrency exchange.
26def __init__(self, id, name, description=attr_dict['description'].default): 27 self.id = id 28 self.name = name 29 self.description = description 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class Exchange.
30 def to_dict(self) -> dict[str, Any]: 31 id = self.id 32 33 name = self.name 34 35 description = self.description 36 37 field_dict: dict[str, Any] = {} 38 field_dict.update(self.additional_properties) 39 field_dict.update( 40 { 41 "id": id, 42 "name": name, 43 } 44 ) 45 if description is not UNSET: 46 field_dict["description"] = description 47 48 return field_dict
50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 d = dict(src_dict) 53 id = d.pop("id") 54 55 name = d.pop("name") 56 57 description = d.pop("description", UNSET) 58 59 exchange = cls( 60 id=id, 61 name=name, 62 description=description, 63 ) 64 65 exchange.additional_properties = d 66 return exchange
21@_attrs_define 22class ExecuteBacktestBody: 23 """ 24 Attributes: 25 prepare_job_id (str): Job ID returned by `POST /prepare` (must be in `Completed` state) Example: 26 13RBLGQlPnfDjO6wyKSX8i. 27 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 28 always yields the same id, for every caller. How much formatting the id ignores depends on 29 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 30 not. 31 Example: 6bsh31ikwkuivhtgcoa6s4. 32 store_signals (bool | Unset): When true, the worker uploads emitted signals to object storage and the 33 response includes `signalsUrl` / `signalsId` fields. Defaults to false. 34 Default: False. 35 equity_curve (EquityCurveOptions | Unset): Requested equity-curve transform, applied server-side in a fixed 36 pipeline order: `resample` (point count) then `differential` (encoding) then `outMode` (JSON shape) — each stage 37 assumes the previous one already ran. A server-side size guard can still force a smaller/deflated shape above 38 its thresholds regardless of what is requested here — see `EquityCurveMeta` for what actually happened. 39 base_config (SweepBaseConfig | Unset): 40 params (ExecuteBacktestBodyParams | Unset): Strategy properties to apply to this run. Omit to run the strategy's 41 declared 42 defaults, which is exactly what a request without this field has always done. 43 44 Each key is the `name` declared on the strategy's `@StrategyProperty`, which 45 need NOT match the Java field it annotates — `GET`/`POST /strategy` returns 46 `declaredProperties` for precisely this. A key naming no declared property is 47 rejected: the job fails with the list of names the strategy does declare, 48 rather than completing at the defaults and handing back a plausible result for 49 parameters nobody chose. 50 51 Scalars only — number, string or boolean. Ranges and lists belong to 52 `executeSweep`; one request here is one run. `null` is not a value: leave the 53 key out to keep a property at its default. Keys are made of letters, digits, 54 `_`, `-` and dots, and may not be `strategyId`, `storeSignals`, `equityCurve`, 55 `backtestEnabled` or `backtestFakeExecution` — those configure the job rather 56 than the strategy. 57 Example: {'ema.fast.period': 9, 'ema.slow.period': 21, 'risk.pct': 0.5}. 58 """ 59 60 prepare_job_id: str 61 strategy_id: str 62 store_signals: bool | Unset = False 63 equity_curve: EquityCurveOptions | Unset = UNSET 64 base_config: SweepBaseConfig | Unset = UNSET 65 params: ExecuteBacktestBodyParams | Unset = UNSET 66 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 67 68 def to_dict(self) -> dict[str, Any]: 69 prepare_job_id = self.prepare_job_id 70 71 strategy_id = self.strategy_id 72 73 store_signals = self.store_signals 74 75 equity_curve: dict[str, Any] | Unset = UNSET 76 if not isinstance(self.equity_curve, Unset): 77 equity_curve = self.equity_curve.to_dict() 78 79 base_config: dict[str, Any] | Unset = UNSET 80 if not isinstance(self.base_config, Unset): 81 base_config = self.base_config.to_dict() 82 83 params: dict[str, Any] | Unset = UNSET 84 if not isinstance(self.params, Unset): 85 params = self.params.to_dict() 86 87 field_dict: dict[str, Any] = {} 88 field_dict.update(self.additional_properties) 89 field_dict.update( 90 { 91 "prepareJobId": prepare_job_id, 92 "strategyId": strategy_id, 93 } 94 ) 95 if store_signals is not UNSET: 96 field_dict["storeSignals"] = store_signals 97 if equity_curve is not UNSET: 98 field_dict["equityCurve"] = equity_curve 99 if base_config is not UNSET: 100 field_dict["baseConfig"] = base_config 101 if params is not UNSET: 102 field_dict["params"] = params 103 104 return field_dict 105 106 @classmethod 107 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 108 from ..models.equity_curve_options import EquityCurveOptions 109 from ..models.execute_backtest_body_params import ExecuteBacktestBodyParams 110 from ..models.sweep_base_config import SweepBaseConfig 111 112 d = dict(src_dict) 113 prepare_job_id = d.pop("prepareJobId") 114 115 strategy_id = d.pop("strategyId") 116 117 store_signals = d.pop("storeSignals", UNSET) 118 119 _equity_curve = d.pop("equityCurve", UNSET) 120 equity_curve: EquityCurveOptions | Unset 121 if isinstance(_equity_curve, Unset): 122 equity_curve = UNSET 123 else: 124 equity_curve = EquityCurveOptions.from_dict(_equity_curve) 125 126 _base_config = d.pop("baseConfig", UNSET) 127 base_config: SweepBaseConfig | Unset 128 if isinstance(_base_config, Unset): 129 base_config = UNSET 130 else: 131 base_config = SweepBaseConfig.from_dict(_base_config) 132 133 _params = d.pop("params", UNSET) 134 params: ExecuteBacktestBodyParams | Unset 135 if isinstance(_params, Unset): 136 params = UNSET 137 else: 138 params = ExecuteBacktestBodyParams.from_dict(_params) 139 140 execute_backtest_body = cls( 141 prepare_job_id=prepare_job_id, 142 strategy_id=strategy_id, 143 store_signals=store_signals, 144 equity_curve=equity_curve, 145 base_config=base_config, 146 params=params, 147 ) 148 149 execute_backtest_body.additional_properties = d 150 return execute_backtest_body 151 152 @property 153 def additional_keys(self) -> list[str]: 154 return list(self.additional_properties.keys()) 155 156 def __getitem__(self, key: str) -> Any: 157 return self.additional_properties[key] 158 159 def __setitem__(self, key: str, value: Any) -> None: 160 self.additional_properties[key] = value 161 162 def __delitem__(self, key: str) -> None: 163 del self.additional_properties[key] 164 165 def __contains__(self, key: str) -> bool: 166 return key in self.additional_properties
Attributes:
prepare_job_id (str): Job ID returned by POST /prepare (must be in Completed state) Example:
13RBLGQlPnfDjO6wyKSX8i.
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see POST /strategy for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
store_signals (bool | Unset): When true, the worker uploads emitted signals to object storage and the
response includes signalsUrl / signalsId fields. Defaults to false.
Default: False.
equity_curve (EquityCurveOptions | Unset): Requested equity-curve transform, applied server-side in a fixed
pipeline order: resample (point count) then differential (encoding) then outMode (JSON shape) — each stage
assumes the previous one already ran. A server-side size guard can still force a smaller/deflated shape above
its thresholds regardless of what is requested here — see EquityCurveMeta for what actually happened.
base_config (SweepBaseConfig | Unset):
params (ExecuteBacktestBodyParams | Unset): Strategy properties to apply to this run. Omit to run the strategy's
declared
defaults, which is exactly what a request without this field has always done.
Each key is the `name` declared on the strategy's `@StrategyProperty`, which
need NOT match the Java field it annotates — `GET`/`POST /strategy` returns
`declaredProperties` for precisely this. A key naming no declared property is
rejected: the job fails with the list of names the strategy does declare,
rather than completing at the defaults and handing back a plausible result for
parameters nobody chose.
Scalars only — number, string or boolean. Ranges and lists belong to
`executeSweep`; one request here is one run. `null` is not a value: leave the
key out to keep a property at its default. Keys are made of letters, digits,
`_`, `-` and dots, and may not be `strategyId`, `storeSignals`, `equityCurve`,
`backtestEnabled` or `backtestFakeExecution` — those configure the job rather
than the strategy.
Example: {'ema.fast.period': 9, 'ema.slow.period': 21, 'risk.pct': 0.5}.
29def __init__(self, prepare_job_id, strategy_id, store_signals=attr_dict['store_signals'].default, equity_curve=attr_dict['equity_curve'].default, base_config=attr_dict['base_config'].default, params=attr_dict['params'].default): 30 self.prepare_job_id = prepare_job_id 31 self.strategy_id = strategy_id 32 self.store_signals = store_signals 33 self.equity_curve = equity_curve 34 self.base_config = base_config 35 self.params = params 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ExecuteBacktestBody.
68 def to_dict(self) -> dict[str, Any]: 69 prepare_job_id = self.prepare_job_id 70 71 strategy_id = self.strategy_id 72 73 store_signals = self.store_signals 74 75 equity_curve: dict[str, Any] | Unset = UNSET 76 if not isinstance(self.equity_curve, Unset): 77 equity_curve = self.equity_curve.to_dict() 78 79 base_config: dict[str, Any] | Unset = UNSET 80 if not isinstance(self.base_config, Unset): 81 base_config = self.base_config.to_dict() 82 83 params: dict[str, Any] | Unset = UNSET 84 if not isinstance(self.params, Unset): 85 params = self.params.to_dict() 86 87 field_dict: dict[str, Any] = {} 88 field_dict.update(self.additional_properties) 89 field_dict.update( 90 { 91 "prepareJobId": prepare_job_id, 92 "strategyId": strategy_id, 93 } 94 ) 95 if store_signals is not UNSET: 96 field_dict["storeSignals"] = store_signals 97 if equity_curve is not UNSET: 98 field_dict["equityCurve"] = equity_curve 99 if base_config is not UNSET: 100 field_dict["baseConfig"] = base_config 101 if params is not UNSET: 102 field_dict["params"] = params 103 104 return field_dict
106 @classmethod 107 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 108 from ..models.equity_curve_options import EquityCurveOptions 109 from ..models.execute_backtest_body_params import ExecuteBacktestBodyParams 110 from ..models.sweep_base_config import SweepBaseConfig 111 112 d = dict(src_dict) 113 prepare_job_id = d.pop("prepareJobId") 114 115 strategy_id = d.pop("strategyId") 116 117 store_signals = d.pop("storeSignals", UNSET) 118 119 _equity_curve = d.pop("equityCurve", UNSET) 120 equity_curve: EquityCurveOptions | Unset 121 if isinstance(_equity_curve, Unset): 122 equity_curve = UNSET 123 else: 124 equity_curve = EquityCurveOptions.from_dict(_equity_curve) 125 126 _base_config = d.pop("baseConfig", UNSET) 127 base_config: SweepBaseConfig | Unset 128 if isinstance(_base_config, Unset): 129 base_config = UNSET 130 else: 131 base_config = SweepBaseConfig.from_dict(_base_config) 132 133 _params = d.pop("params", UNSET) 134 params: ExecuteBacktestBodyParams | Unset 135 if isinstance(_params, Unset): 136 params = UNSET 137 else: 138 params = ExecuteBacktestBodyParams.from_dict(_params) 139 140 execute_backtest_body = cls( 141 prepare_job_id=prepare_job_id, 142 strategy_id=strategy_id, 143 store_signals=store_signals, 144 equity_curve=equity_curve, 145 base_config=base_config, 146 params=params, 147 ) 148 149 execute_backtest_body.additional_properties = d 150 return execute_backtest_body
13@_attrs_define 14class ExecuteBacktestBodyParams: 15 """Strategy properties to apply to this run. Omit to run the strategy's declared 16 defaults, which is exactly what a request without this field has always done. 17 18 Each key is the `name` declared on the strategy's `@StrategyProperty`, which 19 need NOT match the Java field it annotates — `GET`/`POST /strategy` returns 20 `declaredProperties` for precisely this. A key naming no declared property is 21 rejected: the job fails with the list of names the strategy does declare, 22 rather than completing at the defaults and handing back a plausible result for 23 parameters nobody chose. 24 25 Scalars only — number, string or boolean. Ranges and lists belong to 26 `executeSweep`; one request here is one run. `null` is not a value: leave the 27 key out to keep a property at its default. Keys are made of letters, digits, 28 `_`, `-` and dots, and may not be `strategyId`, `storeSignals`, `equityCurve`, 29 `backtestEnabled` or `backtestFakeExecution` — those configure the job rather 30 than the strategy. 31 32 Example: 33 {'ema.fast.period': 9, 'ema.slow.period': 21, 'risk.pct': 0.5} 34 35 """ 36 37 additional_properties: dict[str, bool | float | str] = _attrs_field(init=False, factory=dict) 38 39 def to_dict(self) -> dict[str, Any]: 40 41 field_dict: dict[str, Any] = {} 42 for prop_name, prop in self.additional_properties.items(): 43 field_dict[prop_name] = prop 44 45 return field_dict 46 47 @classmethod 48 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 49 d = dict(src_dict) 50 execute_backtest_body_params = cls() 51 52 additional_properties = {} 53 for prop_name, prop_dict in d.items(): 54 55 def _parse_additional_property(data: object) -> bool | float | str: 56 return cast(bool | float | str, data) 57 58 additional_property = _parse_additional_property(prop_dict) 59 60 additional_properties[prop_name] = additional_property 61 62 execute_backtest_body_params.additional_properties = additional_properties 63 return execute_backtest_body_params 64 65 @property 66 def additional_keys(self) -> list[str]: 67 return list(self.additional_properties.keys()) 68 69 def __getitem__(self, key: str) -> bool | float | str: 70 return self.additional_properties[key] 71 72 def __setitem__(self, key: str, value: bool | float | str) -> None: 73 self.additional_properties[key] = value 74 75 def __delitem__(self, key: str) -> None: 76 del self.additional_properties[key] 77 78 def __contains__(self, key: str) -> bool: 79 return key in self.additional_properties
Strategy properties to apply to this run. Omit to run the strategy's declared defaults, which is exactly what a request without this field has always done.
Each key is the name declared on the strategy's @StrategyProperty, which
need NOT match the Java field it annotates — GET/POST /strategy returns
declaredProperties for precisely this. A key naming no declared property is
rejected: the job fails with the list of names the strategy does declare,
rather than completing at the defaults and handing back a plausible result for
parameters nobody chose.
Scalars only — number, string or boolean. Ranges and lists belong to
executeSweep; one request here is one run. null is not a value: leave the
key out to keep a property at its default. Keys are made of letters, digits,
_, - and dots, and may not be strategyId, storeSignals, equityCurve,
backtestEnabled or backtestFakeExecution — those configure the job rather
than the strategy.
Example:
{'ema.fast.period': 9, 'ema.slow.period': 21, 'risk.pct': 0.5}
47 @classmethod 48 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 49 d = dict(src_dict) 50 execute_backtest_body_params = cls() 51 52 additional_properties = {} 53 for prop_name, prop_dict in d.items(): 54 55 def _parse_additional_property(data: object) -> bool | float | str: 56 return cast(bool | float | str, data) 57 58 additional_property = _parse_additional_property(prop_dict) 59 60 additional_properties[prop_name] = additional_property 61 62 execute_backtest_body_params.additional_properties = additional_properties 63 return execute_backtest_body_params
19@_attrs_define 20class ExecuteSweepAccepted: 21 """ 22 Attributes: 23 sweep_id (str): Example: swp_95e47a7f0966ce11. 24 request_id (str): 25 total_runs (int): 26 shards (int): 27 seed (int): Effective seed used to expand the sweep. 28 queued (bool): False when an identical sweep already exists and was not enqueued again. 29 walk_forward (WalkForwardAccepted | Unset): Echo of the accepted walk-forward configuration, present only when 30 the submit carried one. `inSamplePct` is the resolved value, so a request that omitted it can see what it got. 31 """ 32 33 sweep_id: str 34 request_id: str 35 total_runs: int 36 shards: int 37 seed: int 38 queued: bool 39 walk_forward: WalkForwardAccepted | Unset = UNSET 40 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 41 42 def to_dict(self) -> dict[str, Any]: 43 sweep_id = self.sweep_id 44 45 request_id = self.request_id 46 47 total_runs = self.total_runs 48 49 shards = self.shards 50 51 seed = self.seed 52 53 queued = self.queued 54 55 walk_forward: dict[str, Any] | Unset = UNSET 56 if not isinstance(self.walk_forward, Unset): 57 walk_forward = self.walk_forward.to_dict() 58 59 field_dict: dict[str, Any] = {} 60 field_dict.update(self.additional_properties) 61 field_dict.update( 62 { 63 "sweepId": sweep_id, 64 "requestId": request_id, 65 "totalRuns": total_runs, 66 "shards": shards, 67 "seed": seed, 68 "queued": queued, 69 } 70 ) 71 if walk_forward is not UNSET: 72 field_dict["walkForward"] = walk_forward 73 74 return field_dict 75 76 @classmethod 77 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 78 from ..models.walk_forward_accepted import WalkForwardAccepted 79 80 d = dict(src_dict) 81 sweep_id = d.pop("sweepId") 82 83 request_id = d.pop("requestId") 84 85 total_runs = d.pop("totalRuns") 86 87 shards = d.pop("shards") 88 89 seed = d.pop("seed") 90 91 queued = d.pop("queued") 92 93 _walk_forward = d.pop("walkForward", UNSET) 94 walk_forward: WalkForwardAccepted | Unset 95 if isinstance(_walk_forward, Unset): 96 walk_forward = UNSET 97 else: 98 walk_forward = WalkForwardAccepted.from_dict(_walk_forward) 99 100 execute_sweep_accepted = cls( 101 sweep_id=sweep_id, 102 request_id=request_id, 103 total_runs=total_runs, 104 shards=shards, 105 seed=seed, 106 queued=queued, 107 walk_forward=walk_forward, 108 ) 109 110 execute_sweep_accepted.additional_properties = d 111 return execute_sweep_accepted 112 113 @property 114 def additional_keys(self) -> list[str]: 115 return list(self.additional_properties.keys()) 116 117 def __getitem__(self, key: str) -> Any: 118 return self.additional_properties[key] 119 120 def __setitem__(self, key: str, value: Any) -> None: 121 self.additional_properties[key] = value 122 123 def __delitem__(self, key: str) -> None: 124 del self.additional_properties[key] 125 126 def __contains__(self, key: str) -> bool: 127 return key in self.additional_properties
Attributes:
sweep_id (str): Example: swp_95e47a7f0966ce11.
request_id (str):
total_runs (int):
shards (int):
seed (int): Effective seed used to expand the sweep.
queued (bool): False when an identical sweep already exists and was not enqueued again.
walk_forward (WalkForwardAccepted | Unset): Echo of the accepted walk-forward configuration, present only when
the submit carried one. inSamplePct is the resolved value, so a request that omitted it can see what it got.
30def __init__(self, sweep_id, request_id, total_runs, shards, seed, queued, walk_forward=attr_dict['walk_forward'].default): 31 self.sweep_id = sweep_id 32 self.request_id = request_id 33 self.total_runs = total_runs 34 self.shards = shards 35 self.seed = seed 36 self.queued = queued 37 self.walk_forward = walk_forward 38 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ExecuteSweepAccepted.
42 def to_dict(self) -> dict[str, Any]: 43 sweep_id = self.sweep_id 44 45 request_id = self.request_id 46 47 total_runs = self.total_runs 48 49 shards = self.shards 50 51 seed = self.seed 52 53 queued = self.queued 54 55 walk_forward: dict[str, Any] | Unset = UNSET 56 if not isinstance(self.walk_forward, Unset): 57 walk_forward = self.walk_forward.to_dict() 58 59 field_dict: dict[str, Any] = {} 60 field_dict.update(self.additional_properties) 61 field_dict.update( 62 { 63 "sweepId": sweep_id, 64 "requestId": request_id, 65 "totalRuns": total_runs, 66 "shards": shards, 67 "seed": seed, 68 "queued": queued, 69 } 70 ) 71 if walk_forward is not UNSET: 72 field_dict["walkForward"] = walk_forward 73 74 return field_dict
76 @classmethod 77 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 78 from ..models.walk_forward_accepted import WalkForwardAccepted 79 80 d = dict(src_dict) 81 sweep_id = d.pop("sweepId") 82 83 request_id = d.pop("requestId") 84 85 total_runs = d.pop("totalRuns") 86 87 shards = d.pop("shards") 88 89 seed = d.pop("seed") 90 91 queued = d.pop("queued") 92 93 _walk_forward = d.pop("walkForward", UNSET) 94 walk_forward: WalkForwardAccepted | Unset 95 if isinstance(_walk_forward, Unset): 96 walk_forward = UNSET 97 else: 98 walk_forward = WalkForwardAccepted.from_dict(_walk_forward) 99 100 execute_sweep_accepted = cls( 101 sweep_id=sweep_id, 102 request_id=request_id, 103 total_runs=total_runs, 104 shards=shards, 105 seed=seed, 106 queued=queued, 107 walk_forward=walk_forward, 108 ) 109 110 execute_sweep_accepted.additional_properties = d 111 return execute_sweep_accepted
22@_attrs_define 23class ExecuteSweepRequest: 24 """ 25 Attributes: 26 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 27 always yields the same id, for every caller. How much formatting the id ignores depends on 28 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 29 not. 30 Example: 6bsh31ikwkuivhtgcoa6s4. 31 sweep (SweepSpecRequest): Example: {'sampler': 'lhs', 'seed': 487221, 'samples': 100, 'objective': 'sharpe', 32 'params': {'rsiPeriod': {'from': 7, 'to': 28, 'step': 1}, 'useTrendFilter': {'values': [True, False]}}}. 33 base_config (SweepBaseConfig | Unset): 34 store_signals (bool | Unset): Store signals for every trial. Keep false for normal sweeps. Default: False. 35 shards (int | Unset): Requested horizontal shard count; 0 or omitted selects automatically. Default: 0. 36 min_trade_floor (int | Unset): Trials below this trade count are flagged but remain in the results. Default: 30. 37 walk_forward (WalkForwardRequest | Unset): Opt in to walk-forward validation. Present, the sweep runs as F 38 sequential folds and the result gains a `walkForward` section; absent, nothing about the sweep changes. Two 39 requests that differ only in this block are two different sweeps and do not deduplicate against each other. 40 equity_curve (EquityCurveRequest | Unset): Selection (`mode`/`n`/`maxPct`) plus the transform preference 41 (`resample`/`differential`/`outMode`) applied by `GET .../equityCurve` whenever ITS OWN query params are absent, 42 for a curve this sweep retained. The transform half never affects retention or `sweepId` — a caller can always 43 override it per-request at read time regardless of what was submitted here. 44 """ 45 46 strategy_id: str 47 sweep: SweepSpecRequest 48 base_config: SweepBaseConfig | Unset = UNSET 49 store_signals: bool | Unset = False 50 shards: int | Unset = 0 51 min_trade_floor: int | Unset = 30 52 walk_forward: WalkForwardRequest | Unset = UNSET 53 equity_curve: EquityCurveRequest | Unset = UNSET 54 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 55 56 def to_dict(self) -> dict[str, Any]: 57 strategy_id = self.strategy_id 58 59 sweep = self.sweep.to_dict() 60 61 base_config: dict[str, Any] | Unset = UNSET 62 if not isinstance(self.base_config, Unset): 63 base_config = self.base_config.to_dict() 64 65 store_signals = self.store_signals 66 67 shards = self.shards 68 69 min_trade_floor = self.min_trade_floor 70 71 walk_forward: dict[str, Any] | Unset = UNSET 72 if not isinstance(self.walk_forward, Unset): 73 walk_forward = self.walk_forward.to_dict() 74 75 equity_curve: dict[str, Any] | Unset = UNSET 76 if not isinstance(self.equity_curve, Unset): 77 equity_curve = self.equity_curve.to_dict() 78 79 field_dict: dict[str, Any] = {} 80 field_dict.update(self.additional_properties) 81 field_dict.update( 82 { 83 "strategyId": strategy_id, 84 "sweep": sweep, 85 } 86 ) 87 if base_config is not UNSET: 88 field_dict["baseConfig"] = base_config 89 if store_signals is not UNSET: 90 field_dict["storeSignals"] = store_signals 91 if shards is not UNSET: 92 field_dict["shards"] = shards 93 if min_trade_floor is not UNSET: 94 field_dict["minTradeFloor"] = min_trade_floor 95 if walk_forward is not UNSET: 96 field_dict["walkForward"] = walk_forward 97 if equity_curve is not UNSET: 98 field_dict["equityCurve"] = equity_curve 99 100 return field_dict 101 102 @classmethod 103 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 104 from ..models.equity_curve_request import EquityCurveRequest 105 from ..models.sweep_base_config import SweepBaseConfig 106 from ..models.sweep_spec_request import SweepSpecRequest 107 from ..models.walk_forward_request import WalkForwardRequest 108 109 d = dict(src_dict) 110 strategy_id = d.pop("strategyId") 111 112 sweep = SweepSpecRequest.from_dict(d.pop("sweep")) 113 114 _base_config = d.pop("baseConfig", UNSET) 115 base_config: SweepBaseConfig | Unset 116 if isinstance(_base_config, Unset): 117 base_config = UNSET 118 else: 119 base_config = SweepBaseConfig.from_dict(_base_config) 120 121 store_signals = d.pop("storeSignals", UNSET) 122 123 shards = d.pop("shards", UNSET) 124 125 min_trade_floor = d.pop("minTradeFloor", UNSET) 126 127 _walk_forward = d.pop("walkForward", UNSET) 128 walk_forward: WalkForwardRequest | Unset 129 if isinstance(_walk_forward, Unset): 130 walk_forward = UNSET 131 else: 132 walk_forward = WalkForwardRequest.from_dict(_walk_forward) 133 134 _equity_curve = d.pop("equityCurve", UNSET) 135 equity_curve: EquityCurveRequest | Unset 136 if isinstance(_equity_curve, Unset): 137 equity_curve = UNSET 138 else: 139 equity_curve = EquityCurveRequest.from_dict(_equity_curve) 140 141 execute_sweep_request = cls( 142 strategy_id=strategy_id, 143 sweep=sweep, 144 base_config=base_config, 145 store_signals=store_signals, 146 shards=shards, 147 min_trade_floor=min_trade_floor, 148 walk_forward=walk_forward, 149 equity_curve=equity_curve, 150 ) 151 152 execute_sweep_request.additional_properties = d 153 return execute_sweep_request 154 155 @property 156 def additional_keys(self) -> list[str]: 157 return list(self.additional_properties.keys()) 158 159 def __getitem__(self, key: str) -> Any: 160 return self.additional_properties[key] 161 162 def __setitem__(self, key: str, value: Any) -> None: 163 self.additional_properties[key] = value 164 165 def __delitem__(self, key: str) -> None: 166 del self.additional_properties[key] 167 168 def __contains__(self, key: str) -> bool: 169 return key in self.additional_properties
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see POST /strategy for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
sweep (SweepSpecRequest): Example: {'sampler': 'lhs', 'seed': 487221, 'samples': 100, 'objective': 'sharpe',
'params': {'rsiPeriod': {'from': 7, 'to': 28, 'step': 1}, 'useTrendFilter': {'values': [True, False]}}}.
base_config (SweepBaseConfig | Unset):
store_signals (bool | Unset): Store signals for every trial. Keep false for normal sweeps. Default: False.
shards (int | Unset): Requested horizontal shard count; 0 or omitted selects automatically. Default: 0.
min_trade_floor (int | Unset): Trials below this trade count are flagged but remain in the results. Default: 30.
walk_forward (WalkForwardRequest | Unset): Opt in to walk-forward validation. Present, the sweep runs as F
sequential folds and the result gains a walkForward section; absent, nothing about the sweep changes. Two
requests that differ only in this block are two different sweeps and do not deduplicate against each other.
equity_curve (EquityCurveRequest | Unset): Selection (mode/n/maxPct) plus the transform preference
(resample/differential/outMode) applied by GET .../equityCurve whenever ITS OWN query params are absent,
for a curve this sweep retained. The transform half never affects retention or sweepId — a caller can always
override it per-request at read time regardless of what was submitted here.
31def __init__(self, strategy_id, sweep, base_config=attr_dict['base_config'].default, store_signals=attr_dict['store_signals'].default, shards=attr_dict['shards'].default, min_trade_floor=attr_dict['min_trade_floor'].default, walk_forward=attr_dict['walk_forward'].default, equity_curve=attr_dict['equity_curve'].default): 32 self.strategy_id = strategy_id 33 self.sweep = sweep 34 self.base_config = base_config 35 self.store_signals = store_signals 36 self.shards = shards 37 self.min_trade_floor = min_trade_floor 38 self.walk_forward = walk_forward 39 self.equity_curve = equity_curve 40 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ExecuteSweepRequest.
56 def to_dict(self) -> dict[str, Any]: 57 strategy_id = self.strategy_id 58 59 sweep = self.sweep.to_dict() 60 61 base_config: dict[str, Any] | Unset = UNSET 62 if not isinstance(self.base_config, Unset): 63 base_config = self.base_config.to_dict() 64 65 store_signals = self.store_signals 66 67 shards = self.shards 68 69 min_trade_floor = self.min_trade_floor 70 71 walk_forward: dict[str, Any] | Unset = UNSET 72 if not isinstance(self.walk_forward, Unset): 73 walk_forward = self.walk_forward.to_dict() 74 75 equity_curve: dict[str, Any] | Unset = UNSET 76 if not isinstance(self.equity_curve, Unset): 77 equity_curve = self.equity_curve.to_dict() 78 79 field_dict: dict[str, Any] = {} 80 field_dict.update(self.additional_properties) 81 field_dict.update( 82 { 83 "strategyId": strategy_id, 84 "sweep": sweep, 85 } 86 ) 87 if base_config is not UNSET: 88 field_dict["baseConfig"] = base_config 89 if store_signals is not UNSET: 90 field_dict["storeSignals"] = store_signals 91 if shards is not UNSET: 92 field_dict["shards"] = shards 93 if min_trade_floor is not UNSET: 94 field_dict["minTradeFloor"] = min_trade_floor 95 if walk_forward is not UNSET: 96 field_dict["walkForward"] = walk_forward 97 if equity_curve is not UNSET: 98 field_dict["equityCurve"] = equity_curve 99 100 return field_dict
102 @classmethod 103 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 104 from ..models.equity_curve_request import EquityCurveRequest 105 from ..models.sweep_base_config import SweepBaseConfig 106 from ..models.sweep_spec_request import SweepSpecRequest 107 from ..models.walk_forward_request import WalkForwardRequest 108 109 d = dict(src_dict) 110 strategy_id = d.pop("strategyId") 111 112 sweep = SweepSpecRequest.from_dict(d.pop("sweep")) 113 114 _base_config = d.pop("baseConfig", UNSET) 115 base_config: SweepBaseConfig | Unset 116 if isinstance(_base_config, Unset): 117 base_config = UNSET 118 else: 119 base_config = SweepBaseConfig.from_dict(_base_config) 120 121 store_signals = d.pop("storeSignals", UNSET) 122 123 shards = d.pop("shards", UNSET) 124 125 min_trade_floor = d.pop("minTradeFloor", UNSET) 126 127 _walk_forward = d.pop("walkForward", UNSET) 128 walk_forward: WalkForwardRequest | Unset 129 if isinstance(_walk_forward, Unset): 130 walk_forward = UNSET 131 else: 132 walk_forward = WalkForwardRequest.from_dict(_walk_forward) 133 134 _equity_curve = d.pop("equityCurve", UNSET) 135 equity_curve: EquityCurveRequest | Unset 136 if isinstance(_equity_curve, Unset): 137 equity_curve = UNSET 138 else: 139 equity_curve = EquityCurveRequest.from_dict(_equity_curve) 140 141 execute_sweep_request = cls( 142 strategy_id=strategy_id, 143 sweep=sweep, 144 base_config=base_config, 145 store_signals=store_signals, 146 shards=shards, 147 min_trade_floor=min_trade_floor, 148 walk_forward=walk_forward, 149 equity_curve=equity_curve, 150 ) 151 152 execute_sweep_request.additional_properties = d 153 return execute_sweep_request
26@_attrs_define 27class ExecuteSweepResult: 28 """ 29 Attributes: 30 sweep_id (str): 31 status (ExecuteSweepResultStatus): The sweep's own status vocabulary — not the same set `state.status` below 32 uses. See `state` for why. 33 objective (ExecuteSweepResultObjective): 34 order (ExecuteSweepResultOrder): 35 progress (SweepProgress): How far along a sweep is, and — when the sweep is still running — enough to tell a 36 healthy one from a stuck one. The counts partition the shards (or, for a walk-forward sweep, the folds): every 37 unit is either finished, failed, waiting to be retried, or not yet started. 38 leaderboard_size (int): Total result rows currently available. 39 truncated (bool): True only when the ranked view exceeds its display limit. 40 leaderboard (list[SweepRunRow]): 41 state (JobState): Information about a single job 42 ranking (ExecuteSweepResultRanking | Unset): Which ordering was actually applied, which is not always the one 43 requested: a sweep with no stored parameter grid cannot be plateau-ranked and falls back to `raw`. Always `raw` 44 when `order=natural`. 45 pbo (float | Unset): Probability of backtest overfitting for the sweep as a whole, by combinatorially symmetric 46 cross-validation: how often the configuration that won in-sample lands below median out-of-sample. Above ~0.5 47 the sweep is selecting noise, whatever its top row says. Computed once when the last shard finishes, so it is 48 absent while the sweep is still running and on sweeps too small for the statistic to mean anything. 49 pbo_splits (int | Unset): How many train/test splits the `pbo` figure was averaged over. 50 fail_reason (str | Unset): Why the sweep produced less than it should have — the cause reported by the **first** 51 shard to fail, not a list. It is what turns an inscrutable empty leaderboard into an answer: a sweep can come 52 back `PARTIAL` with `done: 0` because the strategy could not be loaded at all, and without this the response 53 says only that nothing finished. 54 First failure wins and later ones are not recorded, so on a sweep where several shards failed for different 55 reasons this names one of them rather than all. Absent when no shard reported a cause, which is the normal case 56 for a healthy sweep — read it together with `progress.failedShards` rather than as a count of anything. Example: 57 Failed to load/configure strategy. 58 walk_forward (WalkForwardResult | Unset): Present only on a sweep submitted with `walkForward`, and present from 59 acceptance onward — its presence, not its contents, is what identifies a walk-forward sweep. `completedFolds` is 60 0 while the first fold is still running. 61 """ 62 63 sweep_id: str 64 status: ExecuteSweepResultStatus 65 objective: ExecuteSweepResultObjective 66 order: ExecuteSweepResultOrder 67 progress: SweepProgress 68 leaderboard_size: int 69 truncated: bool 70 leaderboard: list[SweepRunRow] 71 state: JobState 72 ranking: ExecuteSweepResultRanking | Unset = UNSET 73 pbo: float | Unset = UNSET 74 pbo_splits: int | Unset = UNSET 75 fail_reason: str | Unset = UNSET 76 walk_forward: WalkForwardResult | Unset = UNSET 77 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 78 79 def to_dict(self) -> dict[str, Any]: 80 sweep_id = self.sweep_id 81 82 status = self.status.value 83 84 objective = self.objective.value 85 86 order = self.order.value 87 88 progress = self.progress.to_dict() 89 90 leaderboard_size = self.leaderboard_size 91 92 truncated = self.truncated 93 94 leaderboard = [] 95 for leaderboard_item_data in self.leaderboard: 96 leaderboard_item = leaderboard_item_data.to_dict() 97 leaderboard.append(leaderboard_item) 98 99 state = self.state.to_dict() 100 101 ranking: str | Unset = UNSET 102 if not isinstance(self.ranking, Unset): 103 ranking = self.ranking.value 104 105 pbo = self.pbo 106 107 pbo_splits = self.pbo_splits 108 109 fail_reason = self.fail_reason 110 111 walk_forward: dict[str, Any] | Unset = UNSET 112 if not isinstance(self.walk_forward, Unset): 113 walk_forward = self.walk_forward.to_dict() 114 115 field_dict: dict[str, Any] = {} 116 field_dict.update(self.additional_properties) 117 field_dict.update( 118 { 119 "sweepId": sweep_id, 120 "status": status, 121 "objective": objective, 122 "order": order, 123 "progress": progress, 124 "leaderboardSize": leaderboard_size, 125 "truncated": truncated, 126 "leaderboard": leaderboard, 127 "state": state, 128 } 129 ) 130 if ranking is not UNSET: 131 field_dict["ranking"] = ranking 132 if pbo is not UNSET: 133 field_dict["pbo"] = pbo 134 if pbo_splits is not UNSET: 135 field_dict["pboSplits"] = pbo_splits 136 if fail_reason is not UNSET: 137 field_dict["failReason"] = fail_reason 138 if walk_forward is not UNSET: 139 field_dict["walkForward"] = walk_forward 140 141 return field_dict 142 143 @classmethod 144 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 145 from ..models.job_state import JobState 146 from ..models.sweep_progress import SweepProgress 147 from ..models.sweep_run_row import SweepRunRow 148 from ..models.walk_forward_result import WalkForwardResult 149 150 d = dict(src_dict) 151 sweep_id = d.pop("sweepId") 152 153 status = ExecuteSweepResultStatus(d.pop("status")) 154 155 objective = ExecuteSweepResultObjective(d.pop("objective")) 156 157 order = ExecuteSweepResultOrder(d.pop("order")) 158 159 progress = SweepProgress.from_dict(d.pop("progress")) 160 161 leaderboard_size = d.pop("leaderboardSize") 162 163 truncated = d.pop("truncated") 164 165 leaderboard = [] 166 _leaderboard = d.pop("leaderboard") 167 for leaderboard_item_data in _leaderboard: 168 leaderboard_item = SweepRunRow.from_dict(leaderboard_item_data) 169 170 leaderboard.append(leaderboard_item) 171 172 state = JobState.from_dict(d.pop("state")) 173 174 _ranking = d.pop("ranking", UNSET) 175 ranking: ExecuteSweepResultRanking | Unset 176 if isinstance(_ranking, Unset): 177 ranking = UNSET 178 else: 179 ranking = ExecuteSweepResultRanking(_ranking) 180 181 pbo = d.pop("pbo", UNSET) 182 183 pbo_splits = d.pop("pboSplits", UNSET) 184 185 fail_reason = d.pop("failReason", UNSET) 186 187 _walk_forward = d.pop("walkForward", UNSET) 188 walk_forward: WalkForwardResult | Unset 189 if isinstance(_walk_forward, Unset): 190 walk_forward = UNSET 191 else: 192 walk_forward = WalkForwardResult.from_dict(_walk_forward) 193 194 execute_sweep_result = cls( 195 sweep_id=sweep_id, 196 status=status, 197 objective=objective, 198 order=order, 199 progress=progress, 200 leaderboard_size=leaderboard_size, 201 truncated=truncated, 202 leaderboard=leaderboard, 203 state=state, 204 ranking=ranking, 205 pbo=pbo, 206 pbo_splits=pbo_splits, 207 fail_reason=fail_reason, 208 walk_forward=walk_forward, 209 ) 210 211 execute_sweep_result.additional_properties = d 212 return execute_sweep_result 213 214 @property 215 def additional_keys(self) -> list[str]: 216 return list(self.additional_properties.keys()) 217 218 def __getitem__(self, key: str) -> Any: 219 return self.additional_properties[key] 220 221 def __setitem__(self, key: str, value: Any) -> None: 222 self.additional_properties[key] = value 223 224 def __delitem__(self, key: str) -> None: 225 del self.additional_properties[key] 226 227 def __contains__(self, key: str) -> bool: 228 return key in self.additional_properties
Attributes:
sweep_id (str):
status (ExecuteSweepResultStatus): The sweep's own status vocabulary — not the same set state.status below
uses. See state for why.
objective (ExecuteSweepResultObjective):
order (ExecuteSweepResultOrder):
progress (SweepProgress): How far along a sweep is, and — when the sweep is still running — enough to tell a
healthy one from a stuck one. The counts partition the shards (or, for a walk-forward sweep, the folds): every
unit is either finished, failed, waiting to be retried, or not yet started.
leaderboard_size (int): Total result rows currently available.
truncated (bool): True only when the ranked view exceeds its display limit.
leaderboard (list[SweepRunRow]):
state (JobState): Information about a single job
ranking (ExecuteSweepResultRanking | Unset): Which ordering was actually applied, which is not always the one
requested: a sweep with no stored parameter grid cannot be plateau-ranked and falls back to raw. Always raw
when order=natural.
pbo (float | Unset): Probability of backtest overfitting for the sweep as a whole, by combinatorially symmetric
cross-validation: how often the configuration that won in-sample lands below median out-of-sample. Above ~0.5
the sweep is selecting noise, whatever its top row says. Computed once when the last shard finishes, so it is
absent while the sweep is still running and on sweeps too small for the statistic to mean anything.
pbo_splits (int | Unset): How many train/test splits the pbo figure was averaged over.
fail_reason (str | Unset): Why the sweep produced less than it should have — the cause reported by the first
shard to fail, not a list. It is what turns an inscrutable empty leaderboard into an answer: a sweep can come
back PARTIAL with done: 0 because the strategy could not be loaded at all, and without this the response
says only that nothing finished.
First failure wins and later ones are not recorded, so on a sweep where several shards failed for different
reasons this names one of them rather than all. Absent when no shard reported a cause, which is the normal case
for a healthy sweep — read it together with progress.failedShards rather than as a count of anything. Example:
Failed to load/configure strategy.
walk_forward (WalkForwardResult | Unset): Present only on a sweep submitted with walkForward, and present from
acceptance onward — its presence, not its contents, is what identifies a walk-forward sweep. completedFolds is
0 while the first fold is still running.
37def __init__(self, sweep_id, status, objective, order, progress, leaderboard_size, truncated, leaderboard, state, ranking=attr_dict['ranking'].default, pbo=attr_dict['pbo'].default, pbo_splits=attr_dict['pbo_splits'].default, fail_reason=attr_dict['fail_reason'].default, walk_forward=attr_dict['walk_forward'].default): 38 self.sweep_id = sweep_id 39 self.status = status 40 self.objective = objective 41 self.order = order 42 self.progress = progress 43 self.leaderboard_size = leaderboard_size 44 self.truncated = truncated 45 self.leaderboard = leaderboard 46 self.state = state 47 self.ranking = ranking 48 self.pbo = pbo 49 self.pbo_splits = pbo_splits 50 self.fail_reason = fail_reason 51 self.walk_forward = walk_forward 52 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ExecuteSweepResult.
79 def to_dict(self) -> dict[str, Any]: 80 sweep_id = self.sweep_id 81 82 status = self.status.value 83 84 objective = self.objective.value 85 86 order = self.order.value 87 88 progress = self.progress.to_dict() 89 90 leaderboard_size = self.leaderboard_size 91 92 truncated = self.truncated 93 94 leaderboard = [] 95 for leaderboard_item_data in self.leaderboard: 96 leaderboard_item = leaderboard_item_data.to_dict() 97 leaderboard.append(leaderboard_item) 98 99 state = self.state.to_dict() 100 101 ranking: str | Unset = UNSET 102 if not isinstance(self.ranking, Unset): 103 ranking = self.ranking.value 104 105 pbo = self.pbo 106 107 pbo_splits = self.pbo_splits 108 109 fail_reason = self.fail_reason 110 111 walk_forward: dict[str, Any] | Unset = UNSET 112 if not isinstance(self.walk_forward, Unset): 113 walk_forward = self.walk_forward.to_dict() 114 115 field_dict: dict[str, Any] = {} 116 field_dict.update(self.additional_properties) 117 field_dict.update( 118 { 119 "sweepId": sweep_id, 120 "status": status, 121 "objective": objective, 122 "order": order, 123 "progress": progress, 124 "leaderboardSize": leaderboard_size, 125 "truncated": truncated, 126 "leaderboard": leaderboard, 127 "state": state, 128 } 129 ) 130 if ranking is not UNSET: 131 field_dict["ranking"] = ranking 132 if pbo is not UNSET: 133 field_dict["pbo"] = pbo 134 if pbo_splits is not UNSET: 135 field_dict["pboSplits"] = pbo_splits 136 if fail_reason is not UNSET: 137 field_dict["failReason"] = fail_reason 138 if walk_forward is not UNSET: 139 field_dict["walkForward"] = walk_forward 140 141 return field_dict
143 @classmethod 144 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 145 from ..models.job_state import JobState 146 from ..models.sweep_progress import SweepProgress 147 from ..models.sweep_run_row import SweepRunRow 148 from ..models.walk_forward_result import WalkForwardResult 149 150 d = dict(src_dict) 151 sweep_id = d.pop("sweepId") 152 153 status = ExecuteSweepResultStatus(d.pop("status")) 154 155 objective = ExecuteSweepResultObjective(d.pop("objective")) 156 157 order = ExecuteSweepResultOrder(d.pop("order")) 158 159 progress = SweepProgress.from_dict(d.pop("progress")) 160 161 leaderboard_size = d.pop("leaderboardSize") 162 163 truncated = d.pop("truncated") 164 165 leaderboard = [] 166 _leaderboard = d.pop("leaderboard") 167 for leaderboard_item_data in _leaderboard: 168 leaderboard_item = SweepRunRow.from_dict(leaderboard_item_data) 169 170 leaderboard.append(leaderboard_item) 171 172 state = JobState.from_dict(d.pop("state")) 173 174 _ranking = d.pop("ranking", UNSET) 175 ranking: ExecuteSweepResultRanking | Unset 176 if isinstance(_ranking, Unset): 177 ranking = UNSET 178 else: 179 ranking = ExecuteSweepResultRanking(_ranking) 180 181 pbo = d.pop("pbo", UNSET) 182 183 pbo_splits = d.pop("pboSplits", UNSET) 184 185 fail_reason = d.pop("failReason", UNSET) 186 187 _walk_forward = d.pop("walkForward", UNSET) 188 walk_forward: WalkForwardResult | Unset 189 if isinstance(_walk_forward, Unset): 190 walk_forward = UNSET 191 else: 192 walk_forward = WalkForwardResult.from_dict(_walk_forward) 193 194 execute_sweep_result = cls( 195 sweep_id=sweep_id, 196 status=status, 197 objective=objective, 198 order=order, 199 progress=progress, 200 leaderboard_size=leaderboard_size, 201 truncated=truncated, 202 leaderboard=leaderboard, 203 state=state, 204 ranking=ranking, 205 pbo=pbo, 206 pbo_splits=pbo_splits, 207 fail_reason=fail_reason, 208 walk_forward=walk_forward, 209 ) 210 211 execute_sweep_result.additional_properties = d 212 return execute_sweep_result
5class ExecuteSweepResultObjective(str, Enum): 6 MAXDD = "maxdd" 7 PNL = "pnl" 8 SHARPE = "sharpe" 9 SORTINO = "sortino" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class ExecuteSweepResultOrder(str, Enum): 6 NATURAL = "natural" 7 RANKED = "ranked" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class ExecuteSweepResultRanking(str, Enum): 6 PLATEAU = "plateau" 7 RAW = "raw" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class ExecuteSweepResultStatus(str, Enum): 6 CANCELLED = "CANCELLED" 7 COMPLETED = "COMPLETED" 8 PARTIAL = "PARTIAL" 9 RUNNING = "RUNNING" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
13@_attrs_define 14class FinalizeDatasetUploadResponse202: 15 """ 16 Attributes: 17 job_id (str): 18 """ 19 20 job_id: str 21 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 22 23 def to_dict(self) -> dict[str, Any]: 24 job_id = self.job_id 25 26 field_dict: dict[str, Any] = {} 27 field_dict.update(self.additional_properties) 28 field_dict.update( 29 { 30 "jobId": job_id, 31 } 32 ) 33 34 return field_dict 35 36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 d = dict(src_dict) 39 job_id = d.pop("jobId") 40 41 finalize_dataset_upload_response_202 = cls( 42 job_id=job_id, 43 ) 44 45 finalize_dataset_upload_response_202.additional_properties = d 46 return finalize_dataset_upload_response_202 47 48 @property 49 def additional_keys(self) -> list[str]: 50 return list(self.additional_properties.keys()) 51 52 def __getitem__(self, key: str) -> Any: 53 return self.additional_properties[key] 54 55 def __setitem__(self, key: str, value: Any) -> None: 56 self.additional_properties[key] = value 57 58 def __delitem__(self, key: str) -> None: 59 del self.additional_properties[key] 60 61 def __contains__(self, key: str) -> bool: 62 return key in self.additional_properties
Attributes: job_id (str):
24def __init__(self, job_id): 25 self.job_id = job_id 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class FinalizeDatasetUploadResponse202.
36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 d = dict(src_dict) 39 job_id = d.pop("jobId") 40 41 finalize_dataset_upload_response_202 = cls( 42 job_id=job_id, 43 ) 44 45 finalize_dataset_upload_response_202.additional_properties = d 46 return finalize_dataset_upload_response_202
12@_attrs_define 13class GetBacktestResultResponse202: 14 """ """ 15 16 def to_dict(self) -> dict[str, Any]: 17 18 field_dict: dict[str, Any] = {} 19 20 return field_dict 21 22 @classmethod 23 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 24 get_backtest_result_response_202 = cls() 25 26 return get_backtest_result_response_202
13@_attrs_define 14class GetStrategyCodeResponse200: 15 """ 16 Attributes: 17 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 18 always yields the same id, for every caller. How much formatting the id ignores depends on 19 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 20 not. 21 Example: 6bsh31ikwkuivhtgcoa6s4. 22 code (str): Raw strategy source code (Java or QTScript), exactly as registered. 23 """ 24 25 strategy_id: str 26 code: str 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 strategy_id = self.strategy_id 31 32 code = self.code 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "strategyId": strategy_id, 39 "code": code, 40 } 41 ) 42 43 return field_dict 44 45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 strategy_id = d.pop("strategyId") 49 50 code = d.pop("code") 51 52 get_strategy_code_response_200 = cls( 53 strategy_id=strategy_id, 54 code=code, 55 ) 56 57 get_strategy_code_response_200.additional_properties = d 58 return get_strategy_code_response_200 59 60 @property 61 def additional_keys(self) -> list[str]: 62 return list(self.additional_properties.keys()) 63 64 def __getitem__(self, key: str) -> Any: 65 return self.additional_properties[key] 66 67 def __setitem__(self, key: str, value: Any) -> None: 68 self.additional_properties[key] = value 69 70 def __delitem__(self, key: str) -> None: 71 del self.additional_properties[key] 72 73 def __contains__(self, key: str) -> bool: 74 return key in self.additional_properties
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see POST /strategy for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
code (str): Raw strategy source code (Java or QTScript), exactly as registered.
25def __init__(self, strategy_id, code): 26 self.strategy_id = strategy_id 27 self.code = code 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class GetStrategyCodeResponse200.
45 @classmethod 46 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 47 d = dict(src_dict) 48 strategy_id = d.pop("strategyId") 49 50 code = d.pop("code") 51 52 get_strategy_code_response_200 = cls( 53 strategy_id=strategy_id, 54 code=code, 55 ) 56 57 get_strategy_code_response_200.additional_properties = d 58 return get_strategy_code_response_200
5class GetSweepResultObjective(str, Enum): 6 MAXDD = "maxdd" 7 PNL = "pnl" 8 SHARPE = "sharpe" 9 SORTINO = "sortino" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class GetSweepResultOrder(str, Enum): 6 NATURAL = "natural" 7 RANKED = "ranked" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class GetSweepResultRanking(str, Enum): 6 PLATEAU = "plateau" 7 RAW = "raw" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class GetSweepSensitivityObjective(str, Enum): 6 MAXDD = "maxdd" 7 PNL = "pnl" 8 SHARPE = "sharpe" 9 SORTINO = "sortino" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class HalLink: 17 """A HAL link object (Hypertext Application Language) 18 19 Attributes: 20 href (str): The link target as an absolute-path URI reference (resolve against the API base). A URI Template 21 (RFC 6570) when `templated` is true. Example: /v1/exchange/binance/spot/instruments. 22 templated (bool | Unset): True when `href` is an RFC 6570 URI Template. 23 """ 24 25 href: str 26 templated: bool | Unset = UNSET 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 href = self.href 31 32 templated = self.templated 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "href": href, 39 } 40 ) 41 if templated is not UNSET: 42 field_dict["templated"] = templated 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 d = dict(src_dict) 49 href = d.pop("href") 50 51 templated = d.pop("templated", UNSET) 52 53 hal_link = cls( 54 href=href, 55 templated=templated, 56 ) 57 58 hal_link.additional_properties = d 59 return hal_link 60 61 @property 62 def additional_keys(self) -> list[str]: 63 return list(self.additional_properties.keys()) 64 65 def __getitem__(self, key: str) -> Any: 66 return self.additional_properties[key] 67 68 def __setitem__(self, key: str, value: Any) -> None: 69 self.additional_properties[key] = value 70 71 def __delitem__(self, key: str) -> None: 72 del self.additional_properties[key] 73 74 def __contains__(self, key: str) -> bool: 75 return key in self.additional_properties
A HAL link object (Hypertext Application Language)
Attributes:
href (str): The link target as an absolute-path URI reference (resolve against the API base). A URI Template
(RFC 6570) when templated is true. Example: /v1/exchange/binance/spot/instruments.
templated (bool | Unset): True when href is an RFC 6570 URI Template.
25def __init__(self, href, templated=attr_dict['templated'].default): 26 self.href = href 27 self.templated = templated 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class HalLink.
29 def to_dict(self) -> dict[str, Any]: 30 href = self.href 31 32 templated = self.templated 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "href": href, 39 } 40 ) 41 if templated is not UNSET: 42 field_dict["templated"] = templated 43 44 return field_dict
19@_attrs_define 20class InstrumentCoverage: 21 """Time coverage of available data for this instrument, per data type 22 23 Attributes: 24 tickers (CoverageWindow | Unset): The time range of available data for a single data type 25 klines (CoverageWindow | Unset): The time range of available data for a single data type 26 """ 27 28 tickers: CoverageWindow | Unset = UNSET 29 klines: CoverageWindow | Unset = UNSET 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 tickers: dict[str, Any] | Unset = UNSET 34 if not isinstance(self.tickers, Unset): 35 tickers = self.tickers.to_dict() 36 37 klines: dict[str, Any] | Unset = UNSET 38 if not isinstance(self.klines, Unset): 39 klines = self.klines.to_dict() 40 41 field_dict: dict[str, Any] = {} 42 field_dict.update(self.additional_properties) 43 field_dict.update({}) 44 if tickers is not UNSET: 45 field_dict["tickers"] = tickers 46 if klines is not UNSET: 47 field_dict["klines"] = klines 48 49 return field_dict 50 51 @classmethod 52 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 53 from ..models.coverage_window import CoverageWindow 54 55 d = dict(src_dict) 56 _tickers = d.pop("tickers", UNSET) 57 tickers: CoverageWindow | Unset 58 if isinstance(_tickers, Unset): 59 tickers = UNSET 60 else: 61 tickers = CoverageWindow.from_dict(_tickers) 62 63 _klines = d.pop("klines", UNSET) 64 klines: CoverageWindow | Unset 65 if isinstance(_klines, Unset): 66 klines = UNSET 67 else: 68 klines = CoverageWindow.from_dict(_klines) 69 70 instrument_coverage = cls( 71 tickers=tickers, 72 klines=klines, 73 ) 74 75 instrument_coverage.additional_properties = d 76 return instrument_coverage 77 78 @property 79 def additional_keys(self) -> list[str]: 80 return list(self.additional_properties.keys()) 81 82 def __getitem__(self, key: str) -> Any: 83 return self.additional_properties[key] 84 85 def __setitem__(self, key: str, value: Any) -> None: 86 self.additional_properties[key] = value 87 88 def __delitem__(self, key: str) -> None: 89 del self.additional_properties[key] 90 91 def __contains__(self, key: str) -> bool: 92 return key in self.additional_properties
Time coverage of available data for this instrument, per data type
Attributes: tickers (CoverageWindow | Unset): The time range of available data for a single data type klines (CoverageWindow | Unset): The time range of available data for a single data type
25def __init__(self, tickers=attr_dict['tickers'].default, klines=attr_dict['klines'].default): 26 self.tickers = tickers 27 self.klines = klines 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class InstrumentCoverage.
32 def to_dict(self) -> dict[str, Any]: 33 tickers: dict[str, Any] | Unset = UNSET 34 if not isinstance(self.tickers, Unset): 35 tickers = self.tickers.to_dict() 36 37 klines: dict[str, Any] | Unset = UNSET 38 if not isinstance(self.klines, Unset): 39 klines = self.klines.to_dict() 40 41 field_dict: dict[str, Any] = {} 42 field_dict.update(self.additional_properties) 43 field_dict.update({}) 44 if tickers is not UNSET: 45 field_dict["tickers"] = tickers 46 if klines is not UNSET: 47 field_dict["klines"] = klines 48 49 return field_dict
51 @classmethod 52 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 53 from ..models.coverage_window import CoverageWindow 54 55 d = dict(src_dict) 56 _tickers = d.pop("tickers", UNSET) 57 tickers: CoverageWindow | Unset 58 if isinstance(_tickers, Unset): 59 tickers = UNSET 60 else: 61 tickers = CoverageWindow.from_dict(_tickers) 62 63 _klines = d.pop("klines", UNSET) 64 klines: CoverageWindow | Unset 65 if isinstance(_klines, Unset): 66 klines = UNSET 67 else: 68 klines = CoverageWindow.from_dict(_klines) 69 70 instrument_coverage = cls( 71 tickers=tickers, 72 klines=klines, 73 ) 74 75 instrument_coverage.additional_properties = d 76 return instrument_coverage
19@_attrs_define 20class InstrumentDetail: 21 """Exchange instrument with per-data-type coverage and market info 22 23 Attributes: 24 id (str): Instrument identifier (e.g. currency pair) Example: BTC/USDT. 25 base (str): Base currency Example: BTC. 26 quote (str): Quote currency Example: USDT. 27 coverage (InstrumentCoverage | Unset): Time coverage of available data for this instrument, per data type 28 last_price (float | Unset): Last traded price Example: 84250.5. 29 volume24h (float | Unset): Trading volume in the last 24 hours (in quote currency) Example: 1234567.89. 30 """ 31 32 id: str 33 base: str 34 quote: str 35 coverage: InstrumentCoverage | Unset = UNSET 36 last_price: float | Unset = UNSET 37 volume24h: float | Unset = UNSET 38 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 39 40 def to_dict(self) -> dict[str, Any]: 41 id = self.id 42 43 base = self.base 44 45 quote = self.quote 46 47 coverage: dict[str, Any] | Unset = UNSET 48 if not isinstance(self.coverage, Unset): 49 coverage = self.coverage.to_dict() 50 51 last_price = self.last_price 52 53 volume24h = self.volume24h 54 55 field_dict: dict[str, Any] = {} 56 field_dict.update(self.additional_properties) 57 field_dict.update( 58 { 59 "id": id, 60 "base": base, 61 "quote": quote, 62 } 63 ) 64 if coverage is not UNSET: 65 field_dict["coverage"] = coverage 66 if last_price is not UNSET: 67 field_dict["lastPrice"] = last_price 68 if volume24h is not UNSET: 69 field_dict["volume24h"] = volume24h 70 71 return field_dict 72 73 @classmethod 74 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 75 from ..models.instrument_coverage import InstrumentCoverage 76 77 d = dict(src_dict) 78 id = d.pop("id") 79 80 base = d.pop("base") 81 82 quote = d.pop("quote") 83 84 _coverage = d.pop("coverage", UNSET) 85 coverage: InstrumentCoverage | Unset 86 if isinstance(_coverage, Unset): 87 coverage = UNSET 88 else: 89 coverage = InstrumentCoverage.from_dict(_coverage) 90 91 last_price = d.pop("lastPrice", UNSET) 92 93 volume24h = d.pop("volume24h", UNSET) 94 95 instrument_detail = cls( 96 id=id, 97 base=base, 98 quote=quote, 99 coverage=coverage, 100 last_price=last_price, 101 volume24h=volume24h, 102 ) 103 104 instrument_detail.additional_properties = d 105 return instrument_detail 106 107 @property 108 def additional_keys(self) -> list[str]: 109 return list(self.additional_properties.keys()) 110 111 def __getitem__(self, key: str) -> Any: 112 return self.additional_properties[key] 113 114 def __setitem__(self, key: str, value: Any) -> None: 115 self.additional_properties[key] = value 116 117 def __delitem__(self, key: str) -> None: 118 del self.additional_properties[key] 119 120 def __contains__(self, key: str) -> bool: 121 return key in self.additional_properties
Exchange instrument with per-data-type coverage and market info
Attributes: id (str): Instrument identifier (e.g. currency pair) Example: BTC/USDT. base (str): Base currency Example: BTC. quote (str): Quote currency Example: USDT. coverage (InstrumentCoverage | Unset): Time coverage of available data for this instrument, per data type last_price (float | Unset): Last traded price Example: 84250.5. volume24h (float | Unset): Trading volume in the last 24 hours (in quote currency) Example: 1234567.89.
29def __init__(self, id, base, quote, coverage=attr_dict['coverage'].default, last_price=attr_dict['last_price'].default, volume24h=attr_dict['volume24h'].default): 30 self.id = id 31 self.base = base 32 self.quote = quote 33 self.coverage = coverage 34 self.last_price = last_price 35 self.volume24h = volume24h 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class InstrumentDetail.
40 def to_dict(self) -> dict[str, Any]: 41 id = self.id 42 43 base = self.base 44 45 quote = self.quote 46 47 coverage: dict[str, Any] | Unset = UNSET 48 if not isinstance(self.coverage, Unset): 49 coverage = self.coverage.to_dict() 50 51 last_price = self.last_price 52 53 volume24h = self.volume24h 54 55 field_dict: dict[str, Any] = {} 56 field_dict.update(self.additional_properties) 57 field_dict.update( 58 { 59 "id": id, 60 "base": base, 61 "quote": quote, 62 } 63 ) 64 if coverage is not UNSET: 65 field_dict["coverage"] = coverage 66 if last_price is not UNSET: 67 field_dict["lastPrice"] = last_price 68 if volume24h is not UNSET: 69 field_dict["volume24h"] = volume24h 70 71 return field_dict
73 @classmethod 74 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 75 from ..models.instrument_coverage import InstrumentCoverage 76 77 d = dict(src_dict) 78 id = d.pop("id") 79 80 base = d.pop("base") 81 82 quote = d.pop("quote") 83 84 _coverage = d.pop("coverage", UNSET) 85 coverage: InstrumentCoverage | Unset 86 if isinstance(_coverage, Unset): 87 coverage = UNSET 88 else: 89 coverage = InstrumentCoverage.from_dict(_coverage) 90 91 last_price = d.pop("lastPrice", UNSET) 92 93 volume24h = d.pop("volume24h", UNSET) 94 95 instrument_detail = cls( 96 id=id, 97 base=base, 98 quote=quote, 99 coverage=coverage, 100 last_price=last_price, 101 volume24h=volume24h, 102 ) 103 104 instrument_detail.additional_properties = d 105 return instrument_detail
19@_attrs_define 20class InstrumentLinks: 21 """HAL `_links` — segment discovery for the instruments listing 22 23 Attributes: 24 self_ (HalLink): A HAL link object (Hypertext Application Language) 25 spot (HalLink | Unset): A HAL link object (Hypertext Application Language) 26 futures (HalLink | Unset): A HAL link object (Hypertext Application Language) 27 """ 28 29 self_: HalLink 30 spot: HalLink | Unset = UNSET 31 futures: HalLink | Unset = UNSET 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 self_ = self.self_.to_dict() 36 37 spot: dict[str, Any] | Unset = UNSET 38 if not isinstance(self.spot, Unset): 39 spot = self.spot.to_dict() 40 41 futures: dict[str, Any] | Unset = UNSET 42 if not isinstance(self.futures, Unset): 43 futures = self.futures.to_dict() 44 45 field_dict: dict[str, Any] = {} 46 field_dict.update(self.additional_properties) 47 field_dict.update( 48 { 49 "self": self_, 50 } 51 ) 52 if spot is not UNSET: 53 field_dict["spot"] = spot 54 if futures is not UNSET: 55 field_dict["futures"] = futures 56 57 return field_dict 58 59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 from ..models.hal_link import HalLink 62 63 d = dict(src_dict) 64 self_ = HalLink.from_dict(d.pop("self")) 65 66 _spot = d.pop("spot", UNSET) 67 spot: HalLink | Unset 68 if isinstance(_spot, Unset): 69 spot = UNSET 70 else: 71 spot = HalLink.from_dict(_spot) 72 73 _futures = d.pop("futures", UNSET) 74 futures: HalLink | Unset 75 if isinstance(_futures, Unset): 76 futures = UNSET 77 else: 78 futures = HalLink.from_dict(_futures) 79 80 instrument_links = cls( 81 self_=self_, 82 spot=spot, 83 futures=futures, 84 ) 85 86 instrument_links.additional_properties = d 87 return instrument_links 88 89 @property 90 def additional_keys(self) -> list[str]: 91 return list(self.additional_properties.keys()) 92 93 def __getitem__(self, key: str) -> Any: 94 return self.additional_properties[key] 95 96 def __setitem__(self, key: str, value: Any) -> None: 97 self.additional_properties[key] = value 98 99 def __delitem__(self, key: str) -> None: 100 del self.additional_properties[key] 101 102 def __contains__(self, key: str) -> bool: 103 return key in self.additional_properties
HAL _links — segment discovery for the instruments listing
Attributes: self_ (HalLink): A HAL link object (Hypertext Application Language) spot (HalLink | Unset): A HAL link object (Hypertext Application Language) futures (HalLink | Unset): A HAL link object (Hypertext Application Language)
26def __init__(self, self_, spot=attr_dict['spot'].default, futures=attr_dict['futures'].default): 27 self.self_ = self_ 28 self.spot = spot 29 self.futures = futures 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class InstrumentLinks.
34 def to_dict(self) -> dict[str, Any]: 35 self_ = self.self_.to_dict() 36 37 spot: dict[str, Any] | Unset = UNSET 38 if not isinstance(self.spot, Unset): 39 spot = self.spot.to_dict() 40 41 futures: dict[str, Any] | Unset = UNSET 42 if not isinstance(self.futures, Unset): 43 futures = self.futures.to_dict() 44 45 field_dict: dict[str, Any] = {} 46 field_dict.update(self.additional_properties) 47 field_dict.update( 48 { 49 "self": self_, 50 } 51 ) 52 if spot is not UNSET: 53 field_dict["spot"] = spot 54 if futures is not UNSET: 55 field_dict["futures"] = futures 56 57 return field_dict
59 @classmethod 60 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 61 from ..models.hal_link import HalLink 62 63 d = dict(src_dict) 64 self_ = HalLink.from_dict(d.pop("self")) 65 66 _spot = d.pop("spot", UNSET) 67 spot: HalLink | Unset 68 if isinstance(_spot, Unset): 69 spot = UNSET 70 else: 71 spot = HalLink.from_dict(_spot) 72 73 _futures = d.pop("futures", UNSET) 74 futures: HalLink | Unset 75 if isinstance(_futures, Unset): 76 futures = UNSET 77 else: 78 futures = HalLink.from_dict(_futures) 79 80 instrument_links = cls( 81 self_=self_, 82 spot=spot, 83 futures=futures, 84 ) 85 86 instrument_links.additional_properties = d 87 return instrument_links
17@_attrs_define 18class InstrumentListMeta: 19 """Metadata describing the instruments listing 20 21 Attributes: 22 updated_at (datetime.datetime): When this listing was last refreshed Example: 2026-07-09T19:09:07Z. 23 exchange (str): The exchange the instruments belong to Example: binance. 24 segment (InstrumentListMetaSegment): The market segment served in `data` Example: spot. 25 """ 26 27 updated_at: datetime.datetime 28 exchange: str 29 segment: InstrumentListMetaSegment 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 updated_at = self.updated_at.isoformat() 34 35 exchange = self.exchange 36 37 segment = self.segment.value 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update( 42 { 43 "updatedAt": updated_at, 44 "exchange": exchange, 45 "segment": segment, 46 } 47 ) 48 49 return field_dict 50 51 @classmethod 52 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 53 d = dict(src_dict) 54 updated_at = isoparse(d.pop("updatedAt")) 55 56 exchange = d.pop("exchange") 57 58 segment = InstrumentListMetaSegment(d.pop("segment")) 59 60 instrument_list_meta = cls( 61 updated_at=updated_at, 62 exchange=exchange, 63 segment=segment, 64 ) 65 66 instrument_list_meta.additional_properties = d 67 return instrument_list_meta 68 69 @property 70 def additional_keys(self) -> list[str]: 71 return list(self.additional_properties.keys()) 72 73 def __getitem__(self, key: str) -> Any: 74 return self.additional_properties[key] 75 76 def __setitem__(self, key: str, value: Any) -> None: 77 self.additional_properties[key] = value 78 79 def __delitem__(self, key: str) -> None: 80 del self.additional_properties[key] 81 82 def __contains__(self, key: str) -> bool: 83 return key in self.additional_properties
Metadata describing the instruments listing
Attributes:
updated_at (datetime.datetime): When this listing was last refreshed Example: 2026-07-09T19:09:07Z.
exchange (str): The exchange the instruments belong to Example: binance.
segment (InstrumentListMetaSegment): The market segment served in data Example: spot.
26def __init__(self, updated_at, exchange, segment): 27 self.updated_at = updated_at 28 self.exchange = exchange 29 self.segment = segment 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class InstrumentListMeta.
32 def to_dict(self) -> dict[str, Any]: 33 updated_at = self.updated_at.isoformat() 34 35 exchange = self.exchange 36 37 segment = self.segment.value 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update( 42 { 43 "updatedAt": updated_at, 44 "exchange": exchange, 45 "segment": segment, 46 } 47 ) 48 49 return field_dict
51 @classmethod 52 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 53 d = dict(src_dict) 54 updated_at = isoparse(d.pop("updatedAt")) 55 56 exchange = d.pop("exchange") 57 58 segment = InstrumentListMetaSegment(d.pop("segment")) 59 60 instrument_list_meta = cls( 61 updated_at=updated_at, 62 exchange=exchange, 63 segment=segment, 64 ) 65 66 instrument_list_meta.additional_properties = d 67 return instrument_list_meta
5class InstrumentListMetaSegment(str, Enum): 6 FUTURES = "futures" 7 SPOT = "spot" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
19@_attrs_define 20class InstrumentListResponse: 21 """HAL-style response envelope for the instruments listing 22 23 Attributes: 24 data (list[InstrumentDetail]): The list of instruments for the segment 25 meta (InstrumentListMeta): Metadata describing the instruments listing 26 field_links (InstrumentLinks): HAL `_links` — segment discovery for the instruments listing 27 """ 28 29 data: list[InstrumentDetail] 30 meta: InstrumentListMeta 31 field_links: InstrumentLinks 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 data = [] 36 for data_item_data in self.data: 37 data_item = data_item_data.to_dict() 38 data.append(data_item) 39 40 meta = self.meta.to_dict() 41 42 field_links = self.field_links.to_dict() 43 44 field_dict: dict[str, Any] = {} 45 field_dict.update(self.additional_properties) 46 field_dict.update( 47 { 48 "data": data, 49 "meta": meta, 50 "_links": field_links, 51 } 52 ) 53 54 return field_dict 55 56 @classmethod 57 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 58 from ..models.instrument_detail import InstrumentDetail 59 from ..models.instrument_links import InstrumentLinks 60 from ..models.instrument_list_meta import InstrumentListMeta 61 62 d = dict(src_dict) 63 data = [] 64 _data = d.pop("data") 65 for data_item_data in _data: 66 data_item = InstrumentDetail.from_dict(data_item_data) 67 68 data.append(data_item) 69 70 meta = InstrumentListMeta.from_dict(d.pop("meta")) 71 72 field_links = InstrumentLinks.from_dict(d.pop("_links")) 73 74 instrument_list_response = cls( 75 data=data, 76 meta=meta, 77 field_links=field_links, 78 ) 79 80 instrument_list_response.additional_properties = d 81 return instrument_list_response 82 83 @property 84 def additional_keys(self) -> list[str]: 85 return list(self.additional_properties.keys()) 86 87 def __getitem__(self, key: str) -> Any: 88 return self.additional_properties[key] 89 90 def __setitem__(self, key: str, value: Any) -> None: 91 self.additional_properties[key] = value 92 93 def __delitem__(self, key: str) -> None: 94 del self.additional_properties[key] 95 96 def __contains__(self, key: str) -> bool: 97 return key in self.additional_properties
HAL-style response envelope for the instruments listing
Attributes:
data (list[InstrumentDetail]): The list of instruments for the segment
meta (InstrumentListMeta): Metadata describing the instruments listing
field_links (InstrumentLinks): HAL _links — segment discovery for the instruments listing
26def __init__(self, data, meta, field_links): 27 self.data = data 28 self.meta = meta 29 self.field_links = field_links 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class InstrumentListResponse.
34 def to_dict(self) -> dict[str, Any]: 35 data = [] 36 for data_item_data in self.data: 37 data_item = data_item_data.to_dict() 38 data.append(data_item) 39 40 meta = self.meta.to_dict() 41 42 field_links = self.field_links.to_dict() 43 44 field_dict: dict[str, Any] = {} 45 field_dict.update(self.additional_properties) 46 field_dict.update( 47 { 48 "data": data, 49 "meta": meta, 50 "_links": field_links, 51 } 52 ) 53 54 return field_dict
56 @classmethod 57 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 58 from ..models.instrument_detail import InstrumentDetail 59 from ..models.instrument_links import InstrumentLinks 60 from ..models.instrument_list_meta import InstrumentListMeta 61 62 d = dict(src_dict) 63 data = [] 64 _data = d.pop("data") 65 for data_item_data in _data: 66 data_item = InstrumentDetail.from_dict(data_item_data) 67 68 data.append(data_item) 69 70 meta = InstrumentListMeta.from_dict(d.pop("meta")) 71 72 field_links = InstrumentLinks.from_dict(d.pop("_links")) 73 74 instrument_list_response = cls( 75 data=data, 76 meta=meta, 77 field_links=field_links, 78 ) 79 80 instrument_list_response.additional_properties = d 81 return instrument_list_response
18@_attrs_define 19class JobState: 20 """Information about a single job 21 22 Attributes: 23 context_id (str): Identifier for the job's execution context. Its current shape is a colon-delimited string 24 encoding the data source type, an internal user id, the exchange, the job id, and the instrument — but that 25 structure is not a committed contract and may change without notice. Treat it as an opaque token: store and pass 26 it back, don't parse it. Example: 27 jctx:ticker:00000000-0000-0000-0000-000000000000:binance:5ikyamio8b3v9wcnfxztzg:btc/usdt:0vicnz3thzhrqvfczks1pu. 28 status (JobStateStatus): Current status of the job. Treat `Completed | Aborted | Failed` as 29 terminal; `New | Started` mean keep polling. A single-instrument prepare 30 is always terminal (`Completed`) — decide from 31 `PrepareJobState.coverageRatio` (or `dataFrom`/`dataTo` against an `rt` dataset, 32 which has no ratio), not by polling. 33 Example: Completed. 34 size (int): Total size of the data being prepared Example: 100. 35 completed (int): The amount of data processed so far Example: 50. 36 status_detail (None | str | Unset): Detailed status information, if available Example: Job completed with error 37 code 5001. 38 start_time (datetime.datetime | None | Unset): Timestamp for when the preparation started Example: 39 2025-01-04T14:00:00Z. 40 end_time (datetime.datetime | None | Unset): Timestamp for when the preparation finished Example: 41 2025-01-04T14:00:20Z. 42 """ 43 44 context_id: str 45 status: JobStateStatus 46 size: int 47 completed: int 48 status_detail: None | str | Unset = UNSET 49 start_time: datetime.datetime | None | Unset = UNSET 50 end_time: datetime.datetime | None | Unset = UNSET 51 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 52 53 def to_dict(self) -> dict[str, Any]: 54 context_id = self.context_id 55 56 status = self.status.value 57 58 size = self.size 59 60 completed = self.completed 61 62 status_detail: None | str | Unset 63 if isinstance(self.status_detail, Unset): 64 status_detail = UNSET 65 else: 66 status_detail = self.status_detail 67 68 start_time: None | str | Unset 69 if isinstance(self.start_time, Unset): 70 start_time = UNSET 71 elif isinstance(self.start_time, datetime.datetime): 72 start_time = self.start_time.isoformat() 73 else: 74 start_time = self.start_time 75 76 end_time: None | str | Unset 77 if isinstance(self.end_time, Unset): 78 end_time = UNSET 79 elif isinstance(self.end_time, datetime.datetime): 80 end_time = self.end_time.isoformat() 81 else: 82 end_time = self.end_time 83 84 field_dict: dict[str, Any] = {} 85 field_dict.update(self.additional_properties) 86 field_dict.update( 87 { 88 "contextId": context_id, 89 "status": status, 90 "size": size, 91 "completed": completed, 92 } 93 ) 94 if status_detail is not UNSET: 95 field_dict["statusDetail"] = status_detail 96 if start_time is not UNSET: 97 field_dict["startTime"] = start_time 98 if end_time is not UNSET: 99 field_dict["endTime"] = end_time 100 101 return field_dict 102 103 @classmethod 104 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 105 d = dict(src_dict) 106 context_id = d.pop("contextId") 107 108 status = JobStateStatus(d.pop("status")) 109 110 size = d.pop("size") 111 112 completed = d.pop("completed") 113 114 def _parse_status_detail(data: object) -> None | str | Unset: 115 if data is None: 116 return data 117 if isinstance(data, Unset): 118 return data 119 return cast(None | str | Unset, data) 120 121 status_detail = _parse_status_detail(d.pop("statusDetail", UNSET)) 122 123 def _parse_start_time(data: object) -> datetime.datetime | None | Unset: 124 if data is None: 125 return data 126 if isinstance(data, Unset): 127 return data 128 try: 129 if not isinstance(data, str): 130 raise TypeError() 131 start_time_type_0 = isoparse(data) 132 133 return start_time_type_0 134 except (TypeError, ValueError, AttributeError, KeyError): 135 pass 136 return cast(datetime.datetime | None | Unset, data) 137 138 start_time = _parse_start_time(d.pop("startTime", UNSET)) 139 140 def _parse_end_time(data: object) -> datetime.datetime | None | Unset: 141 if data is None: 142 return data 143 if isinstance(data, Unset): 144 return data 145 try: 146 if not isinstance(data, str): 147 raise TypeError() 148 end_time_type_0 = isoparse(data) 149 150 return end_time_type_0 151 except (TypeError, ValueError, AttributeError, KeyError): 152 pass 153 return cast(datetime.datetime | None | Unset, data) 154 155 end_time = _parse_end_time(d.pop("endTime", UNSET)) 156 157 job_state = cls( 158 context_id=context_id, 159 status=status, 160 size=size, 161 completed=completed, 162 status_detail=status_detail, 163 start_time=start_time, 164 end_time=end_time, 165 ) 166 167 job_state.additional_properties = d 168 return job_state 169 170 @property 171 def additional_keys(self) -> list[str]: 172 return list(self.additional_properties.keys()) 173 174 def __getitem__(self, key: str) -> Any: 175 return self.additional_properties[key] 176 177 def __setitem__(self, key: str, value: Any) -> None: 178 self.additional_properties[key] = value 179 180 def __delitem__(self, key: str) -> None: 181 del self.additional_properties[key] 182 183 def __contains__(self, key: str) -> bool: 184 return key in self.additional_properties
Information about a single job
Attributes:
context_id (str): Identifier for the job's execution context. Its current shape is a colon-delimited string
encoding the data source type, an internal user id, the exchange, the job id, and the instrument — but that
structure is not a committed contract and may change without notice. Treat it as an opaque token: store and pass
it back, don't parse it. Example:
jctx:ticker:00000000-0000-0000-0000-000000000000:binance:5ikyamio8b3v9wcnfxztzg:btc/usdt:0vicnz3thzhrqvfczks1pu.
status (JobStateStatus): Current status of the job. Treat Completed | Aborted | Failed as
terminal; New | Started mean keep polling. A single-instrument prepare
is always terminal (Completed) — decide from
PrepareJobState.coverageRatio (or dataFrom/dataTo against an rt dataset,
which has no ratio), not by polling.
Example: Completed.
size (int): Total size of the data being prepared Example: 100.
completed (int): The amount of data processed so far Example: 50.
status_detail (None | str | Unset): Detailed status information, if available Example: Job completed with error
code 5001.
start_time (datetime.datetime | None | Unset): Timestamp for when the preparation started Example:
2025-01-04T14:00:00Z.
end_time (datetime.datetime | None | Unset): Timestamp for when the preparation finished Example:
2025-01-04T14:00:20Z.
30def __init__(self, context_id, status, size, completed, status_detail=attr_dict['status_detail'].default, start_time=attr_dict['start_time'].default, end_time=attr_dict['end_time'].default): 31 self.context_id = context_id 32 self.status = status 33 self.size = size 34 self.completed = completed 35 self.status_detail = status_detail 36 self.start_time = start_time 37 self.end_time = end_time 38 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class JobState.
53 def to_dict(self) -> dict[str, Any]: 54 context_id = self.context_id 55 56 status = self.status.value 57 58 size = self.size 59 60 completed = self.completed 61 62 status_detail: None | str | Unset 63 if isinstance(self.status_detail, Unset): 64 status_detail = UNSET 65 else: 66 status_detail = self.status_detail 67 68 start_time: None | str | Unset 69 if isinstance(self.start_time, Unset): 70 start_time = UNSET 71 elif isinstance(self.start_time, datetime.datetime): 72 start_time = self.start_time.isoformat() 73 else: 74 start_time = self.start_time 75 76 end_time: None | str | Unset 77 if isinstance(self.end_time, Unset): 78 end_time = UNSET 79 elif isinstance(self.end_time, datetime.datetime): 80 end_time = self.end_time.isoformat() 81 else: 82 end_time = self.end_time 83 84 field_dict: dict[str, Any] = {} 85 field_dict.update(self.additional_properties) 86 field_dict.update( 87 { 88 "contextId": context_id, 89 "status": status, 90 "size": size, 91 "completed": completed, 92 } 93 ) 94 if status_detail is not UNSET: 95 field_dict["statusDetail"] = status_detail 96 if start_time is not UNSET: 97 field_dict["startTime"] = start_time 98 if end_time is not UNSET: 99 field_dict["endTime"] = end_time 100 101 return field_dict
103 @classmethod 104 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 105 d = dict(src_dict) 106 context_id = d.pop("contextId") 107 108 status = JobStateStatus(d.pop("status")) 109 110 size = d.pop("size") 111 112 completed = d.pop("completed") 113 114 def _parse_status_detail(data: object) -> None | str | Unset: 115 if data is None: 116 return data 117 if isinstance(data, Unset): 118 return data 119 return cast(None | str | Unset, data) 120 121 status_detail = _parse_status_detail(d.pop("statusDetail", UNSET)) 122 123 def _parse_start_time(data: object) -> datetime.datetime | None | Unset: 124 if data is None: 125 return data 126 if isinstance(data, Unset): 127 return data 128 try: 129 if not isinstance(data, str): 130 raise TypeError() 131 start_time_type_0 = isoparse(data) 132 133 return start_time_type_0 134 except (TypeError, ValueError, AttributeError, KeyError): 135 pass 136 return cast(datetime.datetime | None | Unset, data) 137 138 start_time = _parse_start_time(d.pop("startTime", UNSET)) 139 140 def _parse_end_time(data: object) -> datetime.datetime | None | Unset: 141 if data is None: 142 return data 143 if isinstance(data, Unset): 144 return data 145 try: 146 if not isinstance(data, str): 147 raise TypeError() 148 end_time_type_0 = isoparse(data) 149 150 return end_time_type_0 151 except (TypeError, ValueError, AttributeError, KeyError): 152 pass 153 return cast(datetime.datetime | None | Unset, data) 154 155 end_time = _parse_end_time(d.pop("endTime", UNSET)) 156 157 job_state = cls( 158 context_id=context_id, 159 status=status, 160 size=size, 161 completed=completed, 162 status_detail=status_detail, 163 start_time=start_time, 164 end_time=end_time, 165 ) 166 167 job_state.additional_properties = d 168 return job_state
5class JobStateStatus(str, Enum): 6 ABORTED = "Aborted" 7 COMPLETED = "Completed" 8 FAILED = "Failed" 9 NEW = "New" 10 STARTED = "Started" 11 12 def __str__(self) -> str: 13 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class ListDatasetsResponse200: 19 """ 20 Attributes: 21 datasets (list[Dataset]): 22 """ 23 24 datasets: list[Dataset] 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 datasets = [] 29 for datasets_item_data in self.datasets: 30 datasets_item = datasets_item_data.to_dict() 31 datasets.append(datasets_item) 32 33 field_dict: dict[str, Any] = {} 34 field_dict.update(self.additional_properties) 35 field_dict.update( 36 { 37 "datasets": datasets, 38 } 39 ) 40 41 return field_dict 42 43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 from ..models.dataset import Dataset 46 47 d = dict(src_dict) 48 datasets = [] 49 _datasets = d.pop("datasets") 50 for datasets_item_data in _datasets: 51 datasets_item = Dataset.from_dict(datasets_item_data) 52 53 datasets.append(datasets_item) 54 55 list_datasets_response_200 = cls( 56 datasets=datasets, 57 ) 58 59 list_datasets_response_200.additional_properties = d 60 return list_datasets_response_200 61 62 @property 63 def additional_keys(self) -> list[str]: 64 return list(self.additional_properties.keys()) 65 66 def __getitem__(self, key: str) -> Any: 67 return self.additional_properties[key] 68 69 def __setitem__(self, key: str, value: Any) -> None: 70 self.additional_properties[key] = value 71 72 def __delitem__(self, key: str) -> None: 73 del self.additional_properties[key] 74 75 def __contains__(self, key: str) -> bool: 76 return key in self.additional_properties
Attributes: datasets (list[Dataset]):
24def __init__(self, datasets): 25 self.datasets = datasets 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ListDatasetsResponse200.
27 def to_dict(self) -> dict[str, Any]: 28 datasets = [] 29 for datasets_item_data in self.datasets: 30 datasets_item = datasets_item_data.to_dict() 31 datasets.append(datasets_item) 32 33 field_dict: dict[str, Any] = {} 34 field_dict.update(self.additional_properties) 35 field_dict.update( 36 { 37 "datasets": datasets, 38 } 39 ) 40 41 return field_dict
43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 from ..models.dataset import Dataset 46 47 d = dict(src_dict) 48 datasets = [] 49 _datasets = d.pop("datasets") 50 for datasets_item_data in _datasets: 51 datasets_item = Dataset.from_dict(datasets_item_data) 52 53 datasets.append(datasets_item) 54 55 list_datasets_response_200 = cls( 56 datasets=datasets, 57 ) 58 59 list_datasets_response_200.additional_properties = d 60 return list_datasets_response_200
5class ListSegmentInstrumentsSegment(str, Enum): 6 FUTURES = "futures" 7 SPOT = "spot" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class ListStrategiesResponse200: 19 """ 20 Attributes: 21 strategies (list[StrategySummary]): 22 """ 23 24 strategies: list[StrategySummary] 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 strategies = [] 29 for strategies_item_data in self.strategies: 30 strategies_item = strategies_item_data.to_dict() 31 strategies.append(strategies_item) 32 33 field_dict: dict[str, Any] = {} 34 field_dict.update(self.additional_properties) 35 field_dict.update( 36 { 37 "strategies": strategies, 38 } 39 ) 40 41 return field_dict 42 43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 from ..models.strategy_summary import StrategySummary 46 47 d = dict(src_dict) 48 strategies = [] 49 _strategies = d.pop("strategies") 50 for strategies_item_data in _strategies: 51 strategies_item = StrategySummary.from_dict(strategies_item_data) 52 53 strategies.append(strategies_item) 54 55 list_strategies_response_200 = cls( 56 strategies=strategies, 57 ) 58 59 list_strategies_response_200.additional_properties = d 60 return list_strategies_response_200 61 62 @property 63 def additional_keys(self) -> list[str]: 64 return list(self.additional_properties.keys()) 65 66 def __getitem__(self, key: str) -> Any: 67 return self.additional_properties[key] 68 69 def __setitem__(self, key: str, value: Any) -> None: 70 self.additional_properties[key] = value 71 72 def __delitem__(self, key: str) -> None: 73 del self.additional_properties[key] 74 75 def __contains__(self, key: str) -> bool: 76 return key in self.additional_properties
Attributes: strategies (list[StrategySummary]):
24def __init__(self, strategies): 25 self.strategies = strategies 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ListStrategiesResponse200.
27 def to_dict(self) -> dict[str, Any]: 28 strategies = [] 29 for strategies_item_data in self.strategies: 30 strategies_item = strategies_item_data.to_dict() 31 strategies.append(strategies_item) 32 33 field_dict: dict[str, Any] = {} 34 field_dict.update(self.additional_properties) 35 field_dict.update( 36 { 37 "strategies": strategies, 38 } 39 ) 40 41 return field_dict
43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 from ..models.strategy_summary import StrategySummary 46 47 d = dict(src_dict) 48 strategies = [] 49 _strategies = d.pop("strategies") 50 for strategies_item_data in _strategies: 51 strategies_item = StrategySummary.from_dict(strategies_item_data) 52 53 strategies.append(strategies_item) 54 55 list_strategies_response_200 = cls( 56 strategies=strategies, 57 ) 58 59 list_strategies_response_200.additional_properties = d 60 return list_strategies_response_200
13@_attrs_define 14class LiveCommandResult: 15 """ 16 Attributes: 17 run_id (str): 18 command_id (str): This command's own id, generated fresh for this call. A retried request is a second, distinct 19 command — this endpoint takes no idempotency key. 20 effective_at_ms (int): Epoch milliseconds — the market position every execution applies this command at. 21 """ 22 23 run_id: str 24 command_id: str 25 effective_at_ms: int 26 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 27 28 def to_dict(self) -> dict[str, Any]: 29 run_id = self.run_id 30 31 command_id = self.command_id 32 33 effective_at_ms = self.effective_at_ms 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update( 38 { 39 "runId": run_id, 40 "commandId": command_id, 41 "effectiveAtMs": effective_at_ms, 42 } 43 ) 44 45 return field_dict 46 47 @classmethod 48 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 49 d = dict(src_dict) 50 run_id = d.pop("runId") 51 52 command_id = d.pop("commandId") 53 54 effective_at_ms = d.pop("effectiveAtMs") 55 56 live_command_result = cls( 57 run_id=run_id, 58 command_id=command_id, 59 effective_at_ms=effective_at_ms, 60 ) 61 62 live_command_result.additional_properties = d 63 return live_command_result 64 65 @property 66 def additional_keys(self) -> list[str]: 67 return list(self.additional_properties.keys()) 68 69 def __getitem__(self, key: str) -> Any: 70 return self.additional_properties[key] 71 72 def __setitem__(self, key: str, value: Any) -> None: 73 self.additional_properties[key] = value 74 75 def __delitem__(self, key: str) -> None: 76 del self.additional_properties[key] 77 78 def __contains__(self, key: str) -> bool: 79 return key in self.additional_properties
Attributes: run_id (str): command_id (str): This command's own id, generated fresh for this call. A retried request is a second, distinct command — this endpoint takes no idempotency key. effective_at_ms (int): Epoch milliseconds — the market position every execution applies this command at.
26def __init__(self, run_id, command_id, effective_at_ms): 27 self.run_id = run_id 28 self.command_id = command_id 29 self.effective_at_ms = effective_at_ms 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveCommandResult.
28 def to_dict(self) -> dict[str, Any]: 29 run_id = self.run_id 30 31 command_id = self.command_id 32 33 effective_at_ms = self.effective_at_ms 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update( 38 { 39 "runId": run_id, 40 "commandId": command_id, 41 "effectiveAtMs": effective_at_ms, 42 } 43 ) 44 45 return field_dict
47 @classmethod 48 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 49 d = dict(src_dict) 50 run_id = d.pop("runId") 51 52 command_id = d.pop("commandId") 53 54 effective_at_ms = d.pop("effectiveAtMs") 55 56 live_command_result = cls( 57 run_id=run_id, 58 command_id=command_id, 59 effective_at_ms=effective_at_ms, 60 ) 61 62 live_command_result.additional_properties = d 63 return live_command_result
13@_attrs_define 14class LiveConnectionToken: 15 """ 16 Attributes: 17 token (str): Pass as the `token` field of the WebSocket `connect` command — see the "Live execution" guide. 18 expires_at_ms (int): 19 """ 20 21 token: str 22 expires_at_ms: int 23 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 24 25 def to_dict(self) -> dict[str, Any]: 26 token = self.token 27 28 expires_at_ms = self.expires_at_ms 29 30 field_dict: dict[str, Any] = {} 31 field_dict.update(self.additional_properties) 32 field_dict.update( 33 { 34 "token": token, 35 "expiresAtMs": expires_at_ms, 36 } 37 ) 38 39 return field_dict 40 41 @classmethod 42 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 43 d = dict(src_dict) 44 token = d.pop("token") 45 46 expires_at_ms = d.pop("expiresAtMs") 47 48 live_connection_token = cls( 49 token=token, 50 expires_at_ms=expires_at_ms, 51 ) 52 53 live_connection_token.additional_properties = d 54 return live_connection_token 55 56 @property 57 def additional_keys(self) -> list[str]: 58 return list(self.additional_properties.keys()) 59 60 def __getitem__(self, key: str) -> Any: 61 return self.additional_properties[key] 62 63 def __setitem__(self, key: str, value: Any) -> None: 64 self.additional_properties[key] = value 65 66 def __delitem__(self, key: str) -> None: 67 del self.additional_properties[key] 68 69 def __contains__(self, key: str) -> bool: 70 return key in self.additional_properties
Attributes:
token (str): Pass as the token field of the WebSocket connect command — see the "Live execution" guide.
expires_at_ms (int):
25def __init__(self, token, expires_at_ms): 26 self.token = token 27 self.expires_at_ms = expires_at_ms 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveConnectionToken.
25 def to_dict(self) -> dict[str, Any]: 26 token = self.token 27 28 expires_at_ms = self.expires_at_ms 29 30 field_dict: dict[str, Any] = {} 31 field_dict.update(self.additional_properties) 32 field_dict.update( 33 { 34 "token": token, 35 "expiresAtMs": expires_at_ms, 36 } 37 ) 38 39 return field_dict
41 @classmethod 42 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 43 d = dict(src_dict) 44 token = d.pop("token") 45 46 expires_at_ms = d.pop("expiresAtMs") 47 48 live_connection_token = cls( 49 token=token, 50 expires_at_ms=expires_at_ms, 51 ) 52 53 live_connection_token.additional_properties = d 54 return live_connection_token
20@_attrs_define 21class LiveListResponse: 22 """ 23 Attributes: 24 runs (list[LiveRunSummary]): 25 field_links (PublicLiveListLinks | Unset): Present only when another page exists. 26 """ 27 28 runs: list[LiveRunSummary] 29 field_links: PublicLiveListLinks | Unset = UNSET 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 runs = [] 34 for runs_item_data in self.runs: 35 runs_item = runs_item_data.to_dict() 36 runs.append(runs_item) 37 38 field_links: dict[str, Any] | Unset = UNSET 39 if not isinstance(self.field_links, Unset): 40 field_links = self.field_links.to_dict() 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update( 45 { 46 "runs": runs, 47 } 48 ) 49 if field_links is not UNSET: 50 field_dict["_links"] = field_links 51 52 return field_dict 53 54 @classmethod 55 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 56 from ..models.live_run_summary import LiveRunSummary 57 from ..models.public_live_list_links import PublicLiveListLinks 58 59 d = dict(src_dict) 60 runs = [] 61 _runs = d.pop("runs") 62 for runs_item_data in _runs: 63 runs_item = LiveRunSummary.from_dict(runs_item_data) 64 65 runs.append(runs_item) 66 67 _field_links = d.pop("_links", UNSET) 68 field_links: PublicLiveListLinks | Unset 69 if isinstance(_field_links, Unset): 70 field_links = UNSET 71 else: 72 field_links = PublicLiveListLinks.from_dict(_field_links) 73 74 live_list_response = cls( 75 runs=runs, 76 field_links=field_links, 77 ) 78 79 live_list_response.additional_properties = d 80 return live_list_response 81 82 @property 83 def additional_keys(self) -> list[str]: 84 return list(self.additional_properties.keys()) 85 86 def __getitem__(self, key: str) -> Any: 87 return self.additional_properties[key] 88 89 def __setitem__(self, key: str, value: Any) -> None: 90 self.additional_properties[key] = value 91 92 def __delitem__(self, key: str) -> None: 93 del self.additional_properties[key] 94 95 def __contains__(self, key: str) -> bool: 96 return key in self.additional_properties
Attributes: runs (list[LiveRunSummary]): field_links (PublicLiveListLinks | Unset): Present only when another page exists.
25def __init__(self, runs, field_links=attr_dict['field_links'].default): 26 self.runs = runs 27 self.field_links = field_links 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveListResponse.
32 def to_dict(self) -> dict[str, Any]: 33 runs = [] 34 for runs_item_data in self.runs: 35 runs_item = runs_item_data.to_dict() 36 runs.append(runs_item) 37 38 field_links: dict[str, Any] | Unset = UNSET 39 if not isinstance(self.field_links, Unset): 40 field_links = self.field_links.to_dict() 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update( 45 { 46 "runs": runs, 47 } 48 ) 49 if field_links is not UNSET: 50 field_dict["_links"] = field_links 51 52 return field_dict
54 @classmethod 55 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 56 from ..models.live_run_summary import LiveRunSummary 57 from ..models.public_live_list_links import PublicLiveListLinks 58 59 d = dict(src_dict) 60 runs = [] 61 _runs = d.pop("runs") 62 for runs_item_data in _runs: 63 runs_item = LiveRunSummary.from_dict(runs_item_data) 64 65 runs.append(runs_item) 66 67 _field_links = d.pop("_links", UNSET) 68 field_links: PublicLiveListLinks | Unset 69 if isinstance(_field_links, Unset): 70 field_links = UNSET 71 else: 72 field_links = PublicLiveListLinks.from_dict(_field_links) 73 74 live_list_response = cls( 75 runs=runs, 76 field_links=field_links, 77 ) 78 79 live_list_response.additional_properties = d 80 return live_list_response
19@_attrs_define 20class LivePaper: 21 """ 22 Attributes: 23 run_id (str): 24 stage (LivePaperStage): 25 accounts (list[LivePaperAccount]): 26 """ 27 28 run_id: str 29 stage: LivePaperStage 30 accounts: list[LivePaperAccount] 31 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 32 33 def to_dict(self) -> dict[str, Any]: 34 run_id = self.run_id 35 36 stage = self.stage.value 37 38 accounts = [] 39 for accounts_item_data in self.accounts: 40 accounts_item = accounts_item_data.to_dict() 41 accounts.append(accounts_item) 42 43 field_dict: dict[str, Any] = {} 44 field_dict.update(self.additional_properties) 45 field_dict.update( 46 { 47 "runId": run_id, 48 "stage": stage, 49 "accounts": accounts, 50 } 51 ) 52 53 return field_dict 54 55 @classmethod 56 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 57 from ..models.live_paper_account import LivePaperAccount 58 59 d = dict(src_dict) 60 run_id = d.pop("runId") 61 62 stage = LivePaperStage(d.pop("stage")) 63 64 accounts = [] 65 _accounts = d.pop("accounts") 66 for accounts_item_data in _accounts: 67 accounts_item = LivePaperAccount.from_dict(accounts_item_data) 68 69 accounts.append(accounts_item) 70 71 live_paper = cls( 72 run_id=run_id, 73 stage=stage, 74 accounts=accounts, 75 ) 76 77 live_paper.additional_properties = d 78 return live_paper 79 80 @property 81 def additional_keys(self) -> list[str]: 82 return list(self.additional_properties.keys()) 83 84 def __getitem__(self, key: str) -> Any: 85 return self.additional_properties[key] 86 87 def __setitem__(self, key: str, value: Any) -> None: 88 self.additional_properties[key] = value 89 90 def __delitem__(self, key: str) -> None: 91 del self.additional_properties[key] 92 93 def __contains__(self, key: str) -> bool: 94 return key in self.additional_properties
Attributes: run_id (str): stage (LivePaperStage): accounts (list[LivePaperAccount]):
26def __init__(self, run_id, stage, accounts): 27 self.run_id = run_id 28 self.stage = stage 29 self.accounts = accounts 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaper.
33 def to_dict(self) -> dict[str, Any]: 34 run_id = self.run_id 35 36 stage = self.stage.value 37 38 accounts = [] 39 for accounts_item_data in self.accounts: 40 accounts_item = accounts_item_data.to_dict() 41 accounts.append(accounts_item) 42 43 field_dict: dict[str, Any] = {} 44 field_dict.update(self.additional_properties) 45 field_dict.update( 46 { 47 "runId": run_id, 48 "stage": stage, 49 "accounts": accounts, 50 } 51 ) 52 53 return field_dict
55 @classmethod 56 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 57 from ..models.live_paper_account import LivePaperAccount 58 59 d = dict(src_dict) 60 run_id = d.pop("runId") 61 62 stage = LivePaperStage(d.pop("stage")) 63 64 accounts = [] 65 _accounts = d.pop("accounts") 66 for accounts_item_data in _accounts: 67 accounts_item = LivePaperAccount.from_dict(accounts_item_data) 68 69 accounts.append(accounts_item) 70 71 live_paper = cls( 72 run_id=run_id, 73 stage=stage, 74 accounts=accounts, 75 ) 76 77 live_paper.additional_properties = d 78 return live_paper
21@_attrs_define 22class LivePaperAccount: 23 """One simulated account — one per quote currency the run trades. 24 25 Attributes: 26 currency (str): The account's quote currency; every amount below is in it. 27 initial_funding (float): 28 equity (float): Latest recorded equity — see `equityKind`. 29 realised_pnl (float): Sum of the PnL of the closed trades. 30 trades (int): Closed trades. 31 gaps (int): Times open positions were lost because the run was restarted with them open. 32 open_positions (list[LivePaperPosition]): 33 equity_at_ms (int | Unset): Market time of that value. Absent while the account holds its starting capital. 34 equity_kind (LivePaperAccountEquityKind | Unset): `equity` at a closed trade, `mark` at a periodic mark-to- 35 market (includes open positions at market price). 36 kpi (LivePaperKpi | Unset): The same KPIs a backtest reports, over the trades closed so far. Absent until the 37 first closed trade is recorded. 38 """ 39 40 currency: str 41 initial_funding: float 42 equity: float 43 realised_pnl: float 44 trades: int 45 gaps: int 46 open_positions: list[LivePaperPosition] 47 equity_at_ms: int | Unset = UNSET 48 equity_kind: LivePaperAccountEquityKind | Unset = UNSET 49 kpi: LivePaperKpi | Unset = UNSET 50 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 51 52 def to_dict(self) -> dict[str, Any]: 53 currency = self.currency 54 55 initial_funding = self.initial_funding 56 57 equity = self.equity 58 59 realised_pnl = self.realised_pnl 60 61 trades = self.trades 62 63 gaps = self.gaps 64 65 open_positions = [] 66 for open_positions_item_data in self.open_positions: 67 open_positions_item = open_positions_item_data.to_dict() 68 open_positions.append(open_positions_item) 69 70 equity_at_ms = self.equity_at_ms 71 72 equity_kind: str | Unset = UNSET 73 if not isinstance(self.equity_kind, Unset): 74 equity_kind = self.equity_kind.value 75 76 kpi: dict[str, Any] | Unset = UNSET 77 if not isinstance(self.kpi, Unset): 78 kpi = self.kpi.to_dict() 79 80 field_dict: dict[str, Any] = {} 81 field_dict.update(self.additional_properties) 82 field_dict.update( 83 { 84 "currency": currency, 85 "initialFunding": initial_funding, 86 "equity": equity, 87 "realisedPnl": realised_pnl, 88 "trades": trades, 89 "gaps": gaps, 90 "openPositions": open_positions, 91 } 92 ) 93 if equity_at_ms is not UNSET: 94 field_dict["equityAtMs"] = equity_at_ms 95 if equity_kind is not UNSET: 96 field_dict["equityKind"] = equity_kind 97 if kpi is not UNSET: 98 field_dict["kpi"] = kpi 99 100 return field_dict 101 102 @classmethod 103 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 104 from ..models.live_paper_kpi import LivePaperKpi 105 from ..models.live_paper_position import LivePaperPosition 106 107 d = dict(src_dict) 108 currency = d.pop("currency") 109 110 initial_funding = d.pop("initialFunding") 111 112 equity = d.pop("equity") 113 114 realised_pnl = d.pop("realisedPnl") 115 116 trades = d.pop("trades") 117 118 gaps = d.pop("gaps") 119 120 open_positions = [] 121 _open_positions = d.pop("openPositions") 122 for open_positions_item_data in _open_positions: 123 open_positions_item = LivePaperPosition.from_dict(open_positions_item_data) 124 125 open_positions.append(open_positions_item) 126 127 equity_at_ms = d.pop("equityAtMs", UNSET) 128 129 _equity_kind = d.pop("equityKind", UNSET) 130 equity_kind: LivePaperAccountEquityKind | Unset 131 if isinstance(_equity_kind, Unset): 132 equity_kind = UNSET 133 else: 134 equity_kind = LivePaperAccountEquityKind(_equity_kind) 135 136 _kpi = d.pop("kpi", UNSET) 137 kpi: LivePaperKpi | Unset 138 if isinstance(_kpi, Unset): 139 kpi = UNSET 140 else: 141 kpi = LivePaperKpi.from_dict(_kpi) 142 143 live_paper_account = cls( 144 currency=currency, 145 initial_funding=initial_funding, 146 equity=equity, 147 realised_pnl=realised_pnl, 148 trades=trades, 149 gaps=gaps, 150 open_positions=open_positions, 151 equity_at_ms=equity_at_ms, 152 equity_kind=equity_kind, 153 kpi=kpi, 154 ) 155 156 live_paper_account.additional_properties = d 157 return live_paper_account 158 159 @property 160 def additional_keys(self) -> list[str]: 161 return list(self.additional_properties.keys()) 162 163 def __getitem__(self, key: str) -> Any: 164 return self.additional_properties[key] 165 166 def __setitem__(self, key: str, value: Any) -> None: 167 self.additional_properties[key] = value 168 169 def __delitem__(self, key: str) -> None: 170 del self.additional_properties[key] 171 172 def __contains__(self, key: str) -> bool: 173 return key in self.additional_properties
One simulated account — one per quote currency the run trades.
Attributes:
currency (str): The account's quote currency; every amount below is in it.
initial_funding (float):
equity (float): Latest recorded equity — see equityKind.
realised_pnl (float): Sum of the PnL of the closed trades.
trades (int): Closed trades.
gaps (int): Times open positions were lost because the run was restarted with them open.
open_positions (list[LivePaperPosition]):
equity_at_ms (int | Unset): Market time of that value. Absent while the account holds its starting capital.
equity_kind (LivePaperAccountEquityKind | Unset): equity at a closed trade, mark at a periodic mark-to-
market (includes open positions at market price).
kpi (LivePaperKpi | Unset): The same KPIs a backtest reports, over the trades closed so far. Absent until the
first closed trade is recorded.
33def __init__(self, currency, initial_funding, equity, realised_pnl, trades, gaps, open_positions, equity_at_ms=attr_dict['equity_at_ms'].default, equity_kind=attr_dict['equity_kind'].default, kpi=attr_dict['kpi'].default): 34 self.currency = currency 35 self.initial_funding = initial_funding 36 self.equity = equity 37 self.realised_pnl = realised_pnl 38 self.trades = trades 39 self.gaps = gaps 40 self.open_positions = open_positions 41 self.equity_at_ms = equity_at_ms 42 self.equity_kind = equity_kind 43 self.kpi = kpi 44 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperAccount.
52 def to_dict(self) -> dict[str, Any]: 53 currency = self.currency 54 55 initial_funding = self.initial_funding 56 57 equity = self.equity 58 59 realised_pnl = self.realised_pnl 60 61 trades = self.trades 62 63 gaps = self.gaps 64 65 open_positions = [] 66 for open_positions_item_data in self.open_positions: 67 open_positions_item = open_positions_item_data.to_dict() 68 open_positions.append(open_positions_item) 69 70 equity_at_ms = self.equity_at_ms 71 72 equity_kind: str | Unset = UNSET 73 if not isinstance(self.equity_kind, Unset): 74 equity_kind = self.equity_kind.value 75 76 kpi: dict[str, Any] | Unset = UNSET 77 if not isinstance(self.kpi, Unset): 78 kpi = self.kpi.to_dict() 79 80 field_dict: dict[str, Any] = {} 81 field_dict.update(self.additional_properties) 82 field_dict.update( 83 { 84 "currency": currency, 85 "initialFunding": initial_funding, 86 "equity": equity, 87 "realisedPnl": realised_pnl, 88 "trades": trades, 89 "gaps": gaps, 90 "openPositions": open_positions, 91 } 92 ) 93 if equity_at_ms is not UNSET: 94 field_dict["equityAtMs"] = equity_at_ms 95 if equity_kind is not UNSET: 96 field_dict["equityKind"] = equity_kind 97 if kpi is not UNSET: 98 field_dict["kpi"] = kpi 99 100 return field_dict
102 @classmethod 103 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 104 from ..models.live_paper_kpi import LivePaperKpi 105 from ..models.live_paper_position import LivePaperPosition 106 107 d = dict(src_dict) 108 currency = d.pop("currency") 109 110 initial_funding = d.pop("initialFunding") 111 112 equity = d.pop("equity") 113 114 realised_pnl = d.pop("realisedPnl") 115 116 trades = d.pop("trades") 117 118 gaps = d.pop("gaps") 119 120 open_positions = [] 121 _open_positions = d.pop("openPositions") 122 for open_positions_item_data in _open_positions: 123 open_positions_item = LivePaperPosition.from_dict(open_positions_item_data) 124 125 open_positions.append(open_positions_item) 126 127 equity_at_ms = d.pop("equityAtMs", UNSET) 128 129 _equity_kind = d.pop("equityKind", UNSET) 130 equity_kind: LivePaperAccountEquityKind | Unset 131 if isinstance(_equity_kind, Unset): 132 equity_kind = UNSET 133 else: 134 equity_kind = LivePaperAccountEquityKind(_equity_kind) 135 136 _kpi = d.pop("kpi", UNSET) 137 kpi: LivePaperKpi | Unset 138 if isinstance(_kpi, Unset): 139 kpi = UNSET 140 else: 141 kpi = LivePaperKpi.from_dict(_kpi) 142 143 live_paper_account = cls( 144 currency=currency, 145 initial_funding=initial_funding, 146 equity=equity, 147 realised_pnl=realised_pnl, 148 trades=trades, 149 gaps=gaps, 150 open_positions=open_positions, 151 equity_at_ms=equity_at_ms, 152 equity_kind=equity_kind, 153 kpi=kpi, 154 ) 155 156 live_paper_account.additional_properties = d 157 return live_paper_account
5class LivePaperAccountEquityKind(str, Enum): 6 EQUITY = "equity" 7 MARK = "mark" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
16@_attrs_define 17class LivePaperConfig: 18 """Paper trading for this run: the same economics as a backtest's `baseConfig` (same fields, 19 defaults and limits), plus `output`. An empty object takes every default. Each quote 20 currency the run trades gets its own simulated account, opened with `initialFunding` in 21 that currency; accounts are never added together. As returned on a run, the block is 22 normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled 23 in. 24 25 Attributes: 26 initial_funding (float | Unset): Starting capital of each account, in that account's own quote currency. 27 Default: 100.0. 28 fee_rate (float | Unset): Fee rate for both sides (0.001 = 0.1%). Accepted on start; returned resolved into the 29 two fields below. Default: 0.001. 30 buy_fee_rate (float | Unset): Buy-side fee rate; overrides `feeRate`. 31 sell_fee_rate (float | Unset): Sell-side fee rate; overrides `feeRate`. 32 fee_leg (LivePaperConfigFeeLeg | Unset): Which asset fees are charged in. Case-insensitive on start. Default: 33 LivePaperConfigFeeLeg.RECEIVED. 34 percent_amount_to_lock (float | Unset): Share of the account's free balance each entry locks, in percent. 35 Omitted, the strategy's own setting applies, and without one 10%. 36 output (LivePaperConfigOutput | Unset): `separate` keeps paper output out of the run's signals (read it with 37 `GET /live/{runId}/paper`); `mix` also interleaves it into the run's signals as `type: paper`, right after the 38 signal that caused it. Default: LivePaperConfigOutput.SEPARATE. 39 """ 40 41 initial_funding: float | Unset = 100.0 42 fee_rate: float | Unset = 0.001 43 buy_fee_rate: float | Unset = UNSET 44 sell_fee_rate: float | Unset = UNSET 45 fee_leg: LivePaperConfigFeeLeg | Unset = LivePaperConfigFeeLeg.RECEIVED 46 percent_amount_to_lock: float | Unset = UNSET 47 output: LivePaperConfigOutput | Unset = LivePaperConfigOutput.SEPARATE 48 49 def to_dict(self) -> dict[str, Any]: 50 initial_funding = self.initial_funding 51 52 fee_rate = self.fee_rate 53 54 buy_fee_rate = self.buy_fee_rate 55 56 sell_fee_rate = self.sell_fee_rate 57 58 fee_leg: str | Unset = UNSET 59 if not isinstance(self.fee_leg, Unset): 60 fee_leg = self.fee_leg.value 61 62 percent_amount_to_lock = self.percent_amount_to_lock 63 64 output: str | Unset = UNSET 65 if not isinstance(self.output, Unset): 66 output = self.output.value 67 68 field_dict: dict[str, Any] = {} 69 70 field_dict.update({}) 71 if initial_funding is not UNSET: 72 field_dict["initialFunding"] = initial_funding 73 if fee_rate is not UNSET: 74 field_dict["feeRate"] = fee_rate 75 if buy_fee_rate is not UNSET: 76 field_dict["buyFeeRate"] = buy_fee_rate 77 if sell_fee_rate is not UNSET: 78 field_dict["sellFeeRate"] = sell_fee_rate 79 if fee_leg is not UNSET: 80 field_dict["feeLeg"] = fee_leg 81 if percent_amount_to_lock is not UNSET: 82 field_dict["percentAmountToLock"] = percent_amount_to_lock 83 if output is not UNSET: 84 field_dict["output"] = output 85 86 return field_dict 87 88 @classmethod 89 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 90 d = dict(src_dict) 91 initial_funding = d.pop("initialFunding", UNSET) 92 93 fee_rate = d.pop("feeRate", UNSET) 94 95 buy_fee_rate = d.pop("buyFeeRate", UNSET) 96 97 sell_fee_rate = d.pop("sellFeeRate", UNSET) 98 99 _fee_leg = d.pop("feeLeg", UNSET) 100 fee_leg: LivePaperConfigFeeLeg | Unset 101 if isinstance(_fee_leg, Unset): 102 fee_leg = UNSET 103 else: 104 fee_leg = LivePaperConfigFeeLeg(_fee_leg) 105 106 percent_amount_to_lock = d.pop("percentAmountToLock", UNSET) 107 108 _output = d.pop("output", UNSET) 109 output: LivePaperConfigOutput | Unset 110 if isinstance(_output, Unset): 111 output = UNSET 112 else: 113 output = LivePaperConfigOutput(_output) 114 115 live_paper_config = cls( 116 initial_funding=initial_funding, 117 fee_rate=fee_rate, 118 buy_fee_rate=buy_fee_rate, 119 sell_fee_rate=sell_fee_rate, 120 fee_leg=fee_leg, 121 percent_amount_to_lock=percent_amount_to_lock, 122 output=output, 123 ) 124 125 return live_paper_config
Paper trading for this run: the same economics as a backtest's baseConfig (same fields,
defaults and limits), plus output. An empty object takes every default. Each quote
currency the run trades gets its own simulated account, opened with initialFunding in
that currency; accounts are never added together. As returned on a run, the block is
normalised: feeRate is resolved into buyFeeRate/sellFeeRate and defaults are filled
in.
Attributes:
initial_funding (float | Unset): Starting capital of each account, in that account's own quote currency.
Default: 100.0.
fee_rate (float | Unset): Fee rate for both sides (0.001 = 0.1%). Accepted on start; returned resolved into the
two fields below. Default: 0.001.
buy_fee_rate (float | Unset): Buy-side fee rate; overrides `feeRate`.
sell_fee_rate (float | Unset): Sell-side fee rate; overrides `feeRate`.
fee_leg (LivePaperConfigFeeLeg | Unset): Which asset fees are charged in. Case-insensitive on start. Default:
LivePaperConfigFeeLeg.RECEIVED.
percent_amount_to_lock (float | Unset): Share of the account's free balance each entry locks, in percent.
Omitted, the strategy's own setting applies, and without one 10%.
output (LivePaperConfigOutput | Unset): `separate` keeps paper output out of the run's signals (read it with
`GET /live/{runId}/paper`); `mix` also interleaves it into the run's signals as `type: paper`, right after the
signal that caused it. Default: LivePaperConfigOutput.SEPARATE.
29def __init__(self, initial_funding=attr_dict['initial_funding'].default, fee_rate=attr_dict['fee_rate'].default, buy_fee_rate=attr_dict['buy_fee_rate'].default, sell_fee_rate=attr_dict['sell_fee_rate'].default, fee_leg=attr_dict['fee_leg'].default, percent_amount_to_lock=attr_dict['percent_amount_to_lock'].default, output=attr_dict['output'].default): 30 self.initial_funding = initial_funding 31 self.fee_rate = fee_rate 32 self.buy_fee_rate = buy_fee_rate 33 self.sell_fee_rate = sell_fee_rate 34 self.fee_leg = fee_leg 35 self.percent_amount_to_lock = percent_amount_to_lock 36 self.output = output
Method generated by attrs for class LivePaperConfig.
49 def to_dict(self) -> dict[str, Any]: 50 initial_funding = self.initial_funding 51 52 fee_rate = self.fee_rate 53 54 buy_fee_rate = self.buy_fee_rate 55 56 sell_fee_rate = self.sell_fee_rate 57 58 fee_leg: str | Unset = UNSET 59 if not isinstance(self.fee_leg, Unset): 60 fee_leg = self.fee_leg.value 61 62 percent_amount_to_lock = self.percent_amount_to_lock 63 64 output: str | Unset = UNSET 65 if not isinstance(self.output, Unset): 66 output = self.output.value 67 68 field_dict: dict[str, Any] = {} 69 70 field_dict.update({}) 71 if initial_funding is not UNSET: 72 field_dict["initialFunding"] = initial_funding 73 if fee_rate is not UNSET: 74 field_dict["feeRate"] = fee_rate 75 if buy_fee_rate is not UNSET: 76 field_dict["buyFeeRate"] = buy_fee_rate 77 if sell_fee_rate is not UNSET: 78 field_dict["sellFeeRate"] = sell_fee_rate 79 if fee_leg is not UNSET: 80 field_dict["feeLeg"] = fee_leg 81 if percent_amount_to_lock is not UNSET: 82 field_dict["percentAmountToLock"] = percent_amount_to_lock 83 if output is not UNSET: 84 field_dict["output"] = output 85 86 return field_dict
88 @classmethod 89 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 90 d = dict(src_dict) 91 initial_funding = d.pop("initialFunding", UNSET) 92 93 fee_rate = d.pop("feeRate", UNSET) 94 95 buy_fee_rate = d.pop("buyFeeRate", UNSET) 96 97 sell_fee_rate = d.pop("sellFeeRate", UNSET) 98 99 _fee_leg = d.pop("feeLeg", UNSET) 100 fee_leg: LivePaperConfigFeeLeg | Unset 101 if isinstance(_fee_leg, Unset): 102 fee_leg = UNSET 103 else: 104 fee_leg = LivePaperConfigFeeLeg(_fee_leg) 105 106 percent_amount_to_lock = d.pop("percentAmountToLock", UNSET) 107 108 _output = d.pop("output", UNSET) 109 output: LivePaperConfigOutput | Unset 110 if isinstance(_output, Unset): 111 output = UNSET 112 else: 113 output = LivePaperConfigOutput(_output) 114 115 live_paper_config = cls( 116 initial_funding=initial_funding, 117 fee_rate=fee_rate, 118 buy_fee_rate=buy_fee_rate, 119 sell_fee_rate=sell_fee_rate, 120 fee_leg=fee_leg, 121 percent_amount_to_lock=percent_amount_to_lock, 122 output=output, 123 ) 124 125 return live_paper_config
5class LivePaperConfigFeeLeg(str, Enum): 6 BASE = "BASE" 7 QUOTE = "QUOTE" 8 RECEIVED = "RECEIVED" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LivePaperConfigOutput(str, Enum): 6 MIX = "mix" 7 SEPARATE = "separate" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
20@_attrs_define 21class LivePaperEquityPage: 22 """ 23 Attributes: 24 points (list[LivePaperEquityPoint]): 25 field_links (LivePaperEquityPageLinks | Unset): 26 """ 27 28 points: list[LivePaperEquityPoint] 29 field_links: LivePaperEquityPageLinks | Unset = UNSET 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 points = [] 34 for points_item_data in self.points: 35 points_item = points_item_data.to_dict() 36 points.append(points_item) 37 38 field_links: dict[str, Any] | Unset = UNSET 39 if not isinstance(self.field_links, Unset): 40 field_links = self.field_links.to_dict() 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update( 45 { 46 "points": points, 47 } 48 ) 49 if field_links is not UNSET: 50 field_dict["_links"] = field_links 51 52 return field_dict 53 54 @classmethod 55 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 56 from ..models.live_paper_equity_page_links import LivePaperEquityPageLinks 57 from ..models.live_paper_equity_point import LivePaperEquityPoint 58 59 d = dict(src_dict) 60 points = [] 61 _points = d.pop("points") 62 for points_item_data in _points: 63 points_item = LivePaperEquityPoint.from_dict(points_item_data) 64 65 points.append(points_item) 66 67 _field_links = d.pop("_links", UNSET) 68 field_links: LivePaperEquityPageLinks | Unset 69 if isinstance(_field_links, Unset): 70 field_links = UNSET 71 else: 72 field_links = LivePaperEquityPageLinks.from_dict(_field_links) 73 74 live_paper_equity_page = cls( 75 points=points, 76 field_links=field_links, 77 ) 78 79 live_paper_equity_page.additional_properties = d 80 return live_paper_equity_page 81 82 @property 83 def additional_keys(self) -> list[str]: 84 return list(self.additional_properties.keys()) 85 86 def __getitem__(self, key: str) -> Any: 87 return self.additional_properties[key] 88 89 def __setitem__(self, key: str, value: Any) -> None: 90 self.additional_properties[key] = value 91 92 def __delitem__(self, key: str) -> None: 93 del self.additional_properties[key] 94 95 def __contains__(self, key: str) -> bool: 96 return key in self.additional_properties
Attributes: points (list[LivePaperEquityPoint]): field_links (LivePaperEquityPageLinks | Unset):
25def __init__(self, points, field_links=attr_dict['field_links'].default): 26 self.points = points 27 self.field_links = field_links 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperEquityPage.
32 def to_dict(self) -> dict[str, Any]: 33 points = [] 34 for points_item_data in self.points: 35 points_item = points_item_data.to_dict() 36 points.append(points_item) 37 38 field_links: dict[str, Any] | Unset = UNSET 39 if not isinstance(self.field_links, Unset): 40 field_links = self.field_links.to_dict() 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update( 45 { 46 "points": points, 47 } 48 ) 49 if field_links is not UNSET: 50 field_dict["_links"] = field_links 51 52 return field_dict
54 @classmethod 55 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 56 from ..models.live_paper_equity_page_links import LivePaperEquityPageLinks 57 from ..models.live_paper_equity_point import LivePaperEquityPoint 58 59 d = dict(src_dict) 60 points = [] 61 _points = d.pop("points") 62 for points_item_data in _points: 63 points_item = LivePaperEquityPoint.from_dict(points_item_data) 64 65 points.append(points_item) 66 67 _field_links = d.pop("_links", UNSET) 68 field_links: LivePaperEquityPageLinks | Unset 69 if isinstance(_field_links, Unset): 70 field_links = UNSET 71 else: 72 field_links = LivePaperEquityPageLinks.from_dict(_field_links) 73 74 live_paper_equity_page = cls( 75 points=points, 76 field_links=field_links, 77 ) 78 79 live_paper_equity_page.additional_properties = d 80 return live_paper_equity_page
19@_attrs_define 20class LivePaperEquityPageLinks: 21 """ 22 Attributes: 23 next_ (LivePaperEquityPageLinksNext | Unset): 24 """ 25 26 next_: LivePaperEquityPageLinksNext | Unset = UNSET 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 next_: dict[str, Any] | Unset = UNSET 31 if not isinstance(self.next_, Unset): 32 next_ = self.next_.to_dict() 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update({}) 37 if next_ is not UNSET: 38 field_dict["next"] = next_ 39 40 return field_dict 41 42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 from ..models.live_paper_equity_page_links_next import LivePaperEquityPageLinksNext 45 46 d = dict(src_dict) 47 _next_ = d.pop("next", UNSET) 48 next_: LivePaperEquityPageLinksNext | Unset 49 if isinstance(_next_, Unset): 50 next_ = UNSET 51 else: 52 next_ = LivePaperEquityPageLinksNext.from_dict(_next_) 53 54 live_paper_equity_page_links = cls( 55 next_=next_, 56 ) 57 58 live_paper_equity_page_links.additional_properties = d 59 return live_paper_equity_page_links 60 61 @property 62 def additional_keys(self) -> list[str]: 63 return list(self.additional_properties.keys()) 64 65 def __getitem__(self, key: str) -> Any: 66 return self.additional_properties[key] 67 68 def __setitem__(self, key: str, value: Any) -> None: 69 self.additional_properties[key] = value 70 71 def __delitem__(self, key: str) -> None: 72 del self.additional_properties[key] 73 74 def __contains__(self, key: str) -> bool: 75 return key in self.additional_properties
Attributes: next_ (LivePaperEquityPageLinksNext | Unset):
24def __init__(self, next_=attr_dict['next_'].default): 25 self.next_ = next_ 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperEquityPageLinks.
29 def to_dict(self) -> dict[str, Any]: 30 next_: dict[str, Any] | Unset = UNSET 31 if not isinstance(self.next_, Unset): 32 next_ = self.next_.to_dict() 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update({}) 37 if next_ is not UNSET: 38 field_dict["next"] = next_ 39 40 return field_dict
42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 from ..models.live_paper_equity_page_links_next import LivePaperEquityPageLinksNext 45 46 d = dict(src_dict) 47 _next_ = d.pop("next", UNSET) 48 next_: LivePaperEquityPageLinksNext | Unset 49 if isinstance(_next_, Unset): 50 next_ = UNSET 51 else: 52 next_ = LivePaperEquityPageLinksNext.from_dict(_next_) 53 54 live_paper_equity_page_links = cls( 55 next_=next_, 56 ) 57 58 live_paper_equity_page_links.additional_properties = d 59 return live_paper_equity_page_links
15@_attrs_define 16class LivePaperEquityPageLinksNext: 17 """ 18 Attributes: 19 href (str | Unset): 20 """ 21 22 href: str | Unset = UNSET 23 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 24 25 def to_dict(self) -> dict[str, Any]: 26 href = self.href 27 28 field_dict: dict[str, Any] = {} 29 field_dict.update(self.additional_properties) 30 field_dict.update({}) 31 if href is not UNSET: 32 field_dict["href"] = href 33 34 return field_dict 35 36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 d = dict(src_dict) 39 href = d.pop("href", UNSET) 40 41 live_paper_equity_page_links_next = cls( 42 href=href, 43 ) 44 45 live_paper_equity_page_links_next.additional_properties = d 46 return live_paper_equity_page_links_next 47 48 @property 49 def additional_keys(self) -> list[str]: 50 return list(self.additional_properties.keys()) 51 52 def __getitem__(self, key: str) -> Any: 53 return self.additional_properties[key] 54 55 def __setitem__(self, key: str, value: Any) -> None: 56 self.additional_properties[key] = value 57 58 def __delitem__(self, key: str) -> None: 59 del self.additional_properties[key] 60 61 def __contains__(self, key: str) -> bool: 62 return key in self.additional_properties
Attributes: href (str | Unset):
24def __init__(self, href=attr_dict['href'].default): 25 self.href = href 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperEquityPageLinksNext.
36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 d = dict(src_dict) 39 href = d.pop("href", UNSET) 40 41 live_paper_equity_page_links_next = cls( 42 href=href, 43 ) 44 45 live_paper_equity_page_links_next.additional_properties = d 46 return live_paper_equity_page_links_next
16@_attrs_define 17class LivePaperEquityPoint: 18 """ 19 Attributes: 20 currency (str): 21 kind (LivePaperEquityPointKind): 22 event_ts_ms (int): Market time of the point. 23 equity (float | Unset): Absent on a `gap`. 24 """ 25 26 currency: str 27 kind: LivePaperEquityPointKind 28 event_ts_ms: int 29 equity: float | Unset = UNSET 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 currency = self.currency 34 35 kind = self.kind.value 36 37 event_ts_ms = self.event_ts_ms 38 39 equity = self.equity 40 41 field_dict: dict[str, Any] = {} 42 field_dict.update(self.additional_properties) 43 field_dict.update( 44 { 45 "currency": currency, 46 "kind": kind, 47 "eventTsMs": event_ts_ms, 48 } 49 ) 50 if equity is not UNSET: 51 field_dict["equity"] = equity 52 53 return field_dict 54 55 @classmethod 56 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 57 d = dict(src_dict) 58 currency = d.pop("currency") 59 60 kind = LivePaperEquityPointKind(d.pop("kind")) 61 62 event_ts_ms = d.pop("eventTsMs") 63 64 equity = d.pop("equity", UNSET) 65 66 live_paper_equity_point = cls( 67 currency=currency, 68 kind=kind, 69 event_ts_ms=event_ts_ms, 70 equity=equity, 71 ) 72 73 live_paper_equity_point.additional_properties = d 74 return live_paper_equity_point 75 76 @property 77 def additional_keys(self) -> list[str]: 78 return list(self.additional_properties.keys()) 79 80 def __getitem__(self, key: str) -> Any: 81 return self.additional_properties[key] 82 83 def __setitem__(self, key: str, value: Any) -> None: 84 self.additional_properties[key] = value 85 86 def __delitem__(self, key: str) -> None: 87 del self.additional_properties[key] 88 89 def __contains__(self, key: str) -> bool: 90 return key in self.additional_properties
Attributes:
currency (str):
kind (LivePaperEquityPointKind):
event_ts_ms (int): Market time of the point.
equity (float | Unset): Absent on a gap.
27def __init__(self, currency, kind, event_ts_ms, equity=attr_dict['equity'].default): 28 self.currency = currency 29 self.kind = kind 30 self.event_ts_ms = event_ts_ms 31 self.equity = equity 32 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperEquityPoint.
32 def to_dict(self) -> dict[str, Any]: 33 currency = self.currency 34 35 kind = self.kind.value 36 37 event_ts_ms = self.event_ts_ms 38 39 equity = self.equity 40 41 field_dict: dict[str, Any] = {} 42 field_dict.update(self.additional_properties) 43 field_dict.update( 44 { 45 "currency": currency, 46 "kind": kind, 47 "eventTsMs": event_ts_ms, 48 } 49 ) 50 if equity is not UNSET: 51 field_dict["equity"] = equity 52 53 return field_dict
55 @classmethod 56 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 57 d = dict(src_dict) 58 currency = d.pop("currency") 59 60 kind = LivePaperEquityPointKind(d.pop("kind")) 61 62 event_ts_ms = d.pop("eventTsMs") 63 64 equity = d.pop("equity", UNSET) 65 66 live_paper_equity_point = cls( 67 currency=currency, 68 kind=kind, 69 event_ts_ms=event_ts_ms, 70 equity=equity, 71 ) 72 73 live_paper_equity_point.additional_properties = d 74 return live_paper_equity_point
5class LivePaperEquityPointKind(str, Enum): 6 EQUITY = "equity" 7 GAP = "gap" 8 MARK = "mark" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class LivePaperKpi: 17 """The same KPIs a backtest reports, over the trades closed so far. Absent until the first closed trade is recorded. 18 19 Attributes: 20 total_trades (int | Unset): 21 win_count (int | Unset): 22 loss_count (int | Unset): 23 win_rate (float | Unset): Ratio (0.5 = half the trades won). 24 pnl_total (float | Unset): 25 pnl_total_percent (float | Unset): Percent of `initialFunding` (0-100 scale). 26 sharpe_ratio (float | None | Unset): 27 sortino_ratio (float | None | Unset): 28 cagr (float | None | Unset): Ratio (0.15 for 15%). 29 max_drawdown (float | Unset): 30 max_drawdown_percent (float | Unset): Percent (0-100 scale). 31 """ 32 33 total_trades: int | Unset = UNSET 34 win_count: int | Unset = UNSET 35 loss_count: int | Unset = UNSET 36 win_rate: float | Unset = UNSET 37 pnl_total: float | Unset = UNSET 38 pnl_total_percent: float | Unset = UNSET 39 sharpe_ratio: float | None | Unset = UNSET 40 sortino_ratio: float | None | Unset = UNSET 41 cagr: float | None | Unset = UNSET 42 max_drawdown: float | Unset = UNSET 43 max_drawdown_percent: float | Unset = UNSET 44 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 45 46 def to_dict(self) -> dict[str, Any]: 47 total_trades = self.total_trades 48 49 win_count = self.win_count 50 51 loss_count = self.loss_count 52 53 win_rate = self.win_rate 54 55 pnl_total = self.pnl_total 56 57 pnl_total_percent = self.pnl_total_percent 58 59 sharpe_ratio: float | None | Unset 60 if isinstance(self.sharpe_ratio, Unset): 61 sharpe_ratio = UNSET 62 else: 63 sharpe_ratio = self.sharpe_ratio 64 65 sortino_ratio: float | None | Unset 66 if isinstance(self.sortino_ratio, Unset): 67 sortino_ratio = UNSET 68 else: 69 sortino_ratio = self.sortino_ratio 70 71 cagr: float | None | Unset 72 if isinstance(self.cagr, Unset): 73 cagr = UNSET 74 else: 75 cagr = self.cagr 76 77 max_drawdown = self.max_drawdown 78 79 max_drawdown_percent = self.max_drawdown_percent 80 81 field_dict: dict[str, Any] = {} 82 field_dict.update(self.additional_properties) 83 field_dict.update({}) 84 if total_trades is not UNSET: 85 field_dict["totalTrades"] = total_trades 86 if win_count is not UNSET: 87 field_dict["winCount"] = win_count 88 if loss_count is not UNSET: 89 field_dict["lossCount"] = loss_count 90 if win_rate is not UNSET: 91 field_dict["winRate"] = win_rate 92 if pnl_total is not UNSET: 93 field_dict["pnlTotal"] = pnl_total 94 if pnl_total_percent is not UNSET: 95 field_dict["pnlTotalPercent"] = pnl_total_percent 96 if sharpe_ratio is not UNSET: 97 field_dict["sharpeRatio"] = sharpe_ratio 98 if sortino_ratio is not UNSET: 99 field_dict["sortinoRatio"] = sortino_ratio 100 if cagr is not UNSET: 101 field_dict["cagr"] = cagr 102 if max_drawdown is not UNSET: 103 field_dict["maxDrawdown"] = max_drawdown 104 if max_drawdown_percent is not UNSET: 105 field_dict["maxDrawdownPercent"] = max_drawdown_percent 106 107 return field_dict 108 109 @classmethod 110 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 111 d = dict(src_dict) 112 total_trades = d.pop("totalTrades", UNSET) 113 114 win_count = d.pop("winCount", UNSET) 115 116 loss_count = d.pop("lossCount", UNSET) 117 118 win_rate = d.pop("winRate", UNSET) 119 120 pnl_total = d.pop("pnlTotal", UNSET) 121 122 pnl_total_percent = d.pop("pnlTotalPercent", UNSET) 123 124 def _parse_sharpe_ratio(data: object) -> float | None | Unset: 125 if data is None: 126 return data 127 if isinstance(data, Unset): 128 return data 129 return cast(float | None | Unset, data) 130 131 sharpe_ratio = _parse_sharpe_ratio(d.pop("sharpeRatio", UNSET)) 132 133 def _parse_sortino_ratio(data: object) -> float | None | Unset: 134 if data is None: 135 return data 136 if isinstance(data, Unset): 137 return data 138 return cast(float | None | Unset, data) 139 140 sortino_ratio = _parse_sortino_ratio(d.pop("sortinoRatio", UNSET)) 141 142 def _parse_cagr(data: object) -> float | None | Unset: 143 if data is None: 144 return data 145 if isinstance(data, Unset): 146 return data 147 return cast(float | None | Unset, data) 148 149 cagr = _parse_cagr(d.pop("cagr", UNSET)) 150 151 max_drawdown = d.pop("maxDrawdown", UNSET) 152 153 max_drawdown_percent = d.pop("maxDrawdownPercent", UNSET) 154 155 live_paper_kpi = cls( 156 total_trades=total_trades, 157 win_count=win_count, 158 loss_count=loss_count, 159 win_rate=win_rate, 160 pnl_total=pnl_total, 161 pnl_total_percent=pnl_total_percent, 162 sharpe_ratio=sharpe_ratio, 163 sortino_ratio=sortino_ratio, 164 cagr=cagr, 165 max_drawdown=max_drawdown, 166 max_drawdown_percent=max_drawdown_percent, 167 ) 168 169 live_paper_kpi.additional_properties = d 170 return live_paper_kpi 171 172 @property 173 def additional_keys(self) -> list[str]: 174 return list(self.additional_properties.keys()) 175 176 def __getitem__(self, key: str) -> Any: 177 return self.additional_properties[key] 178 179 def __setitem__(self, key: str, value: Any) -> None: 180 self.additional_properties[key] = value 181 182 def __delitem__(self, key: str) -> None: 183 del self.additional_properties[key] 184 185 def __contains__(self, key: str) -> bool: 186 return key in self.additional_properties
The same KPIs a backtest reports, over the trades closed so far. Absent until the first closed trade is recorded.
Attributes:
total_trades (int | Unset):
win_count (int | Unset):
loss_count (int | Unset):
win_rate (float | Unset): Ratio (0.5 = half the trades won).
pnl_total (float | Unset):
pnl_total_percent (float | Unset): Percent of initialFunding (0-100 scale).
sharpe_ratio (float | None | Unset):
sortino_ratio (float | None | Unset):
cagr (float | None | Unset): Ratio (0.15 for 15%).
max_drawdown (float | Unset):
max_drawdown_percent (float | Unset): Percent (0-100 scale).
34def __init__(self, total_trades=attr_dict['total_trades'].default, win_count=attr_dict['win_count'].default, loss_count=attr_dict['loss_count'].default, win_rate=attr_dict['win_rate'].default, pnl_total=attr_dict['pnl_total'].default, pnl_total_percent=attr_dict['pnl_total_percent'].default, sharpe_ratio=attr_dict['sharpe_ratio'].default, sortino_ratio=attr_dict['sortino_ratio'].default, cagr=attr_dict['cagr'].default, max_drawdown=attr_dict['max_drawdown'].default, max_drawdown_percent=attr_dict['max_drawdown_percent'].default): 35 self.total_trades = total_trades 36 self.win_count = win_count 37 self.loss_count = loss_count 38 self.win_rate = win_rate 39 self.pnl_total = pnl_total 40 self.pnl_total_percent = pnl_total_percent 41 self.sharpe_ratio = sharpe_ratio 42 self.sortino_ratio = sortino_ratio 43 self.cagr = cagr 44 self.max_drawdown = max_drawdown 45 self.max_drawdown_percent = max_drawdown_percent 46 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperKpi.
46 def to_dict(self) -> dict[str, Any]: 47 total_trades = self.total_trades 48 49 win_count = self.win_count 50 51 loss_count = self.loss_count 52 53 win_rate = self.win_rate 54 55 pnl_total = self.pnl_total 56 57 pnl_total_percent = self.pnl_total_percent 58 59 sharpe_ratio: float | None | Unset 60 if isinstance(self.sharpe_ratio, Unset): 61 sharpe_ratio = UNSET 62 else: 63 sharpe_ratio = self.sharpe_ratio 64 65 sortino_ratio: float | None | Unset 66 if isinstance(self.sortino_ratio, Unset): 67 sortino_ratio = UNSET 68 else: 69 sortino_ratio = self.sortino_ratio 70 71 cagr: float | None | Unset 72 if isinstance(self.cagr, Unset): 73 cagr = UNSET 74 else: 75 cagr = self.cagr 76 77 max_drawdown = self.max_drawdown 78 79 max_drawdown_percent = self.max_drawdown_percent 80 81 field_dict: dict[str, Any] = {} 82 field_dict.update(self.additional_properties) 83 field_dict.update({}) 84 if total_trades is not UNSET: 85 field_dict["totalTrades"] = total_trades 86 if win_count is not UNSET: 87 field_dict["winCount"] = win_count 88 if loss_count is not UNSET: 89 field_dict["lossCount"] = loss_count 90 if win_rate is not UNSET: 91 field_dict["winRate"] = win_rate 92 if pnl_total is not UNSET: 93 field_dict["pnlTotal"] = pnl_total 94 if pnl_total_percent is not UNSET: 95 field_dict["pnlTotalPercent"] = pnl_total_percent 96 if sharpe_ratio is not UNSET: 97 field_dict["sharpeRatio"] = sharpe_ratio 98 if sortino_ratio is not UNSET: 99 field_dict["sortinoRatio"] = sortino_ratio 100 if cagr is not UNSET: 101 field_dict["cagr"] = cagr 102 if max_drawdown is not UNSET: 103 field_dict["maxDrawdown"] = max_drawdown 104 if max_drawdown_percent is not UNSET: 105 field_dict["maxDrawdownPercent"] = max_drawdown_percent 106 107 return field_dict
109 @classmethod 110 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 111 d = dict(src_dict) 112 total_trades = d.pop("totalTrades", UNSET) 113 114 win_count = d.pop("winCount", UNSET) 115 116 loss_count = d.pop("lossCount", UNSET) 117 118 win_rate = d.pop("winRate", UNSET) 119 120 pnl_total = d.pop("pnlTotal", UNSET) 121 122 pnl_total_percent = d.pop("pnlTotalPercent", UNSET) 123 124 def _parse_sharpe_ratio(data: object) -> float | None | Unset: 125 if data is None: 126 return data 127 if isinstance(data, Unset): 128 return data 129 return cast(float | None | Unset, data) 130 131 sharpe_ratio = _parse_sharpe_ratio(d.pop("sharpeRatio", UNSET)) 132 133 def _parse_sortino_ratio(data: object) -> float | None | Unset: 134 if data is None: 135 return data 136 if isinstance(data, Unset): 137 return data 138 return cast(float | None | Unset, data) 139 140 sortino_ratio = _parse_sortino_ratio(d.pop("sortinoRatio", UNSET)) 141 142 def _parse_cagr(data: object) -> float | None | Unset: 143 if data is None: 144 return data 145 if isinstance(data, Unset): 146 return data 147 return cast(float | None | Unset, data) 148 149 cagr = _parse_cagr(d.pop("cagr", UNSET)) 150 151 max_drawdown = d.pop("maxDrawdown", UNSET) 152 153 max_drawdown_percent = d.pop("maxDrawdownPercent", UNSET) 154 155 live_paper_kpi = cls( 156 total_trades=total_trades, 157 win_count=win_count, 158 loss_count=loss_count, 159 win_rate=win_rate, 160 pnl_total=pnl_total, 161 pnl_total_percent=pnl_total_percent, 162 sharpe_ratio=sharpe_ratio, 163 sortino_ratio=sortino_ratio, 164 cagr=cagr, 165 max_drawdown=max_drawdown, 166 max_drawdown_percent=max_drawdown_percent, 167 ) 168 169 live_paper_kpi.additional_properties = d 170 return live_paper_kpi
13@_attrs_define 14class LivePaperPosition: 15 """ 16 Attributes: 17 instrument (str): Example: BTC/USDT. 18 base (float): Amount held, in the base asset. 19 cost (float): What it cost, in the account's currency. 20 """ 21 22 instrument: str 23 base: float 24 cost: float 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 instrument = self.instrument 29 30 base = self.base 31 32 cost = self.cost 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "instrument": instrument, 39 "base": base, 40 "cost": cost, 41 } 42 ) 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 d = dict(src_dict) 49 instrument = d.pop("instrument") 50 51 base = d.pop("base") 52 53 cost = d.pop("cost") 54 55 live_paper_position = cls( 56 instrument=instrument, 57 base=base, 58 cost=cost, 59 ) 60 61 live_paper_position.additional_properties = d 62 return live_paper_position 63 64 @property 65 def additional_keys(self) -> list[str]: 66 return list(self.additional_properties.keys()) 67 68 def __getitem__(self, key: str) -> Any: 69 return self.additional_properties[key] 70 71 def __setitem__(self, key: str, value: Any) -> None: 72 self.additional_properties[key] = value 73 74 def __delitem__(self, key: str) -> None: 75 del self.additional_properties[key] 76 77 def __contains__(self, key: str) -> bool: 78 return key in self.additional_properties
Attributes: instrument (str): Example: BTC/USDT. base (float): Amount held, in the base asset. cost (float): What it cost, in the account's currency.
26def __init__(self, instrument, base, cost): 27 self.instrument = instrument 28 self.base = base 29 self.cost = cost 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LivePaperPosition.
27 def to_dict(self) -> dict[str, Any]: 28 instrument = self.instrument 29 30 base = self.base 31 32 cost = self.cost 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "instrument": instrument, 39 "base": base, 40 "cost": cost, 41 } 42 ) 43 44 return field_dict
46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 d = dict(src_dict) 49 instrument = d.pop("instrument") 50 51 base = d.pop("base") 52 53 cost = d.pop("cost") 54 55 live_paper_position = cls( 56 instrument=instrument, 57 base=base, 58 cost=cost, 59 ) 60 61 live_paper_position.additional_properties = d 62 return live_paper_position
5class LivePaperStage(str, Enum): 6 LIVE = "LIVE" 7 SANDBOX = "SANDBOX" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
13@_attrs_define 14class LiveParamsUpdateResult: 15 """ 16 Attributes: 17 run_id (str): 18 params_version (int): 19 effective_at_ms (int): Epoch milliseconds — the earliest moment the new values are guaranteed to be in effect. 20 """ 21 22 run_id: str 23 params_version: int 24 effective_at_ms: int 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 run_id = self.run_id 29 30 params_version = self.params_version 31 32 effective_at_ms = self.effective_at_ms 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "runId": run_id, 39 "paramsVersion": params_version, 40 "effectiveAtMs": effective_at_ms, 41 } 42 ) 43 44 return field_dict 45 46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 d = dict(src_dict) 49 run_id = d.pop("runId") 50 51 params_version = d.pop("paramsVersion") 52 53 effective_at_ms = d.pop("effectiveAtMs") 54 55 live_params_update_result = cls( 56 run_id=run_id, 57 params_version=params_version, 58 effective_at_ms=effective_at_ms, 59 ) 60 61 live_params_update_result.additional_properties = d 62 return live_params_update_result 63 64 @property 65 def additional_keys(self) -> list[str]: 66 return list(self.additional_properties.keys()) 67 68 def __getitem__(self, key: str) -> Any: 69 return self.additional_properties[key] 70 71 def __setitem__(self, key: str, value: Any) -> None: 72 self.additional_properties[key] = value 73 74 def __delitem__(self, key: str) -> None: 75 del self.additional_properties[key] 76 77 def __contains__(self, key: str) -> bool: 78 return key in self.additional_properties
Attributes: run_id (str): params_version (int): effective_at_ms (int): Epoch milliseconds — the earliest moment the new values are guaranteed to be in effect.
26def __init__(self, run_id, params_version, effective_at_ms): 27 self.run_id = run_id 28 self.params_version = params_version 29 self.effective_at_ms = effective_at_ms 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveParamsUpdateResult.
27 def to_dict(self) -> dict[str, Any]: 28 run_id = self.run_id 29 30 params_version = self.params_version 31 32 effective_at_ms = self.effective_at_ms 33 34 field_dict: dict[str, Any] = {} 35 field_dict.update(self.additional_properties) 36 field_dict.update( 37 { 38 "runId": run_id, 39 "paramsVersion": params_version, 40 "effectiveAtMs": effective_at_ms, 41 } 42 ) 43 44 return field_dict
46 @classmethod 47 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 48 d = dict(src_dict) 49 run_id = d.pop("runId") 50 51 params_version = d.pop("paramsVersion") 52 53 effective_at_ms = d.pop("effectiveAtMs") 54 55 live_params_update_result = cls( 56 run_id=run_id, 57 params_version=params_version, 58 effective_at_ms=effective_at_ms, 59 ) 60 61 live_params_update_result.additional_properties = d 62 return live_params_update_result
26@_attrs_define 27class LiveRun: 28 """A live run's full state, as returned by stopping it through its strategy, and the base of the representations 29 returned by starting and by reading it. `warmFrom` is declared by those two (`LiveRunWithStream` and 30 `LiveRunDetail`) and not here, because the response to stopping a run does not carry it. 31 32 Attributes: 33 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 34 always yields the same id, for every caller. How much formatting the id ignores depends on 35 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 36 not. 37 Example: 6bsh31ikwkuivhtgcoa6s4. 38 run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET 39 /live/public`. 40 visibility (LiveRunVisibility): 41 stage (LiveRunStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a second 42 execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically when the 43 24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts `LIVE`, 44 unless you started it with `sandbox: true`. 45 state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING` 46 (behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call 47 for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different 48 signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`. 49 `LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a 50 running run with something to look at. See the Live execution guide. 51 desired (LiveRunDesired): What you last asked for. `state` can lag this briefly after `DELETE`. 52 sources (list[LiveSource]): 53 params (LiveRunParams): 54 params_version (int): Increments on every accepted `PUT .../params` call, including one that resends the current 55 values. 56 relay (bool): Whether this run's signals are relayed over the WebSocket channel described in the "Live 57 execution" guide. It is the value requested at start, in either stage. 58 started_at_ms (int): Epoch milliseconds. 59 name (str | Unset): 60 description (str | Unset): 61 reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is 62 never a 63 stack trace or an internal message. Either `resource: ...` (the platform stopped the run for 64 exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for 65 a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's 66 definition was refused, the run could not start after several attempts, the strategy failed while 67 processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow: 68 read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays 69 `desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your 70 live-run limit) until then; one that can never run because its strategy cannot consume its source 71 type is stopped by the platform itself (`desired: STOPPED`), so it holds no place. 72 gate (LiveRunGate | Unset): The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and 73 present once it ends, so an absent `gate` means the trial has not finished. A run that started in `LIVE` without 74 a trial has it from the start: the verdict of the earlier run it relies on, with `inheritedFrom` naming that 75 run. `passed` is the verdict; the rest is diagnostic detail whose shape is not yet stabilized as public API: 76 treat it as opaque. 77 paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's `baseConfig` 78 (same fields, 79 defaults and limits), plus `output`. An empty object takes every default. Each quote 80 currency the run trades gets its own simulated account, opened with `initialFunding` in 81 that currency; accounts are never added together. As returned on a run, the block is 82 normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled 83 in. 84 stats (LiveRunStats | Unset): What a run has been doing, as of its last snapshot. The platform refreshes it 85 about once a minute 86 while the run is being executed, so `opsPerSecond` is an average over that interval, not an 87 instantaneous rate. 88 """ 89 90 strategy_id: str 91 run_id: str 92 visibility: LiveRunVisibility 93 stage: LiveRunStage 94 state: str 95 desired: LiveRunDesired 96 sources: list[LiveSource] 97 params: LiveRunParams 98 params_version: int 99 relay: bool 100 started_at_ms: int 101 name: str | Unset = UNSET 102 description: str | Unset = UNSET 103 reason: str | Unset = UNSET 104 gate: LiveRunGate | Unset = UNSET 105 paper: LivePaperConfig | Unset = UNSET 106 stats: LiveRunStats | Unset = UNSET 107 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 108 109 def to_dict(self) -> dict[str, Any]: 110 strategy_id = self.strategy_id 111 112 run_id = self.run_id 113 114 visibility = self.visibility.value 115 116 stage = self.stage.value 117 118 state = self.state 119 120 desired = self.desired.value 121 122 sources = [] 123 for sources_item_data in self.sources: 124 sources_item = sources_item_data.to_dict() 125 sources.append(sources_item) 126 127 params = self.params.to_dict() 128 129 params_version = self.params_version 130 131 relay = self.relay 132 133 started_at_ms = self.started_at_ms 134 135 name = self.name 136 137 description = self.description 138 139 reason = self.reason 140 141 gate: dict[str, Any] | Unset = UNSET 142 if not isinstance(self.gate, Unset): 143 gate = self.gate.to_dict() 144 145 paper: dict[str, Any] | Unset = UNSET 146 if not isinstance(self.paper, Unset): 147 paper = self.paper.to_dict() 148 149 stats: dict[str, Any] | Unset = UNSET 150 if not isinstance(self.stats, Unset): 151 stats = self.stats.to_dict() 152 153 field_dict: dict[str, Any] = {} 154 field_dict.update(self.additional_properties) 155 field_dict.update( 156 { 157 "strategyId": strategy_id, 158 "runId": run_id, 159 "visibility": visibility, 160 "stage": stage, 161 "state": state, 162 "desired": desired, 163 "sources": sources, 164 "params": params, 165 "paramsVersion": params_version, 166 "relay": relay, 167 "startedAtMs": started_at_ms, 168 } 169 ) 170 if name is not UNSET: 171 field_dict["name"] = name 172 if description is not UNSET: 173 field_dict["description"] = description 174 if reason is not UNSET: 175 field_dict["reason"] = reason 176 if gate is not UNSET: 177 field_dict["gate"] = gate 178 if paper is not UNSET: 179 field_dict["paper"] = paper 180 if stats is not UNSET: 181 field_dict["stats"] = stats 182 183 return field_dict 184 185 @classmethod 186 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 187 from ..models.live_paper_config import LivePaperConfig 188 from ..models.live_run_gate import LiveRunGate 189 from ..models.live_run_params import LiveRunParams 190 from ..models.live_run_stats import LiveRunStats 191 from ..models.live_source import LiveSource 192 193 d = dict(src_dict) 194 strategy_id = d.pop("strategyId") 195 196 run_id = d.pop("runId") 197 198 visibility = LiveRunVisibility(d.pop("visibility")) 199 200 stage = LiveRunStage(d.pop("stage")) 201 202 state = d.pop("state") 203 204 desired = LiveRunDesired(d.pop("desired")) 205 206 sources = [] 207 _sources = d.pop("sources") 208 for sources_item_data in _sources: 209 sources_item = LiveSource.from_dict(sources_item_data) 210 211 sources.append(sources_item) 212 213 params = LiveRunParams.from_dict(d.pop("params")) 214 215 params_version = d.pop("paramsVersion") 216 217 relay = d.pop("relay") 218 219 started_at_ms = d.pop("startedAtMs") 220 221 name = d.pop("name", UNSET) 222 223 description = d.pop("description", UNSET) 224 225 reason = d.pop("reason", UNSET) 226 227 _gate = d.pop("gate", UNSET) 228 gate: LiveRunGate | Unset 229 if isinstance(_gate, Unset): 230 gate = UNSET 231 else: 232 gate = LiveRunGate.from_dict(_gate) 233 234 _paper = d.pop("paper", UNSET) 235 paper: LivePaperConfig | Unset 236 if isinstance(_paper, Unset): 237 paper = UNSET 238 else: 239 paper = LivePaperConfig.from_dict(_paper) 240 241 _stats = d.pop("stats", UNSET) 242 stats: LiveRunStats | Unset 243 if isinstance(_stats, Unset): 244 stats = UNSET 245 else: 246 stats = LiveRunStats.from_dict(_stats) 247 248 live_run = cls( 249 strategy_id=strategy_id, 250 run_id=run_id, 251 visibility=visibility, 252 stage=stage, 253 state=state, 254 desired=desired, 255 sources=sources, 256 params=params, 257 params_version=params_version, 258 relay=relay, 259 started_at_ms=started_at_ms, 260 name=name, 261 description=description, 262 reason=reason, 263 gate=gate, 264 paper=paper, 265 stats=stats, 266 ) 267 268 live_run.additional_properties = d 269 return live_run 270 271 @property 272 def additional_keys(self) -> list[str]: 273 return list(self.additional_properties.keys()) 274 275 def __getitem__(self, key: str) -> Any: 276 return self.additional_properties[key] 277 278 def __setitem__(self, key: str, value: Any) -> None: 279 self.additional_properties[key] = value 280 281 def __delitem__(self, key: str) -> None: 282 del self.additional_properties[key] 283 284 def __contains__(self, key: str) -> bool: 285 return key in self.additional_properties
A live run's full state, as returned by stopping it through its strategy, and the base of the representations
returned by starting and by reading it. warmFrom is declared by those two (LiveRunWithStream and
LiveRunDetail) and not here, because the response to stopping a run does not carry it.
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see `POST /strategy` for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET
/live/public`.
visibility (LiveRunVisibility):
stage (LiveRunStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a second
execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically when the
24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts `LIVE`,
unless you started it with `sandbox: true`.
state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING`
(behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call
for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different
signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`.
`LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a
running run with something to look at. See the Live execution guide.
desired (LiveRunDesired): What you last asked for. `state` can lag this briefly after `DELETE`.
sources (list[LiveSource]):
params (LiveRunParams):
params_version (int): Increments on every accepted `PUT .../params` call, including one that resends the current
values.
relay (bool): Whether this run's signals are relayed over the WebSocket channel described in the "Live
execution" guide. It is the value requested at start, in either stage.
started_at_ms (int): Epoch milliseconds.
name (str | Unset):
description (str | Unset):
reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is
never a
stack trace or an internal message. Either `resource: ...` (the platform stopped the run for
exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for
a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's
definition was refused, the run could not start after several attempts, the strategy failed while
processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow:
read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays
`desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your
live-run limit) until then; one that can never run because its strategy cannot consume its source
type is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
gate (LiveRunGate | Unset): The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and
present once it ends, so an absent `gate` means the trial has not finished. A run that started in `LIVE` without
a trial has it from the start: the verdict of the earlier run it relies on, with `inheritedFrom` naming that
run. `passed` is the verdict; the rest is diagnostic detail whose shape is not yet stabilized as public API:
treat it as opaque.
paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's `baseConfig`
(same fields,
defaults and limits), plus `output`. An empty object takes every default. Each quote
currency the run trades gets its own simulated account, opened with `initialFunding` in
that currency; accounts are never added together. As returned on a run, the block is
normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled
in.
stats (LiveRunStats | Unset): What a run has been doing, as of its last snapshot. The platform refreshes it
about once a minute
while the run is being executed, so `opsPerSecond` is an average over that interval, not an
instantaneous rate.
40def __init__(self, strategy_id, run_id, visibility, stage, state, desired, sources, params, params_version, relay, started_at_ms, name=attr_dict['name'].default, description=attr_dict['description'].default, reason=attr_dict['reason'].default, gate=attr_dict['gate'].default, paper=attr_dict['paper'].default, stats=attr_dict['stats'].default): 41 self.strategy_id = strategy_id 42 self.run_id = run_id 43 self.visibility = visibility 44 self.stage = stage 45 self.state = state 46 self.desired = desired 47 self.sources = sources 48 self.params = params 49 self.params_version = params_version 50 self.relay = relay 51 self.started_at_ms = started_at_ms 52 self.name = name 53 self.description = description 54 self.reason = reason 55 self.gate = gate 56 self.paper = paper 57 self.stats = stats 58 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveRun.
109 def to_dict(self) -> dict[str, Any]: 110 strategy_id = self.strategy_id 111 112 run_id = self.run_id 113 114 visibility = self.visibility.value 115 116 stage = self.stage.value 117 118 state = self.state 119 120 desired = self.desired.value 121 122 sources = [] 123 for sources_item_data in self.sources: 124 sources_item = sources_item_data.to_dict() 125 sources.append(sources_item) 126 127 params = self.params.to_dict() 128 129 params_version = self.params_version 130 131 relay = self.relay 132 133 started_at_ms = self.started_at_ms 134 135 name = self.name 136 137 description = self.description 138 139 reason = self.reason 140 141 gate: dict[str, Any] | Unset = UNSET 142 if not isinstance(self.gate, Unset): 143 gate = self.gate.to_dict() 144 145 paper: dict[str, Any] | Unset = UNSET 146 if not isinstance(self.paper, Unset): 147 paper = self.paper.to_dict() 148 149 stats: dict[str, Any] | Unset = UNSET 150 if not isinstance(self.stats, Unset): 151 stats = self.stats.to_dict() 152 153 field_dict: dict[str, Any] = {} 154 field_dict.update(self.additional_properties) 155 field_dict.update( 156 { 157 "strategyId": strategy_id, 158 "runId": run_id, 159 "visibility": visibility, 160 "stage": stage, 161 "state": state, 162 "desired": desired, 163 "sources": sources, 164 "params": params, 165 "paramsVersion": params_version, 166 "relay": relay, 167 "startedAtMs": started_at_ms, 168 } 169 ) 170 if name is not UNSET: 171 field_dict["name"] = name 172 if description is not UNSET: 173 field_dict["description"] = description 174 if reason is not UNSET: 175 field_dict["reason"] = reason 176 if gate is not UNSET: 177 field_dict["gate"] = gate 178 if paper is not UNSET: 179 field_dict["paper"] = paper 180 if stats is not UNSET: 181 field_dict["stats"] = stats 182 183 return field_dict
185 @classmethod 186 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 187 from ..models.live_paper_config import LivePaperConfig 188 from ..models.live_run_gate import LiveRunGate 189 from ..models.live_run_params import LiveRunParams 190 from ..models.live_run_stats import LiveRunStats 191 from ..models.live_source import LiveSource 192 193 d = dict(src_dict) 194 strategy_id = d.pop("strategyId") 195 196 run_id = d.pop("runId") 197 198 visibility = LiveRunVisibility(d.pop("visibility")) 199 200 stage = LiveRunStage(d.pop("stage")) 201 202 state = d.pop("state") 203 204 desired = LiveRunDesired(d.pop("desired")) 205 206 sources = [] 207 _sources = d.pop("sources") 208 for sources_item_data in _sources: 209 sources_item = LiveSource.from_dict(sources_item_data) 210 211 sources.append(sources_item) 212 213 params = LiveRunParams.from_dict(d.pop("params")) 214 215 params_version = d.pop("paramsVersion") 216 217 relay = d.pop("relay") 218 219 started_at_ms = d.pop("startedAtMs") 220 221 name = d.pop("name", UNSET) 222 223 description = d.pop("description", UNSET) 224 225 reason = d.pop("reason", UNSET) 226 227 _gate = d.pop("gate", UNSET) 228 gate: LiveRunGate | Unset 229 if isinstance(_gate, Unset): 230 gate = UNSET 231 else: 232 gate = LiveRunGate.from_dict(_gate) 233 234 _paper = d.pop("paper", UNSET) 235 paper: LivePaperConfig | Unset 236 if isinstance(_paper, Unset): 237 paper = UNSET 238 else: 239 paper = LivePaperConfig.from_dict(_paper) 240 241 _stats = d.pop("stats", UNSET) 242 stats: LiveRunStats | Unset 243 if isinstance(_stats, Unset): 244 stats = UNSET 245 else: 246 stats = LiveRunStats.from_dict(_stats) 247 248 live_run = cls( 249 strategy_id=strategy_id, 250 run_id=run_id, 251 visibility=visibility, 252 stage=stage, 253 state=state, 254 desired=desired, 255 sources=sources, 256 params=params, 257 params_version=params_version, 258 relay=relay, 259 started_at_ms=started_at_ms, 260 name=name, 261 description=description, 262 reason=reason, 263 gate=gate, 264 paper=paper, 265 stats=stats, 266 ) 267 268 live_run.additional_properties = d 269 return live_run
21@_attrs_define 22class LiveRunCompact: 23 """A run's state as returned by `PATCH /live/{runId}` — narrower than `LiveRun` (no `strategyId`, `params`, or 24 `desired`), since this endpoint is addressed by `runId` alone. 25 26 Attributes: 27 run_id (str): 28 visibility (LiveRunCompactVisibility): 29 stage (LiveRunCompactStage): 30 state (str): 31 sources (list[LiveSource]): 32 name (str | Unset): 33 description (str | Unset): 34 """ 35 36 run_id: str 37 visibility: LiveRunCompactVisibility 38 stage: LiveRunCompactStage 39 state: str 40 sources: list[LiveSource] 41 name: str | Unset = UNSET 42 description: str | Unset = UNSET 43 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 44 45 def to_dict(self) -> dict[str, Any]: 46 run_id = self.run_id 47 48 visibility = self.visibility.value 49 50 stage = self.stage.value 51 52 state = self.state 53 54 sources = [] 55 for sources_item_data in self.sources: 56 sources_item = sources_item_data.to_dict() 57 sources.append(sources_item) 58 59 name = self.name 60 61 description = self.description 62 63 field_dict: dict[str, Any] = {} 64 field_dict.update(self.additional_properties) 65 field_dict.update( 66 { 67 "runId": run_id, 68 "visibility": visibility, 69 "stage": stage, 70 "state": state, 71 "sources": sources, 72 } 73 ) 74 if name is not UNSET: 75 field_dict["name"] = name 76 if description is not UNSET: 77 field_dict["description"] = description 78 79 return field_dict 80 81 @classmethod 82 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 83 from ..models.live_source import LiveSource 84 85 d = dict(src_dict) 86 run_id = d.pop("runId") 87 88 visibility = LiveRunCompactVisibility(d.pop("visibility")) 89 90 stage = LiveRunCompactStage(d.pop("stage")) 91 92 state = d.pop("state") 93 94 sources = [] 95 _sources = d.pop("sources") 96 for sources_item_data in _sources: 97 sources_item = LiveSource.from_dict(sources_item_data) 98 99 sources.append(sources_item) 100 101 name = d.pop("name", UNSET) 102 103 description = d.pop("description", UNSET) 104 105 live_run_compact = cls( 106 run_id=run_id, 107 visibility=visibility, 108 stage=stage, 109 state=state, 110 sources=sources, 111 name=name, 112 description=description, 113 ) 114 115 live_run_compact.additional_properties = d 116 return live_run_compact 117 118 @property 119 def additional_keys(self) -> list[str]: 120 return list(self.additional_properties.keys()) 121 122 def __getitem__(self, key: str) -> Any: 123 return self.additional_properties[key] 124 125 def __setitem__(self, key: str, value: Any) -> None: 126 self.additional_properties[key] = value 127 128 def __delitem__(self, key: str) -> None: 129 del self.additional_properties[key] 130 131 def __contains__(self, key: str) -> bool: 132 return key in self.additional_properties
A run's state as returned by PATCH /live/{runId} — narrower than LiveRun (no strategyId, params, or
desired), since this endpoint is addressed by runId alone.
Attributes:
run_id (str):
visibility (LiveRunCompactVisibility):
stage (LiveRunCompactStage):
state (str):
sources (list[LiveSource]):
name (str | Unset):
description (str | Unset):
30def __init__(self, run_id, visibility, stage, state, sources, name=attr_dict['name'].default, description=attr_dict['description'].default): 31 self.run_id = run_id 32 self.visibility = visibility 33 self.stage = stage 34 self.state = state 35 self.sources = sources 36 self.name = name 37 self.description = description 38 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveRunCompact.
45 def to_dict(self) -> dict[str, Any]: 46 run_id = self.run_id 47 48 visibility = self.visibility.value 49 50 stage = self.stage.value 51 52 state = self.state 53 54 sources = [] 55 for sources_item_data in self.sources: 56 sources_item = sources_item_data.to_dict() 57 sources.append(sources_item) 58 59 name = self.name 60 61 description = self.description 62 63 field_dict: dict[str, Any] = {} 64 field_dict.update(self.additional_properties) 65 field_dict.update( 66 { 67 "runId": run_id, 68 "visibility": visibility, 69 "stage": stage, 70 "state": state, 71 "sources": sources, 72 } 73 ) 74 if name is not UNSET: 75 field_dict["name"] = name 76 if description is not UNSET: 77 field_dict["description"] = description 78 79 return field_dict
81 @classmethod 82 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 83 from ..models.live_source import LiveSource 84 85 d = dict(src_dict) 86 run_id = d.pop("runId") 87 88 visibility = LiveRunCompactVisibility(d.pop("visibility")) 89 90 stage = LiveRunCompactStage(d.pop("stage")) 91 92 state = d.pop("state") 93 94 sources = [] 95 _sources = d.pop("sources") 96 for sources_item_data in _sources: 97 sources_item = LiveSource.from_dict(sources_item_data) 98 99 sources.append(sources_item) 100 101 name = d.pop("name", UNSET) 102 103 description = d.pop("description", UNSET) 104 105 live_run_compact = cls( 106 run_id=run_id, 107 visibility=visibility, 108 stage=stage, 109 state=state, 110 sources=sources, 111 name=name, 112 description=description, 113 ) 114 115 live_run_compact.additional_properties = d 116 return live_run_compact
5class LiveRunCompactStage(str, Enum): 6 LIVE = "LIVE" 7 SANDBOX = "SANDBOX" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveRunCompactVisibility(str, Enum): 6 PRIVATE = "private" 7 PUBLIC = "public" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveRunDesired(str, Enum): 6 RUNNING = "RUNNING" 7 STOPPED = "STOPPED" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
26@_attrs_define 27class LiveRunDetail: 28 """A run as returned by `GET /live/{runId}`, the full state of `LiveRun` plus when it last changed. 29 30 Attributes: 31 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 32 always yields the same id, for every caller. How much formatting the id ignores depends on 33 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 34 not. 35 Example: 6bsh31ikwkuivhtgcoa6s4. 36 run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET 37 /live/public`. 38 visibility (LiveRunVisibility): 39 stage (LiveRunStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a second 40 execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically when the 41 24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts `LIVE`, 42 unless you started it with `sandbox: true`. 43 state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING` 44 (behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call 45 for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different 46 signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`. 47 `LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a 48 running run with something to look at. See the Live execution guide. 49 desired (LiveRunDesired): What you last asked for. `state` can lag this briefly after `DELETE`. 50 sources (list[LiveSource]): 51 params (LiveRunParams): 52 params_version (int): Increments on every accepted `PUT .../params` call, including one that resends the current 53 values. 54 relay (bool): Whether this run's signals are relayed over the WebSocket channel described in the "Live 55 execution" guide. It is the value requested at start, in either stage. 56 started_at_ms (int): Epoch milliseconds. 57 updated_at_ms (int): Epoch milliseconds of the run's last change, from any cause. It only moves forward, so of 58 two reads of the same run the one with the larger value is the newer. 59 name (str | Unset): 60 description (str | Unset): 61 reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is 62 never a 63 stack trace or an internal message. Either `resource: ...` (the platform stopped the run for 64 exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for 65 a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's 66 definition was refused, the run could not start after several attempts, the strategy failed while 67 processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow: 68 read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays 69 `desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your 70 live-run limit) until then; one that can never run because its strategy cannot consume its source 71 type is stopped by the platform itself (`desired: STOPPED`), so it holds no place. 72 gate (LiveRunGate | Unset): The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and 73 present once it ends, so an absent `gate` means the trial has not finished. A run that started in `LIVE` without 74 a trial has it from the start: the verdict of the earlier run it relies on, with `inheritedFrom` naming that 75 run. `passed` is the verdict; the rest is diagnostic detail whose shape is not yet stabilized as public API: 76 treat it as opaque. 77 paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's `baseConfig` 78 (same fields, 79 defaults and limits), plus `output`. An empty object takes every default. Each quote 80 currency the run trades gets its own simulated account, opened with `initialFunding` in 81 that currency; accounts are never added together. As returned on a run, the block is 82 normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled 83 in. 84 stats (LiveRunStats | Unset): What a run has been doing, as of its last snapshot. The platform refreshes it 85 about once a minute 86 while the run is being executed, so `opsPerSecond` is an average over that interval, not an 87 instantaneous rate. 88 warm_from (int | Unset): The `warmFrom` in effect for this run, in seconds: the one requested when the run was 89 started or, when none was, the one the platform chose (the distance from the run's start back to the start of 90 the current 15-minute block, 0 to 900). It is never `null`. It is present on every run started since the field 91 exists and absent from a run started before it existed. It never changes while the run exists. 92 """ 93 94 strategy_id: str 95 run_id: str 96 visibility: LiveRunVisibility 97 stage: LiveRunStage 98 state: str 99 desired: LiveRunDesired 100 sources: list[LiveSource] 101 params: LiveRunParams 102 params_version: int 103 relay: bool 104 started_at_ms: int 105 updated_at_ms: int 106 name: str | Unset = UNSET 107 description: str | Unset = UNSET 108 reason: str | Unset = UNSET 109 gate: LiveRunGate | Unset = UNSET 110 paper: LivePaperConfig | Unset = UNSET 111 stats: LiveRunStats | Unset = UNSET 112 warm_from: int | Unset = UNSET 113 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 114 115 def to_dict(self) -> dict[str, Any]: 116 strategy_id = self.strategy_id 117 118 run_id = self.run_id 119 120 visibility = self.visibility.value 121 122 stage = self.stage.value 123 124 state = self.state 125 126 desired = self.desired.value 127 128 sources = [] 129 for sources_item_data in self.sources: 130 sources_item = sources_item_data.to_dict() 131 sources.append(sources_item) 132 133 params = self.params.to_dict() 134 135 params_version = self.params_version 136 137 relay = self.relay 138 139 started_at_ms = self.started_at_ms 140 141 updated_at_ms = self.updated_at_ms 142 143 name = self.name 144 145 description = self.description 146 147 reason = self.reason 148 149 gate: dict[str, Any] | Unset = UNSET 150 if not isinstance(self.gate, Unset): 151 gate = self.gate.to_dict() 152 153 paper: dict[str, Any] | Unset = UNSET 154 if not isinstance(self.paper, Unset): 155 paper = self.paper.to_dict() 156 157 stats: dict[str, Any] | Unset = UNSET 158 if not isinstance(self.stats, Unset): 159 stats = self.stats.to_dict() 160 161 warm_from = self.warm_from 162 163 field_dict: dict[str, Any] = {} 164 field_dict.update(self.additional_properties) 165 field_dict.update( 166 { 167 "strategyId": strategy_id, 168 "runId": run_id, 169 "visibility": visibility, 170 "stage": stage, 171 "state": state, 172 "desired": desired, 173 "sources": sources, 174 "params": params, 175 "paramsVersion": params_version, 176 "relay": relay, 177 "startedAtMs": started_at_ms, 178 "updatedAtMs": updated_at_ms, 179 } 180 ) 181 if name is not UNSET: 182 field_dict["name"] = name 183 if description is not UNSET: 184 field_dict["description"] = description 185 if reason is not UNSET: 186 field_dict["reason"] = reason 187 if gate is not UNSET: 188 field_dict["gate"] = gate 189 if paper is not UNSET: 190 field_dict["paper"] = paper 191 if stats is not UNSET: 192 field_dict["stats"] = stats 193 if warm_from is not UNSET: 194 field_dict["warmFrom"] = warm_from 195 196 return field_dict 197 198 @classmethod 199 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 200 from ..models.live_paper_config import LivePaperConfig 201 from ..models.live_run_gate import LiveRunGate 202 from ..models.live_run_params import LiveRunParams 203 from ..models.live_run_stats import LiveRunStats 204 from ..models.live_source import LiveSource 205 206 d = dict(src_dict) 207 strategy_id = d.pop("strategyId") 208 209 run_id = d.pop("runId") 210 211 visibility = LiveRunVisibility(d.pop("visibility")) 212 213 stage = LiveRunStage(d.pop("stage")) 214 215 state = d.pop("state") 216 217 desired = LiveRunDesired(d.pop("desired")) 218 219 sources = [] 220 _sources = d.pop("sources") 221 for sources_item_data in _sources: 222 sources_item = LiveSource.from_dict(sources_item_data) 223 224 sources.append(sources_item) 225 226 params = LiveRunParams.from_dict(d.pop("params")) 227 228 params_version = d.pop("paramsVersion") 229 230 relay = d.pop("relay") 231 232 started_at_ms = d.pop("startedAtMs") 233 234 updated_at_ms = d.pop("updatedAtMs") 235 236 name = d.pop("name", UNSET) 237 238 description = d.pop("description", UNSET) 239 240 reason = d.pop("reason", UNSET) 241 242 _gate = d.pop("gate", UNSET) 243 gate: LiveRunGate | Unset 244 if isinstance(_gate, Unset): 245 gate = UNSET 246 else: 247 gate = LiveRunGate.from_dict(_gate) 248 249 _paper = d.pop("paper", UNSET) 250 paper: LivePaperConfig | Unset 251 if isinstance(_paper, Unset): 252 paper = UNSET 253 else: 254 paper = LivePaperConfig.from_dict(_paper) 255 256 _stats = d.pop("stats", UNSET) 257 stats: LiveRunStats | Unset 258 if isinstance(_stats, Unset): 259 stats = UNSET 260 else: 261 stats = LiveRunStats.from_dict(_stats) 262 263 warm_from = d.pop("warmFrom", UNSET) 264 265 live_run_detail = cls( 266 strategy_id=strategy_id, 267 run_id=run_id, 268 visibility=visibility, 269 stage=stage, 270 state=state, 271 desired=desired, 272 sources=sources, 273 params=params, 274 params_version=params_version, 275 relay=relay, 276 started_at_ms=started_at_ms, 277 updated_at_ms=updated_at_ms, 278 name=name, 279 description=description, 280 reason=reason, 281 gate=gate, 282 paper=paper, 283 stats=stats, 284 warm_from=warm_from, 285 ) 286 287 live_run_detail.additional_properties = d 288 return live_run_detail 289 290 @property 291 def additional_keys(self) -> list[str]: 292 return list(self.additional_properties.keys()) 293 294 def __getitem__(self, key: str) -> Any: 295 return self.additional_properties[key] 296 297 def __setitem__(self, key: str, value: Any) -> None: 298 self.additional_properties[key] = value 299 300 def __delitem__(self, key: str) -> None: 301 del self.additional_properties[key] 302 303 def __contains__(self, key: str) -> bool: 304 return key in self.additional_properties
A run as returned by GET /live/{runId}, the full state of LiveRun plus when it last changed.
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see POST /strategy for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
run_id (str): This run's own id — its canonical identity for PATCH/PUT .../params and for GET
/live/public.
visibility (LiveRunVisibility):
stage (LiveRunStage): A new run starts SANDBOX, a 24-hour trial in which it is compared against a second
execution and checked for resource use and stability. A run that passes moves to LIVE automatically when the
24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts LIVE,
unless you started it with sandbox: true.
state (str): The run's health right now: STARTING (no runner has reported on it yet), RUNNING, LAGGING
(behind the market data, usually while catching up; clears by itself), HUNG (stuck inside one strategy call
for longer than allowed; clears when it returns), DEGRADED (its independent executions produced different
signals), FAILED (refused, could not start or failed while running; reason says why) or STOPPED.
LAGGING, HUNG and DEGRADED come and go on a running run. The set may grow: read an unknown value as a
running run with something to look at. See the Live execution guide.
desired (LiveRunDesired): What you last asked for. state can lag this briefly after DELETE.
sources (list[LiveSource]):
params (LiveRunParams):
params_version (int): Increments on every accepted PUT .../params call, including one that resends the current
values.
relay (bool): Whether this run's signals are relayed over the WebSocket channel described in the "Live
execution" guide. It is the value requested at start, in either stage.
started_at_ms (int): Epoch milliseconds.
updated_at_ms (int): Epoch milliseconds of the run's last change, from any cause. It only moves forward, so of
two reads of the same run the one with the larger value is the newer.
name (str | Unset):
description (str | Unset):
reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is
never a
stack trace or an internal message. Either resource: ... (the platform stopped the run for
exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for
a FAILED run: the strategy cannot consume the source type the run was started with, the run's
definition was refused, the run could not start after several attempts, the strategy failed while
processing data, the run lost its data feed, or the generic The run failed.. The set may grow:
read an unrecognised sentence as a failure and do not parse it. A FAILED run usually stays
desired: RUNNING until you stop it, and counts as active (409 on a new start, and toward your
live-run limit) until then; one that can never run because its strategy cannot consume its source
type is stopped by the platform itself (desired: STOPPED), so it holds no place.
gate (LiveRunGate | Unset): The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and
present once it ends, so an absent gate means the trial has not finished. A run that started in LIVE without
a trial has it from the start: the verdict of the earlier run it relies on, with inheritedFrom naming that
run. passed is the verdict; the rest is diagnostic detail whose shape is not yet stabilized as public API:
treat it as opaque.
paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's baseConfig
(same fields,
defaults and limits), plus output. An empty object takes every default. Each quote
currency the run trades gets its own simulated account, opened with initialFunding in
that currency; accounts are never added together. As returned on a run, the block is
normalised: feeRate is resolved into buyFeeRate/sellFeeRate and defaults are filled
in.
stats (LiveRunStats | Unset): What a run has been doing, as of its last snapshot. The platform refreshes it
about once a minute
while the run is being executed, so opsPerSecond is an average over that interval, not an
instantaneous rate.
warm_from (int | Unset): The warmFrom in effect for this run, in seconds: the one requested when the run was
started or, when none was, the one the platform chose (the distance from the run's start back to the start of
the current 15-minute block, 0 to 900). It is never null. It is present on every run started since the field
exists and absent from a run started before it existed. It never changes while the run exists.
42def __init__(self, strategy_id, run_id, visibility, stage, state, desired, sources, params, params_version, relay, started_at_ms, updated_at_ms, name=attr_dict['name'].default, description=attr_dict['description'].default, reason=attr_dict['reason'].default, gate=attr_dict['gate'].default, paper=attr_dict['paper'].default, stats=attr_dict['stats'].default, warm_from=attr_dict['warm_from'].default): 43 self.strategy_id = strategy_id 44 self.run_id = run_id 45 self.visibility = visibility 46 self.stage = stage 47 self.state = state 48 self.desired = desired 49 self.sources = sources 50 self.params = params 51 self.params_version = params_version 52 self.relay = relay 53 self.started_at_ms = started_at_ms 54 self.updated_at_ms = updated_at_ms 55 self.name = name 56 self.description = description 57 self.reason = reason 58 self.gate = gate 59 self.paper = paper 60 self.stats = stats 61 self.warm_from = warm_from 62 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveRunDetail.
115 def to_dict(self) -> dict[str, Any]: 116 strategy_id = self.strategy_id 117 118 run_id = self.run_id 119 120 visibility = self.visibility.value 121 122 stage = self.stage.value 123 124 state = self.state 125 126 desired = self.desired.value 127 128 sources = [] 129 for sources_item_data in self.sources: 130 sources_item = sources_item_data.to_dict() 131 sources.append(sources_item) 132 133 params = self.params.to_dict() 134 135 params_version = self.params_version 136 137 relay = self.relay 138 139 started_at_ms = self.started_at_ms 140 141 updated_at_ms = self.updated_at_ms 142 143 name = self.name 144 145 description = self.description 146 147 reason = self.reason 148 149 gate: dict[str, Any] | Unset = UNSET 150 if not isinstance(self.gate, Unset): 151 gate = self.gate.to_dict() 152 153 paper: dict[str, Any] | Unset = UNSET 154 if not isinstance(self.paper, Unset): 155 paper = self.paper.to_dict() 156 157 stats: dict[str, Any] | Unset = UNSET 158 if not isinstance(self.stats, Unset): 159 stats = self.stats.to_dict() 160 161 warm_from = self.warm_from 162 163 field_dict: dict[str, Any] = {} 164 field_dict.update(self.additional_properties) 165 field_dict.update( 166 { 167 "strategyId": strategy_id, 168 "runId": run_id, 169 "visibility": visibility, 170 "stage": stage, 171 "state": state, 172 "desired": desired, 173 "sources": sources, 174 "params": params, 175 "paramsVersion": params_version, 176 "relay": relay, 177 "startedAtMs": started_at_ms, 178 "updatedAtMs": updated_at_ms, 179 } 180 ) 181 if name is not UNSET: 182 field_dict["name"] = name 183 if description is not UNSET: 184 field_dict["description"] = description 185 if reason is not UNSET: 186 field_dict["reason"] = reason 187 if gate is not UNSET: 188 field_dict["gate"] = gate 189 if paper is not UNSET: 190 field_dict["paper"] = paper 191 if stats is not UNSET: 192 field_dict["stats"] = stats 193 if warm_from is not UNSET: 194 field_dict["warmFrom"] = warm_from 195 196 return field_dict
198 @classmethod 199 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 200 from ..models.live_paper_config import LivePaperConfig 201 from ..models.live_run_gate import LiveRunGate 202 from ..models.live_run_params import LiveRunParams 203 from ..models.live_run_stats import LiveRunStats 204 from ..models.live_source import LiveSource 205 206 d = dict(src_dict) 207 strategy_id = d.pop("strategyId") 208 209 run_id = d.pop("runId") 210 211 visibility = LiveRunVisibility(d.pop("visibility")) 212 213 stage = LiveRunStage(d.pop("stage")) 214 215 state = d.pop("state") 216 217 desired = LiveRunDesired(d.pop("desired")) 218 219 sources = [] 220 _sources = d.pop("sources") 221 for sources_item_data in _sources: 222 sources_item = LiveSource.from_dict(sources_item_data) 223 224 sources.append(sources_item) 225 226 params = LiveRunParams.from_dict(d.pop("params")) 227 228 params_version = d.pop("paramsVersion") 229 230 relay = d.pop("relay") 231 232 started_at_ms = d.pop("startedAtMs") 233 234 updated_at_ms = d.pop("updatedAtMs") 235 236 name = d.pop("name", UNSET) 237 238 description = d.pop("description", UNSET) 239 240 reason = d.pop("reason", UNSET) 241 242 _gate = d.pop("gate", UNSET) 243 gate: LiveRunGate | Unset 244 if isinstance(_gate, Unset): 245 gate = UNSET 246 else: 247 gate = LiveRunGate.from_dict(_gate) 248 249 _paper = d.pop("paper", UNSET) 250 paper: LivePaperConfig | Unset 251 if isinstance(_paper, Unset): 252 paper = UNSET 253 else: 254 paper = LivePaperConfig.from_dict(_paper) 255 256 _stats = d.pop("stats", UNSET) 257 stats: LiveRunStats | Unset 258 if isinstance(_stats, Unset): 259 stats = UNSET 260 else: 261 stats = LiveRunStats.from_dict(_stats) 262 263 warm_from = d.pop("warmFrom", UNSET) 264 265 live_run_detail = cls( 266 strategy_id=strategy_id, 267 run_id=run_id, 268 visibility=visibility, 269 stage=stage, 270 state=state, 271 desired=desired, 272 sources=sources, 273 params=params, 274 params_version=params_version, 275 relay=relay, 276 started_at_ms=started_at_ms, 277 updated_at_ms=updated_at_ms, 278 name=name, 279 description=description, 280 reason=reason, 281 gate=gate, 282 paper=paper, 283 stats=stats, 284 warm_from=warm_from, 285 ) 286 287 live_run_detail.additional_properties = d 288 return live_run_detail
13@_attrs_define 14class LiveRunGate: 15 """The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and present once it ends, so an absent 16 `gate` means the trial has not finished. A run that started in `LIVE` without a trial has it from the start: the 17 verdict of the earlier run it relies on, with `inheritedFrom` naming that run. `passed` is the verdict; the rest is 18 diagnostic detail whose shape is not yet stabilized as public API: treat it as opaque. 19 20 """ 21 22 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 23 24 def to_dict(self) -> dict[str, Any]: 25 26 field_dict: dict[str, Any] = {} 27 field_dict.update(self.additional_properties) 28 29 return field_dict 30 31 @classmethod 32 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 33 d = dict(src_dict) 34 live_run_gate = cls() 35 36 live_run_gate.additional_properties = d 37 return live_run_gate 38 39 @property 40 def additional_keys(self) -> list[str]: 41 return list(self.additional_properties.keys()) 42 43 def __getitem__(self, key: str) -> Any: 44 return self.additional_properties[key] 45 46 def __setitem__(self, key: str, value: Any) -> None: 47 self.additional_properties[key] = value 48 49 def __delitem__(self, key: str) -> None: 50 del self.additional_properties[key] 51 52 def __contains__(self, key: str) -> bool: 53 return key in self.additional_properties
The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and present once it ends, so an absent
gate means the trial has not finished. A run that started in LIVE without a trial has it from the start: the
verdict of the earlier run it relies on, with inheritedFrom naming that run. passed is the verdict; the rest is
diagnostic detail whose shape is not yet stabilized as public API: treat it as opaque.
13@_attrs_define 14class LiveRunParams: 15 """ """ 16 17 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 18 19 def to_dict(self) -> dict[str, Any]: 20 21 field_dict: dict[str, Any] = {} 22 field_dict.update(self.additional_properties) 23 24 return field_dict 25 26 @classmethod 27 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 28 d = dict(src_dict) 29 live_run_params = cls() 30 31 live_run_params.additional_properties = d 32 return live_run_params 33 34 @property 35 def additional_keys(self) -> list[str]: 36 return list(self.additional_properties.keys()) 37 38 def __getitem__(self, key: str) -> Any: 39 return self.additional_properties[key] 40 41 def __setitem__(self, key: str, value: Any) -> None: 42 self.additional_properties[key] = value 43 44 def __delitem__(self, key: str) -> None: 45 del self.additional_properties[key] 46 47 def __contains__(self, key: str) -> bool: 48 return key in self.additional_properties
5class LiveRunStage(str, Enum): 6 LIVE = "LIVE" 7 SANDBOX = "SANDBOX" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class LiveRunStats: 17 """What a run has been doing, as of its last snapshot. The platform refreshes it about once a minute 18 while the run is being executed, so `opsPerSecond` is an average over that interval, not an 19 instantaneous rate. 20 21 Attributes: 22 processed (int): Updates of instruments the run has accepted since it started executing. It can start again from 23 zero if the run is restarted. 24 ops_per_second (float): Updates accepted per second over the last refresh interval. `0` when none arrived. 25 instruments_seen (int): How many distinct instruments the run has received an update for. 26 as_of_ms (int): Epoch milliseconds when these counters were last written. 27 stale (bool): `true` when the run is meant to be running (`desired` is `RUNNING`) and its counters have not 28 been refreshed for several refresh intervals: the platform has stopped updating them, which is 29 worth checking against `state`. `false` otherwise. A run whose `processed` is flat is not stale; 30 `progressedAtMs` is how to tell it apart. 31 progressed_at_ms (int | Unset): Epoch milliseconds of the last snapshot in which `processed` had grown. Absent 32 until the run has 33 processed anything. A run fed by a source that updates rarely (a funding rate, for example) can 34 stay flat for hours: that is how such a run behaves, not a fault. 35 """ 36 37 processed: int 38 ops_per_second: float 39 instruments_seen: int 40 as_of_ms: int 41 stale: bool 42 progressed_at_ms: int | Unset = UNSET 43 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 44 45 def to_dict(self) -> dict[str, Any]: 46 processed = self.processed 47 48 ops_per_second = self.ops_per_second 49 50 instruments_seen = self.instruments_seen 51 52 as_of_ms = self.as_of_ms 53 54 stale = self.stale 55 56 progressed_at_ms = self.progressed_at_ms 57 58 field_dict: dict[str, Any] = {} 59 field_dict.update(self.additional_properties) 60 field_dict.update( 61 { 62 "processed": processed, 63 "opsPerSecond": ops_per_second, 64 "instrumentsSeen": instruments_seen, 65 "asOfMs": as_of_ms, 66 "stale": stale, 67 } 68 ) 69 if progressed_at_ms is not UNSET: 70 field_dict["progressedAtMs"] = progressed_at_ms 71 72 return field_dict 73 74 @classmethod 75 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 76 d = dict(src_dict) 77 processed = d.pop("processed") 78 79 ops_per_second = d.pop("opsPerSecond") 80 81 instruments_seen = d.pop("instrumentsSeen") 82 83 as_of_ms = d.pop("asOfMs") 84 85 stale = d.pop("stale") 86 87 progressed_at_ms = d.pop("progressedAtMs", UNSET) 88 89 live_run_stats = cls( 90 processed=processed, 91 ops_per_second=ops_per_second, 92 instruments_seen=instruments_seen, 93 as_of_ms=as_of_ms, 94 stale=stale, 95 progressed_at_ms=progressed_at_ms, 96 ) 97 98 live_run_stats.additional_properties = d 99 return live_run_stats 100 101 @property 102 def additional_keys(self) -> list[str]: 103 return list(self.additional_properties.keys()) 104 105 def __getitem__(self, key: str) -> Any: 106 return self.additional_properties[key] 107 108 def __setitem__(self, key: str, value: Any) -> None: 109 self.additional_properties[key] = value 110 111 def __delitem__(self, key: str) -> None: 112 del self.additional_properties[key] 113 114 def __contains__(self, key: str) -> bool: 115 return key in self.additional_properties
What a run has been doing, as of its last snapshot. The platform refreshes it about once a minute
while the run is being executed, so opsPerSecond is an average over that interval, not an
instantaneous rate.
Attributes:
processed (int): Updates of instruments the run has accepted since it started executing. It can start again from
zero if the run is restarted.
ops_per_second (float): Updates accepted per second over the last refresh interval. `0` when none arrived.
instruments_seen (int): How many distinct instruments the run has received an update for.
as_of_ms (int): Epoch milliseconds when these counters were last written.
stale (bool): `true` when the run is meant to be running (`desired` is `RUNNING`) and its counters have not
been refreshed for several refresh intervals: the platform has stopped updating them, which is
worth checking against `state`. `false` otherwise. A run whose `processed` is flat is not stale;
`progressedAtMs` is how to tell it apart.
progressed_at_ms (int | Unset): Epoch milliseconds of the last snapshot in which `processed` had grown. Absent
until the run has
processed anything. A run fed by a source that updates rarely (a funding rate, for example) can
stay flat for hours: that is how such a run behaves, not a fault.
29def __init__(self, processed, ops_per_second, instruments_seen, as_of_ms, stale, progressed_at_ms=attr_dict['progressed_at_ms'].default): 30 self.processed = processed 31 self.ops_per_second = ops_per_second 32 self.instruments_seen = instruments_seen 33 self.as_of_ms = as_of_ms 34 self.stale = stale 35 self.progressed_at_ms = progressed_at_ms 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveRunStats.
45 def to_dict(self) -> dict[str, Any]: 46 processed = self.processed 47 48 ops_per_second = self.ops_per_second 49 50 instruments_seen = self.instruments_seen 51 52 as_of_ms = self.as_of_ms 53 54 stale = self.stale 55 56 progressed_at_ms = self.progressed_at_ms 57 58 field_dict: dict[str, Any] = {} 59 field_dict.update(self.additional_properties) 60 field_dict.update( 61 { 62 "processed": processed, 63 "opsPerSecond": ops_per_second, 64 "instrumentsSeen": instruments_seen, 65 "asOfMs": as_of_ms, 66 "stale": stale, 67 } 68 ) 69 if progressed_at_ms is not UNSET: 70 field_dict["progressedAtMs"] = progressed_at_ms 71 72 return field_dict
74 @classmethod 75 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 76 d = dict(src_dict) 77 processed = d.pop("processed") 78 79 ops_per_second = d.pop("opsPerSecond") 80 81 instruments_seen = d.pop("instrumentsSeen") 82 83 as_of_ms = d.pop("asOfMs") 84 85 stale = d.pop("stale") 86 87 progressed_at_ms = d.pop("progressedAtMs", UNSET) 88 89 live_run_stats = cls( 90 processed=processed, 91 ops_per_second=ops_per_second, 92 instruments_seen=instruments_seen, 93 as_of_ms=as_of_ms, 94 stale=stale, 95 progressed_at_ms=progressed_at_ms, 96 ) 97 98 live_run_stats.additional_properties = d 99 return live_run_stats
22@_attrs_define 23class LiveRunSummary: 24 """A run as it appears in `GET /live` — one of your own, narrower than `LiveRun` (no `params`, `paramsVersion`, 25 `relay`, or `gate`), since listing stays cheap regardless of how many runs you have. Check a specific run's full 26 state with `GET /strategy/{strategyId}/live`. 27 28 Attributes: 29 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 30 always yields the same id, for every caller. How much formatting the id ignores depends on 31 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 32 not. 33 Example: 6bsh31ikwkuivhtgcoa6s4. 34 run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET 35 /live/public`. 36 visibility (LiveRunSummaryVisibility): 37 stage (LiveRunSummaryStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a 38 second execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically 39 when the 24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts 40 `LIVE`, unless you started it with `sandbox: true`. 41 state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING` 42 (behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call 43 for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different 44 signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`. 45 `LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a 46 running run with something to look at. See the Live execution guide. 47 desired (LiveRunSummaryDesired): What you last asked for. `state` can lag this briefly after `DELETE`. 48 sources (list[LiveSource]): 49 created_at_ms (int): Epoch milliseconds this run was started. 50 started_at_ms (int): Epoch milliseconds. 51 name (str | Unset): 52 description (str | Unset): 53 reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is 54 never a 55 stack trace or an internal message. Either `resource: ...` (the platform stopped the run for 56 exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for 57 a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's 58 definition was refused, the run could not start after several attempts, the strategy failed while 59 processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow: 60 read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays 61 `desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your 62 live-run limit) until then; one that can never run because its strategy cannot consume its source 63 type is stopped by the platform itself (`desired: STOPPED`), so it holds no place. 64 """ 65 66 strategy_id: str 67 run_id: str 68 visibility: LiveRunSummaryVisibility 69 stage: LiveRunSummaryStage 70 state: str 71 desired: LiveRunSummaryDesired 72 sources: list[LiveSource] 73 created_at_ms: int 74 started_at_ms: int 75 name: str | Unset = UNSET 76 description: str | Unset = UNSET 77 reason: str | Unset = UNSET 78 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 79 80 def to_dict(self) -> dict[str, Any]: 81 strategy_id = self.strategy_id 82 83 run_id = self.run_id 84 85 visibility = self.visibility.value 86 87 stage = self.stage.value 88 89 state = self.state 90 91 desired = self.desired.value 92 93 sources = [] 94 for sources_item_data in self.sources: 95 sources_item = sources_item_data.to_dict() 96 sources.append(sources_item) 97 98 created_at_ms = self.created_at_ms 99 100 started_at_ms = self.started_at_ms 101 102 name = self.name 103 104 description = self.description 105 106 reason = self.reason 107 108 field_dict: dict[str, Any] = {} 109 field_dict.update(self.additional_properties) 110 field_dict.update( 111 { 112 "strategyId": strategy_id, 113 "runId": run_id, 114 "visibility": visibility, 115 "stage": stage, 116 "state": state, 117 "desired": desired, 118 "sources": sources, 119 "createdAtMs": created_at_ms, 120 "startedAtMs": started_at_ms, 121 } 122 ) 123 if name is not UNSET: 124 field_dict["name"] = name 125 if description is not UNSET: 126 field_dict["description"] = description 127 if reason is not UNSET: 128 field_dict["reason"] = reason 129 130 return field_dict 131 132 @classmethod 133 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 134 from ..models.live_source import LiveSource 135 136 d = dict(src_dict) 137 strategy_id = d.pop("strategyId") 138 139 run_id = d.pop("runId") 140 141 visibility = LiveRunSummaryVisibility(d.pop("visibility")) 142 143 stage = LiveRunSummaryStage(d.pop("stage")) 144 145 state = d.pop("state") 146 147 desired = LiveRunSummaryDesired(d.pop("desired")) 148 149 sources = [] 150 _sources = d.pop("sources") 151 for sources_item_data in _sources: 152 sources_item = LiveSource.from_dict(sources_item_data) 153 154 sources.append(sources_item) 155 156 created_at_ms = d.pop("createdAtMs") 157 158 started_at_ms = d.pop("startedAtMs") 159 160 name = d.pop("name", UNSET) 161 162 description = d.pop("description", UNSET) 163 164 reason = d.pop("reason", UNSET) 165 166 live_run_summary = cls( 167 strategy_id=strategy_id, 168 run_id=run_id, 169 visibility=visibility, 170 stage=stage, 171 state=state, 172 desired=desired, 173 sources=sources, 174 created_at_ms=created_at_ms, 175 started_at_ms=started_at_ms, 176 name=name, 177 description=description, 178 reason=reason, 179 ) 180 181 live_run_summary.additional_properties = d 182 return live_run_summary 183 184 @property 185 def additional_keys(self) -> list[str]: 186 return list(self.additional_properties.keys()) 187 188 def __getitem__(self, key: str) -> Any: 189 return self.additional_properties[key] 190 191 def __setitem__(self, key: str, value: Any) -> None: 192 self.additional_properties[key] = value 193 194 def __delitem__(self, key: str) -> None: 195 del self.additional_properties[key] 196 197 def __contains__(self, key: str) -> bool: 198 return key in self.additional_properties
A run as it appears in GET /live — one of your own, narrower than LiveRun (no params, paramsVersion,
relay, or gate), since listing stays cheap regardless of how many runs you have. Check a specific run's full
state with GET /strategy/{strategyId}/live.
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see `POST /strategy` for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET
/live/public`.
visibility (LiveRunSummaryVisibility):
stage (LiveRunSummaryStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a
second execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically
when the 24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts
`LIVE`, unless you started it with `sandbox: true`.
state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING`
(behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call
for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different
signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`.
`LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a
running run with something to look at. See the Live execution guide.
desired (LiveRunSummaryDesired): What you last asked for. `state` can lag this briefly after `DELETE`.
sources (list[LiveSource]):
created_at_ms (int): Epoch milliseconds this run was started.
started_at_ms (int): Epoch milliseconds.
name (str | Unset):
description (str | Unset):
reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is
never a
stack trace or an internal message. Either `resource: ...` (the platform stopped the run for
exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for
a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's
definition was refused, the run could not start after several attempts, the strategy failed while
processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow:
read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays
`desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your
live-run limit) until then; one that can never run because its strategy cannot consume its source
type is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
35def __init__(self, strategy_id, run_id, visibility, stage, state, desired, sources, created_at_ms, started_at_ms, name=attr_dict['name'].default, description=attr_dict['description'].default, reason=attr_dict['reason'].default): 36 self.strategy_id = strategy_id 37 self.run_id = run_id 38 self.visibility = visibility 39 self.stage = stage 40 self.state = state 41 self.desired = desired 42 self.sources = sources 43 self.created_at_ms = created_at_ms 44 self.started_at_ms = started_at_ms 45 self.name = name 46 self.description = description 47 self.reason = reason 48 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveRunSummary.
80 def to_dict(self) -> dict[str, Any]: 81 strategy_id = self.strategy_id 82 83 run_id = self.run_id 84 85 visibility = self.visibility.value 86 87 stage = self.stage.value 88 89 state = self.state 90 91 desired = self.desired.value 92 93 sources = [] 94 for sources_item_data in self.sources: 95 sources_item = sources_item_data.to_dict() 96 sources.append(sources_item) 97 98 created_at_ms = self.created_at_ms 99 100 started_at_ms = self.started_at_ms 101 102 name = self.name 103 104 description = self.description 105 106 reason = self.reason 107 108 field_dict: dict[str, Any] = {} 109 field_dict.update(self.additional_properties) 110 field_dict.update( 111 { 112 "strategyId": strategy_id, 113 "runId": run_id, 114 "visibility": visibility, 115 "stage": stage, 116 "state": state, 117 "desired": desired, 118 "sources": sources, 119 "createdAtMs": created_at_ms, 120 "startedAtMs": started_at_ms, 121 } 122 ) 123 if name is not UNSET: 124 field_dict["name"] = name 125 if description is not UNSET: 126 field_dict["description"] = description 127 if reason is not UNSET: 128 field_dict["reason"] = reason 129 130 return field_dict
132 @classmethod 133 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 134 from ..models.live_source import LiveSource 135 136 d = dict(src_dict) 137 strategy_id = d.pop("strategyId") 138 139 run_id = d.pop("runId") 140 141 visibility = LiveRunSummaryVisibility(d.pop("visibility")) 142 143 stage = LiveRunSummaryStage(d.pop("stage")) 144 145 state = d.pop("state") 146 147 desired = LiveRunSummaryDesired(d.pop("desired")) 148 149 sources = [] 150 _sources = d.pop("sources") 151 for sources_item_data in _sources: 152 sources_item = LiveSource.from_dict(sources_item_data) 153 154 sources.append(sources_item) 155 156 created_at_ms = d.pop("createdAtMs") 157 158 started_at_ms = d.pop("startedAtMs") 159 160 name = d.pop("name", UNSET) 161 162 description = d.pop("description", UNSET) 163 164 reason = d.pop("reason", UNSET) 165 166 live_run_summary = cls( 167 strategy_id=strategy_id, 168 run_id=run_id, 169 visibility=visibility, 170 stage=stage, 171 state=state, 172 desired=desired, 173 sources=sources, 174 created_at_ms=created_at_ms, 175 started_at_ms=started_at_ms, 176 name=name, 177 description=description, 178 reason=reason, 179 ) 180 181 live_run_summary.additional_properties = d 182 return live_run_summary
5class LiveRunSummaryDesired(str, Enum): 6 RUNNING = "RUNNING" 7 STOPPED = "STOPPED" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveRunSummaryStage(str, Enum): 6 LIVE = "LIVE" 7 SANDBOX = "SANDBOX" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveRunSummaryVisibility(str, Enum): 6 PRIVATE = "private" 7 PUBLIC = "public" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveRunVisibility(str, Enum): 6 PRIVATE = "private" 7 PUBLIC = "public" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
26@_attrs_define 27class LiveRunWithStream: 28 """A run as `LiveRun` describes it, plus its `warmFrom` (absent only for a run started before the field existed) and 29 its `streamUrl` when it has one. It is what **starting a run** and 30 `GET /strategy/{strategyId}/live` return: your own run, read with your own credentials. Stopping a run 31 returns `LiveRun`, which carries neither `warmFrom` nor the URL, and `GET /live/{runId}` returns `LiveRunDetail`, 32 which carries `warmFrom` and never the URL. 33 34 Attributes: 35 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 36 always yields the same id, for every caller. How much formatting the id ignores depends on 37 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 38 not. 39 Example: 6bsh31ikwkuivhtgcoa6s4. 40 run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET 41 /live/public`. 42 visibility (LiveRunVisibility): 43 stage (LiveRunStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a second 44 execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically when the 45 24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts `LIVE`, 46 unless you started it with `sandbox: true`. 47 state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING` 48 (behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call 49 for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different 50 signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`. 51 `LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a 52 running run with something to look at. See the Live execution guide. 53 desired (LiveRunDesired): What you last asked for. `state` can lag this briefly after `DELETE`. 54 sources (list[LiveSource]): 55 params (LiveRunParams): 56 params_version (int): Increments on every accepted `PUT .../params` call, including one that resends the current 57 values. 58 relay (bool): Whether this run's signals are relayed over the WebSocket channel described in the "Live 59 execution" guide. It is the value requested at start, in either stage. 60 started_at_ms (int): Epoch milliseconds. 61 name (str | Unset): 62 description (str | Unset): 63 reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is 64 never a 65 stack trace or an internal message. Either `resource: ...` (the platform stopped the run for 66 exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for 67 a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's 68 definition was refused, the run could not start after several attempts, the strategy failed while 69 processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow: 70 read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays 71 `desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your 72 live-run limit) until then; one that can never run because its strategy cannot consume its source 73 type is stopped by the platform itself (`desired: STOPPED`), so it holds no place. 74 gate (LiveRunGate | Unset): The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and 75 present once it ends, so an absent `gate` means the trial has not finished. A run that started in `LIVE` without 76 a trial has it from the start: the verdict of the earlier run it relies on, with `inheritedFrom` naming that 77 run. `passed` is the verdict; the rest is diagnostic detail whose shape is not yet stabilized as public API: 78 treat it as opaque. 79 paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's `baseConfig` 80 (same fields, 81 defaults and limits), plus `output`. An empty object takes every default. Each quote 82 currency the run trades gets its own simulated account, opened with `initialFunding` in 83 that currency; accounts are never added together. As returned on a run, the block is 84 normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled 85 in. 86 stats (LiveRunStats | Unset): What a run has been doing, as of its last snapshot. The platform refreshes it 87 about once a minute 88 while the run is being executed, so `opsPerSecond` is an average over that interval, not an 89 instantaneous rate. 90 warm_from (int | Unset): The `warmFrom` in effect for this run, in seconds: the one requested when the run was 91 started or, when none was, the one the platform chose (the distance from the run's start back to the start of 92 the current 15-minute block, 0 to 900). It is never `null`. It is present on every run started since the field 93 exists and absent from a run started before it existed. It never changes while the run exists. 94 stream_url (str | Unset): The run's secret stream URL (`wss://…`). **Treat it like a password**: anyone who 95 holds it can read 96 this run's signals, from the sandbox stage on. Present only when the run was started with 97 `stream: true`, is wanted running, has not had its stream revoked, and your plan still lets you 98 broadcast; absent otherwise (a plan that lets you broadcast again gets the same URL back). Rotate 99 it with `POST /live/{runId}/stream` if it leaks, revoke it with `DELETE /live/{runId}/stream`. 100 """ 101 102 strategy_id: str 103 run_id: str 104 visibility: LiveRunVisibility 105 stage: LiveRunStage 106 state: str 107 desired: LiveRunDesired 108 sources: list[LiveSource] 109 params: LiveRunParams 110 params_version: int 111 relay: bool 112 started_at_ms: int 113 name: str | Unset = UNSET 114 description: str | Unset = UNSET 115 reason: str | Unset = UNSET 116 gate: LiveRunGate | Unset = UNSET 117 paper: LivePaperConfig | Unset = UNSET 118 stats: LiveRunStats | Unset = UNSET 119 warm_from: int | Unset = UNSET 120 stream_url: str | Unset = UNSET 121 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 122 123 def to_dict(self) -> dict[str, Any]: 124 strategy_id = self.strategy_id 125 126 run_id = self.run_id 127 128 visibility = self.visibility.value 129 130 stage = self.stage.value 131 132 state = self.state 133 134 desired = self.desired.value 135 136 sources = [] 137 for sources_item_data in self.sources: 138 sources_item = sources_item_data.to_dict() 139 sources.append(sources_item) 140 141 params = self.params.to_dict() 142 143 params_version = self.params_version 144 145 relay = self.relay 146 147 started_at_ms = self.started_at_ms 148 149 name = self.name 150 151 description = self.description 152 153 reason = self.reason 154 155 gate: dict[str, Any] | Unset = UNSET 156 if not isinstance(self.gate, Unset): 157 gate = self.gate.to_dict() 158 159 paper: dict[str, Any] | Unset = UNSET 160 if not isinstance(self.paper, Unset): 161 paper = self.paper.to_dict() 162 163 stats: dict[str, Any] | Unset = UNSET 164 if not isinstance(self.stats, Unset): 165 stats = self.stats.to_dict() 166 167 warm_from = self.warm_from 168 169 stream_url = self.stream_url 170 171 field_dict: dict[str, Any] = {} 172 field_dict.update(self.additional_properties) 173 field_dict.update( 174 { 175 "strategyId": strategy_id, 176 "runId": run_id, 177 "visibility": visibility, 178 "stage": stage, 179 "state": state, 180 "desired": desired, 181 "sources": sources, 182 "params": params, 183 "paramsVersion": params_version, 184 "relay": relay, 185 "startedAtMs": started_at_ms, 186 } 187 ) 188 if name is not UNSET: 189 field_dict["name"] = name 190 if description is not UNSET: 191 field_dict["description"] = description 192 if reason is not UNSET: 193 field_dict["reason"] = reason 194 if gate is not UNSET: 195 field_dict["gate"] = gate 196 if paper is not UNSET: 197 field_dict["paper"] = paper 198 if stats is not UNSET: 199 field_dict["stats"] = stats 200 if warm_from is not UNSET: 201 field_dict["warmFrom"] = warm_from 202 if stream_url is not UNSET: 203 field_dict["streamUrl"] = stream_url 204 205 return field_dict 206 207 @classmethod 208 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 209 from ..models.live_paper_config import LivePaperConfig 210 from ..models.live_run_gate import LiveRunGate 211 from ..models.live_run_params import LiveRunParams 212 from ..models.live_run_stats import LiveRunStats 213 from ..models.live_source import LiveSource 214 215 d = dict(src_dict) 216 strategy_id = d.pop("strategyId") 217 218 run_id = d.pop("runId") 219 220 visibility = LiveRunVisibility(d.pop("visibility")) 221 222 stage = LiveRunStage(d.pop("stage")) 223 224 state = d.pop("state") 225 226 desired = LiveRunDesired(d.pop("desired")) 227 228 sources = [] 229 _sources = d.pop("sources") 230 for sources_item_data in _sources: 231 sources_item = LiveSource.from_dict(sources_item_data) 232 233 sources.append(sources_item) 234 235 params = LiveRunParams.from_dict(d.pop("params")) 236 237 params_version = d.pop("paramsVersion") 238 239 relay = d.pop("relay") 240 241 started_at_ms = d.pop("startedAtMs") 242 243 name = d.pop("name", UNSET) 244 245 description = d.pop("description", UNSET) 246 247 reason = d.pop("reason", UNSET) 248 249 _gate = d.pop("gate", UNSET) 250 gate: LiveRunGate | Unset 251 if isinstance(_gate, Unset): 252 gate = UNSET 253 else: 254 gate = LiveRunGate.from_dict(_gate) 255 256 _paper = d.pop("paper", UNSET) 257 paper: LivePaperConfig | Unset 258 if isinstance(_paper, Unset): 259 paper = UNSET 260 else: 261 paper = LivePaperConfig.from_dict(_paper) 262 263 _stats = d.pop("stats", UNSET) 264 stats: LiveRunStats | Unset 265 if isinstance(_stats, Unset): 266 stats = UNSET 267 else: 268 stats = LiveRunStats.from_dict(_stats) 269 270 warm_from = d.pop("warmFrom", UNSET) 271 272 stream_url = d.pop("streamUrl", UNSET) 273 274 live_run_with_stream = cls( 275 strategy_id=strategy_id, 276 run_id=run_id, 277 visibility=visibility, 278 stage=stage, 279 state=state, 280 desired=desired, 281 sources=sources, 282 params=params, 283 params_version=params_version, 284 relay=relay, 285 started_at_ms=started_at_ms, 286 name=name, 287 description=description, 288 reason=reason, 289 gate=gate, 290 paper=paper, 291 stats=stats, 292 warm_from=warm_from, 293 stream_url=stream_url, 294 ) 295 296 live_run_with_stream.additional_properties = d 297 return live_run_with_stream 298 299 @property 300 def additional_keys(self) -> list[str]: 301 return list(self.additional_properties.keys()) 302 303 def __getitem__(self, key: str) -> Any: 304 return self.additional_properties[key] 305 306 def __setitem__(self, key: str, value: Any) -> None: 307 self.additional_properties[key] = value 308 309 def __delitem__(self, key: str) -> None: 310 del self.additional_properties[key] 311 312 def __contains__(self, key: str) -> bool: 313 return key in self.additional_properties
A run as LiveRun describes it, plus its warmFrom (absent only for a run started before the field existed) and
its streamUrl when it has one. It is what starting a run and
GET /strategy/{strategyId}/live return: your own run, read with your own credentials. Stopping a run
returns LiveRun, which carries neither warmFrom nor the URL, and GET /live/{runId} returns LiveRunDetail,
which carries warmFrom and never the URL.
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see `POST /strategy` for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
run_id (str): This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET
/live/public`.
visibility (LiveRunVisibility):
stage (LiveRunStage): A new run starts `SANDBOX`, a 24-hour trial in which it is compared against a second
execution and checked for resource use and stability. A run that passes moves to `LIVE` automatically when the
24 hours are up. A run of a strategy that an earlier run of yours already took through the trial starts `LIVE`,
unless you started it with `sandbox: true`.
state (str): The run's health right now: `STARTING` (no runner has reported on it yet), `RUNNING`, `LAGGING`
(behind the market data, usually while catching up; clears by itself), `HUNG` (stuck inside one strategy call
for longer than allowed; clears when it returns), `DEGRADED` (its independent executions produced different
signals), `FAILED` (refused, could not start or failed while running; `reason` says why) or `STOPPED`.
`LAGGING`, `HUNG` and `DEGRADED` come and go on a running run. The set may grow: read an unknown value as a
running run with something to look at. See the Live execution guide.
desired (LiveRunDesired): What you last asked for. `state` can lag this briefly after `DELETE`.
sources (list[LiveSource]):
params (LiveRunParams):
params_version (int): Increments on every accepted `PUT .../params` call, including one that resends the current
values.
relay (bool): Whether this run's signals are relayed over the WebSocket channel described in the "Live
execution" guide. It is the value requested at start, in either stage.
started_at_ms (int): Epoch milliseconds.
name (str | Unset):
description (str | Unset):
reason (str | Unset): Why the run stopped or failed, when there is something to say; absent otherwise. It is
never a
stack trace or an internal message. Either `resource: ...` (the platform stopped the run for
exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for
a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's
definition was refused, the run could not start after several attempts, the strategy failed while
processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow:
read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays
`desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your
live-run limit) until then; one that can never run because its strategy cannot consume its source
type is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
gate (LiveRunGate | Unset): The sandbox trial's promotion verdict. Absent for the whole 24-hour trial and
present once it ends, so an absent `gate` means the trial has not finished. A run that started in `LIVE` without
a trial has it from the start: the verdict of the earlier run it relies on, with `inheritedFrom` naming that
run. `passed` is the verdict; the rest is diagnostic detail whose shape is not yet stabilized as public API:
treat it as opaque.
paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's `baseConfig`
(same fields,
defaults and limits), plus `output`. An empty object takes every default. Each quote
currency the run trades gets its own simulated account, opened with `initialFunding` in
that currency; accounts are never added together. As returned on a run, the block is
normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled
in.
stats (LiveRunStats | Unset): What a run has been doing, as of its last snapshot. The platform refreshes it
about once a minute
while the run is being executed, so `opsPerSecond` is an average over that interval, not an
instantaneous rate.
warm_from (int | Unset): The `warmFrom` in effect for this run, in seconds: the one requested when the run was
started or, when none was, the one the platform chose (the distance from the run's start back to the start of
the current 15-minute block, 0 to 900). It is never `null`. It is present on every run started since the field
exists and absent from a run started before it existed. It never changes while the run exists.
stream_url (str | Unset): The run's secret stream URL (`wss://…`). **Treat it like a password**: anyone who
holds it can read
this run's signals, from the sandbox stage on. Present only when the run was started with
`stream: true`, is wanted running, has not had its stream revoked, and your plan still lets you
broadcast; absent otherwise (a plan that lets you broadcast again gets the same URL back). Rotate
it with `POST /live/{runId}/stream` if it leaks, revoke it with `DELETE /live/{runId}/stream`.
42def __init__(self, strategy_id, run_id, visibility, stage, state, desired, sources, params, params_version, relay, started_at_ms, name=attr_dict['name'].default, description=attr_dict['description'].default, reason=attr_dict['reason'].default, gate=attr_dict['gate'].default, paper=attr_dict['paper'].default, stats=attr_dict['stats'].default, warm_from=attr_dict['warm_from'].default, stream_url=attr_dict['stream_url'].default): 43 self.strategy_id = strategy_id 44 self.run_id = run_id 45 self.visibility = visibility 46 self.stage = stage 47 self.state = state 48 self.desired = desired 49 self.sources = sources 50 self.params = params 51 self.params_version = params_version 52 self.relay = relay 53 self.started_at_ms = started_at_ms 54 self.name = name 55 self.description = description 56 self.reason = reason 57 self.gate = gate 58 self.paper = paper 59 self.stats = stats 60 self.warm_from = warm_from 61 self.stream_url = stream_url 62 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveRunWithStream.
123 def to_dict(self) -> dict[str, Any]: 124 strategy_id = self.strategy_id 125 126 run_id = self.run_id 127 128 visibility = self.visibility.value 129 130 stage = self.stage.value 131 132 state = self.state 133 134 desired = self.desired.value 135 136 sources = [] 137 for sources_item_data in self.sources: 138 sources_item = sources_item_data.to_dict() 139 sources.append(sources_item) 140 141 params = self.params.to_dict() 142 143 params_version = self.params_version 144 145 relay = self.relay 146 147 started_at_ms = self.started_at_ms 148 149 name = self.name 150 151 description = self.description 152 153 reason = self.reason 154 155 gate: dict[str, Any] | Unset = UNSET 156 if not isinstance(self.gate, Unset): 157 gate = self.gate.to_dict() 158 159 paper: dict[str, Any] | Unset = UNSET 160 if not isinstance(self.paper, Unset): 161 paper = self.paper.to_dict() 162 163 stats: dict[str, Any] | Unset = UNSET 164 if not isinstance(self.stats, Unset): 165 stats = self.stats.to_dict() 166 167 warm_from = self.warm_from 168 169 stream_url = self.stream_url 170 171 field_dict: dict[str, Any] = {} 172 field_dict.update(self.additional_properties) 173 field_dict.update( 174 { 175 "strategyId": strategy_id, 176 "runId": run_id, 177 "visibility": visibility, 178 "stage": stage, 179 "state": state, 180 "desired": desired, 181 "sources": sources, 182 "params": params, 183 "paramsVersion": params_version, 184 "relay": relay, 185 "startedAtMs": started_at_ms, 186 } 187 ) 188 if name is not UNSET: 189 field_dict["name"] = name 190 if description is not UNSET: 191 field_dict["description"] = description 192 if reason is not UNSET: 193 field_dict["reason"] = reason 194 if gate is not UNSET: 195 field_dict["gate"] = gate 196 if paper is not UNSET: 197 field_dict["paper"] = paper 198 if stats is not UNSET: 199 field_dict["stats"] = stats 200 if warm_from is not UNSET: 201 field_dict["warmFrom"] = warm_from 202 if stream_url is not UNSET: 203 field_dict["streamUrl"] = stream_url 204 205 return field_dict
207 @classmethod 208 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 209 from ..models.live_paper_config import LivePaperConfig 210 from ..models.live_run_gate import LiveRunGate 211 from ..models.live_run_params import LiveRunParams 212 from ..models.live_run_stats import LiveRunStats 213 from ..models.live_source import LiveSource 214 215 d = dict(src_dict) 216 strategy_id = d.pop("strategyId") 217 218 run_id = d.pop("runId") 219 220 visibility = LiveRunVisibility(d.pop("visibility")) 221 222 stage = LiveRunStage(d.pop("stage")) 223 224 state = d.pop("state") 225 226 desired = LiveRunDesired(d.pop("desired")) 227 228 sources = [] 229 _sources = d.pop("sources") 230 for sources_item_data in _sources: 231 sources_item = LiveSource.from_dict(sources_item_data) 232 233 sources.append(sources_item) 234 235 params = LiveRunParams.from_dict(d.pop("params")) 236 237 params_version = d.pop("paramsVersion") 238 239 relay = d.pop("relay") 240 241 started_at_ms = d.pop("startedAtMs") 242 243 name = d.pop("name", UNSET) 244 245 description = d.pop("description", UNSET) 246 247 reason = d.pop("reason", UNSET) 248 249 _gate = d.pop("gate", UNSET) 250 gate: LiveRunGate | Unset 251 if isinstance(_gate, Unset): 252 gate = UNSET 253 else: 254 gate = LiveRunGate.from_dict(_gate) 255 256 _paper = d.pop("paper", UNSET) 257 paper: LivePaperConfig | Unset 258 if isinstance(_paper, Unset): 259 paper = UNSET 260 else: 261 paper = LivePaperConfig.from_dict(_paper) 262 263 _stats = d.pop("stats", UNSET) 264 stats: LiveRunStats | Unset 265 if isinstance(_stats, Unset): 266 stats = UNSET 267 else: 268 stats = LiveRunStats.from_dict(_stats) 269 270 warm_from = d.pop("warmFrom", UNSET) 271 272 stream_url = d.pop("streamUrl", UNSET) 273 274 live_run_with_stream = cls( 275 strategy_id=strategy_id, 276 run_id=run_id, 277 visibility=visibility, 278 stage=stage, 279 state=state, 280 desired=desired, 281 sources=sources, 282 params=params, 283 params_version=params_version, 284 relay=relay, 285 started_at_ms=started_at_ms, 286 name=name, 287 description=description, 288 reason=reason, 289 gate=gate, 290 paper=paper, 291 stats=stats, 292 warm_from=warm_from, 293 stream_url=stream_url, 294 ) 295 296 live_run_with_stream.additional_properties = d 297 return live_run_with_stream
23@_attrs_define 24class LiveSignal: 25 """One signal, in the same shape the real-time signal channel delivers. 26 27 Attributes: 28 v (int): Envelope schema version. 29 signal_id (str): Stable id for this exact signal — dedupe on it across reconnects or overlapping reads. 30 run_id (str): 31 stage (LiveSignalStage): The stage the run was in when this signal was produced. 32 type_ (LiveSignalType): `paper` items appear only for a run whose `paper.output` is `mix`; they are not relayed 33 over the WebSocket channel. 34 event_ts_ms (int): Market time the signal was produced. 35 emitted_at_ms (int): Time it was published — always at or after `eventTsMs`. 36 instrument (LiveSignalInstrument | None): The instrument the signal is about. `null` only for a `paper` item 37 about a whole account (`equity`, `mark`, `kpi`), whose `data.currency` names the account. 38 digest (str): Content hash, for checking that two independent deliveries of the same signal agree. 39 params_version (int | Unset): The parameter set in force when this signal was produced. 40 kind (None | str | Unset): `BUY`/`SELL` for a `hint`, the command name for a `command`; for `paper`, what the 41 item is: `fill`, `trade`, `equity`, `mark`, `kpi` or `gap`. Absent otherwise. 42 order (LiveSignalOrderType0 | None | Unset): Present only for a `hint`. 43 data (LiveSignalData | Unset): The signal's own free-form payload, what the strategy put there with 44 `signal.set(...)`. Whoever may read the run may read it, so on a `public` run it is public. A signal whose 45 `data` is over 8 KiB (8,192 bytes of its JSON) is not pushed on the WebSocket channel, and `GET 46 /live/{runId}/signals` returns it whole. 47 regenerated (bool | Unset): `true` only for a signal republished to fill a gap in the record. 48 """ 49 50 v: int 51 signal_id: str 52 run_id: str 53 stage: LiveSignalStage 54 type_: LiveSignalType 55 event_ts_ms: int 56 emitted_at_ms: int 57 instrument: LiveSignalInstrument | None 58 digest: str 59 params_version: int | Unset = UNSET 60 kind: None | str | Unset = UNSET 61 order: LiveSignalOrderType0 | None | Unset = UNSET 62 data: LiveSignalData | Unset = UNSET 63 regenerated: bool | Unset = UNSET 64 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 65 66 def to_dict(self) -> dict[str, Any]: 67 from ..models.live_signal_instrument import LiveSignalInstrument 68 from ..models.live_signal_order_type_0 import LiveSignalOrderType0 69 70 v = self.v 71 72 signal_id = self.signal_id 73 74 run_id = self.run_id 75 76 stage = self.stage.value 77 78 type_ = self.type_.value 79 80 event_ts_ms = self.event_ts_ms 81 82 emitted_at_ms = self.emitted_at_ms 83 84 instrument: dict[str, Any] | None 85 if isinstance(self.instrument, LiveSignalInstrument): 86 instrument = self.instrument.to_dict() 87 else: 88 instrument = self.instrument 89 90 digest = self.digest 91 92 params_version = self.params_version 93 94 kind: None | str | Unset 95 if isinstance(self.kind, Unset): 96 kind = UNSET 97 else: 98 kind = self.kind 99 100 order: dict[str, Any] | None | Unset 101 if isinstance(self.order, Unset): 102 order = UNSET 103 elif isinstance(self.order, LiveSignalOrderType0): 104 order = self.order.to_dict() 105 else: 106 order = self.order 107 108 data: dict[str, Any] | Unset = UNSET 109 if not isinstance(self.data, Unset): 110 data = self.data.to_dict() 111 112 regenerated = self.regenerated 113 114 field_dict: dict[str, Any] = {} 115 field_dict.update(self.additional_properties) 116 field_dict.update( 117 { 118 "v": v, 119 "signalId": signal_id, 120 "runId": run_id, 121 "stage": stage, 122 "type": type_, 123 "eventTsMs": event_ts_ms, 124 "emittedAtMs": emitted_at_ms, 125 "instrument": instrument, 126 "digest": digest, 127 } 128 ) 129 if params_version is not UNSET: 130 field_dict["paramsVersion"] = params_version 131 if kind is not UNSET: 132 field_dict["kind"] = kind 133 if order is not UNSET: 134 field_dict["order"] = order 135 if data is not UNSET: 136 field_dict["data"] = data 137 if regenerated is not UNSET: 138 field_dict["regenerated"] = regenerated 139 140 return field_dict 141 142 @classmethod 143 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 144 from ..models.live_signal_data import LiveSignalData 145 from ..models.live_signal_instrument import LiveSignalInstrument 146 from ..models.live_signal_order_type_0 import LiveSignalOrderType0 147 148 d = dict(src_dict) 149 v = d.pop("v") 150 151 signal_id = d.pop("signalId") 152 153 run_id = d.pop("runId") 154 155 stage = LiveSignalStage(d.pop("stage")) 156 157 type_ = LiveSignalType(d.pop("type")) 158 159 event_ts_ms = d.pop("eventTsMs") 160 161 emitted_at_ms = d.pop("emittedAtMs") 162 163 def _parse_instrument(data: object) -> LiveSignalInstrument | None: 164 if data is None: 165 return data 166 try: 167 if not isinstance(data, dict): 168 raise TypeError() 169 instrument_type_0 = LiveSignalInstrument.from_dict(data) 170 171 return instrument_type_0 172 except (TypeError, ValueError, AttributeError, KeyError): 173 pass 174 return cast(LiveSignalInstrument | None, data) 175 176 instrument = _parse_instrument(d.pop("instrument")) 177 178 digest = d.pop("digest") 179 180 params_version = d.pop("paramsVersion", UNSET) 181 182 def _parse_kind(data: object) -> None | str | Unset: 183 if data is None: 184 return data 185 if isinstance(data, Unset): 186 return data 187 return cast(None | str | Unset, data) 188 189 kind = _parse_kind(d.pop("kind", UNSET)) 190 191 def _parse_order(data: object) -> LiveSignalOrderType0 | None | Unset: 192 if data is None: 193 return data 194 if isinstance(data, Unset): 195 return data 196 try: 197 if not isinstance(data, dict): 198 raise TypeError() 199 componentsschemas_live_signal_order_type_0 = LiveSignalOrderType0.from_dict(data) 200 201 return componentsschemas_live_signal_order_type_0 202 except (TypeError, ValueError, AttributeError, KeyError): 203 pass 204 return cast(LiveSignalOrderType0 | None | Unset, data) 205 206 order = _parse_order(d.pop("order", UNSET)) 207 208 _data = d.pop("data", UNSET) 209 data: LiveSignalData | Unset 210 if isinstance(_data, Unset): 211 data = UNSET 212 else: 213 data = LiveSignalData.from_dict(_data) 214 215 regenerated = d.pop("regenerated", UNSET) 216 217 live_signal = cls( 218 v=v, 219 signal_id=signal_id, 220 run_id=run_id, 221 stage=stage, 222 type_=type_, 223 event_ts_ms=event_ts_ms, 224 emitted_at_ms=emitted_at_ms, 225 instrument=instrument, 226 digest=digest, 227 params_version=params_version, 228 kind=kind, 229 order=order, 230 data=data, 231 regenerated=regenerated, 232 ) 233 234 live_signal.additional_properties = d 235 return live_signal 236 237 @property 238 def additional_keys(self) -> list[str]: 239 return list(self.additional_properties.keys()) 240 241 def __getitem__(self, key: str) -> Any: 242 return self.additional_properties[key] 243 244 def __setitem__(self, key: str, value: Any) -> None: 245 self.additional_properties[key] = value 246 247 def __delitem__(self, key: str) -> None: 248 del self.additional_properties[key] 249 250 def __contains__(self, key: str) -> bool: 251 return key in self.additional_properties
One signal, in the same shape the real-time signal channel delivers.
Attributes:
v (int): Envelope schema version.
signal_id (str): Stable id for this exact signal — dedupe on it across reconnects or overlapping reads.
run_id (str):
stage (LiveSignalStage): The stage the run was in when this signal was produced.
type_ (LiveSignalType): paper items appear only for a run whose paper.output is mix; they are not relayed
over the WebSocket channel.
event_ts_ms (int): Market time the signal was produced.
emitted_at_ms (int): Time it was published — always at or after eventTsMs.
instrument (LiveSignalInstrument | None): The instrument the signal is about. null only for a paper item
about a whole account (equity, mark, kpi), whose data.currency names the account.
digest (str): Content hash, for checking that two independent deliveries of the same signal agree.
params_version (int | Unset): The parameter set in force when this signal was produced.
kind (None | str | Unset): BUY/SELL for a hint, the command name for a command; for paper, what the
item is: fill, trade, equity, mark, kpi or gap. Absent otherwise.
order (LiveSignalOrderType0 | None | Unset): Present only for a hint.
data (LiveSignalData | Unset): The signal's own free-form payload, what the strategy put there with
signal.set(...). Whoever may read the run may read it, so on a public run it is public. A signal whose
data is over 8 KiB (8,192 bytes of its JSON) is not pushed on the WebSocket channel, and GET
/live/{runId}/signals returns it whole.
regenerated (bool | Unset): true only for a signal republished to fill a gap in the record.
37def __init__(self, v, signal_id, run_id, stage, type_, event_ts_ms, emitted_at_ms, instrument, digest, params_version=attr_dict['params_version'].default, kind=attr_dict['kind'].default, order=attr_dict['order'].default, data=attr_dict['data'].default, regenerated=attr_dict['regenerated'].default): 38 self.v = v 39 self.signal_id = signal_id 40 self.run_id = run_id 41 self.stage = stage 42 self.type_ = type_ 43 self.event_ts_ms = event_ts_ms 44 self.emitted_at_ms = emitted_at_ms 45 self.instrument = instrument 46 self.digest = digest 47 self.params_version = params_version 48 self.kind = kind 49 self.order = order 50 self.data = data 51 self.regenerated = regenerated 52 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveSignal.
66 def to_dict(self) -> dict[str, Any]: 67 from ..models.live_signal_instrument import LiveSignalInstrument 68 from ..models.live_signal_order_type_0 import LiveSignalOrderType0 69 70 v = self.v 71 72 signal_id = self.signal_id 73 74 run_id = self.run_id 75 76 stage = self.stage.value 77 78 type_ = self.type_.value 79 80 event_ts_ms = self.event_ts_ms 81 82 emitted_at_ms = self.emitted_at_ms 83 84 instrument: dict[str, Any] | None 85 if isinstance(self.instrument, LiveSignalInstrument): 86 instrument = self.instrument.to_dict() 87 else: 88 instrument = self.instrument 89 90 digest = self.digest 91 92 params_version = self.params_version 93 94 kind: None | str | Unset 95 if isinstance(self.kind, Unset): 96 kind = UNSET 97 else: 98 kind = self.kind 99 100 order: dict[str, Any] | None | Unset 101 if isinstance(self.order, Unset): 102 order = UNSET 103 elif isinstance(self.order, LiveSignalOrderType0): 104 order = self.order.to_dict() 105 else: 106 order = self.order 107 108 data: dict[str, Any] | Unset = UNSET 109 if not isinstance(self.data, Unset): 110 data = self.data.to_dict() 111 112 regenerated = self.regenerated 113 114 field_dict: dict[str, Any] = {} 115 field_dict.update(self.additional_properties) 116 field_dict.update( 117 { 118 "v": v, 119 "signalId": signal_id, 120 "runId": run_id, 121 "stage": stage, 122 "type": type_, 123 "eventTsMs": event_ts_ms, 124 "emittedAtMs": emitted_at_ms, 125 "instrument": instrument, 126 "digest": digest, 127 } 128 ) 129 if params_version is not UNSET: 130 field_dict["paramsVersion"] = params_version 131 if kind is not UNSET: 132 field_dict["kind"] = kind 133 if order is not UNSET: 134 field_dict["order"] = order 135 if data is not UNSET: 136 field_dict["data"] = data 137 if regenerated is not UNSET: 138 field_dict["regenerated"] = regenerated 139 140 return field_dict
142 @classmethod 143 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 144 from ..models.live_signal_data import LiveSignalData 145 from ..models.live_signal_instrument import LiveSignalInstrument 146 from ..models.live_signal_order_type_0 import LiveSignalOrderType0 147 148 d = dict(src_dict) 149 v = d.pop("v") 150 151 signal_id = d.pop("signalId") 152 153 run_id = d.pop("runId") 154 155 stage = LiveSignalStage(d.pop("stage")) 156 157 type_ = LiveSignalType(d.pop("type")) 158 159 event_ts_ms = d.pop("eventTsMs") 160 161 emitted_at_ms = d.pop("emittedAtMs") 162 163 def _parse_instrument(data: object) -> LiveSignalInstrument | None: 164 if data is None: 165 return data 166 try: 167 if not isinstance(data, dict): 168 raise TypeError() 169 instrument_type_0 = LiveSignalInstrument.from_dict(data) 170 171 return instrument_type_0 172 except (TypeError, ValueError, AttributeError, KeyError): 173 pass 174 return cast(LiveSignalInstrument | None, data) 175 176 instrument = _parse_instrument(d.pop("instrument")) 177 178 digest = d.pop("digest") 179 180 params_version = d.pop("paramsVersion", UNSET) 181 182 def _parse_kind(data: object) -> None | str | Unset: 183 if data is None: 184 return data 185 if isinstance(data, Unset): 186 return data 187 return cast(None | str | Unset, data) 188 189 kind = _parse_kind(d.pop("kind", UNSET)) 190 191 def _parse_order(data: object) -> LiveSignalOrderType0 | None | Unset: 192 if data is None: 193 return data 194 if isinstance(data, Unset): 195 return data 196 try: 197 if not isinstance(data, dict): 198 raise TypeError() 199 componentsschemas_live_signal_order_type_0 = LiveSignalOrderType0.from_dict(data) 200 201 return componentsschemas_live_signal_order_type_0 202 except (TypeError, ValueError, AttributeError, KeyError): 203 pass 204 return cast(LiveSignalOrderType0 | None | Unset, data) 205 206 order = _parse_order(d.pop("order", UNSET)) 207 208 _data = d.pop("data", UNSET) 209 data: LiveSignalData | Unset 210 if isinstance(_data, Unset): 211 data = UNSET 212 else: 213 data = LiveSignalData.from_dict(_data) 214 215 regenerated = d.pop("regenerated", UNSET) 216 217 live_signal = cls( 218 v=v, 219 signal_id=signal_id, 220 run_id=run_id, 221 stage=stage, 222 type_=type_, 223 event_ts_ms=event_ts_ms, 224 emitted_at_ms=emitted_at_ms, 225 instrument=instrument, 226 digest=digest, 227 params_version=params_version, 228 kind=kind, 229 order=order, 230 data=data, 231 regenerated=regenerated, 232 ) 233 234 live_signal.additional_properties = d 235 return live_signal
13@_attrs_define 14class LiveSignalData: 15 """The signal's own free-form payload, what the strategy put there with `signal.set(...)`. Whoever may read the run may 16 read it, so on a `public` run it is public. A signal whose `data` is over 8 KiB (8,192 bytes of its JSON) is not 17 pushed on the WebSocket channel, and `GET /live/{runId}/signals` returns it whole. 18 19 """ 20 21 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 22 23 def to_dict(self) -> dict[str, Any]: 24 25 field_dict: dict[str, Any] = {} 26 field_dict.update(self.additional_properties) 27 28 return field_dict 29 30 @classmethod 31 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 32 d = dict(src_dict) 33 live_signal_data = cls() 34 35 live_signal_data.additional_properties = d 36 return live_signal_data 37 38 @property 39 def additional_keys(self) -> list[str]: 40 return list(self.additional_properties.keys()) 41 42 def __getitem__(self, key: str) -> Any: 43 return self.additional_properties[key] 44 45 def __setitem__(self, key: str, value: Any) -> None: 46 self.additional_properties[key] = value 47 48 def __delitem__(self, key: str) -> None: 49 del self.additional_properties[key] 50 51 def __contains__(self, key: str) -> bool: 52 return key in self.additional_properties
The signal's own free-form payload, what the strategy put there with signal.set(...). Whoever may read the run may
read it, so on a public run it is public. A signal whose data is over 8 KiB (8,192 bytes of its JSON) is not
pushed on the WebSocket channel, and GET /live/{runId}/signals returns it whole.
15@_attrs_define 16class LiveSignalInstrument: 17 """ 18 Attributes: 19 exchange (str | Unset): 20 segment (str | Unset): 21 symbol (str | Unset): Slashed form, e.g. `BTC/USDT`. 22 """ 23 24 exchange: str | Unset = UNSET 25 segment: str | Unset = UNSET 26 symbol: str | Unset = UNSET 27 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 28 29 def to_dict(self) -> dict[str, Any]: 30 exchange = self.exchange 31 32 segment = self.segment 33 34 symbol = self.symbol 35 36 field_dict: dict[str, Any] = {} 37 field_dict.update(self.additional_properties) 38 field_dict.update({}) 39 if exchange is not UNSET: 40 field_dict["exchange"] = exchange 41 if segment is not UNSET: 42 field_dict["segment"] = segment 43 if symbol is not UNSET: 44 field_dict["symbol"] = symbol 45 46 return field_dict 47 48 @classmethod 49 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 50 d = dict(src_dict) 51 exchange = d.pop("exchange", UNSET) 52 53 segment = d.pop("segment", UNSET) 54 55 symbol = d.pop("symbol", UNSET) 56 57 live_signal_instrument = cls( 58 exchange=exchange, 59 segment=segment, 60 symbol=symbol, 61 ) 62 63 live_signal_instrument.additional_properties = d 64 return live_signal_instrument 65 66 @property 67 def additional_keys(self) -> list[str]: 68 return list(self.additional_properties.keys()) 69 70 def __getitem__(self, key: str) -> Any: 71 return self.additional_properties[key] 72 73 def __setitem__(self, key: str, value: Any) -> None: 74 self.additional_properties[key] = value 75 76 def __delitem__(self, key: str) -> None: 77 del self.additional_properties[key] 78 79 def __contains__(self, key: str) -> bool: 80 return key in self.additional_properties
Attributes:
exchange (str | Unset):
segment (str | Unset):
symbol (str | Unset): Slashed form, e.g. BTC/USDT.
26def __init__(self, exchange=attr_dict['exchange'].default, segment=attr_dict['segment'].default, symbol=attr_dict['symbol'].default): 27 self.exchange = exchange 28 self.segment = segment 29 self.symbol = symbol 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveSignalInstrument.
29 def to_dict(self) -> dict[str, Any]: 30 exchange = self.exchange 31 32 segment = self.segment 33 34 symbol = self.symbol 35 36 field_dict: dict[str, Any] = {} 37 field_dict.update(self.additional_properties) 38 field_dict.update({}) 39 if exchange is not UNSET: 40 field_dict["exchange"] = exchange 41 if segment is not UNSET: 42 field_dict["segment"] = segment 43 if symbol is not UNSET: 44 field_dict["symbol"] = symbol 45 46 return field_dict
48 @classmethod 49 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 50 d = dict(src_dict) 51 exchange = d.pop("exchange", UNSET) 52 53 segment = d.pop("segment", UNSET) 54 55 symbol = d.pop("symbol", UNSET) 56 57 live_signal_instrument = cls( 58 exchange=exchange, 59 segment=segment, 60 symbol=symbol, 61 ) 62 63 live_signal_instrument.additional_properties = d 64 return live_signal_instrument
15@_attrs_define 16class LiveSignalOrderType0: 17 """Present only for a `hint`. 18 19 Attributes: 20 order_kind (str | Unset): 21 price (None | str | Unset): 22 amount (None | str | Unset): 23 stop_price (None | str | Unset): 24 trail_pct (None | str | Unset): 25 """ 26 27 order_kind: str | Unset = UNSET 28 price: None | str | Unset = UNSET 29 amount: None | str | Unset = UNSET 30 stop_price: None | str | Unset = UNSET 31 trail_pct: None | str | Unset = UNSET 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 order_kind = self.order_kind 36 37 price: None | str | Unset 38 if isinstance(self.price, Unset): 39 price = UNSET 40 else: 41 price = self.price 42 43 amount: None | str | Unset 44 if isinstance(self.amount, Unset): 45 amount = UNSET 46 else: 47 amount = self.amount 48 49 stop_price: None | str | Unset 50 if isinstance(self.stop_price, Unset): 51 stop_price = UNSET 52 else: 53 stop_price = self.stop_price 54 55 trail_pct: None | str | Unset 56 if isinstance(self.trail_pct, Unset): 57 trail_pct = UNSET 58 else: 59 trail_pct = self.trail_pct 60 61 field_dict: dict[str, Any] = {} 62 field_dict.update(self.additional_properties) 63 field_dict.update({}) 64 if order_kind is not UNSET: 65 field_dict["orderKind"] = order_kind 66 if price is not UNSET: 67 field_dict["price"] = price 68 if amount is not UNSET: 69 field_dict["amount"] = amount 70 if stop_price is not UNSET: 71 field_dict["stopPrice"] = stop_price 72 if trail_pct is not UNSET: 73 field_dict["trailPct"] = trail_pct 74 75 return field_dict 76 77 @classmethod 78 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 79 d = dict(src_dict) 80 order_kind = d.pop("orderKind", UNSET) 81 82 def _parse_price(data: object) -> None | str | Unset: 83 if data is None: 84 return data 85 if isinstance(data, Unset): 86 return data 87 return cast(None | str | Unset, data) 88 89 price = _parse_price(d.pop("price", UNSET)) 90 91 def _parse_amount(data: object) -> None | str | Unset: 92 if data is None: 93 return data 94 if isinstance(data, Unset): 95 return data 96 return cast(None | str | Unset, data) 97 98 amount = _parse_amount(d.pop("amount", UNSET)) 99 100 def _parse_stop_price(data: object) -> None | str | Unset: 101 if data is None: 102 return data 103 if isinstance(data, Unset): 104 return data 105 return cast(None | str | Unset, data) 106 107 stop_price = _parse_stop_price(d.pop("stopPrice", UNSET)) 108 109 def _parse_trail_pct(data: object) -> None | str | Unset: 110 if data is None: 111 return data 112 if isinstance(data, Unset): 113 return data 114 return cast(None | str | Unset, data) 115 116 trail_pct = _parse_trail_pct(d.pop("trailPct", UNSET)) 117 118 live_signal_order_type_0 = cls( 119 order_kind=order_kind, 120 price=price, 121 amount=amount, 122 stop_price=stop_price, 123 trail_pct=trail_pct, 124 ) 125 126 live_signal_order_type_0.additional_properties = d 127 return live_signal_order_type_0 128 129 @property 130 def additional_keys(self) -> list[str]: 131 return list(self.additional_properties.keys()) 132 133 def __getitem__(self, key: str) -> Any: 134 return self.additional_properties[key] 135 136 def __setitem__(self, key: str, value: Any) -> None: 137 self.additional_properties[key] = value 138 139 def __delitem__(self, key: str) -> None: 140 del self.additional_properties[key] 141 142 def __contains__(self, key: str) -> bool: 143 return key in self.additional_properties
Present only for a hint.
Attributes: order_kind (str | Unset): price (None | str | Unset): amount (None | str | Unset): stop_price (None | str | Unset): trail_pct (None | str | Unset):
28def __init__(self, order_kind=attr_dict['order_kind'].default, price=attr_dict['price'].default, amount=attr_dict['amount'].default, stop_price=attr_dict['stop_price'].default, trail_pct=attr_dict['trail_pct'].default): 29 self.order_kind = order_kind 30 self.price = price 31 self.amount = amount 32 self.stop_price = stop_price 33 self.trail_pct = trail_pct 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveSignalOrderType0.
34 def to_dict(self) -> dict[str, Any]: 35 order_kind = self.order_kind 36 37 price: None | str | Unset 38 if isinstance(self.price, Unset): 39 price = UNSET 40 else: 41 price = self.price 42 43 amount: None | str | Unset 44 if isinstance(self.amount, Unset): 45 amount = UNSET 46 else: 47 amount = self.amount 48 49 stop_price: None | str | Unset 50 if isinstance(self.stop_price, Unset): 51 stop_price = UNSET 52 else: 53 stop_price = self.stop_price 54 55 trail_pct: None | str | Unset 56 if isinstance(self.trail_pct, Unset): 57 trail_pct = UNSET 58 else: 59 trail_pct = self.trail_pct 60 61 field_dict: dict[str, Any] = {} 62 field_dict.update(self.additional_properties) 63 field_dict.update({}) 64 if order_kind is not UNSET: 65 field_dict["orderKind"] = order_kind 66 if price is not UNSET: 67 field_dict["price"] = price 68 if amount is not UNSET: 69 field_dict["amount"] = amount 70 if stop_price is not UNSET: 71 field_dict["stopPrice"] = stop_price 72 if trail_pct is not UNSET: 73 field_dict["trailPct"] = trail_pct 74 75 return field_dict
77 @classmethod 78 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 79 d = dict(src_dict) 80 order_kind = d.pop("orderKind", UNSET) 81 82 def _parse_price(data: object) -> None | str | Unset: 83 if data is None: 84 return data 85 if isinstance(data, Unset): 86 return data 87 return cast(None | str | Unset, data) 88 89 price = _parse_price(d.pop("price", UNSET)) 90 91 def _parse_amount(data: object) -> None | str | Unset: 92 if data is None: 93 return data 94 if isinstance(data, Unset): 95 return data 96 return cast(None | str | Unset, data) 97 98 amount = _parse_amount(d.pop("amount", UNSET)) 99 100 def _parse_stop_price(data: object) -> None | str | Unset: 101 if data is None: 102 return data 103 if isinstance(data, Unset): 104 return data 105 return cast(None | str | Unset, data) 106 107 stop_price = _parse_stop_price(d.pop("stopPrice", UNSET)) 108 109 def _parse_trail_pct(data: object) -> None | str | Unset: 110 if data is None: 111 return data 112 if isinstance(data, Unset): 113 return data 114 return cast(None | str | Unset, data) 115 116 trail_pct = _parse_trail_pct(d.pop("trailPct", UNSET)) 117 118 live_signal_order_type_0 = cls( 119 order_kind=order_kind, 120 price=price, 121 amount=amount, 122 stop_price=stop_price, 123 trail_pct=trail_pct, 124 ) 125 126 live_signal_order_type_0.additional_properties = d 127 return live_signal_order_type_0
20@_attrs_define 21class LiveSignalPage: 22 """One page of a run's recorded signals, oldest first. 23 24 Attributes: 25 signals (list[LiveSignal]): 26 available_since_ms (int | Unset): The oldest moment this run's signals can still be read from. Absent when the 27 run has produced nothing yet. It moves forward over time as older signals are discarded, so a `sinceMs` earlier 28 than this is served from here instead. 29 field_links (PublicLiveListLinks | Unset): Present only when another page exists. 30 """ 31 32 signals: list[LiveSignal] 33 available_since_ms: int | Unset = UNSET 34 field_links: PublicLiveListLinks | Unset = UNSET 35 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 36 37 def to_dict(self) -> dict[str, Any]: 38 signals = [] 39 for signals_item_data in self.signals: 40 signals_item = signals_item_data.to_dict() 41 signals.append(signals_item) 42 43 available_since_ms = self.available_since_ms 44 45 field_links: dict[str, Any] | Unset = UNSET 46 if not isinstance(self.field_links, Unset): 47 field_links = self.field_links.to_dict() 48 49 field_dict: dict[str, Any] = {} 50 field_dict.update(self.additional_properties) 51 field_dict.update( 52 { 53 "signals": signals, 54 } 55 ) 56 if available_since_ms is not UNSET: 57 field_dict["availableSinceMs"] = available_since_ms 58 if field_links is not UNSET: 59 field_dict["_links"] = field_links 60 61 return field_dict 62 63 @classmethod 64 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 65 from ..models.live_signal import LiveSignal 66 from ..models.public_live_list_links import PublicLiveListLinks 67 68 d = dict(src_dict) 69 signals = [] 70 _signals = d.pop("signals") 71 for signals_item_data in _signals: 72 signals_item = LiveSignal.from_dict(signals_item_data) 73 74 signals.append(signals_item) 75 76 available_since_ms = d.pop("availableSinceMs", UNSET) 77 78 _field_links = d.pop("_links", UNSET) 79 field_links: PublicLiveListLinks | Unset 80 if isinstance(_field_links, Unset): 81 field_links = UNSET 82 else: 83 field_links = PublicLiveListLinks.from_dict(_field_links) 84 85 live_signal_page = cls( 86 signals=signals, 87 available_since_ms=available_since_ms, 88 field_links=field_links, 89 ) 90 91 live_signal_page.additional_properties = d 92 return live_signal_page 93 94 @property 95 def additional_keys(self) -> list[str]: 96 return list(self.additional_properties.keys()) 97 98 def __getitem__(self, key: str) -> Any: 99 return self.additional_properties[key] 100 101 def __setitem__(self, key: str, value: Any) -> None: 102 self.additional_properties[key] = value 103 104 def __delitem__(self, key: str) -> None: 105 del self.additional_properties[key] 106 107 def __contains__(self, key: str) -> bool: 108 return key in self.additional_properties
One page of a run's recorded signals, oldest first.
Attributes:
signals (list[LiveSignal]):
available_since_ms (int | Unset): The oldest moment this run's signals can still be read from. Absent when the
run has produced nothing yet. It moves forward over time as older signals are discarded, so a sinceMs earlier
than this is served from here instead.
field_links (PublicLiveListLinks | Unset): Present only when another page exists.
26def __init__(self, signals, available_since_ms=attr_dict['available_since_ms'].default, field_links=attr_dict['field_links'].default): 27 self.signals = signals 28 self.available_since_ms = available_since_ms 29 self.field_links = field_links 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveSignalPage.
37 def to_dict(self) -> dict[str, Any]: 38 signals = [] 39 for signals_item_data in self.signals: 40 signals_item = signals_item_data.to_dict() 41 signals.append(signals_item) 42 43 available_since_ms = self.available_since_ms 44 45 field_links: dict[str, Any] | Unset = UNSET 46 if not isinstance(self.field_links, Unset): 47 field_links = self.field_links.to_dict() 48 49 field_dict: dict[str, Any] = {} 50 field_dict.update(self.additional_properties) 51 field_dict.update( 52 { 53 "signals": signals, 54 } 55 ) 56 if available_since_ms is not UNSET: 57 field_dict["availableSinceMs"] = available_since_ms 58 if field_links is not UNSET: 59 field_dict["_links"] = field_links 60 61 return field_dict
63 @classmethod 64 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 65 from ..models.live_signal import LiveSignal 66 from ..models.public_live_list_links import PublicLiveListLinks 67 68 d = dict(src_dict) 69 signals = [] 70 _signals = d.pop("signals") 71 for signals_item_data in _signals: 72 signals_item = LiveSignal.from_dict(signals_item_data) 73 74 signals.append(signals_item) 75 76 available_since_ms = d.pop("availableSinceMs", UNSET) 77 78 _field_links = d.pop("_links", UNSET) 79 field_links: PublicLiveListLinks | Unset 80 if isinstance(_field_links, Unset): 81 field_links = UNSET 82 else: 83 field_links = PublicLiveListLinks.from_dict(_field_links) 84 85 live_signal_page = cls( 86 signals=signals, 87 available_since_ms=available_since_ms, 88 field_links=field_links, 89 ) 90 91 live_signal_page.additional_properties = d 92 return live_signal_page
5class LiveSignalStage(str, Enum): 6 LIVE = "live" 7 SANDBOX = "sandbox" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveSignalType(str, Enum): 6 COMMAND = "command" 7 HINT = "hint" 8 INFO = "info" 9 MARKER = "marker" 10 PAPER = "paper" 11 12 def __str__(self) -> str: 13 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class LiveSource: 17 """One market feed a live run consumes. Exactly one entry per run today. 18 19 Attributes: 20 venue_type (str): Venue category. `cx` (centralized exchange) is the only one live runs support today. Example: 21 cx. 22 exchange (str): Example: binance. 23 segment (str): Example: spot. 24 type_ (LiveSourceType): Both `ticker` and `kline` connect to the lightest (fastest) cadence available for the 25 exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet. 26 instruments (list[str]): The instruments the run reads. For a run started with a list, that list as sent; for 27 one started without `instruments`, or with `["*"]`, what the start resolved: the list of pairs the compilation 28 of the strategy records as the instruments it accepts, when it records one, or `["*"]` for every instrument the 29 exchange/segment offers (tier-gated). An entry is written `BASE/QUOTE` and either side can be `*` to mean any, 30 such as any base paired with USDT. Symbols are not case-sensitive and spaces around them are ignored, so 31 `btc/usdt` and `BTC/USDT` are the same instrument. Example: ['BTC/USDT']. 32 """ 33 34 venue_type: str 35 exchange: str 36 segment: str 37 type_: LiveSourceType 38 instruments: list[str] 39 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 40 41 def to_dict(self) -> dict[str, Any]: 42 venue_type = self.venue_type 43 44 exchange = self.exchange 45 46 segment = self.segment 47 48 type_ = self.type_.value 49 50 instruments = self.instruments 51 52 field_dict: dict[str, Any] = {} 53 field_dict.update(self.additional_properties) 54 field_dict.update( 55 { 56 "venueType": venue_type, 57 "exchange": exchange, 58 "segment": segment, 59 "type": type_, 60 "instruments": instruments, 61 } 62 ) 63 64 return field_dict 65 66 @classmethod 67 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 68 d = dict(src_dict) 69 venue_type = d.pop("venueType") 70 71 exchange = d.pop("exchange") 72 73 segment = d.pop("segment") 74 75 type_ = LiveSourceType(d.pop("type")) 76 77 instruments = cast(list[str], d.pop("instruments")) 78 79 live_source = cls( 80 venue_type=venue_type, 81 exchange=exchange, 82 segment=segment, 83 type_=type_, 84 instruments=instruments, 85 ) 86 87 live_source.additional_properties = d 88 return live_source 89 90 @property 91 def additional_keys(self) -> list[str]: 92 return list(self.additional_properties.keys()) 93 94 def __getitem__(self, key: str) -> Any: 95 return self.additional_properties[key] 96 97 def __setitem__(self, key: str, value: Any) -> None: 98 self.additional_properties[key] = value 99 100 def __delitem__(self, key: str) -> None: 101 del self.additional_properties[key] 102 103 def __contains__(self, key: str) -> bool: 104 return key in self.additional_properties
One market feed a live run consumes. Exactly one entry per run today.
Attributes:
venue_type (str): Venue category. cx (centralized exchange) is the only one live runs support today. Example:
cx.
exchange (str): Example: binance.
segment (str): Example: spot.
type_ (LiveSourceType): Both ticker and kline connect to the lightest (fastest) cadence available for the
exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet.
instruments (list[str]): The instruments the run reads. For a run started with a list, that list as sent; for
one started without instruments, or with ["*"], what the start resolved: the list of pairs the compilation
of the strategy records as the instruments it accepts, when it records one, or ["*"] for every instrument the
exchange/segment offers (tier-gated). An entry is written BASE/QUOTE and either side can be * to mean any,
such as any base paired with USDT. Symbols are not case-sensitive and spaces around them are ignored, so
btc/usdt and BTC/USDT are the same instrument. Example: ['BTC/USDT'].
28def __init__(self, venue_type, exchange, segment, type_, instruments): 29 self.venue_type = venue_type 30 self.exchange = exchange 31 self.segment = segment 32 self.type_ = type_ 33 self.instruments = instruments 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveSource.
41 def to_dict(self) -> dict[str, Any]: 42 venue_type = self.venue_type 43 44 exchange = self.exchange 45 46 segment = self.segment 47 48 type_ = self.type_.value 49 50 instruments = self.instruments 51 52 field_dict: dict[str, Any] = {} 53 field_dict.update(self.additional_properties) 54 field_dict.update( 55 { 56 "venueType": venue_type, 57 "exchange": exchange, 58 "segment": segment, 59 "type": type_, 60 "instruments": instruments, 61 } 62 ) 63 64 return field_dict
66 @classmethod 67 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 68 d = dict(src_dict) 69 venue_type = d.pop("venueType") 70 71 exchange = d.pop("exchange") 72 73 segment = d.pop("segment") 74 75 type_ = LiveSourceType(d.pop("type")) 76 77 instruments = cast(list[str], d.pop("instruments")) 78 79 live_source = cls( 80 venue_type=venue_type, 81 exchange=exchange, 82 segment=segment, 83 type_=type_, 84 instruments=instruments, 85 ) 86 87 live_source.additional_properties = d 88 return live_source
16@_attrs_define 17class LiveSourceRequest: 18 """One market feed to start a live run on. Exactly one entry per run today. It is `LiveSource` as you ask for it: the 19 only difference is that `instruments` can be left out. 20 21 Attributes: 22 venue_type (str): Venue category. `cx` (centralized exchange) is the only one live runs support today. Example: 23 cx. 24 exchange (str): Example: binance. 25 segment (str): Example: spot. 26 type_ (LiveSourceRequestType): Both `ticker` and `kline` connect to the lightest (fastest) cadence available for 27 the exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet. 28 instruments (list[str] | Unset): Which instruments the run reads. A QTScript strategy can declare which 29 instruments it accepts with an `instruments` line in its source. When the compilation of the strategy records 30 that selection as a list of pairs, leaving `instruments` out, or sending `["*"]`, takes that list; otherwise the 31 run reads every instrument the exchange/segment offers. A list of instruments is taken as sent, and `[]` and 32 `null` are refused with `400`. An entry is written `BASE/QUOTE`; either side can be `*` to mean any: any base 33 can be paired with USDT, and BTC can be paired with any quote. Entries are not case-sensitive and spaces around 34 them are ignored, so `btc/usdt` and `BTC/USDT` are the same instrument. An entry that is not of that form (no 35 `/`, an empty side, a `.` or a space inside a side, or a `*` mixed with other characters of a side) makes the 36 run fail when it starts. Plan limits: a list with an entry that has a `*` on a side counts like `["*"]` and only 37 plans that include the wildcard accept it; the other entries are counted one by one. The instruments the run 38 actually reads come back in the run's `sources`. Example: ['BTC/USDT']. 39 """ 40 41 venue_type: str 42 exchange: str 43 segment: str 44 type_: LiveSourceRequestType 45 instruments: list[str] | Unset = UNSET 46 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 47 48 def to_dict(self) -> dict[str, Any]: 49 venue_type = self.venue_type 50 51 exchange = self.exchange 52 53 segment = self.segment 54 55 type_ = self.type_.value 56 57 instruments: list[str] | Unset = UNSET 58 if not isinstance(self.instruments, Unset): 59 instruments = self.instruments 60 61 field_dict: dict[str, Any] = {} 62 field_dict.update(self.additional_properties) 63 field_dict.update( 64 { 65 "venueType": venue_type, 66 "exchange": exchange, 67 "segment": segment, 68 "type": type_, 69 } 70 ) 71 if instruments is not UNSET: 72 field_dict["instruments"] = instruments 73 74 return field_dict 75 76 @classmethod 77 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 78 d = dict(src_dict) 79 venue_type = d.pop("venueType") 80 81 exchange = d.pop("exchange") 82 83 segment = d.pop("segment") 84 85 type_ = LiveSourceRequestType(d.pop("type")) 86 87 instruments = cast(list[str], d.pop("instruments", UNSET)) 88 89 live_source_request = cls( 90 venue_type=venue_type, 91 exchange=exchange, 92 segment=segment, 93 type_=type_, 94 instruments=instruments, 95 ) 96 97 live_source_request.additional_properties = d 98 return live_source_request 99 100 @property 101 def additional_keys(self) -> list[str]: 102 return list(self.additional_properties.keys()) 103 104 def __getitem__(self, key: str) -> Any: 105 return self.additional_properties[key] 106 107 def __setitem__(self, key: str, value: Any) -> None: 108 self.additional_properties[key] = value 109 110 def __delitem__(self, key: str) -> None: 111 del self.additional_properties[key] 112 113 def __contains__(self, key: str) -> bool: 114 return key in self.additional_properties
One market feed to start a live run on. Exactly one entry per run today. It is LiveSource as you ask for it: the
only difference is that instruments can be left out.
Attributes:
venue_type (str): Venue category. `cx` (centralized exchange) is the only one live runs support today. Example:
cx.
exchange (str): Example: binance.
segment (str): Example: spot.
type_ (LiveSourceRequestType): Both `ticker` and `kline` connect to the lightest (fastest) cadence available for
the exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet.
instruments (list[str] | Unset): Which instruments the run reads. A QTScript strategy can declare which
instruments it accepts with an `instruments` line in its source. When the compilation of the strategy records
that selection as a list of pairs, leaving `instruments` out, or sending `["*"]`, takes that list; otherwise the
run reads every instrument the exchange/segment offers. A list of instruments is taken as sent, and `[]` and
`null` are refused with `400`. An entry is written `BASE/QUOTE`; either side can be `*` to mean any: any base
can be paired with USDT, and BTC can be paired with any quote. Entries are not case-sensitive and spaces around
them are ignored, so `btc/usdt` and `BTC/USDT` are the same instrument. An entry that is not of that form (no
`/`, an empty side, a `.` or a space inside a side, or a `*` mixed with other characters of a side) makes the
run fail when it starts. Plan limits: a list with an entry that has a `*` on a side counts like `["*"]` and only
plans that include the wildcard accept it; the other entries are counted one by one. The instruments the run
actually reads come back in the run's `sources`. Example: ['BTC/USDT'].
28def __init__(self, venue_type, exchange, segment, type_, instruments=attr_dict['instruments'].default): 29 self.venue_type = venue_type 30 self.exchange = exchange 31 self.segment = segment 32 self.type_ = type_ 33 self.instruments = instruments 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveSourceRequest.
48 def to_dict(self) -> dict[str, Any]: 49 venue_type = self.venue_type 50 51 exchange = self.exchange 52 53 segment = self.segment 54 55 type_ = self.type_.value 56 57 instruments: list[str] | Unset = UNSET 58 if not isinstance(self.instruments, Unset): 59 instruments = self.instruments 60 61 field_dict: dict[str, Any] = {} 62 field_dict.update(self.additional_properties) 63 field_dict.update( 64 { 65 "venueType": venue_type, 66 "exchange": exchange, 67 "segment": segment, 68 "type": type_, 69 } 70 ) 71 if instruments is not UNSET: 72 field_dict["instruments"] = instruments 73 74 return field_dict
76 @classmethod 77 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 78 d = dict(src_dict) 79 venue_type = d.pop("venueType") 80 81 exchange = d.pop("exchange") 82 83 segment = d.pop("segment") 84 85 type_ = LiveSourceRequestType(d.pop("type")) 86 87 instruments = cast(list[str], d.pop("instruments", UNSET)) 88 89 live_source_request = cls( 90 venue_type=venue_type, 91 exchange=exchange, 92 segment=segment, 93 type_=type_, 94 instruments=instruments, 95 ) 96 97 live_source_request.additional_properties = d 98 return live_source_request
5class LiveSourceRequestType(str, Enum): 6 KLINE = "kline" 7 TICKER = "ticker" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class LiveSourceType(str, Enum): 6 KLINE = "kline" 7 TICKER = "ticker" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
13@_attrs_define 14class LiveStreamRevoked: 15 """What `DELETE /live/{runId}/stream` returns. 16 17 Attributes: 18 run_id (str): 19 revoked (bool): Always `true`. 20 """ 21 22 run_id: str 23 revoked: bool 24 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 25 26 def to_dict(self) -> dict[str, Any]: 27 run_id = self.run_id 28 29 revoked = self.revoked 30 31 field_dict: dict[str, Any] = {} 32 field_dict.update(self.additional_properties) 33 field_dict.update( 34 { 35 "runId": run_id, 36 "revoked": revoked, 37 } 38 ) 39 40 return field_dict 41 42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 d = dict(src_dict) 45 run_id = d.pop("runId") 46 47 revoked = d.pop("revoked") 48 49 live_stream_revoked = cls( 50 run_id=run_id, 51 revoked=revoked, 52 ) 53 54 live_stream_revoked.additional_properties = d 55 return live_stream_revoked 56 57 @property 58 def additional_keys(self) -> list[str]: 59 return list(self.additional_properties.keys()) 60 61 def __getitem__(self, key: str) -> Any: 62 return self.additional_properties[key] 63 64 def __setitem__(self, key: str, value: Any) -> None: 65 self.additional_properties[key] = value 66 67 def __delitem__(self, key: str) -> None: 68 del self.additional_properties[key] 69 70 def __contains__(self, key: str) -> bool: 71 return key in self.additional_properties
What DELETE /live/{runId}/stream returns.
Attributes:
run_id (str):
revoked (bool): Always true.
25def __init__(self, run_id, revoked): 26 self.run_id = run_id 27 self.revoked = revoked 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveStreamRevoked.
42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 d = dict(src_dict) 45 run_id = d.pop("runId") 46 47 revoked = d.pop("revoked") 48 49 live_stream_revoked = cls( 50 run_id=run_id, 51 revoked=revoked, 52 ) 53 54 live_stream_revoked.additional_properties = d 55 return live_stream_revoked
13@_attrs_define 14class LiveStreamUrl: 15 """A run's new stream URL, as returned by `POST /live/{runId}/stream`. 16 17 Attributes: 18 stream_url (str): The run's new secret stream URL. The previous one has stopped working. 19 """ 20 21 stream_url: str 22 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 23 24 def to_dict(self) -> dict[str, Any]: 25 stream_url = self.stream_url 26 27 field_dict: dict[str, Any] = {} 28 field_dict.update(self.additional_properties) 29 field_dict.update( 30 { 31 "streamUrl": stream_url, 32 } 33 ) 34 35 return field_dict 36 37 @classmethod 38 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 39 d = dict(src_dict) 40 stream_url = d.pop("streamUrl") 41 42 live_stream_url = cls( 43 stream_url=stream_url, 44 ) 45 46 live_stream_url.additional_properties = d 47 return live_stream_url 48 49 @property 50 def additional_keys(self) -> list[str]: 51 return list(self.additional_properties.keys()) 52 53 def __getitem__(self, key: str) -> Any: 54 return self.additional_properties[key] 55 56 def __setitem__(self, key: str, value: Any) -> None: 57 self.additional_properties[key] = value 58 59 def __delitem__(self, key: str) -> None: 60 del self.additional_properties[key] 61 62 def __contains__(self, key: str) -> bool: 63 return key in self.additional_properties
A run's new stream URL, as returned by POST /live/{runId}/stream.
Attributes: stream_url (str): The run's new secret stream URL. The previous one has stopped working.
24def __init__(self, stream_url): 25 self.stream_url = stream_url 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class LiveStreamUrl.
16@_attrs_define 17class Notice: 18 """A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth 19 knowing about how the strategy is wired, not necessarily an error. 20 21 Attributes: 22 level (str): Severity as the engine classified it. Example: WARN. 23 code (str): Stable identifier for the kind of finding; safe to match on. Example: indicator.bar-data-on-ticker- 24 path. 25 message (str): Human-readable explanation. Example: Indicator requires bar data but is on the ticker path. 26 provenance (NoticeProvenance | Unset): Where it came from, which matters because the two silences differ: an 27 empty list from a 28 real run (`execute`) is a clean bill of health, while an empty list from 29 `compile-dry-run` is only a lower bound over a bounded synthetic series. 30 Example: compile-dry-run. 31 """ 32 33 level: str 34 code: str 35 message: str 36 provenance: NoticeProvenance | Unset = UNSET 37 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 38 39 def to_dict(self) -> dict[str, Any]: 40 level = self.level 41 42 code = self.code 43 44 message = self.message 45 46 provenance: str | Unset = UNSET 47 if not isinstance(self.provenance, Unset): 48 provenance = self.provenance.value 49 50 field_dict: dict[str, Any] = {} 51 field_dict.update(self.additional_properties) 52 field_dict.update( 53 { 54 "level": level, 55 "code": code, 56 "message": message, 57 } 58 ) 59 if provenance is not UNSET: 60 field_dict["provenance"] = provenance 61 62 return field_dict 63 64 @classmethod 65 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 66 d = dict(src_dict) 67 level = d.pop("level") 68 69 code = d.pop("code") 70 71 message = d.pop("message") 72 73 _provenance = d.pop("provenance", UNSET) 74 provenance: NoticeProvenance | Unset 75 if isinstance(_provenance, Unset): 76 provenance = UNSET 77 else: 78 provenance = NoticeProvenance(_provenance) 79 80 notice = cls( 81 level=level, 82 code=code, 83 message=message, 84 provenance=provenance, 85 ) 86 87 notice.additional_properties = d 88 return notice 89 90 @property 91 def additional_keys(self) -> list[str]: 92 return list(self.additional_properties.keys()) 93 94 def __getitem__(self, key: str) -> Any: 95 return self.additional_properties[key] 96 97 def __setitem__(self, key: str, value: Any) -> None: 98 self.additional_properties[key] = value 99 100 def __delitem__(self, key: str) -> None: 101 del self.additional_properties[key] 102 103 def __contains__(self, key: str) -> bool: 104 return key in self.additional_properties
A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth knowing about how the strategy is wired, not necessarily an error.
Attributes:
level (str): Severity as the engine classified it. Example: WARN.
code (str): Stable identifier for the kind of finding; safe to match on. Example: indicator.bar-data-on-ticker-
path.
message (str): Human-readable explanation. Example: Indicator requires bar data but is on the ticker path.
provenance (NoticeProvenance | Unset): Where it came from, which matters because the two silences differ: an
empty list from a
real run (`execute`) is a clean bill of health, while an empty list from
`compile-dry-run` is only a lower bound over a bounded synthetic series.
Example: compile-dry-run.
27def __init__(self, level, code, message, provenance=attr_dict['provenance'].default): 28 self.level = level 29 self.code = code 30 self.message = message 31 self.provenance = provenance 32 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class Notice.
39 def to_dict(self) -> dict[str, Any]: 40 level = self.level 41 42 code = self.code 43 44 message = self.message 45 46 provenance: str | Unset = UNSET 47 if not isinstance(self.provenance, Unset): 48 provenance = self.provenance.value 49 50 field_dict: dict[str, Any] = {} 51 field_dict.update(self.additional_properties) 52 field_dict.update( 53 { 54 "level": level, 55 "code": code, 56 "message": message, 57 } 58 ) 59 if provenance is not UNSET: 60 field_dict["provenance"] = provenance 61 62 return field_dict
64 @classmethod 65 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 66 d = dict(src_dict) 67 level = d.pop("level") 68 69 code = d.pop("code") 70 71 message = d.pop("message") 72 73 _provenance = d.pop("provenance", UNSET) 74 provenance: NoticeProvenance | Unset 75 if isinstance(_provenance, Unset): 76 provenance = UNSET 77 else: 78 provenance = NoticeProvenance(_provenance) 79 80 notice = cls( 81 level=level, 82 code=code, 83 message=message, 84 provenance=provenance, 85 ) 86 87 notice.additional_properties = d 88 return notice
5class NoticeProvenance(str, Enum): 6 COMPILE_DRY_RUN = "compile-dry-run" 7 EXECUTE = "execute" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
22@_attrs_define 23class PrepareJobState: 24 """State of a single-instrument prepare job — the `JobState` shape plus a coverage summary. 25 A single-instrument prepare is always terminal (`status: Completed`): the client decides 26 what to do from `coverageRatio` (e.g. execute if it is at or above a chosen threshold) 27 rather than polling for missing hours that may never arrive — a missing hour for one 28 instrument usually means low activity, not missing data. 29 30 **Two coverage shapes, by exchange vs. dataset.** Against a managed exchange, coverage is 31 walked hour by hour: `totalHours`/`hoursWithData`/`hoursWithoutData`. Against a 32 dataset-backed prepare (`exchangeId: user`), coverage is reported on the dataset's own 33 cadence grid instead — hour-walking a daily dataset would report `1/24` and read as 34 broken — via `cadence`/`gaps`/`largestGapSteps`; `totalHours`/`hoursWithData`/ 35 `hoursWithoutData` are absent in that case. `dataFrom`/`dataTo` are present either way, and 36 `coverageRatio` too, computed accordingly — except against a dataset whose `cadence` is `rt`: 37 with no fixed step there is no expected row count to measure against, so `coverageRatio` 38 is absent and `gaps`/`largestGapSteps` are `0`. 39 40 Attributes: 41 context_id (str): Identifier for the job's execution context. Its current shape is a colon-delimited string 42 encoding the data source type, an internal user id, the exchange, the job id, and the instrument — but that 43 structure is not a committed contract and may change without notice. Treat it as an opaque token: store and pass 44 it back, don't parse it. Example: 45 jctx:ticker:00000000-0000-0000-0000-000000000000:binance:5ikyamio8b3v9wcnfxztzg:btc/usdt:0vicnz3thzhrqvfczks1pu. 46 status (JobStateStatus): Current status of the job. Treat `Completed | Aborted | Failed` as 47 terminal; `New | Started` mean keep polling. A single-instrument prepare 48 is always terminal (`Completed`) — decide from 49 `PrepareJobState.coverageRatio` (or `dataFrom`/`dataTo` against an `rt` dataset, 50 which has no ratio), not by polling. 51 Example: Completed. 52 size (int): Total size of the data being prepared Example: 100. 53 completed (int): The amount of data processed so far Example: 50. 54 status_detail (None | str | Unset): Detailed status information, if available Example: Job completed with error 55 code 5001. 56 start_time (datetime.datetime | None | Unset): Timestamp for when the preparation started Example: 57 2025-01-04T14:00:00Z. 58 end_time (datetime.datetime | None | Unset): Timestamp for when the preparation finished Example: 59 2025-01-04T14:00:20Z. 60 data_from (datetime.datetime | None | Unset): Start of the available data range for the prepared instrument. 61 Example: 2026-04-14T13:00:00Z. 62 data_to (datetime.datetime | None | Unset): End of the available data range for the prepared instrument. 63 Example: 2026-04-14T15:30:05Z. 64 coverage_ratio (float | Unset): Against a managed exchange: `hoursWithData / totalHours` in `[0,1]` (`1.0` when 65 `totalHours` is 0), the fraction of hours in the requested range that have served 66 data. Against a dataset (`exchangeId: user`): `rows / expectedStepsAtCadence` 67 over the dataset version's own range — echoing what ingest computed once, not 68 recomputed against a narrower prepare request. Absent for an `rt` dataset (no 69 fixed step, so no expected row count). 70 Example: 0.994. 71 total_hours (int | Unset): Number of whole hours in the requested prepare range. Managed exchanges only — 72 absent for a dataset-backed prepare. 73 Example: 168. 74 hours_with_data (int | Unset): Number of hours in the range that have data. Managed exchanges only — absent for 75 a dataset-backed prepare. 76 Example: 167. 77 cadence (str | Unset): The dataset version's own discovered cadence — a fixed grid (e.g. `1m`, `1h`) or 78 `rt` (see `DatasetVersion.cadence`). Only present for a dataset-backed prepare 79 (`exchangeId: user`). 80 Example: 1m. 81 gaps (int | Unset): Number of gaps in the dataset version at its own cadence, as discovered at ingest 82 time. `0` for `rt`. Only present for a dataset-backed prepare. 83 largest_gap_steps (int | Unset): The largest gap in the dataset version, in units of its own cadence step. `0` 84 for 85 `rt`. Only present for a dataset-backed prepare. 86 hours_without_data (list[PrepareJobStateHoursWithoutDataItem] | Unset): One entry per hour in the range that has 87 no data, with a rationale. Managed 88 exchanges only — absent for a dataset-backed prepare. 89 """ 90 91 context_id: str 92 status: JobStateStatus 93 size: int 94 completed: int 95 status_detail: None | str | Unset = UNSET 96 start_time: datetime.datetime | None | Unset = UNSET 97 end_time: datetime.datetime | None | Unset = UNSET 98 data_from: datetime.datetime | None | Unset = UNSET 99 data_to: datetime.datetime | None | Unset = UNSET 100 coverage_ratio: float | Unset = UNSET 101 total_hours: int | Unset = UNSET 102 hours_with_data: int | Unset = UNSET 103 cadence: str | Unset = UNSET 104 gaps: int | Unset = UNSET 105 largest_gap_steps: int | Unset = UNSET 106 hours_without_data: list[PrepareJobStateHoursWithoutDataItem] | Unset = UNSET 107 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 108 109 def to_dict(self) -> dict[str, Any]: 110 context_id = self.context_id 111 112 status = self.status.value 113 114 size = self.size 115 116 completed = self.completed 117 118 status_detail: None | str | Unset 119 if isinstance(self.status_detail, Unset): 120 status_detail = UNSET 121 else: 122 status_detail = self.status_detail 123 124 start_time: None | str | Unset 125 if isinstance(self.start_time, Unset): 126 start_time = UNSET 127 elif isinstance(self.start_time, datetime.datetime): 128 start_time = self.start_time.isoformat() 129 else: 130 start_time = self.start_time 131 132 end_time: None | str | Unset 133 if isinstance(self.end_time, Unset): 134 end_time = UNSET 135 elif isinstance(self.end_time, datetime.datetime): 136 end_time = self.end_time.isoformat() 137 else: 138 end_time = self.end_time 139 140 data_from: None | str | Unset 141 if isinstance(self.data_from, Unset): 142 data_from = UNSET 143 elif isinstance(self.data_from, datetime.datetime): 144 data_from = self.data_from.isoformat() 145 else: 146 data_from = self.data_from 147 148 data_to: None | str | Unset 149 if isinstance(self.data_to, Unset): 150 data_to = UNSET 151 elif isinstance(self.data_to, datetime.datetime): 152 data_to = self.data_to.isoformat() 153 else: 154 data_to = self.data_to 155 156 coverage_ratio = self.coverage_ratio 157 158 total_hours = self.total_hours 159 160 hours_with_data = self.hours_with_data 161 162 cadence = self.cadence 163 164 gaps = self.gaps 165 166 largest_gap_steps = self.largest_gap_steps 167 168 hours_without_data: list[dict[str, Any]] | Unset = UNSET 169 if not isinstance(self.hours_without_data, Unset): 170 hours_without_data = [] 171 for hours_without_data_item_data in self.hours_without_data: 172 hours_without_data_item = hours_without_data_item_data.to_dict() 173 hours_without_data.append(hours_without_data_item) 174 175 field_dict: dict[str, Any] = {} 176 field_dict.update(self.additional_properties) 177 field_dict.update( 178 { 179 "contextId": context_id, 180 "status": status, 181 "size": size, 182 "completed": completed, 183 } 184 ) 185 if status_detail is not UNSET: 186 field_dict["statusDetail"] = status_detail 187 if start_time is not UNSET: 188 field_dict["startTime"] = start_time 189 if end_time is not UNSET: 190 field_dict["endTime"] = end_time 191 if data_from is not UNSET: 192 field_dict["dataFrom"] = data_from 193 if data_to is not UNSET: 194 field_dict["dataTo"] = data_to 195 if coverage_ratio is not UNSET: 196 field_dict["coverageRatio"] = coverage_ratio 197 if total_hours is not UNSET: 198 field_dict["totalHours"] = total_hours 199 if hours_with_data is not UNSET: 200 field_dict["hoursWithData"] = hours_with_data 201 if cadence is not UNSET: 202 field_dict["cadence"] = cadence 203 if gaps is not UNSET: 204 field_dict["gaps"] = gaps 205 if largest_gap_steps is not UNSET: 206 field_dict["largestGapSteps"] = largest_gap_steps 207 if hours_without_data is not UNSET: 208 field_dict["hoursWithoutData"] = hours_without_data 209 210 return field_dict 211 212 @classmethod 213 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 214 from ..models.prepare_job_state_hours_without_data_item import PrepareJobStateHoursWithoutDataItem 215 216 d = dict(src_dict) 217 context_id = d.pop("contextId") 218 219 status = JobStateStatus(d.pop("status")) 220 221 size = d.pop("size") 222 223 completed = d.pop("completed") 224 225 def _parse_status_detail(data: object) -> None | str | Unset: 226 if data is None: 227 return data 228 if isinstance(data, Unset): 229 return data 230 return cast(None | str | Unset, data) 231 232 status_detail = _parse_status_detail(d.pop("statusDetail", UNSET)) 233 234 def _parse_start_time(data: object) -> datetime.datetime | None | Unset: 235 if data is None: 236 return data 237 if isinstance(data, Unset): 238 return data 239 try: 240 if not isinstance(data, str): 241 raise TypeError() 242 start_time_type_0 = isoparse(data) 243 244 return start_time_type_0 245 except (TypeError, ValueError, AttributeError, KeyError): 246 pass 247 return cast(datetime.datetime | None | Unset, data) 248 249 start_time = _parse_start_time(d.pop("startTime", UNSET)) 250 251 def _parse_end_time(data: object) -> datetime.datetime | None | Unset: 252 if data is None: 253 return data 254 if isinstance(data, Unset): 255 return data 256 try: 257 if not isinstance(data, str): 258 raise TypeError() 259 end_time_type_0 = isoparse(data) 260 261 return end_time_type_0 262 except (TypeError, ValueError, AttributeError, KeyError): 263 pass 264 return cast(datetime.datetime | None | Unset, data) 265 266 end_time = _parse_end_time(d.pop("endTime", UNSET)) 267 268 def _parse_data_from(data: object) -> datetime.datetime | None | Unset: 269 if data is None: 270 return data 271 if isinstance(data, Unset): 272 return data 273 try: 274 if not isinstance(data, str): 275 raise TypeError() 276 data_from_type_0 = isoparse(data) 277 278 return data_from_type_0 279 except (TypeError, ValueError, AttributeError, KeyError): 280 pass 281 return cast(datetime.datetime | None | Unset, data) 282 283 data_from = _parse_data_from(d.pop("dataFrom", UNSET)) 284 285 def _parse_data_to(data: object) -> datetime.datetime | None | Unset: 286 if data is None: 287 return data 288 if isinstance(data, Unset): 289 return data 290 try: 291 if not isinstance(data, str): 292 raise TypeError() 293 data_to_type_0 = isoparse(data) 294 295 return data_to_type_0 296 except (TypeError, ValueError, AttributeError, KeyError): 297 pass 298 return cast(datetime.datetime | None | Unset, data) 299 300 data_to = _parse_data_to(d.pop("dataTo", UNSET)) 301 302 coverage_ratio = d.pop("coverageRatio", UNSET) 303 304 total_hours = d.pop("totalHours", UNSET) 305 306 hours_with_data = d.pop("hoursWithData", UNSET) 307 308 cadence = d.pop("cadence", UNSET) 309 310 gaps = d.pop("gaps", UNSET) 311 312 largest_gap_steps = d.pop("largestGapSteps", UNSET) 313 314 _hours_without_data = d.pop("hoursWithoutData", UNSET) 315 hours_without_data: list[PrepareJobStateHoursWithoutDataItem] | Unset = UNSET 316 if _hours_without_data is not UNSET: 317 hours_without_data = [] 318 for hours_without_data_item_data in _hours_without_data: 319 hours_without_data_item = PrepareJobStateHoursWithoutDataItem.from_dict(hours_without_data_item_data) 320 321 hours_without_data.append(hours_without_data_item) 322 323 prepare_job_state = cls( 324 context_id=context_id, 325 status=status, 326 size=size, 327 completed=completed, 328 status_detail=status_detail, 329 start_time=start_time, 330 end_time=end_time, 331 data_from=data_from, 332 data_to=data_to, 333 coverage_ratio=coverage_ratio, 334 total_hours=total_hours, 335 hours_with_data=hours_with_data, 336 cadence=cadence, 337 gaps=gaps, 338 largest_gap_steps=largest_gap_steps, 339 hours_without_data=hours_without_data, 340 ) 341 342 prepare_job_state.additional_properties = d 343 return prepare_job_state 344 345 @property 346 def additional_keys(self) -> list[str]: 347 return list(self.additional_properties.keys()) 348 349 def __getitem__(self, key: str) -> Any: 350 return self.additional_properties[key] 351 352 def __setitem__(self, key: str, value: Any) -> None: 353 self.additional_properties[key] = value 354 355 def __delitem__(self, key: str) -> None: 356 del self.additional_properties[key] 357 358 def __contains__(self, key: str) -> bool: 359 return key in self.additional_properties
State of a single-instrument prepare job — the JobState shape plus a coverage summary.
A single-instrument prepare is always terminal (status: Completed): the client decides
what to do from coverageRatio (e.g. execute if it is at or above a chosen threshold)
rather than polling for missing hours that may never arrive — a missing hour for one
instrument usually means low activity, not missing data.
Two coverage shapes, by exchange vs. dataset. Against a managed exchange, coverage is
walked hour by hour: totalHours/hoursWithData/hoursWithoutData. Against a
dataset-backed prepare (exchangeId: user), coverage is reported on the dataset's own
cadence grid instead — hour-walking a daily dataset would report 1/24 and read as
broken — via cadence/gaps/largestGapSteps; totalHours/hoursWithData/
hoursWithoutData are absent in that case. dataFrom/dataTo are present either way, and
coverageRatio too, computed accordingly — except against a dataset whose cadence is rt:
with no fixed step there is no expected row count to measure against, so coverageRatio
is absent and gaps/largestGapSteps are 0.
Attributes:
context_id (str): Identifier for the job's execution context. Its current shape is a colon-delimited string
encoding the data source type, an internal user id, the exchange, the job id, and the instrument — but that
structure is not a committed contract and may change without notice. Treat it as an opaque token: store and pass
it back, don't parse it. Example:
jctx:ticker:00000000-0000-0000-0000-000000000000:binance:5ikyamio8b3v9wcnfxztzg:btc/usdt:0vicnz3thzhrqvfczks1pu.
status (JobStateStatus): Current status of the job. Treat `Completed | Aborted | Failed` as
terminal; `New | Started` mean keep polling. A single-instrument prepare
is always terminal (`Completed`) — decide from
`PrepareJobState.coverageRatio` (or `dataFrom`/`dataTo` against an `rt` dataset,
which has no ratio), not by polling.
Example: Completed.
size (int): Total size of the data being prepared Example: 100.
completed (int): The amount of data processed so far Example: 50.
status_detail (None | str | Unset): Detailed status information, if available Example: Job completed with error
code 5001.
start_time (datetime.datetime | None | Unset): Timestamp for when the preparation started Example:
2025-01-04T14:00:00Z.
end_time (datetime.datetime | None | Unset): Timestamp for when the preparation finished Example:
2025-01-04T14:00:20Z.
data_from (datetime.datetime | None | Unset): Start of the available data range for the prepared instrument.
Example: 2026-04-14T13:00:00Z.
data_to (datetime.datetime | None | Unset): End of the available data range for the prepared instrument.
Example: 2026-04-14T15:30:05Z.
coverage_ratio (float | Unset): Against a managed exchange: `hoursWithData / totalHours` in `[0,1]` (`1.0` when
`totalHours` is 0), the fraction of hours in the requested range that have served
data. Against a dataset (`exchangeId: user`): `rows / expectedStepsAtCadence`
over the dataset version's own range — echoing what ingest computed once, not
recomputed against a narrower prepare request. Absent for an `rt` dataset (no
fixed step, so no expected row count).
Example: 0.994.
total_hours (int | Unset): Number of whole hours in the requested prepare range. Managed exchanges only —
absent for a dataset-backed prepare.
Example: 168.
hours_with_data (int | Unset): Number of hours in the range that have data. Managed exchanges only — absent for
a dataset-backed prepare.
Example: 167.
cadence (str | Unset): The dataset version's own discovered cadence — a fixed grid (e.g. `1m`, `1h`) or
`rt` (see `DatasetVersion.cadence`). Only present for a dataset-backed prepare
(`exchangeId: user`).
Example: 1m.
gaps (int | Unset): Number of gaps in the dataset version at its own cadence, as discovered at ingest
time. `0` for `rt`. Only present for a dataset-backed prepare.
largest_gap_steps (int | Unset): The largest gap in the dataset version, in units of its own cadence step. `0`
for
`rt`. Only present for a dataset-backed prepare.
hours_without_data (list[PrepareJobStateHoursWithoutDataItem] | Unset): One entry per hour in the range that has
no data, with a rationale. Managed
exchanges only — absent for a dataset-backed prepare.
39def __init__(self, context_id, status, size, completed, status_detail=attr_dict['status_detail'].default, start_time=attr_dict['start_time'].default, end_time=attr_dict['end_time'].default, data_from=attr_dict['data_from'].default, data_to=attr_dict['data_to'].default, coverage_ratio=attr_dict['coverage_ratio'].default, total_hours=attr_dict['total_hours'].default, hours_with_data=attr_dict['hours_with_data'].default, cadence=attr_dict['cadence'].default, gaps=attr_dict['gaps'].default, largest_gap_steps=attr_dict['largest_gap_steps'].default, hours_without_data=attr_dict['hours_without_data'].default): 40 self.context_id = context_id 41 self.status = status 42 self.size = size 43 self.completed = completed 44 self.status_detail = status_detail 45 self.start_time = start_time 46 self.end_time = end_time 47 self.data_from = data_from 48 self.data_to = data_to 49 self.coverage_ratio = coverage_ratio 50 self.total_hours = total_hours 51 self.hours_with_data = hours_with_data 52 self.cadence = cadence 53 self.gaps = gaps 54 self.largest_gap_steps = largest_gap_steps 55 self.hours_without_data = hours_without_data 56 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PrepareJobState.
109 def to_dict(self) -> dict[str, Any]: 110 context_id = self.context_id 111 112 status = self.status.value 113 114 size = self.size 115 116 completed = self.completed 117 118 status_detail: None | str | Unset 119 if isinstance(self.status_detail, Unset): 120 status_detail = UNSET 121 else: 122 status_detail = self.status_detail 123 124 start_time: None | str | Unset 125 if isinstance(self.start_time, Unset): 126 start_time = UNSET 127 elif isinstance(self.start_time, datetime.datetime): 128 start_time = self.start_time.isoformat() 129 else: 130 start_time = self.start_time 131 132 end_time: None | str | Unset 133 if isinstance(self.end_time, Unset): 134 end_time = UNSET 135 elif isinstance(self.end_time, datetime.datetime): 136 end_time = self.end_time.isoformat() 137 else: 138 end_time = self.end_time 139 140 data_from: None | str | Unset 141 if isinstance(self.data_from, Unset): 142 data_from = UNSET 143 elif isinstance(self.data_from, datetime.datetime): 144 data_from = self.data_from.isoformat() 145 else: 146 data_from = self.data_from 147 148 data_to: None | str | Unset 149 if isinstance(self.data_to, Unset): 150 data_to = UNSET 151 elif isinstance(self.data_to, datetime.datetime): 152 data_to = self.data_to.isoformat() 153 else: 154 data_to = self.data_to 155 156 coverage_ratio = self.coverage_ratio 157 158 total_hours = self.total_hours 159 160 hours_with_data = self.hours_with_data 161 162 cadence = self.cadence 163 164 gaps = self.gaps 165 166 largest_gap_steps = self.largest_gap_steps 167 168 hours_without_data: list[dict[str, Any]] | Unset = UNSET 169 if not isinstance(self.hours_without_data, Unset): 170 hours_without_data = [] 171 for hours_without_data_item_data in self.hours_without_data: 172 hours_without_data_item = hours_without_data_item_data.to_dict() 173 hours_without_data.append(hours_without_data_item) 174 175 field_dict: dict[str, Any] = {} 176 field_dict.update(self.additional_properties) 177 field_dict.update( 178 { 179 "contextId": context_id, 180 "status": status, 181 "size": size, 182 "completed": completed, 183 } 184 ) 185 if status_detail is not UNSET: 186 field_dict["statusDetail"] = status_detail 187 if start_time is not UNSET: 188 field_dict["startTime"] = start_time 189 if end_time is not UNSET: 190 field_dict["endTime"] = end_time 191 if data_from is not UNSET: 192 field_dict["dataFrom"] = data_from 193 if data_to is not UNSET: 194 field_dict["dataTo"] = data_to 195 if coverage_ratio is not UNSET: 196 field_dict["coverageRatio"] = coverage_ratio 197 if total_hours is not UNSET: 198 field_dict["totalHours"] = total_hours 199 if hours_with_data is not UNSET: 200 field_dict["hoursWithData"] = hours_with_data 201 if cadence is not UNSET: 202 field_dict["cadence"] = cadence 203 if gaps is not UNSET: 204 field_dict["gaps"] = gaps 205 if largest_gap_steps is not UNSET: 206 field_dict["largestGapSteps"] = largest_gap_steps 207 if hours_without_data is not UNSET: 208 field_dict["hoursWithoutData"] = hours_without_data 209 210 return field_dict
212 @classmethod 213 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 214 from ..models.prepare_job_state_hours_without_data_item import PrepareJobStateHoursWithoutDataItem 215 216 d = dict(src_dict) 217 context_id = d.pop("contextId") 218 219 status = JobStateStatus(d.pop("status")) 220 221 size = d.pop("size") 222 223 completed = d.pop("completed") 224 225 def _parse_status_detail(data: object) -> None | str | Unset: 226 if data is None: 227 return data 228 if isinstance(data, Unset): 229 return data 230 return cast(None | str | Unset, data) 231 232 status_detail = _parse_status_detail(d.pop("statusDetail", UNSET)) 233 234 def _parse_start_time(data: object) -> datetime.datetime | None | Unset: 235 if data is None: 236 return data 237 if isinstance(data, Unset): 238 return data 239 try: 240 if not isinstance(data, str): 241 raise TypeError() 242 start_time_type_0 = isoparse(data) 243 244 return start_time_type_0 245 except (TypeError, ValueError, AttributeError, KeyError): 246 pass 247 return cast(datetime.datetime | None | Unset, data) 248 249 start_time = _parse_start_time(d.pop("startTime", UNSET)) 250 251 def _parse_end_time(data: object) -> datetime.datetime | None | Unset: 252 if data is None: 253 return data 254 if isinstance(data, Unset): 255 return data 256 try: 257 if not isinstance(data, str): 258 raise TypeError() 259 end_time_type_0 = isoparse(data) 260 261 return end_time_type_0 262 except (TypeError, ValueError, AttributeError, KeyError): 263 pass 264 return cast(datetime.datetime | None | Unset, data) 265 266 end_time = _parse_end_time(d.pop("endTime", UNSET)) 267 268 def _parse_data_from(data: object) -> datetime.datetime | None | Unset: 269 if data is None: 270 return data 271 if isinstance(data, Unset): 272 return data 273 try: 274 if not isinstance(data, str): 275 raise TypeError() 276 data_from_type_0 = isoparse(data) 277 278 return data_from_type_0 279 except (TypeError, ValueError, AttributeError, KeyError): 280 pass 281 return cast(datetime.datetime | None | Unset, data) 282 283 data_from = _parse_data_from(d.pop("dataFrom", UNSET)) 284 285 def _parse_data_to(data: object) -> datetime.datetime | None | Unset: 286 if data is None: 287 return data 288 if isinstance(data, Unset): 289 return data 290 try: 291 if not isinstance(data, str): 292 raise TypeError() 293 data_to_type_0 = isoparse(data) 294 295 return data_to_type_0 296 except (TypeError, ValueError, AttributeError, KeyError): 297 pass 298 return cast(datetime.datetime | None | Unset, data) 299 300 data_to = _parse_data_to(d.pop("dataTo", UNSET)) 301 302 coverage_ratio = d.pop("coverageRatio", UNSET) 303 304 total_hours = d.pop("totalHours", UNSET) 305 306 hours_with_data = d.pop("hoursWithData", UNSET) 307 308 cadence = d.pop("cadence", UNSET) 309 310 gaps = d.pop("gaps", UNSET) 311 312 largest_gap_steps = d.pop("largestGapSteps", UNSET) 313 314 _hours_without_data = d.pop("hoursWithoutData", UNSET) 315 hours_without_data: list[PrepareJobStateHoursWithoutDataItem] | Unset = UNSET 316 if _hours_without_data is not UNSET: 317 hours_without_data = [] 318 for hours_without_data_item_data in _hours_without_data: 319 hours_without_data_item = PrepareJobStateHoursWithoutDataItem.from_dict(hours_without_data_item_data) 320 321 hours_without_data.append(hours_without_data_item) 322 323 prepare_job_state = cls( 324 context_id=context_id, 325 status=status, 326 size=size, 327 completed=completed, 328 status_detail=status_detail, 329 start_time=start_time, 330 end_time=end_time, 331 data_from=data_from, 332 data_to=data_to, 333 coverage_ratio=coverage_ratio, 334 total_hours=total_hours, 335 hours_with_data=hours_with_data, 336 cadence=cadence, 337 gaps=gaps, 338 largest_gap_steps=largest_gap_steps, 339 hours_without_data=hours_without_data, 340 ) 341 342 prepare_job_state.additional_properties = d 343 return prepare_job_state
18@_attrs_define 19class PrepareJobStateHoursWithoutDataItem: 20 """ 21 Attributes: 22 hour (datetime.datetime | Unset): The hour (UTC, hour-aligned) that has no data. Example: 2026-04-14T02:00:00Z. 23 expected (int | Unset): Expected row count for the hour (currently always 0; reserved for 24 future use). The rationale never depends on it. 25 rationale (PrepareJobStateHoursWithoutDataItemRationale | Unset): Why the hour has no data. 26 `pending_conversion`: data for this hour is 27 still being produced — a re-poll may fill it. `low_activity`: the 28 instrument did not trade that hour. `unknown`: no data to classify by. 29 Example: low_activity. 30 """ 31 32 hour: datetime.datetime | Unset = UNSET 33 expected: int | Unset = UNSET 34 rationale: PrepareJobStateHoursWithoutDataItemRationale | Unset = UNSET 35 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 36 37 def to_dict(self) -> dict[str, Any]: 38 hour: str | Unset = UNSET 39 if not isinstance(self.hour, Unset): 40 hour = self.hour.isoformat() 41 42 expected = self.expected 43 44 rationale: str | Unset = UNSET 45 if not isinstance(self.rationale, Unset): 46 rationale = self.rationale.value 47 48 field_dict: dict[str, Any] = {} 49 field_dict.update(self.additional_properties) 50 field_dict.update({}) 51 if hour is not UNSET: 52 field_dict["hour"] = hour 53 if expected is not UNSET: 54 field_dict["expected"] = expected 55 if rationale is not UNSET: 56 field_dict["rationale"] = rationale 57 58 return field_dict 59 60 @classmethod 61 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 62 d = dict(src_dict) 63 _hour = d.pop("hour", UNSET) 64 hour: datetime.datetime | Unset 65 if isinstance(_hour, Unset): 66 hour = UNSET 67 else: 68 hour = isoparse(_hour) 69 70 expected = d.pop("expected", UNSET) 71 72 _rationale = d.pop("rationale", UNSET) 73 rationale: PrepareJobStateHoursWithoutDataItemRationale | Unset 74 if isinstance(_rationale, Unset): 75 rationale = UNSET 76 else: 77 rationale = PrepareJobStateHoursWithoutDataItemRationale(_rationale) 78 79 prepare_job_state_hours_without_data_item = cls( 80 hour=hour, 81 expected=expected, 82 rationale=rationale, 83 ) 84 85 prepare_job_state_hours_without_data_item.additional_properties = d 86 return prepare_job_state_hours_without_data_item 87 88 @property 89 def additional_keys(self) -> list[str]: 90 return list(self.additional_properties.keys()) 91 92 def __getitem__(self, key: str) -> Any: 93 return self.additional_properties[key] 94 95 def __setitem__(self, key: str, value: Any) -> None: 96 self.additional_properties[key] = value 97 98 def __delitem__(self, key: str) -> None: 99 del self.additional_properties[key] 100 101 def __contains__(self, key: str) -> bool: 102 return key in self.additional_properties
Attributes:
hour (datetime.datetime | Unset): The hour (UTC, hour-aligned) that has no data. Example: 2026-04-14T02:00:00Z.
expected (int | Unset): Expected row count for the hour (currently always 0; reserved for
future use). The rationale never depends on it.
rationale (PrepareJobStateHoursWithoutDataItemRationale | Unset): Why the hour has no data.
pending_conversion: data for this hour is
still being produced — a re-poll may fill it. low_activity: the
instrument did not trade that hour. unknown: no data to classify by.
Example: low_activity.
26def __init__(self, hour=attr_dict['hour'].default, expected=attr_dict['expected'].default, rationale=attr_dict['rationale'].default): 27 self.hour = hour 28 self.expected = expected 29 self.rationale = rationale 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PrepareJobStateHoursWithoutDataItem.
37 def to_dict(self) -> dict[str, Any]: 38 hour: str | Unset = UNSET 39 if not isinstance(self.hour, Unset): 40 hour = self.hour.isoformat() 41 42 expected = self.expected 43 44 rationale: str | Unset = UNSET 45 if not isinstance(self.rationale, Unset): 46 rationale = self.rationale.value 47 48 field_dict: dict[str, Any] = {} 49 field_dict.update(self.additional_properties) 50 field_dict.update({}) 51 if hour is not UNSET: 52 field_dict["hour"] = hour 53 if expected is not UNSET: 54 field_dict["expected"] = expected 55 if rationale is not UNSET: 56 field_dict["rationale"] = rationale 57 58 return field_dict
60 @classmethod 61 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 62 d = dict(src_dict) 63 _hour = d.pop("hour", UNSET) 64 hour: datetime.datetime | Unset 65 if isinstance(_hour, Unset): 66 hour = UNSET 67 else: 68 hour = isoparse(_hour) 69 70 expected = d.pop("expected", UNSET) 71 72 _rationale = d.pop("rationale", UNSET) 73 rationale: PrepareJobStateHoursWithoutDataItemRationale | Unset 74 if isinstance(_rationale, Unset): 75 rationale = UNSET 76 else: 77 rationale = PrepareJobStateHoursWithoutDataItemRationale(_rationale) 78 79 prepare_job_state_hours_without_data_item = cls( 80 hour=hour, 81 expected=expected, 82 rationale=rationale, 83 ) 84 85 prepare_job_state_hours_without_data_item.additional_properties = d 86 return prepare_job_state_hours_without_data_item
5class PrepareJobStateHoursWithoutDataItemRationale(str, Enum): 6 LOW_ACTIVITY = "low_activity" 7 PENDING_CONVERSION = "pending_conversion" 8 UNKNOWN = "unknown" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
15@_attrs_define 16class PrepareRequest: 17 """Two shapes, chosen by the `exchangeId` path segment. Against a managed exchange, 18 `instrument` is required and `datasetId`/`datasetVersionId` are ignored. Against the 19 reserved `exchangeId: user`, send `datasetId` instead of `instrument` — `instrument` is 20 ignored there, since it comes from the dataset itself. 21 22 Example: 23 {'instrument': 'BTC/USDT', 'from': '2024-12-13T00:00:00Z', 'to': '2024-12-14T00:00:00Z', 'cadence': '1m'} 24 25 Attributes: 26 from_ (str): Start date for the preparation process. Supports the following formats: 27 - ISO-8601 (e.g. 2024-12-14T23:59:59Z) 28 - ISO DATE (e.g. 2024-12-14) 29 - BASIC ISO DATE (e.g., 20241214) 30 Example: 2024-12-13T00:00:00Z. 31 to (str): End date for the preparation process. Supports the following formats: 32 - ISO-8601 (e.g. 2024-12-14T23:59:59Z) 33 - ISO DATE (e.g. 2024-12-14) 34 - BASIC ISO DATE (e.g., 20241214) 35 Example: 2024-12-14. 36 instrument (str | Unset): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT. 37 dataset_id (str | Unset): Only for `exchangeId: user`: the id of a dataset created via `POST /datasets`, in 38 place 39 of `instrument`. Ignored against a managed exchange. 40 Example: ds_3f9a1c2e7b0d4a5f. 41 dataset_version_id (str | Unset): Only for `exchangeId: user`, and optional even then: pins a specific past 42 version of 43 the dataset instead of its current one. Defaults to the dataset's current version. 44 Example: dsv_8e2b4f19c6a03d7e. 45 cadence (str | Unset): Output bar cadence for the prepared range. Coarser cadences are produced on demand by 46 resampling the source and stored alongside the native blob in cache. A target finer 47 than the source, or not an exact multiple of it, returns `400`. What's accepted, and 48 what omitting it means, depends on the source: 49 50 * Managed exchange, `ticker` or `funding` — one of `1s`, `5s`, `1m`, `3m`, `5m`, `15m`, 51 `30m`, `1h`, `2h`, `4h`, `8h`, `12h`, `1d`, `1w`, `1q`; any other label returns `400`. 52 Omitted = `1s`, the publisher's native cadence. 53 * Managed exchange, `kline` — one of `1s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`; 54 any other label, including `5s`, `3m` and `8h`, returns `400` and names the accepted 55 ones. Omitted = `1s`. This is the width of the bars a run reads: it is chosen here, 56 once, and the same strategy can be run at several cadences by preparing the range at 57 each. 58 * Dataset (`exchangeId: user`) — omitted = the dataset version's own discovered 59 `cadence` (see `DatasetVersion.cadence`), served as-is. Any cadence equal to or 60 coarser than it and an exact multiple of it is accepted, including ones outside the 61 managed-exchange list (e.g. `15s`); an `rt` dataset can be resampled to any fixed 62 cadence. 63 """ 64 65 from_: str 66 to: str 67 instrument: str | Unset = UNSET 68 dataset_id: str | Unset = UNSET 69 dataset_version_id: str | Unset = UNSET 70 cadence: str | Unset = UNSET 71 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 72 73 def to_dict(self) -> dict[str, Any]: 74 from_ = self.from_ 75 76 to = self.to 77 78 instrument = self.instrument 79 80 dataset_id = self.dataset_id 81 82 dataset_version_id = self.dataset_version_id 83 84 cadence = self.cadence 85 86 field_dict: dict[str, Any] = {} 87 field_dict.update(self.additional_properties) 88 field_dict.update( 89 { 90 "from": from_, 91 "to": to, 92 } 93 ) 94 if instrument is not UNSET: 95 field_dict["instrument"] = instrument 96 if dataset_id is not UNSET: 97 field_dict["datasetId"] = dataset_id 98 if dataset_version_id is not UNSET: 99 field_dict["datasetVersionId"] = dataset_version_id 100 if cadence is not UNSET: 101 field_dict["cadence"] = cadence 102 103 return field_dict 104 105 @classmethod 106 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 107 d = dict(src_dict) 108 from_ = d.pop("from") 109 110 to = d.pop("to") 111 112 instrument = d.pop("instrument", UNSET) 113 114 dataset_id = d.pop("datasetId", UNSET) 115 116 dataset_version_id = d.pop("datasetVersionId", UNSET) 117 118 cadence = d.pop("cadence", UNSET) 119 120 prepare_request = cls( 121 from_=from_, 122 to=to, 123 instrument=instrument, 124 dataset_id=dataset_id, 125 dataset_version_id=dataset_version_id, 126 cadence=cadence, 127 ) 128 129 prepare_request.additional_properties = d 130 return prepare_request 131 132 @property 133 def additional_keys(self) -> list[str]: 134 return list(self.additional_properties.keys()) 135 136 def __getitem__(self, key: str) -> Any: 137 return self.additional_properties[key] 138 139 def __setitem__(self, key: str, value: Any) -> None: 140 self.additional_properties[key] = value 141 142 def __delitem__(self, key: str) -> None: 143 del self.additional_properties[key] 144 145 def __contains__(self, key: str) -> bool: 146 return key in self.additional_properties
Two shapes, chosen by the exchangeId path segment. Against a managed exchange,
instrument is required and datasetId/datasetVersionId are ignored. Against the
reserved exchangeId: user, send datasetId instead of instrument — instrument is
ignored there, since it comes from the dataset itself.
Example:
{'instrument': 'BTC/USDT', 'from': '2024-12-13T00:00:00Z', 'to': '2024-12-14T00:00:00Z', 'cadence': '1m'}
Attributes:
from_ (str): Start date for the preparation process. Supports the following formats:
- ISO-8601 (e.g. 2024-12-14T23:59:59Z)
- ISO DATE (e.g. 2024-12-14)
- BASIC ISO DATE (e.g., 20241214)
Example: 2024-12-13T00:00:00Z.
to (str): End date for the preparation process. Supports the following formats:
- ISO-8601 (e.g. 2024-12-14T23:59:59Z)
- ISO DATE (e.g. 2024-12-14)
- BASIC ISO DATE (e.g., 20241214)
Example: 2024-12-14.
instrument (str | Unset): Exchange instrument identifier (e.g. a currency pair) Example: BTC/USDT.
dataset_id (str | Unset): Only for `exchangeId: user`: the id of a dataset created via `POST /datasets`, in
place
of `instrument`. Ignored against a managed exchange.
Example: ds_3f9a1c2e7b0d4a5f.
dataset_version_id (str | Unset): Only for `exchangeId: user`, and optional even then: pins a specific past
version of
the dataset instead of its current one. Defaults to the dataset's current version.
Example: dsv_8e2b4f19c6a03d7e.
cadence (str | Unset): Output bar cadence for the prepared range. Coarser cadences are produced on demand by
resampling the source and stored alongside the native blob in cache. A target finer
than the source, or not an exact multiple of it, returns `400`. What's accepted, and
what omitting it means, depends on the source:
* Managed exchange, `ticker` or `funding` — one of `1s`, `5s`, `1m`, `3m`, `5m`, `15m`,
`30m`, `1h`, `2h`, `4h`, `8h`, `12h`, `1d`, `1w`, `1q`; any other label returns `400`.
Omitted = `1s`, the publisher's native cadence.
* Managed exchange, `kline` — one of `1s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`;
any other label, including `5s`, `3m` and `8h`, returns `400` and names the accepted
ones. Omitted = `1s`. This is the width of the bars a run reads: it is chosen here,
once, and the same strategy can be run at several cadences by preparing the range at
each.
* Dataset (`exchangeId: user`) — omitted = the dataset version's own discovered
`cadence` (see `DatasetVersion.cadence`), served as-is. Any cadence equal to or
coarser than it and an exact multiple of it is accepted, including ones outside the
managed-exchange list (e.g. `15s`); an `rt` dataset can be resampled to any fixed
cadence.
29def __init__(self, from_, to, instrument=attr_dict['instrument'].default, dataset_id=attr_dict['dataset_id'].default, dataset_version_id=attr_dict['dataset_version_id'].default, cadence=attr_dict['cadence'].default): 30 self.from_ = from_ 31 self.to = to 32 self.instrument = instrument 33 self.dataset_id = dataset_id 34 self.dataset_version_id = dataset_version_id 35 self.cadence = cadence 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PrepareRequest.
73 def to_dict(self) -> dict[str, Any]: 74 from_ = self.from_ 75 76 to = self.to 77 78 instrument = self.instrument 79 80 dataset_id = self.dataset_id 81 82 dataset_version_id = self.dataset_version_id 83 84 cadence = self.cadence 85 86 field_dict: dict[str, Any] = {} 87 field_dict.update(self.additional_properties) 88 field_dict.update( 89 { 90 "from": from_, 91 "to": to, 92 } 93 ) 94 if instrument is not UNSET: 95 field_dict["instrument"] = instrument 96 if dataset_id is not UNSET: 97 field_dict["datasetId"] = dataset_id 98 if dataset_version_id is not UNSET: 99 field_dict["datasetVersionId"] = dataset_version_id 100 if cadence is not UNSET: 101 field_dict["cadence"] = cadence 102 103 return field_dict
105 @classmethod 106 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 107 d = dict(src_dict) 108 from_ = d.pop("from") 109 110 to = d.pop("to") 111 112 instrument = d.pop("instrument", UNSET) 113 114 dataset_id = d.pop("datasetId", UNSET) 115 116 dataset_version_id = d.pop("datasetVersionId", UNSET) 117 118 cadence = d.pop("cadence", UNSET) 119 120 prepare_request = cls( 121 from_=from_, 122 to=to, 123 instrument=instrument, 124 dataset_id=dataset_id, 125 dataset_version_id=dataset_version_id, 126 cadence=cadence, 127 ) 128 129 prepare_request.additional_properties = d 130 return prepare_request
19@_attrs_define 20class PublicLiveListLinks: 21 """Present only when another page exists. 22 23 Attributes: 24 next_ (PublicLiveNextLink | Unset): 25 """ 26 27 next_: PublicLiveNextLink | Unset = UNSET 28 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 29 30 def to_dict(self) -> dict[str, Any]: 31 next_: dict[str, Any] | Unset = UNSET 32 if not isinstance(self.next_, Unset): 33 next_ = self.next_.to_dict() 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update({}) 38 if next_ is not UNSET: 39 field_dict["next"] = next_ 40 41 return field_dict 42 43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 from ..models.public_live_next_link import PublicLiveNextLink 46 47 d = dict(src_dict) 48 _next_ = d.pop("next", UNSET) 49 next_: PublicLiveNextLink | Unset 50 if isinstance(_next_, Unset): 51 next_ = UNSET 52 else: 53 next_ = PublicLiveNextLink.from_dict(_next_) 54 55 public_live_list_links = cls( 56 next_=next_, 57 ) 58 59 public_live_list_links.additional_properties = d 60 return public_live_list_links 61 62 @property 63 def additional_keys(self) -> list[str]: 64 return list(self.additional_properties.keys()) 65 66 def __getitem__(self, key: str) -> Any: 67 return self.additional_properties[key] 68 69 def __setitem__(self, key: str, value: Any) -> None: 70 self.additional_properties[key] = value 71 72 def __delitem__(self, key: str) -> None: 73 del self.additional_properties[key] 74 75 def __contains__(self, key: str) -> bool: 76 return key in self.additional_properties
Present only when another page exists.
Attributes: next_ (PublicLiveNextLink | Unset):
24def __init__(self, next_=attr_dict['next_'].default): 25 self.next_ = next_ 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PublicLiveListLinks.
30 def to_dict(self) -> dict[str, Any]: 31 next_: dict[str, Any] | Unset = UNSET 32 if not isinstance(self.next_, Unset): 33 next_ = self.next_.to_dict() 34 35 field_dict: dict[str, Any] = {} 36 field_dict.update(self.additional_properties) 37 field_dict.update({}) 38 if next_ is not UNSET: 39 field_dict["next"] = next_ 40 41 return field_dict
43 @classmethod 44 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 45 from ..models.public_live_next_link import PublicLiveNextLink 46 47 d = dict(src_dict) 48 _next_ = d.pop("next", UNSET) 49 next_: PublicLiveNextLink | Unset 50 if isinstance(_next_, Unset): 51 next_ = UNSET 52 else: 53 next_ = PublicLiveNextLink.from_dict(_next_) 54 55 public_live_list_links = cls( 56 next_=next_, 57 ) 58 59 public_live_list_links.additional_properties = d 60 return public_live_list_links
20@_attrs_define 21class PublicLiveListResponse: 22 """ 23 Attributes: 24 runs (list[PublicLiveRun]): 25 field_links (PublicLiveListLinks | Unset): Present only when another page exists. 26 """ 27 28 runs: list[PublicLiveRun] 29 field_links: PublicLiveListLinks | Unset = UNSET 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 runs = [] 34 for runs_item_data in self.runs: 35 runs_item = runs_item_data.to_dict() 36 runs.append(runs_item) 37 38 field_links: dict[str, Any] | Unset = UNSET 39 if not isinstance(self.field_links, Unset): 40 field_links = self.field_links.to_dict() 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update( 45 { 46 "runs": runs, 47 } 48 ) 49 if field_links is not UNSET: 50 field_dict["_links"] = field_links 51 52 return field_dict 53 54 @classmethod 55 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 56 from ..models.public_live_list_links import PublicLiveListLinks 57 from ..models.public_live_run import PublicLiveRun 58 59 d = dict(src_dict) 60 runs = [] 61 _runs = d.pop("runs") 62 for runs_item_data in _runs: 63 runs_item = PublicLiveRun.from_dict(runs_item_data) 64 65 runs.append(runs_item) 66 67 _field_links = d.pop("_links", UNSET) 68 field_links: PublicLiveListLinks | Unset 69 if isinstance(_field_links, Unset): 70 field_links = UNSET 71 else: 72 field_links = PublicLiveListLinks.from_dict(_field_links) 73 74 public_live_list_response = cls( 75 runs=runs, 76 field_links=field_links, 77 ) 78 79 public_live_list_response.additional_properties = d 80 return public_live_list_response 81 82 @property 83 def additional_keys(self) -> list[str]: 84 return list(self.additional_properties.keys()) 85 86 def __getitem__(self, key: str) -> Any: 87 return self.additional_properties[key] 88 89 def __setitem__(self, key: str, value: Any) -> None: 90 self.additional_properties[key] = value 91 92 def __delitem__(self, key: str) -> None: 93 del self.additional_properties[key] 94 95 def __contains__(self, key: str) -> bool: 96 return key in self.additional_properties
Attributes: runs (list[PublicLiveRun]): field_links (PublicLiveListLinks | Unset): Present only when another page exists.
25def __init__(self, runs, field_links=attr_dict['field_links'].default): 26 self.runs = runs 27 self.field_links = field_links 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PublicLiveListResponse.
32 def to_dict(self) -> dict[str, Any]: 33 runs = [] 34 for runs_item_data in self.runs: 35 runs_item = runs_item_data.to_dict() 36 runs.append(runs_item) 37 38 field_links: dict[str, Any] | Unset = UNSET 39 if not isinstance(self.field_links, Unset): 40 field_links = self.field_links.to_dict() 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update( 45 { 46 "runs": runs, 47 } 48 ) 49 if field_links is not UNSET: 50 field_dict["_links"] = field_links 51 52 return field_dict
54 @classmethod 55 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 56 from ..models.public_live_list_links import PublicLiveListLinks 57 from ..models.public_live_run import PublicLiveRun 58 59 d = dict(src_dict) 60 runs = [] 61 _runs = d.pop("runs") 62 for runs_item_data in _runs: 63 runs_item = PublicLiveRun.from_dict(runs_item_data) 64 65 runs.append(runs_item) 66 67 _field_links = d.pop("_links", UNSET) 68 field_links: PublicLiveListLinks | Unset 69 if isinstance(_field_links, Unset): 70 field_links = UNSET 71 else: 72 field_links = PublicLiveListLinks.from_dict(_field_links) 73 74 public_live_list_response = cls( 75 runs=runs, 76 field_links=field_links, 77 ) 78 79 public_live_list_response.additional_properties = d 80 return public_live_list_response
15@_attrs_define 16class PublicLiveNextLink: 17 """ 18 Attributes: 19 href (str | Unset): 20 """ 21 22 href: str | Unset = UNSET 23 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 24 25 def to_dict(self) -> dict[str, Any]: 26 href = self.href 27 28 field_dict: dict[str, Any] = {} 29 field_dict.update(self.additional_properties) 30 field_dict.update({}) 31 if href is not UNSET: 32 field_dict["href"] = href 33 34 return field_dict 35 36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 d = dict(src_dict) 39 href = d.pop("href", UNSET) 40 41 public_live_next_link = cls( 42 href=href, 43 ) 44 45 public_live_next_link.additional_properties = d 46 return public_live_next_link 47 48 @property 49 def additional_keys(self) -> list[str]: 50 return list(self.additional_properties.keys()) 51 52 def __getitem__(self, key: str) -> Any: 53 return self.additional_properties[key] 54 55 def __setitem__(self, key: str, value: Any) -> None: 56 self.additional_properties[key] = value 57 58 def __delitem__(self, key: str) -> None: 59 del self.additional_properties[key] 60 61 def __contains__(self, key: str) -> bool: 62 return key in self.additional_properties
Attributes: href (str | Unset):
24def __init__(self, href=attr_dict['href'].default): 25 self.href = href 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PublicLiveNextLink.
19@_attrs_define 20class PublicLiveRun: 21 """A run as it appears in `GET /live/public` — never reveals who owns it or which strategy it runs. 22 23 Attributes: 24 run_id (str): 25 sources (list[LiveSource]): 26 state (str): 27 created_at_ms (int): 28 name (str | Unset): 29 description (str | Unset): 30 """ 31 32 run_id: str 33 sources: list[LiveSource] 34 state: str 35 created_at_ms: int 36 name: str | Unset = UNSET 37 description: str | Unset = UNSET 38 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 39 40 def to_dict(self) -> dict[str, Any]: 41 run_id = self.run_id 42 43 sources = [] 44 for sources_item_data in self.sources: 45 sources_item = sources_item_data.to_dict() 46 sources.append(sources_item) 47 48 state = self.state 49 50 created_at_ms = self.created_at_ms 51 52 name = self.name 53 54 description = self.description 55 56 field_dict: dict[str, Any] = {} 57 field_dict.update(self.additional_properties) 58 field_dict.update( 59 { 60 "runId": run_id, 61 "sources": sources, 62 "state": state, 63 "createdAtMs": created_at_ms, 64 } 65 ) 66 if name is not UNSET: 67 field_dict["name"] = name 68 if description is not UNSET: 69 field_dict["description"] = description 70 71 return field_dict 72 73 @classmethod 74 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 75 from ..models.live_source import LiveSource 76 77 d = dict(src_dict) 78 run_id = d.pop("runId") 79 80 sources = [] 81 _sources = d.pop("sources") 82 for sources_item_data in _sources: 83 sources_item = LiveSource.from_dict(sources_item_data) 84 85 sources.append(sources_item) 86 87 state = d.pop("state") 88 89 created_at_ms = d.pop("createdAtMs") 90 91 name = d.pop("name", UNSET) 92 93 description = d.pop("description", UNSET) 94 95 public_live_run = cls( 96 run_id=run_id, 97 sources=sources, 98 state=state, 99 created_at_ms=created_at_ms, 100 name=name, 101 description=description, 102 ) 103 104 public_live_run.additional_properties = d 105 return public_live_run 106 107 @property 108 def additional_keys(self) -> list[str]: 109 return list(self.additional_properties.keys()) 110 111 def __getitem__(self, key: str) -> Any: 112 return self.additional_properties[key] 113 114 def __setitem__(self, key: str, value: Any) -> None: 115 self.additional_properties[key] = value 116 117 def __delitem__(self, key: str) -> None: 118 del self.additional_properties[key] 119 120 def __contains__(self, key: str) -> bool: 121 return key in self.additional_properties
A run as it appears in GET /live/public — never reveals who owns it or which strategy it runs.
Attributes: run_id (str): sources (list[LiveSource]): state (str): created_at_ms (int): name (str | Unset): description (str | Unset):
29def __init__(self, run_id, sources, state, created_at_ms, name=attr_dict['name'].default, description=attr_dict['description'].default): 30 self.run_id = run_id 31 self.sources = sources 32 self.state = state 33 self.created_at_ms = created_at_ms 34 self.name = name 35 self.description = description 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class PublicLiveRun.
40 def to_dict(self) -> dict[str, Any]: 41 run_id = self.run_id 42 43 sources = [] 44 for sources_item_data in self.sources: 45 sources_item = sources_item_data.to_dict() 46 sources.append(sources_item) 47 48 state = self.state 49 50 created_at_ms = self.created_at_ms 51 52 name = self.name 53 54 description = self.description 55 56 field_dict: dict[str, Any] = {} 57 field_dict.update(self.additional_properties) 58 field_dict.update( 59 { 60 "runId": run_id, 61 "sources": sources, 62 "state": state, 63 "createdAtMs": created_at_ms, 64 } 65 ) 66 if name is not UNSET: 67 field_dict["name"] = name 68 if description is not UNSET: 69 field_dict["description"] = description 70 71 return field_dict
73 @classmethod 74 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 75 from ..models.live_source import LiveSource 76 77 d = dict(src_dict) 78 run_id = d.pop("runId") 79 80 sources = [] 81 _sources = d.pop("sources") 82 for sources_item_data in _sources: 83 sources_item = LiveSource.from_dict(sources_item_data) 84 85 sources.append(sources_item) 86 87 state = d.pop("state") 88 89 created_at_ms = d.pop("createdAtMs") 90 91 name = d.pop("name", UNSET) 92 93 description = d.pop("description", UNSET) 94 95 public_live_run = cls( 96 run_id=run_id, 97 sources=sources, 98 state=state, 99 created_at_ms=created_at_ms, 100 name=name, 101 description=description, 102 ) 103 104 public_live_run.additional_properties = d 105 return public_live_run
13@_attrs_define 14class ResponseError: 15 """General response error 16 17 Attributes: 18 code (int): Status code Example: 400. 19 message (str): Error description Example: Invalid request. 20 """ 21 22 code: int 23 message: str 24 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 25 26 def to_dict(self) -> dict[str, Any]: 27 code = self.code 28 29 message = self.message 30 31 field_dict: dict[str, Any] = {} 32 field_dict.update(self.additional_properties) 33 field_dict.update( 34 { 35 "code": code, 36 "message": message, 37 } 38 ) 39 40 return field_dict 41 42 @classmethod 43 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 44 d = dict(src_dict) 45 code = d.pop("code") 46 47 message = d.pop("message") 48 49 response_error = cls( 50 code=code, 51 message=message, 52 ) 53 54 response_error.additional_properties = d 55 return response_error 56 57 @property 58 def additional_keys(self) -> list[str]: 59 return list(self.additional_properties.keys()) 60 61 def __getitem__(self, key: str) -> Any: 62 return self.additional_properties[key] 63 64 def __setitem__(self, key: str, value: Any) -> None: 65 self.additional_properties[key] = value 66 67 def __delitem__(self, key: str) -> None: 68 del self.additional_properties[key] 69 70 def __contains__(self, key: str) -> bool: 71 return key in self.additional_properties
General response error
Attributes: code (int): Status code Example: 400. message (str): Error description Example: Invalid request.
25def __init__(self, code, message): 26 self.code = code 27 self.message = message 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ResponseError.
24@_attrs_define 25class ResultMap: 26 """Execution result map. Always includes core fields (hostName, iops, strategyId, instrument). Yield metrics (pnlTotal, 27 pnlTotalPercent, totalTrades, winRate, equityCurve, etc.) are present when the strategy emitted at least one trade. 28 When signal storage is enabled, includes signal fields described below. `notices` carries what the run had to say 29 about itself, and is absent when it had nothing. 30 31 Attributes: 32 strategy_id (str): **Not the `strategyId` you compiled with** — this is the execution context id, 33 `strategy:<user>:<strategyId>`. The compiled strategy's id is the last `:`-separated 34 segment; that, not this whole string, is what `GET /strategy/{strategyId}` takes. 35 36 Take the segment after the last `:` rather than counting from the front: the shape has 37 changed once already and callers that indexed a fixed position broke on it. 38 Example: strategy:00000000-0000-0000-0000-000000000000:2iyvtenlzh9dabqtxn7nbv. 39 instrument (str): The instrument (currency pair) that was backtested Example: BTC/USDT. 40 host_name (str | Unset): Identifier of the worker that executed the strategy. Useful when reporting issues so 41 support can correlate with logs. Example: executor10. 42 iops (float | Unset): Instrument operations per second throughput during execution Example: 123956.53. 43 notices (list[Notice] | Unset): Diagnostics the engine raised over this run, each with `provenance: execute`. 44 45 **Absent means nothing was raised.** This is the one surface where silence is a real 46 answer: the run happened, over your data, start to finish, and the engine found nothing 47 worth saying. That is not true of the compile path, where an empty list only means a 48 short synthetic series reached nothing — see `GET /strategy/{strategyId}`. 49 50 Notices are raised on failed and aborted runs too, and those are the ones most worth 51 reading: a run that produced no trades often did so for a reason stated here. 52 notices_truncated (int | Unset): How many notices were dropped past the cap of 50. Absent when none were. A 53 large value usually means one fault repeating per instrument or per parameter vector rather than 50 distinct 54 problems. Example: 3. 55 pnl_total (float | Unset): Total profit and loss in the output currency Example: 42.75. 56 pnl_total_percent (float | Unset): Total PnL as a percentage of the initial capital (`backtestFunding`). Zero 57 when `backtestFunding` is 0. Example: 42.75. 58 total_trades (int | Unset): Total number of trades executed by the strategy Example: 156. 59 win_rate (float | Unset): Fraction of profitable trades, 0.0-1.0 (a rate, not a percent — multiply by 100 to 60 display as one). Zero when `totalTrades` is 0. Example: 0.5833. 61 sharpe_ratio (float | Unset): Risk-adjusted return ratio (mean return / standard deviation of returns) Example: 62 1.245. 63 sortino_ratio (float | Unset): Downside risk-adjusted return ratio (mean return / downside deviation) Example: 64 1.872. 65 cagr (float | Unset): Compound Annual Growth Rate (eg. 0.15 for 15%) Example: 0.1534. 66 max_drawdown (float | Unset): Maximum absolute drawdown in the output currency Example: 12.5. 67 max_drawdown_percent (float | Unset): Maximum percentage drawdown from peak equity Example: 8.75. 68 equity_curve (EquityCurveResult | Unset): An equity curve, shaped per `meta.outMode`: `points` when `ARRAY`, 69 `timestamps` + `equities` (parallel arrays) when `SHORT`. Used identically wherever a curve is returned — a 70 plain backtest's inline `equityCurve` and a sweep row's `equityCurve` are the same type. `url` is present 71 *instead of* any points when the curve is served by pointer rather than inline (a sweep row's top-N winners 72 only): `GET` it separately to fetch this exact same shape with the points populated. 73 params (ResultMapParams | Unset): The strategy properties this run was given, echoed back as sent. Absent when 74 the request carried none, so its presence is what distinguishes a parameterised run from one at the declared 75 defaults — a stored result cannot otherwise say which vector produced it, and this endpoint is meant to be 76 called repeatedly over one prepare. Example: {'ema.fast.period': 9, 'ema.slow.period': 21}. 77 signal_count (int | Unset): Number of signals emitted during strategy execution Example: 100000. 78 signals_id (str | Unset): Storage key for the signals file. Treat as opaque; use signalsUrl to download. 79 Example: 00000000-0000-0000-0000-000000000000/exec/binance/3vsndwikcuaatjmb83fjtl. 80 signals_url (str | Unset): HTTPS URL to download the signals Parquet file. Use signalsUpload to know when it's 81 ready. Example: 82 https://storage.qtsurfer.com/00000000-0000-0000-0000-000000000000/exec/binance/3vsndwikcuaatjmb83fjtl.parquet. 83 signals_upload (ResultMapSignalsUpload | Unset): Upload status. Done = signal file is available at signalsUrl. 84 Failed = upload error (see signalsUploadReason). Skipped = no signals emitted. Example: Done. 85 signals_uploaded_at (datetime.datetime | Unset): ISO 8601 timestamp of when the upload completed. Only present 86 when signalsUpload is Done. Example: 2026-03-18T13:21:48.170Z. 87 signals_upload_reason (str | Unset): Human-readable reason when signalsUpload is Failed or Skipped. Example: 88 signal file generation failed. 89 """ 90 91 strategy_id: str 92 instrument: str 93 host_name: str | Unset = UNSET 94 iops: float | Unset = UNSET 95 notices: list[Notice] | Unset = UNSET 96 notices_truncated: int | Unset = UNSET 97 pnl_total: float | Unset = UNSET 98 pnl_total_percent: float | Unset = UNSET 99 total_trades: int | Unset = UNSET 100 win_rate: float | Unset = UNSET 101 sharpe_ratio: float | Unset = UNSET 102 sortino_ratio: float | Unset = UNSET 103 cagr: float | Unset = UNSET 104 max_drawdown: float | Unset = UNSET 105 max_drawdown_percent: float | Unset = UNSET 106 equity_curve: EquityCurveResult | Unset = UNSET 107 params: ResultMapParams | Unset = UNSET 108 signal_count: int | Unset = UNSET 109 signals_id: str | Unset = UNSET 110 signals_url: str | Unset = UNSET 111 signals_upload: ResultMapSignalsUpload | Unset = UNSET 112 signals_uploaded_at: datetime.datetime | Unset = UNSET 113 signals_upload_reason: str | Unset = UNSET 114 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 115 116 def to_dict(self) -> dict[str, Any]: 117 strategy_id = self.strategy_id 118 119 instrument = self.instrument 120 121 host_name = self.host_name 122 123 iops = self.iops 124 125 notices: list[dict[str, Any]] | Unset = UNSET 126 if not isinstance(self.notices, Unset): 127 notices = [] 128 for notices_item_data in self.notices: 129 notices_item = notices_item_data.to_dict() 130 notices.append(notices_item) 131 132 notices_truncated = self.notices_truncated 133 134 pnl_total = self.pnl_total 135 136 pnl_total_percent = self.pnl_total_percent 137 138 total_trades = self.total_trades 139 140 win_rate = self.win_rate 141 142 sharpe_ratio = self.sharpe_ratio 143 144 sortino_ratio = self.sortino_ratio 145 146 cagr = self.cagr 147 148 max_drawdown = self.max_drawdown 149 150 max_drawdown_percent = self.max_drawdown_percent 151 152 equity_curve: dict[str, Any] | Unset = UNSET 153 if not isinstance(self.equity_curve, Unset): 154 equity_curve = self.equity_curve.to_dict() 155 156 params: dict[str, Any] | Unset = UNSET 157 if not isinstance(self.params, Unset): 158 params = self.params.to_dict() 159 160 signal_count = self.signal_count 161 162 signals_id = self.signals_id 163 164 signals_url = self.signals_url 165 166 signals_upload: str | Unset = UNSET 167 if not isinstance(self.signals_upload, Unset): 168 signals_upload = self.signals_upload.value 169 170 signals_uploaded_at: str | Unset = UNSET 171 if not isinstance(self.signals_uploaded_at, Unset): 172 signals_uploaded_at = self.signals_uploaded_at.isoformat() 173 174 signals_upload_reason = self.signals_upload_reason 175 176 field_dict: dict[str, Any] = {} 177 field_dict.update(self.additional_properties) 178 field_dict.update( 179 { 180 "strategyId": strategy_id, 181 "instrument": instrument, 182 } 183 ) 184 if host_name is not UNSET: 185 field_dict["hostName"] = host_name 186 if iops is not UNSET: 187 field_dict["iops"] = iops 188 if notices is not UNSET: 189 field_dict["notices"] = notices 190 if notices_truncated is not UNSET: 191 field_dict["noticesTruncated"] = notices_truncated 192 if pnl_total is not UNSET: 193 field_dict["pnlTotal"] = pnl_total 194 if pnl_total_percent is not UNSET: 195 field_dict["pnlTotalPercent"] = pnl_total_percent 196 if total_trades is not UNSET: 197 field_dict["totalTrades"] = total_trades 198 if win_rate is not UNSET: 199 field_dict["winRate"] = win_rate 200 if sharpe_ratio is not UNSET: 201 field_dict["sharpeRatio"] = sharpe_ratio 202 if sortino_ratio is not UNSET: 203 field_dict["sortinoRatio"] = sortino_ratio 204 if cagr is not UNSET: 205 field_dict["cagr"] = cagr 206 if max_drawdown is not UNSET: 207 field_dict["maxDrawdown"] = max_drawdown 208 if max_drawdown_percent is not UNSET: 209 field_dict["maxDrawdownPercent"] = max_drawdown_percent 210 if equity_curve is not UNSET: 211 field_dict["equityCurve"] = equity_curve 212 if params is not UNSET: 213 field_dict["params"] = params 214 if signal_count is not UNSET: 215 field_dict["signalCount"] = signal_count 216 if signals_id is not UNSET: 217 field_dict["signalsId"] = signals_id 218 if signals_url is not UNSET: 219 field_dict["signalsUrl"] = signals_url 220 if signals_upload is not UNSET: 221 field_dict["signalsUpload"] = signals_upload 222 if signals_uploaded_at is not UNSET: 223 field_dict["signalsUploadedAt"] = signals_uploaded_at 224 if signals_upload_reason is not UNSET: 225 field_dict["signalsUploadReason"] = signals_upload_reason 226 227 return field_dict 228 229 @classmethod 230 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 231 from ..models.equity_curve_result import EquityCurveResult 232 from ..models.notice import Notice 233 from ..models.result_map_params import ResultMapParams 234 235 d = dict(src_dict) 236 strategy_id = d.pop("strategyId") 237 238 instrument = d.pop("instrument") 239 240 host_name = d.pop("hostName", UNSET) 241 242 iops = d.pop("iops", UNSET) 243 244 _notices = d.pop("notices", UNSET) 245 notices: list[Notice] | Unset = UNSET 246 if _notices is not UNSET: 247 notices = [] 248 for notices_item_data in _notices: 249 notices_item = Notice.from_dict(notices_item_data) 250 251 notices.append(notices_item) 252 253 notices_truncated = d.pop("noticesTruncated", UNSET) 254 255 pnl_total = d.pop("pnlTotal", UNSET) 256 257 pnl_total_percent = d.pop("pnlTotalPercent", UNSET) 258 259 total_trades = d.pop("totalTrades", UNSET) 260 261 win_rate = d.pop("winRate", UNSET) 262 263 sharpe_ratio = d.pop("sharpeRatio", UNSET) 264 265 sortino_ratio = d.pop("sortinoRatio", UNSET) 266 267 cagr = d.pop("cagr", UNSET) 268 269 max_drawdown = d.pop("maxDrawdown", UNSET) 270 271 max_drawdown_percent = d.pop("maxDrawdownPercent", UNSET) 272 273 _equity_curve = d.pop("equityCurve", UNSET) 274 equity_curve: EquityCurveResult | Unset 275 if isinstance(_equity_curve, Unset): 276 equity_curve = UNSET 277 else: 278 equity_curve = EquityCurveResult.from_dict(_equity_curve) 279 280 _params = d.pop("params", UNSET) 281 params: ResultMapParams | Unset 282 if isinstance(_params, Unset): 283 params = UNSET 284 else: 285 params = ResultMapParams.from_dict(_params) 286 287 signal_count = d.pop("signalCount", UNSET) 288 289 signals_id = d.pop("signalsId", UNSET) 290 291 signals_url = d.pop("signalsUrl", UNSET) 292 293 _signals_upload = d.pop("signalsUpload", UNSET) 294 signals_upload: ResultMapSignalsUpload | Unset 295 if isinstance(_signals_upload, Unset): 296 signals_upload = UNSET 297 else: 298 signals_upload = ResultMapSignalsUpload(_signals_upload) 299 300 _signals_uploaded_at = d.pop("signalsUploadedAt", UNSET) 301 signals_uploaded_at: datetime.datetime | Unset 302 if isinstance(_signals_uploaded_at, Unset): 303 signals_uploaded_at = UNSET 304 else: 305 signals_uploaded_at = isoparse(_signals_uploaded_at) 306 307 signals_upload_reason = d.pop("signalsUploadReason", UNSET) 308 309 result_map = cls( 310 strategy_id=strategy_id, 311 instrument=instrument, 312 host_name=host_name, 313 iops=iops, 314 notices=notices, 315 notices_truncated=notices_truncated, 316 pnl_total=pnl_total, 317 pnl_total_percent=pnl_total_percent, 318 total_trades=total_trades, 319 win_rate=win_rate, 320 sharpe_ratio=sharpe_ratio, 321 sortino_ratio=sortino_ratio, 322 cagr=cagr, 323 max_drawdown=max_drawdown, 324 max_drawdown_percent=max_drawdown_percent, 325 equity_curve=equity_curve, 326 params=params, 327 signal_count=signal_count, 328 signals_id=signals_id, 329 signals_url=signals_url, 330 signals_upload=signals_upload, 331 signals_uploaded_at=signals_uploaded_at, 332 signals_upload_reason=signals_upload_reason, 333 ) 334 335 result_map.additional_properties = d 336 return result_map 337 338 @property 339 def additional_keys(self) -> list[str]: 340 return list(self.additional_properties.keys()) 341 342 def __getitem__(self, key: str) -> Any: 343 return self.additional_properties[key] 344 345 def __setitem__(self, key: str, value: Any) -> None: 346 self.additional_properties[key] = value 347 348 def __delitem__(self, key: str) -> None: 349 del self.additional_properties[key] 350 351 def __contains__(self, key: str) -> bool: 352 return key in self.additional_properties
Execution result map. Always includes core fields (hostName, iops, strategyId, instrument). Yield metrics (pnlTotal,
pnlTotalPercent, totalTrades, winRate, equityCurve, etc.) are present when the strategy emitted at least one trade.
When signal storage is enabled, includes signal fields described below. notices carries what the run had to say
about itself, and is absent when it had nothing.
Attributes:
strategy_id (str): **Not the `strategyId` you compiled with** — this is the execution context id,
`strategy:<user>:<strategyId>`. The compiled strategy's id is the last `:`-separated
segment; that, not this whole string, is what `GET /strategy/{strategyId}` takes.
Take the segment after the last `:` rather than counting from the front: the shape has
changed once already and callers that indexed a fixed position broke on it.
Example: strategy:00000000-0000-0000-0000-000000000000:2iyvtenlzh9dabqtxn7nbv.
instrument (str): The instrument (currency pair) that was backtested Example: BTC/USDT.
host_name (str | Unset): Identifier of the worker that executed the strategy. Useful when reporting issues so
support can correlate with logs. Example: executor10.
iops (float | Unset): Instrument operations per second throughput during execution Example: 123956.53.
notices (list[Notice] | Unset): Diagnostics the engine raised over this run, each with `provenance: execute`.
**Absent means nothing was raised.** This is the one surface where silence is a real
answer: the run happened, over your data, start to finish, and the engine found nothing
worth saying. That is not true of the compile path, where an empty list only means a
short synthetic series reached nothing — see `GET /strategy/{strategyId}`.
Notices are raised on failed and aborted runs too, and those are the ones most worth
reading: a run that produced no trades often did so for a reason stated here.
notices_truncated (int | Unset): How many notices were dropped past the cap of 50. Absent when none were. A
large value usually means one fault repeating per instrument or per parameter vector rather than 50 distinct
problems. Example: 3.
pnl_total (float | Unset): Total profit and loss in the output currency Example: 42.75.
pnl_total_percent (float | Unset): Total PnL as a percentage of the initial capital (`backtestFunding`). Zero
when `backtestFunding` is 0. Example: 42.75.
total_trades (int | Unset): Total number of trades executed by the strategy Example: 156.
win_rate (float | Unset): Fraction of profitable trades, 0.0-1.0 (a rate, not a percent — multiply by 100 to
display as one). Zero when `totalTrades` is 0. Example: 0.5833.
sharpe_ratio (float | Unset): Risk-adjusted return ratio (mean return / standard deviation of returns) Example:
1.245.
sortino_ratio (float | Unset): Downside risk-adjusted return ratio (mean return / downside deviation) Example:
1.872.
cagr (float | Unset): Compound Annual Growth Rate (eg. 0.15 for 15%) Example: 0.1534.
max_drawdown (float | Unset): Maximum absolute drawdown in the output currency Example: 12.5.
max_drawdown_percent (float | Unset): Maximum percentage drawdown from peak equity Example: 8.75.
equity_curve (EquityCurveResult | Unset): An equity curve, shaped per `meta.outMode`: `points` when `ARRAY`,
`timestamps` + `equities` (parallel arrays) when `SHORT`. Used identically wherever a curve is returned — a
plain backtest's inline `equityCurve` and a sweep row's `equityCurve` are the same type. `url` is present
*instead of* any points when the curve is served by pointer rather than inline (a sweep row's top-N winners
only): `GET` it separately to fetch this exact same shape with the points populated.
params (ResultMapParams | Unset): The strategy properties this run was given, echoed back as sent. Absent when
the request carried none, so its presence is what distinguishes a parameterised run from one at the declared
defaults — a stored result cannot otherwise say which vector produced it, and this endpoint is meant to be
called repeatedly over one prepare. Example: {'ema.fast.period': 9, 'ema.slow.period': 21}.
signal_count (int | Unset): Number of signals emitted during strategy execution Example: 100000.
signals_id (str | Unset): Storage key for the signals file. Treat as opaque; use signalsUrl to download.
Example: 00000000-0000-0000-0000-000000000000/exec/binance/3vsndwikcuaatjmb83fjtl.
signals_url (str | Unset): HTTPS URL to download the signals Parquet file. Use signalsUpload to know when it's
ready. Example:
https://storage.qtsurfer.com/00000000-0000-0000-0000-000000000000/exec/binance/3vsndwikcuaatjmb83fjtl.parquet.
signals_upload (ResultMapSignalsUpload | Unset): Upload status. Done = signal file is available at signalsUrl.
Failed = upload error (see signalsUploadReason). Skipped = no signals emitted. Example: Done.
signals_uploaded_at (datetime.datetime | Unset): ISO 8601 timestamp of when the upload completed. Only present
when signalsUpload is Done. Example: 2026-03-18T13:21:48.170Z.
signals_upload_reason (str | Unset): Human-readable reason when signalsUpload is Failed or Skipped. Example:
signal file generation failed.
46def __init__(self, strategy_id, instrument, host_name=attr_dict['host_name'].default, iops=attr_dict['iops'].default, notices=attr_dict['notices'].default, notices_truncated=attr_dict['notices_truncated'].default, pnl_total=attr_dict['pnl_total'].default, pnl_total_percent=attr_dict['pnl_total_percent'].default, total_trades=attr_dict['total_trades'].default, win_rate=attr_dict['win_rate'].default, sharpe_ratio=attr_dict['sharpe_ratio'].default, sortino_ratio=attr_dict['sortino_ratio'].default, cagr=attr_dict['cagr'].default, max_drawdown=attr_dict['max_drawdown'].default, max_drawdown_percent=attr_dict['max_drawdown_percent'].default, equity_curve=attr_dict['equity_curve'].default, params=attr_dict['params'].default, signal_count=attr_dict['signal_count'].default, signals_id=attr_dict['signals_id'].default, signals_url=attr_dict['signals_url'].default, signals_upload=attr_dict['signals_upload'].default, signals_uploaded_at=attr_dict['signals_uploaded_at'].default, signals_upload_reason=attr_dict['signals_upload_reason'].default): 47 self.strategy_id = strategy_id 48 self.instrument = instrument 49 self.host_name = host_name 50 self.iops = iops 51 self.notices = notices 52 self.notices_truncated = notices_truncated 53 self.pnl_total = pnl_total 54 self.pnl_total_percent = pnl_total_percent 55 self.total_trades = total_trades 56 self.win_rate = win_rate 57 self.sharpe_ratio = sharpe_ratio 58 self.sortino_ratio = sortino_ratio 59 self.cagr = cagr 60 self.max_drawdown = max_drawdown 61 self.max_drawdown_percent = max_drawdown_percent 62 self.equity_curve = equity_curve 63 self.params = params 64 self.signal_count = signal_count 65 self.signals_id = signals_id 66 self.signals_url = signals_url 67 self.signals_upload = signals_upload 68 self.signals_uploaded_at = signals_uploaded_at 69 self.signals_upload_reason = signals_upload_reason 70 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class ResultMap.
116 def to_dict(self) -> dict[str, Any]: 117 strategy_id = self.strategy_id 118 119 instrument = self.instrument 120 121 host_name = self.host_name 122 123 iops = self.iops 124 125 notices: list[dict[str, Any]] | Unset = UNSET 126 if not isinstance(self.notices, Unset): 127 notices = [] 128 for notices_item_data in self.notices: 129 notices_item = notices_item_data.to_dict() 130 notices.append(notices_item) 131 132 notices_truncated = self.notices_truncated 133 134 pnl_total = self.pnl_total 135 136 pnl_total_percent = self.pnl_total_percent 137 138 total_trades = self.total_trades 139 140 win_rate = self.win_rate 141 142 sharpe_ratio = self.sharpe_ratio 143 144 sortino_ratio = self.sortino_ratio 145 146 cagr = self.cagr 147 148 max_drawdown = self.max_drawdown 149 150 max_drawdown_percent = self.max_drawdown_percent 151 152 equity_curve: dict[str, Any] | Unset = UNSET 153 if not isinstance(self.equity_curve, Unset): 154 equity_curve = self.equity_curve.to_dict() 155 156 params: dict[str, Any] | Unset = UNSET 157 if not isinstance(self.params, Unset): 158 params = self.params.to_dict() 159 160 signal_count = self.signal_count 161 162 signals_id = self.signals_id 163 164 signals_url = self.signals_url 165 166 signals_upload: str | Unset = UNSET 167 if not isinstance(self.signals_upload, Unset): 168 signals_upload = self.signals_upload.value 169 170 signals_uploaded_at: str | Unset = UNSET 171 if not isinstance(self.signals_uploaded_at, Unset): 172 signals_uploaded_at = self.signals_uploaded_at.isoformat() 173 174 signals_upload_reason = self.signals_upload_reason 175 176 field_dict: dict[str, Any] = {} 177 field_dict.update(self.additional_properties) 178 field_dict.update( 179 { 180 "strategyId": strategy_id, 181 "instrument": instrument, 182 } 183 ) 184 if host_name is not UNSET: 185 field_dict["hostName"] = host_name 186 if iops is not UNSET: 187 field_dict["iops"] = iops 188 if notices is not UNSET: 189 field_dict["notices"] = notices 190 if notices_truncated is not UNSET: 191 field_dict["noticesTruncated"] = notices_truncated 192 if pnl_total is not UNSET: 193 field_dict["pnlTotal"] = pnl_total 194 if pnl_total_percent is not UNSET: 195 field_dict["pnlTotalPercent"] = pnl_total_percent 196 if total_trades is not UNSET: 197 field_dict["totalTrades"] = total_trades 198 if win_rate is not UNSET: 199 field_dict["winRate"] = win_rate 200 if sharpe_ratio is not UNSET: 201 field_dict["sharpeRatio"] = sharpe_ratio 202 if sortino_ratio is not UNSET: 203 field_dict["sortinoRatio"] = sortino_ratio 204 if cagr is not UNSET: 205 field_dict["cagr"] = cagr 206 if max_drawdown is not UNSET: 207 field_dict["maxDrawdown"] = max_drawdown 208 if max_drawdown_percent is not UNSET: 209 field_dict["maxDrawdownPercent"] = max_drawdown_percent 210 if equity_curve is not UNSET: 211 field_dict["equityCurve"] = equity_curve 212 if params is not UNSET: 213 field_dict["params"] = params 214 if signal_count is not UNSET: 215 field_dict["signalCount"] = signal_count 216 if signals_id is not UNSET: 217 field_dict["signalsId"] = signals_id 218 if signals_url is not UNSET: 219 field_dict["signalsUrl"] = signals_url 220 if signals_upload is not UNSET: 221 field_dict["signalsUpload"] = signals_upload 222 if signals_uploaded_at is not UNSET: 223 field_dict["signalsUploadedAt"] = signals_uploaded_at 224 if signals_upload_reason is not UNSET: 225 field_dict["signalsUploadReason"] = signals_upload_reason 226 227 return field_dict
229 @classmethod 230 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 231 from ..models.equity_curve_result import EquityCurveResult 232 from ..models.notice import Notice 233 from ..models.result_map_params import ResultMapParams 234 235 d = dict(src_dict) 236 strategy_id = d.pop("strategyId") 237 238 instrument = d.pop("instrument") 239 240 host_name = d.pop("hostName", UNSET) 241 242 iops = d.pop("iops", UNSET) 243 244 _notices = d.pop("notices", UNSET) 245 notices: list[Notice] | Unset = UNSET 246 if _notices is not UNSET: 247 notices = [] 248 for notices_item_data in _notices: 249 notices_item = Notice.from_dict(notices_item_data) 250 251 notices.append(notices_item) 252 253 notices_truncated = d.pop("noticesTruncated", UNSET) 254 255 pnl_total = d.pop("pnlTotal", UNSET) 256 257 pnl_total_percent = d.pop("pnlTotalPercent", UNSET) 258 259 total_trades = d.pop("totalTrades", UNSET) 260 261 win_rate = d.pop("winRate", UNSET) 262 263 sharpe_ratio = d.pop("sharpeRatio", UNSET) 264 265 sortino_ratio = d.pop("sortinoRatio", UNSET) 266 267 cagr = d.pop("cagr", UNSET) 268 269 max_drawdown = d.pop("maxDrawdown", UNSET) 270 271 max_drawdown_percent = d.pop("maxDrawdownPercent", UNSET) 272 273 _equity_curve = d.pop("equityCurve", UNSET) 274 equity_curve: EquityCurveResult | Unset 275 if isinstance(_equity_curve, Unset): 276 equity_curve = UNSET 277 else: 278 equity_curve = EquityCurveResult.from_dict(_equity_curve) 279 280 _params = d.pop("params", UNSET) 281 params: ResultMapParams | Unset 282 if isinstance(_params, Unset): 283 params = UNSET 284 else: 285 params = ResultMapParams.from_dict(_params) 286 287 signal_count = d.pop("signalCount", UNSET) 288 289 signals_id = d.pop("signalsId", UNSET) 290 291 signals_url = d.pop("signalsUrl", UNSET) 292 293 _signals_upload = d.pop("signalsUpload", UNSET) 294 signals_upload: ResultMapSignalsUpload | Unset 295 if isinstance(_signals_upload, Unset): 296 signals_upload = UNSET 297 else: 298 signals_upload = ResultMapSignalsUpload(_signals_upload) 299 300 _signals_uploaded_at = d.pop("signalsUploadedAt", UNSET) 301 signals_uploaded_at: datetime.datetime | Unset 302 if isinstance(_signals_uploaded_at, Unset): 303 signals_uploaded_at = UNSET 304 else: 305 signals_uploaded_at = isoparse(_signals_uploaded_at) 306 307 signals_upload_reason = d.pop("signalsUploadReason", UNSET) 308 309 result_map = cls( 310 strategy_id=strategy_id, 311 instrument=instrument, 312 host_name=host_name, 313 iops=iops, 314 notices=notices, 315 notices_truncated=notices_truncated, 316 pnl_total=pnl_total, 317 pnl_total_percent=pnl_total_percent, 318 total_trades=total_trades, 319 win_rate=win_rate, 320 sharpe_ratio=sharpe_ratio, 321 sortino_ratio=sortino_ratio, 322 cagr=cagr, 323 max_drawdown=max_drawdown, 324 max_drawdown_percent=max_drawdown_percent, 325 equity_curve=equity_curve, 326 params=params, 327 signal_count=signal_count, 328 signals_id=signals_id, 329 signals_url=signals_url, 330 signals_upload=signals_upload, 331 signals_uploaded_at=signals_uploaded_at, 332 signals_upload_reason=signals_upload_reason, 333 ) 334 335 result_map.additional_properties = d 336 return result_map
13@_attrs_define 14class ResultMapParams: 15 """The strategy properties this run was given, echoed back as sent. Absent when the request carried none, so its 16 presence is what distinguishes a parameterised run from one at the declared defaults — a stored result cannot 17 otherwise say which vector produced it, and this endpoint is meant to be called repeatedly over one prepare. 18 19 Example: 20 {'ema.fast.period': 9, 'ema.slow.period': 21} 21 22 """ 23 24 additional_properties: dict[str, bool | float | str] = _attrs_field(init=False, factory=dict) 25 26 def to_dict(self) -> dict[str, Any]: 27 28 field_dict: dict[str, Any] = {} 29 for prop_name, prop in self.additional_properties.items(): 30 field_dict[prop_name] = prop 31 32 return field_dict 33 34 @classmethod 35 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 36 d = dict(src_dict) 37 result_map_params = cls() 38 39 additional_properties = {} 40 for prop_name, prop_dict in d.items(): 41 42 def _parse_additional_property(data: object) -> bool | float | str: 43 return cast(bool | float | str, data) 44 45 additional_property = _parse_additional_property(prop_dict) 46 47 additional_properties[prop_name] = additional_property 48 49 result_map_params.additional_properties = additional_properties 50 return result_map_params 51 52 @property 53 def additional_keys(self) -> list[str]: 54 return list(self.additional_properties.keys()) 55 56 def __getitem__(self, key: str) -> bool | float | str: 57 return self.additional_properties[key] 58 59 def __setitem__(self, key: str, value: bool | float | str) -> None: 60 self.additional_properties[key] = value 61 62 def __delitem__(self, key: str) -> None: 63 del self.additional_properties[key] 64 65 def __contains__(self, key: str) -> bool: 66 return key in self.additional_properties
The strategy properties this run was given, echoed back as sent. Absent when the request carried none, so its presence is what distinguishes a parameterised run from one at the declared defaults — a stored result cannot otherwise say which vector produced it, and this endpoint is meant to be called repeatedly over one prepare.
Example:
{'ema.fast.period': 9, 'ema.slow.period': 21}
34 @classmethod 35 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 36 d = dict(src_dict) 37 result_map_params = cls() 38 39 additional_properties = {} 40 for prop_name, prop_dict in d.items(): 41 42 def _parse_additional_property(data: object) -> bool | float | str: 43 return cast(bool | float | str, data) 44 45 additional_property = _parse_additional_property(prop_dict) 46 47 additional_properties[prop_name] = additional_property 48 49 result_map_params.additional_properties = additional_properties 50 return result_map_params
5class ResultMapSignalsUpload(str, Enum): 6 DONE = "Done" 7 FAILED = "Failed" 8 SKIPPED = "Skipped" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
19@_attrs_define 20class SendLiveCommandRequest: 21 """ 22 Attributes: 23 command (str): The command's text — non-blank. 24 properties (SendLiveCommandRequestProperties | Unset): An optional map of your own choosing, alongside command. 25 Absent means none; when given, it must be a JSON object, and `command` and `properties` are the only keys the 26 body may carry. Each entry lands as a top-level entry on the strategy's `CommandRequest` — no key is off limits, 27 since the command's own text is kept separately. 28 """ 29 30 command: str 31 properties: SendLiveCommandRequestProperties | Unset = UNSET 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 command = self.command 36 37 properties: dict[str, Any] | Unset = UNSET 38 if not isinstance(self.properties, Unset): 39 properties = self.properties.to_dict() 40 41 field_dict: dict[str, Any] = {} 42 field_dict.update(self.additional_properties) 43 field_dict.update( 44 { 45 "command": command, 46 } 47 ) 48 if properties is not UNSET: 49 field_dict["properties"] = properties 50 51 return field_dict 52 53 @classmethod 54 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 55 from ..models.send_live_command_request_properties import SendLiveCommandRequestProperties 56 57 d = dict(src_dict) 58 command = d.pop("command") 59 60 _properties = d.pop("properties", UNSET) 61 properties: SendLiveCommandRequestProperties | Unset 62 if isinstance(_properties, Unset): 63 properties = UNSET 64 else: 65 properties = SendLiveCommandRequestProperties.from_dict(_properties) 66 67 send_live_command_request = cls( 68 command=command, 69 properties=properties, 70 ) 71 72 send_live_command_request.additional_properties = d 73 return send_live_command_request 74 75 @property 76 def additional_keys(self) -> list[str]: 77 return list(self.additional_properties.keys()) 78 79 def __getitem__(self, key: str) -> Any: 80 return self.additional_properties[key] 81 82 def __setitem__(self, key: str, value: Any) -> None: 83 self.additional_properties[key] = value 84 85 def __delitem__(self, key: str) -> None: 86 del self.additional_properties[key] 87 88 def __contains__(self, key: str) -> bool: 89 return key in self.additional_properties
Attributes:
command (str): The command's text — non-blank.
properties (SendLiveCommandRequestProperties | Unset): An optional map of your own choosing, alongside command.
Absent means none; when given, it must be a JSON object, and command and properties are the only keys the
body may carry. Each entry lands as a top-level entry on the strategy's CommandRequest — no key is off limits,
since the command's own text is kept separately.
25def __init__(self, command, properties=attr_dict['properties'].default): 26 self.command = command 27 self.properties = properties 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SendLiveCommandRequest.
34 def to_dict(self) -> dict[str, Any]: 35 command = self.command 36 37 properties: dict[str, Any] | Unset = UNSET 38 if not isinstance(self.properties, Unset): 39 properties = self.properties.to_dict() 40 41 field_dict: dict[str, Any] = {} 42 field_dict.update(self.additional_properties) 43 field_dict.update( 44 { 45 "command": command, 46 } 47 ) 48 if properties is not UNSET: 49 field_dict["properties"] = properties 50 51 return field_dict
53 @classmethod 54 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 55 from ..models.send_live_command_request_properties import SendLiveCommandRequestProperties 56 57 d = dict(src_dict) 58 command = d.pop("command") 59 60 _properties = d.pop("properties", UNSET) 61 properties: SendLiveCommandRequestProperties | Unset 62 if isinstance(_properties, Unset): 63 properties = UNSET 64 else: 65 properties = SendLiveCommandRequestProperties.from_dict(_properties) 66 67 send_live_command_request = cls( 68 command=command, 69 properties=properties, 70 ) 71 72 send_live_command_request.additional_properties = d 73 return send_live_command_request
13@_attrs_define 14class SendLiveCommandRequestProperties: 15 """An optional map of your own choosing, alongside command. Absent means none; when given, it must be a JSON object, 16 and `command` and `properties` are the only keys the body may carry. Each entry lands as a top-level entry on the 17 strategy's `CommandRequest` — no key is off limits, since the command's own text is kept separately. 18 19 """ 20 21 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 22 23 def to_dict(self) -> dict[str, Any]: 24 25 field_dict: dict[str, Any] = {} 26 field_dict.update(self.additional_properties) 27 28 return field_dict 29 30 @classmethod 31 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 32 d = dict(src_dict) 33 send_live_command_request_properties = cls() 34 35 send_live_command_request_properties.additional_properties = d 36 return send_live_command_request_properties 37 38 @property 39 def additional_keys(self) -> list[str]: 40 return list(self.additional_properties.keys()) 41 42 def __getitem__(self, key: str) -> Any: 43 return self.additional_properties[key] 44 45 def __setitem__(self, key: str, value: Any) -> None: 46 self.additional_properties[key] = value 47 48 def __delitem__(self, key: str) -> None: 49 del self.additional_properties[key] 50 51 def __contains__(self, key: str) -> bool: 52 return key in self.additional_properties
An optional map of your own choosing, alongside command. Absent means none; when given, it must be a JSON object,
and command and properties are the only keys the body may carry. Each entry lands as a top-level entry on the
strategy's CommandRequest — no key is off limits, since the command's own text is kept separately.
Method generated by attrs for class SendLiveCommandRequestProperties.
22@_attrs_define 23class StartLiveRequest: 24 """ 25 Attributes: 26 sources (list[LiveSourceRequest]): 27 params (StartLiveRequestParams | Unset): Strategy parameters to start with. Opaque key/value pairs — see this 28 strategy's own `declaredProperties` (from `POST /strategy`) for the keys it accepts. 29 visibility (StartLiveRequestVisibility | Unset): A `public` run appears in `GET /live/public` and its signal 30 channel accepts subscriptions from anyone, not only you — from the moment it is in the `live` stage, which is 31 when it is promoted or, for a run that starts there, at once. While it is a `sandbox` trial, `public` is only 32 what you asked for, and only you can read it. Default: StartLiveRequestVisibility.PRIVATE. 33 relay (bool | Unset): Request that this run's signals be relayed over its WebSocket channel, from its first 34 signal — in the `sandbox` stage too, where only you can subscribe to it. See the "Live execution" guide. 35 Default: False. 36 sandbox (bool | Unset): Start in the `sandbox` stage even though an earlier run of yours already took this 37 compiled strategy 38 through it. Without it, such a strategy starts in `LIVE` at once; with `true` it starts in `SANDBOX` like 39 a first run, which is how to read its signals back over the connection (`history`, kept for the 40 `sandbox` stage only) while you debug it. For a strategy that has not been through the sandbox it 41 changes nothing: it always starts there. Anything other than `true` or `false` is `400`. 42 Default: False. 43 stream (bool | Unset): Ask for a **stream URL**: a secret address that a simple client, or a service that passes 44 your signals 45 on to others, can open as a plain WebSocket to receive this run's signals as they are produced, one JSON 46 text frame per signal, with none of the live-execution protocol around it. The URL comes back as 47 `streamUrl` in the response to this call. Available from the `sandbox` stage on, on the plans that may 48 broadcast; any other plan gets `429`. It can be asked for **only when the run is started** (not added 49 later), and it also turns `relay` on. See the "Live execution" guide, "A plain WebSocket stream of a run". 50 Default: False. 51 warm_from (int | Unset): How many seconds before the run's start to replay the market feed from, so the 52 strategy's indicators and 53 windows have history when its first live tick arrives. `0` replays nothing: the run delivers its first 54 signal as soon as it is running, but its indicators start empty and the first bar of a window can be 55 partial. Omitted, the platform replays from the start of the current 15-minute block: between 0 and 900 56 seconds before the run's start, depending on when it starts (0 if it starts exactly on a quarter hour), 57 so the first bar of a 15-minute window is complete. The value in effect, the one you sent or the one the 58 platform chose, is reported back as `warmFrom` on the run. Signals about the replayed time 59 are not pushed on the run's channel or stream: they describe events from before the run started. 60 It can be set **only when the run is started**: it is not a parameter of `PUT /live/{runId}/params`, and 61 changing it means stopping the run and starting it again. Anything that is not an integer from 0 to 3600 62 is `400`. See the "Live execution" guide, "Warming up". 63 name (str | Unset): 64 description (str | Unset): 65 paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's `baseConfig` 66 (same fields, 67 defaults and limits), plus `output`. An empty object takes every default. Each quote 68 currency the run trades gets its own simulated account, opened with `initialFunding` in 69 that currency; accounts are never added together. As returned on a run, the block is 70 normalised: `feeRate` is resolved into `buyFeeRate`/`sellFeeRate` and defaults are filled 71 in. 72 """ 73 74 sources: list[LiveSourceRequest] 75 params: StartLiveRequestParams | Unset = UNSET 76 visibility: StartLiveRequestVisibility | Unset = StartLiveRequestVisibility.PRIVATE 77 relay: bool | Unset = False 78 sandbox: bool | Unset = False 79 stream: bool | Unset = False 80 warm_from: int | Unset = UNSET 81 name: str | Unset = UNSET 82 description: str | Unset = UNSET 83 paper: LivePaperConfig | Unset = UNSET 84 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 85 86 def to_dict(self) -> dict[str, Any]: 87 sources = [] 88 for sources_item_data in self.sources: 89 sources_item = sources_item_data.to_dict() 90 sources.append(sources_item) 91 92 params: dict[str, Any] | Unset = UNSET 93 if not isinstance(self.params, Unset): 94 params = self.params.to_dict() 95 96 visibility: str | Unset = UNSET 97 if not isinstance(self.visibility, Unset): 98 visibility = self.visibility.value 99 100 relay = self.relay 101 102 sandbox = self.sandbox 103 104 stream = self.stream 105 106 warm_from = self.warm_from 107 108 name = self.name 109 110 description = self.description 111 112 paper: dict[str, Any] | Unset = UNSET 113 if not isinstance(self.paper, Unset): 114 paper = self.paper.to_dict() 115 116 field_dict: dict[str, Any] = {} 117 field_dict.update(self.additional_properties) 118 field_dict.update( 119 { 120 "sources": sources, 121 } 122 ) 123 if params is not UNSET: 124 field_dict["params"] = params 125 if visibility is not UNSET: 126 field_dict["visibility"] = visibility 127 if relay is not UNSET: 128 field_dict["relay"] = relay 129 if sandbox is not UNSET: 130 field_dict["sandbox"] = sandbox 131 if stream is not UNSET: 132 field_dict["stream"] = stream 133 if warm_from is not UNSET: 134 field_dict["warmFrom"] = warm_from 135 if name is not UNSET: 136 field_dict["name"] = name 137 if description is not UNSET: 138 field_dict["description"] = description 139 if paper is not UNSET: 140 field_dict["paper"] = paper 141 142 return field_dict 143 144 @classmethod 145 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 146 from ..models.live_paper_config import LivePaperConfig 147 from ..models.live_source_request import LiveSourceRequest 148 from ..models.start_live_request_params import StartLiveRequestParams 149 150 d = dict(src_dict) 151 sources = [] 152 _sources = d.pop("sources") 153 for sources_item_data in _sources: 154 sources_item = LiveSourceRequest.from_dict(sources_item_data) 155 156 sources.append(sources_item) 157 158 _params = d.pop("params", UNSET) 159 params: StartLiveRequestParams | Unset 160 if isinstance(_params, Unset): 161 params = UNSET 162 else: 163 params = StartLiveRequestParams.from_dict(_params) 164 165 _visibility = d.pop("visibility", UNSET) 166 visibility: StartLiveRequestVisibility | Unset 167 if isinstance(_visibility, Unset): 168 visibility = UNSET 169 else: 170 visibility = StartLiveRequestVisibility(_visibility) 171 172 relay = d.pop("relay", UNSET) 173 174 sandbox = d.pop("sandbox", UNSET) 175 176 stream = d.pop("stream", UNSET) 177 178 warm_from = d.pop("warmFrom", UNSET) 179 180 name = d.pop("name", UNSET) 181 182 description = d.pop("description", UNSET) 183 184 _paper = d.pop("paper", UNSET) 185 paper: LivePaperConfig | Unset 186 if isinstance(_paper, Unset): 187 paper = UNSET 188 else: 189 paper = LivePaperConfig.from_dict(_paper) 190 191 start_live_request = cls( 192 sources=sources, 193 params=params, 194 visibility=visibility, 195 relay=relay, 196 sandbox=sandbox, 197 stream=stream, 198 warm_from=warm_from, 199 name=name, 200 description=description, 201 paper=paper, 202 ) 203 204 start_live_request.additional_properties = d 205 return start_live_request 206 207 @property 208 def additional_keys(self) -> list[str]: 209 return list(self.additional_properties.keys()) 210 211 def __getitem__(self, key: str) -> Any: 212 return self.additional_properties[key] 213 214 def __setitem__(self, key: str, value: Any) -> None: 215 self.additional_properties[key] = value 216 217 def __delitem__(self, key: str) -> None: 218 del self.additional_properties[key] 219 220 def __contains__(self, key: str) -> bool: 221 return key in self.additional_properties
Attributes:
sources (list[LiveSourceRequest]):
params (StartLiveRequestParams | Unset): Strategy parameters to start with. Opaque key/value pairs — see this
strategy's own declaredProperties (from POST /strategy) for the keys it accepts.
visibility (StartLiveRequestVisibility | Unset): A public run appears in GET /live/public and its signal
channel accepts subscriptions from anyone, not only you — from the moment it is in the live stage, which is
when it is promoted or, for a run that starts there, at once. While it is a sandbox trial, public is only
what you asked for, and only you can read it. Default: StartLiveRequestVisibility.PRIVATE.
relay (bool | Unset): Request that this run's signals be relayed over its WebSocket channel, from its first
signal — in the sandbox stage too, where only you can subscribe to it. See the "Live execution" guide.
Default: False.
sandbox (bool | Unset): Start in the sandbox stage even though an earlier run of yours already took this
compiled strategy
through it. Without it, such a strategy starts in LIVE at once; with true it starts in SANDBOX like
a first run, which is how to read its signals back over the connection (history, kept for the
sandbox stage only) while you debug it. For a strategy that has not been through the sandbox it
changes nothing: it always starts there. Anything other than true or false is 400.
Default: False.
stream (bool | Unset): Ask for a stream URL: a secret address that a simple client, or a service that passes
your signals
on to others, can open as a plain WebSocket to receive this run's signals as they are produced, one JSON
text frame per signal, with none of the live-execution protocol around it. The URL comes back as
streamUrl in the response to this call. Available from the sandbox stage on, on the plans that may
broadcast; any other plan gets 429. It can be asked for only when the run is started (not added
later), and it also turns relay on. See the "Live execution" guide, "A plain WebSocket stream of a run".
Default: False.
warm_from (int | Unset): How many seconds before the run's start to replay the market feed from, so the
strategy's indicators and
windows have history when its first live tick arrives. 0 replays nothing: the run delivers its first
signal as soon as it is running, but its indicators start empty and the first bar of a window can be
partial. Omitted, the platform replays from the start of the current 15-minute block: between 0 and 900
seconds before the run's start, depending on when it starts (0 if it starts exactly on a quarter hour),
so the first bar of a 15-minute window is complete. The value in effect, the one you sent or the one the
platform chose, is reported back as warmFrom on the run. Signals about the replayed time
are not pushed on the run's channel or stream: they describe events from before the run started.
It can be set only when the run is started: it is not a parameter of PUT /live/{runId}/params, and
changing it means stopping the run and starting it again. Anything that is not an integer from 0 to 3600
is 400. See the "Live execution" guide, "Warming up".
name (str | Unset):
description (str | Unset):
paper (LivePaperConfig | Unset): Paper trading for this run: the same economics as a backtest's baseConfig
(same fields,
defaults and limits), plus output. An empty object takes every default. Each quote
currency the run trades gets its own simulated account, opened with initialFunding in
that currency; accounts are never added together. As returned on a run, the block is
normalised: feeRate is resolved into buyFeeRate/sellFeeRate and defaults are filled
in.
33def __init__(self, sources, params=attr_dict['params'].default, visibility=attr_dict['visibility'].default, relay=attr_dict['relay'].default, sandbox=attr_dict['sandbox'].default, stream=attr_dict['stream'].default, warm_from=attr_dict['warm_from'].default, name=attr_dict['name'].default, description=attr_dict['description'].default, paper=attr_dict['paper'].default): 34 self.sources = sources 35 self.params = params 36 self.visibility = visibility 37 self.relay = relay 38 self.sandbox = sandbox 39 self.stream = stream 40 self.warm_from = warm_from 41 self.name = name 42 self.description = description 43 self.paper = paper 44 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class StartLiveRequest.
86 def to_dict(self) -> dict[str, Any]: 87 sources = [] 88 for sources_item_data in self.sources: 89 sources_item = sources_item_data.to_dict() 90 sources.append(sources_item) 91 92 params: dict[str, Any] | Unset = UNSET 93 if not isinstance(self.params, Unset): 94 params = self.params.to_dict() 95 96 visibility: str | Unset = UNSET 97 if not isinstance(self.visibility, Unset): 98 visibility = self.visibility.value 99 100 relay = self.relay 101 102 sandbox = self.sandbox 103 104 stream = self.stream 105 106 warm_from = self.warm_from 107 108 name = self.name 109 110 description = self.description 111 112 paper: dict[str, Any] | Unset = UNSET 113 if not isinstance(self.paper, Unset): 114 paper = self.paper.to_dict() 115 116 field_dict: dict[str, Any] = {} 117 field_dict.update(self.additional_properties) 118 field_dict.update( 119 { 120 "sources": sources, 121 } 122 ) 123 if params is not UNSET: 124 field_dict["params"] = params 125 if visibility is not UNSET: 126 field_dict["visibility"] = visibility 127 if relay is not UNSET: 128 field_dict["relay"] = relay 129 if sandbox is not UNSET: 130 field_dict["sandbox"] = sandbox 131 if stream is not UNSET: 132 field_dict["stream"] = stream 133 if warm_from is not UNSET: 134 field_dict["warmFrom"] = warm_from 135 if name is not UNSET: 136 field_dict["name"] = name 137 if description is not UNSET: 138 field_dict["description"] = description 139 if paper is not UNSET: 140 field_dict["paper"] = paper 141 142 return field_dict
144 @classmethod 145 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 146 from ..models.live_paper_config import LivePaperConfig 147 from ..models.live_source_request import LiveSourceRequest 148 from ..models.start_live_request_params import StartLiveRequestParams 149 150 d = dict(src_dict) 151 sources = [] 152 _sources = d.pop("sources") 153 for sources_item_data in _sources: 154 sources_item = LiveSourceRequest.from_dict(sources_item_data) 155 156 sources.append(sources_item) 157 158 _params = d.pop("params", UNSET) 159 params: StartLiveRequestParams | Unset 160 if isinstance(_params, Unset): 161 params = UNSET 162 else: 163 params = StartLiveRequestParams.from_dict(_params) 164 165 _visibility = d.pop("visibility", UNSET) 166 visibility: StartLiveRequestVisibility | Unset 167 if isinstance(_visibility, Unset): 168 visibility = UNSET 169 else: 170 visibility = StartLiveRequestVisibility(_visibility) 171 172 relay = d.pop("relay", UNSET) 173 174 sandbox = d.pop("sandbox", UNSET) 175 176 stream = d.pop("stream", UNSET) 177 178 warm_from = d.pop("warmFrom", UNSET) 179 180 name = d.pop("name", UNSET) 181 182 description = d.pop("description", UNSET) 183 184 _paper = d.pop("paper", UNSET) 185 paper: LivePaperConfig | Unset 186 if isinstance(_paper, Unset): 187 paper = UNSET 188 else: 189 paper = LivePaperConfig.from_dict(_paper) 190 191 start_live_request = cls( 192 sources=sources, 193 params=params, 194 visibility=visibility, 195 relay=relay, 196 sandbox=sandbox, 197 stream=stream, 198 warm_from=warm_from, 199 name=name, 200 description=description, 201 paper=paper, 202 ) 203 204 start_live_request.additional_properties = d 205 return start_live_request
13@_attrs_define 14class StartLiveRequestParams: 15 """Strategy parameters to start with. Opaque key/value pairs — see this strategy's own `declaredProperties` (from `POST 16 /strategy`) for the keys it accepts. 17 18 """ 19 20 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 21 22 def to_dict(self) -> dict[str, Any]: 23 24 field_dict: dict[str, Any] = {} 25 field_dict.update(self.additional_properties) 26 27 return field_dict 28 29 @classmethod 30 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 31 d = dict(src_dict) 32 start_live_request_params = cls() 33 34 start_live_request_params.additional_properties = d 35 return start_live_request_params 36 37 @property 38 def additional_keys(self) -> list[str]: 39 return list(self.additional_properties.keys()) 40 41 def __getitem__(self, key: str) -> Any: 42 return self.additional_properties[key] 43 44 def __setitem__(self, key: str, value: Any) -> None: 45 self.additional_properties[key] = value 46 47 def __delitem__(self, key: str) -> None: 48 del self.additional_properties[key] 49 50 def __contains__(self, key: str) -> bool: 51 return key in self.additional_properties
Strategy parameters to start with. Opaque key/value pairs — see this strategy's own declaredProperties (from POST
/strategy) for the keys it accepts.
5class StartLiveRequestVisibility(str, Enum): 6 PRIVATE = "private" 7 PUBLIC = "public" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class StrategyLinks: 19 """HAL `_links` for a strategy — present on a full `StrategyState` body (`GET 20 /strategy/{strategyId}`, and `POST /strategy/{strategyId}/validate`'s already-validated 21 `200`), absent from that same endpoint's `202` — a deliberately partial stub carrying only 22 what is known before a check has even started. Following `code` can still `404` once 23 present: it documents its own honest "nothing to return" for a strategy with no source of 24 its own (a `REFERENCE` marketplace copy, or one resolved only through the platform's shared 25 pool). This link says where to look, not that something is there. 26 27 Attributes: 28 code (HalLink): A HAL link object (Hypertext Application Language) 29 """ 30 31 code: HalLink 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 code = self.code.to_dict() 36 37 field_dict: dict[str, Any] = {} 38 field_dict.update(self.additional_properties) 39 field_dict.update( 40 { 41 "code": code, 42 } 43 ) 44 45 return field_dict 46 47 @classmethod 48 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 49 from ..models.hal_link import HalLink 50 51 d = dict(src_dict) 52 code = HalLink.from_dict(d.pop("code")) 53 54 strategy_links = cls( 55 code=code, 56 ) 57 58 strategy_links.additional_properties = d 59 return strategy_links 60 61 @property 62 def additional_keys(self) -> list[str]: 63 return list(self.additional_properties.keys()) 64 65 def __getitem__(self, key: str) -> Any: 66 return self.additional_properties[key] 67 68 def __setitem__(self, key: str, value: Any) -> None: 69 self.additional_properties[key] = value 70 71 def __delitem__(self, key: str) -> None: 72 del self.additional_properties[key] 73 74 def __contains__(self, key: str) -> bool: 75 return key in self.additional_properties
HAL _links for a strategy — present on a full StrategyState body (GET
/strategy/{strategyId}, and POST /strategy/{strategyId}/validate's already-validated
200), absent from that same endpoint's 202 — a deliberately partial stub carrying only
what is known before a check has even started. Following code can still 404 once
present: it documents its own honest "nothing to return" for a strategy with no source of
its own (a REFERENCE marketplace copy, or one resolved only through the platform's shared
pool). This link says where to look, not that something is there.
Attributes:
code (HalLink): A HAL link object (Hypertext Application Language)
24def __init__(self, code): 25 self.code = code 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class StrategyLinks.
47 @classmethod 48 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 49 from ..models.hal_link import HalLink 50 51 d = dict(src_dict) 52 code = HalLink.from_dict(d.pop("code")) 53 54 strategy_links = cls( 55 code=code, 56 ) 57 58 strategy_links.additional_properties = d 59 return strategy_links
24@_attrs_define 25class StrategyState: 26 """What is known about a registered strategy: that it compiled, and what validating it found. 27 28 **`validation: passed` does not mean the strategy is correct.** It means the class loaded and 29 survived the first event of a short synthetic run — a floor, not a guarantee. When 30 `dryRunIncomplete` is true it is a lower floor still, because the run did not finish. 31 32 Example: 33 {'strategyId': '6bsh31ikwkuivhtgcoa6s4', 'validation': 'passed', 'compiledAt': '2026-08-04T16:23:04Z', 34 'requiredSources': ['Ticker'], 'validatedAt': '2026-08-04T16:24:11Z', 'notices': [{'level': 'WARN', 'code': 35 'indicator.bar-data-on-ticker-path', 'message': 'Indicator requires bar data but is on the ticker path', 36 'provenance': 'compile-dry-run'}], '_links': {'code': {'href': '/v1/strategy/6bsh31ikwkuivhtgcoa6s4/code'}}} 37 38 Attributes: 39 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 40 always yields the same id, for every caller. How much formatting the id ignores depends on 41 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 42 not. 43 Example: 6bsh31ikwkuivhtgcoa6s4. 44 validation (StrategyStateValidation): * `not_validated` — registered, never checked. `POST 45 /strategy/{strategyId}/validate` 46 checks it. 47 * `pending` — a check was asked for and has not answered yet. 48 * `passed` — the class loaded and survived its first event. 49 * `failed` — it did not; `detail` says how. 50 Example: passed. 51 compiled_at (datetime.datetime | Unset): When the live compilation was produced. 52 required_sources (list[StrategyStateRequiredSourcesItem] | Unset): The market data a strategy needs, read off 53 the compiled class rather than off anything 54 you sent — `TickerStrategy`, `KlineStrategy` and `FundingRateStrategy` each declare one, 55 and a `MultiSourceStrategy` declares a set. 56 57 **Absent is not "needs nothing".** A strategy always needs market data, so an absent 58 field never means an empty requirement — it means the platform could not establish the 59 answer without constructing your strategy, which it will not do to fill in a field. 60 That happens for a `MultiSourceStrategy`, for a class that overrides 61 `getMarketDataSource()`, and for anything registered before this field existed; 62 re-registering the source fills it in. 63 Example: ['Ticker']. 64 validated_at (datetime.datetime | Unset): When the verdict was recorded. Absent until there is one. 65 detail (str | Unset): Why validation failed, or why a queued check has not reported. Present on `failed`, and 66 alongside `validationStalled`. 67 notices (list[Notice] | Unset): What the run surfaced. An empty or absent list is not a clean bill of health 68 when 69 `dryRunIncomplete` is true — see that field. 70 notices_truncated (int | Unset): How many notices were dropped past the cap. Absent when none were. Example: 3. 71 dry_run_incomplete (bool | Unset): The check did not finish its budget — it ran out of time, was refused because 72 the 73 platform was already holding too many unfinishable runs, or hit a failure attributable to 74 the synthetic instrument rather than to your strategy. The verdict stands as far as it 75 went; it simply reached less than a full run would. 76 validation_stalled (bool | Unset): A queued check has not reported for far longer than one takes. Nothing is 77 disproved about 78 the strategy — the check has not run. Stop waiting and re-request it later. 79 field_links (StrategyLinks | Unset): HAL `_links` for a strategy — present on a full `StrategyState` body (`GET 80 /strategy/{strategyId}`, and `POST /strategy/{strategyId}/validate`'s already-validated 81 `200`), absent from that same endpoint's `202` — a deliberately partial stub carrying only 82 what is known before a check has even started. Following `code` can still `404` once 83 present: it documents its own honest "nothing to return" for a strategy with no source of 84 its own (a `REFERENCE` marketplace copy, or one resolved only through the platform's shared 85 pool). This link says where to look, not that something is there. 86 """ 87 88 strategy_id: str 89 validation: StrategyStateValidation 90 compiled_at: datetime.datetime | Unset = UNSET 91 required_sources: list[StrategyStateRequiredSourcesItem] | Unset = UNSET 92 validated_at: datetime.datetime | Unset = UNSET 93 detail: str | Unset = UNSET 94 notices: list[Notice] | Unset = UNSET 95 notices_truncated: int | Unset = UNSET 96 dry_run_incomplete: bool | Unset = UNSET 97 validation_stalled: bool | Unset = UNSET 98 field_links: StrategyLinks | Unset = UNSET 99 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 100 101 def to_dict(self) -> dict[str, Any]: 102 strategy_id = self.strategy_id 103 104 validation = self.validation.value 105 106 compiled_at: str | Unset = UNSET 107 if not isinstance(self.compiled_at, Unset): 108 compiled_at = self.compiled_at.isoformat() 109 110 required_sources: list[str] | Unset = UNSET 111 if not isinstance(self.required_sources, Unset): 112 required_sources = [] 113 for required_sources_item_data in self.required_sources: 114 required_sources_item = required_sources_item_data.value 115 required_sources.append(required_sources_item) 116 117 validated_at: str | Unset = UNSET 118 if not isinstance(self.validated_at, Unset): 119 validated_at = self.validated_at.isoformat() 120 121 detail = self.detail 122 123 notices: list[dict[str, Any]] | Unset = UNSET 124 if not isinstance(self.notices, Unset): 125 notices = [] 126 for notices_item_data in self.notices: 127 notices_item = notices_item_data.to_dict() 128 notices.append(notices_item) 129 130 notices_truncated = self.notices_truncated 131 132 dry_run_incomplete = self.dry_run_incomplete 133 134 validation_stalled = self.validation_stalled 135 136 field_links: dict[str, Any] | Unset = UNSET 137 if not isinstance(self.field_links, Unset): 138 field_links = self.field_links.to_dict() 139 140 field_dict: dict[str, Any] = {} 141 field_dict.update(self.additional_properties) 142 field_dict.update( 143 { 144 "strategyId": strategy_id, 145 "validation": validation, 146 } 147 ) 148 if compiled_at is not UNSET: 149 field_dict["compiledAt"] = compiled_at 150 if required_sources is not UNSET: 151 field_dict["requiredSources"] = required_sources 152 if validated_at is not UNSET: 153 field_dict["validatedAt"] = validated_at 154 if detail is not UNSET: 155 field_dict["detail"] = detail 156 if notices is not UNSET: 157 field_dict["notices"] = notices 158 if notices_truncated is not UNSET: 159 field_dict["noticesTruncated"] = notices_truncated 160 if dry_run_incomplete is not UNSET: 161 field_dict["dryRunIncomplete"] = dry_run_incomplete 162 if validation_stalled is not UNSET: 163 field_dict["validationStalled"] = validation_stalled 164 if field_links is not UNSET: 165 field_dict["_links"] = field_links 166 167 return field_dict 168 169 @classmethod 170 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 171 from ..models.notice import Notice 172 from ..models.strategy_links import StrategyLinks 173 174 d = dict(src_dict) 175 strategy_id = d.pop("strategyId") 176 177 validation = StrategyStateValidation(d.pop("validation")) 178 179 _compiled_at = d.pop("compiledAt", UNSET) 180 compiled_at: datetime.datetime | Unset 181 if isinstance(_compiled_at, Unset): 182 compiled_at = UNSET 183 else: 184 compiled_at = isoparse(_compiled_at) 185 186 _required_sources = d.pop("requiredSources", UNSET) 187 required_sources: list[StrategyStateRequiredSourcesItem] | Unset = UNSET 188 if _required_sources is not UNSET: 189 required_sources = [] 190 for required_sources_item_data in _required_sources: 191 required_sources_item = StrategyStateRequiredSourcesItem(required_sources_item_data) 192 193 required_sources.append(required_sources_item) 194 195 _validated_at = d.pop("validatedAt", UNSET) 196 validated_at: datetime.datetime | Unset 197 if isinstance(_validated_at, Unset): 198 validated_at = UNSET 199 else: 200 validated_at = isoparse(_validated_at) 201 202 detail = d.pop("detail", UNSET) 203 204 _notices = d.pop("notices", UNSET) 205 notices: list[Notice] | Unset = UNSET 206 if _notices is not UNSET: 207 notices = [] 208 for notices_item_data in _notices: 209 notices_item = Notice.from_dict(notices_item_data) 210 211 notices.append(notices_item) 212 213 notices_truncated = d.pop("noticesTruncated", UNSET) 214 215 dry_run_incomplete = d.pop("dryRunIncomplete", UNSET) 216 217 validation_stalled = d.pop("validationStalled", UNSET) 218 219 _field_links = d.pop("_links", UNSET) 220 field_links: StrategyLinks | Unset 221 if isinstance(_field_links, Unset): 222 field_links = UNSET 223 else: 224 field_links = StrategyLinks.from_dict(_field_links) 225 226 strategy_state = cls( 227 strategy_id=strategy_id, 228 validation=validation, 229 compiled_at=compiled_at, 230 required_sources=required_sources, 231 validated_at=validated_at, 232 detail=detail, 233 notices=notices, 234 notices_truncated=notices_truncated, 235 dry_run_incomplete=dry_run_incomplete, 236 validation_stalled=validation_stalled, 237 field_links=field_links, 238 ) 239 240 strategy_state.additional_properties = d 241 return strategy_state 242 243 @property 244 def additional_keys(self) -> list[str]: 245 return list(self.additional_properties.keys()) 246 247 def __getitem__(self, key: str) -> Any: 248 return self.additional_properties[key] 249 250 def __setitem__(self, key: str, value: Any) -> None: 251 self.additional_properties[key] = value 252 253 def __delitem__(self, key: str) -> None: 254 del self.additional_properties[key] 255 256 def __contains__(self, key: str) -> bool: 257 return key in self.additional_properties
What is known about a registered strategy: that it compiled, and what validating it found.
validation: passed does not mean the strategy is correct. It means the class loaded and
survived the first event of a short synthetic run — a floor, not a guarantee. When
dryRunIncomplete is true it is a lower floor still, because the run did not finish.
Example:
{'strategyId': '6bsh31ikwkuivhtgcoa6s4', 'validation': 'passed', 'compiledAt': '2026-08-04T16:23:04Z',
'requiredSources': ['Ticker'], 'validatedAt': '2026-08-04T16:24:11Z', 'notices': [{'level': 'WARN', 'code':
'indicator.bar-data-on-ticker-path', 'message': 'Indicator requires bar data but is on the ticker path',
'provenance': 'compile-dry-run'}], '_links': {'code': {'href': '/v1/strategy/6bsh31ikwkuivhtgcoa6s4/code'}}}
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see `POST /strategy` for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
validation (StrategyStateValidation): * `not_validated` — registered, never checked. `POST
/strategy/{strategyId}/validate`
checks it.
* `pending` — a check was asked for and has not answered yet.
* `passed` — the class loaded and survived its first event.
* `failed` — it did not; `detail` says how.
Example: passed.
compiled_at (datetime.datetime | Unset): When the live compilation was produced.
required_sources (list[StrategyStateRequiredSourcesItem] | Unset): The market data a strategy needs, read off
the compiled class rather than off anything
you sent — `TickerStrategy`, `KlineStrategy` and `FundingRateStrategy` each declare one,
and a `MultiSourceStrategy` declares a set.
**Absent is not "needs nothing".** A strategy always needs market data, so an absent
field never means an empty requirement — it means the platform could not establish the
answer without constructing your strategy, which it will not do to fill in a field.
That happens for a `MultiSourceStrategy`, for a class that overrides
`getMarketDataSource()`, and for anything registered before this field existed;
re-registering the source fills it in.
Example: ['Ticker'].
validated_at (datetime.datetime | Unset): When the verdict was recorded. Absent until there is one.
detail (str | Unset): Why validation failed, or why a queued check has not reported. Present on `failed`, and
alongside `validationStalled`.
notices (list[Notice] | Unset): What the run surfaced. An empty or absent list is not a clean bill of health
when
`dryRunIncomplete` is true — see that field.
notices_truncated (int | Unset): How many notices were dropped past the cap. Absent when none were. Example: 3.
dry_run_incomplete (bool | Unset): The check did not finish its budget — it ran out of time, was refused because
the
platform was already holding too many unfinishable runs, or hit a failure attributable to
the synthetic instrument rather than to your strategy. The verdict stands as far as it
went; it simply reached less than a full run would.
validation_stalled (bool | Unset): A queued check has not reported for far longer than one takes. Nothing is
disproved about
the strategy — the check has not run. Stop waiting and re-request it later.
field_links (StrategyLinks | Unset): HAL `_links` for a strategy — present on a full `StrategyState` body (`GET
/strategy/{strategyId}`, and `POST /strategy/{strategyId}/validate`'s already-validated
`200`), absent from that same endpoint's `202` — a deliberately partial stub carrying only
what is known before a check has even started. Following `code` can still `404` once
present: it documents its own honest "nothing to return" for a strategy with no source of
its own (a `REFERENCE` marketplace copy, or one resolved only through the platform's shared
pool). This link says where to look, not that something is there.
34def __init__(self, strategy_id, validation, compiled_at=attr_dict['compiled_at'].default, required_sources=attr_dict['required_sources'].default, validated_at=attr_dict['validated_at'].default, detail=attr_dict['detail'].default, notices=attr_dict['notices'].default, notices_truncated=attr_dict['notices_truncated'].default, dry_run_incomplete=attr_dict['dry_run_incomplete'].default, validation_stalled=attr_dict['validation_stalled'].default, field_links=attr_dict['field_links'].default): 35 self.strategy_id = strategy_id 36 self.validation = validation 37 self.compiled_at = compiled_at 38 self.required_sources = required_sources 39 self.validated_at = validated_at 40 self.detail = detail 41 self.notices = notices 42 self.notices_truncated = notices_truncated 43 self.dry_run_incomplete = dry_run_incomplete 44 self.validation_stalled = validation_stalled 45 self.field_links = field_links 46 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class StrategyState.
101 def to_dict(self) -> dict[str, Any]: 102 strategy_id = self.strategy_id 103 104 validation = self.validation.value 105 106 compiled_at: str | Unset = UNSET 107 if not isinstance(self.compiled_at, Unset): 108 compiled_at = self.compiled_at.isoformat() 109 110 required_sources: list[str] | Unset = UNSET 111 if not isinstance(self.required_sources, Unset): 112 required_sources = [] 113 for required_sources_item_data in self.required_sources: 114 required_sources_item = required_sources_item_data.value 115 required_sources.append(required_sources_item) 116 117 validated_at: str | Unset = UNSET 118 if not isinstance(self.validated_at, Unset): 119 validated_at = self.validated_at.isoformat() 120 121 detail = self.detail 122 123 notices: list[dict[str, Any]] | Unset = UNSET 124 if not isinstance(self.notices, Unset): 125 notices = [] 126 for notices_item_data in self.notices: 127 notices_item = notices_item_data.to_dict() 128 notices.append(notices_item) 129 130 notices_truncated = self.notices_truncated 131 132 dry_run_incomplete = self.dry_run_incomplete 133 134 validation_stalled = self.validation_stalled 135 136 field_links: dict[str, Any] | Unset = UNSET 137 if not isinstance(self.field_links, Unset): 138 field_links = self.field_links.to_dict() 139 140 field_dict: dict[str, Any] = {} 141 field_dict.update(self.additional_properties) 142 field_dict.update( 143 { 144 "strategyId": strategy_id, 145 "validation": validation, 146 } 147 ) 148 if compiled_at is not UNSET: 149 field_dict["compiledAt"] = compiled_at 150 if required_sources is not UNSET: 151 field_dict["requiredSources"] = required_sources 152 if validated_at is not UNSET: 153 field_dict["validatedAt"] = validated_at 154 if detail is not UNSET: 155 field_dict["detail"] = detail 156 if notices is not UNSET: 157 field_dict["notices"] = notices 158 if notices_truncated is not UNSET: 159 field_dict["noticesTruncated"] = notices_truncated 160 if dry_run_incomplete is not UNSET: 161 field_dict["dryRunIncomplete"] = dry_run_incomplete 162 if validation_stalled is not UNSET: 163 field_dict["validationStalled"] = validation_stalled 164 if field_links is not UNSET: 165 field_dict["_links"] = field_links 166 167 return field_dict
169 @classmethod 170 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 171 from ..models.notice import Notice 172 from ..models.strategy_links import StrategyLinks 173 174 d = dict(src_dict) 175 strategy_id = d.pop("strategyId") 176 177 validation = StrategyStateValidation(d.pop("validation")) 178 179 _compiled_at = d.pop("compiledAt", UNSET) 180 compiled_at: datetime.datetime | Unset 181 if isinstance(_compiled_at, Unset): 182 compiled_at = UNSET 183 else: 184 compiled_at = isoparse(_compiled_at) 185 186 _required_sources = d.pop("requiredSources", UNSET) 187 required_sources: list[StrategyStateRequiredSourcesItem] | Unset = UNSET 188 if _required_sources is not UNSET: 189 required_sources = [] 190 for required_sources_item_data in _required_sources: 191 required_sources_item = StrategyStateRequiredSourcesItem(required_sources_item_data) 192 193 required_sources.append(required_sources_item) 194 195 _validated_at = d.pop("validatedAt", UNSET) 196 validated_at: datetime.datetime | Unset 197 if isinstance(_validated_at, Unset): 198 validated_at = UNSET 199 else: 200 validated_at = isoparse(_validated_at) 201 202 detail = d.pop("detail", UNSET) 203 204 _notices = d.pop("notices", UNSET) 205 notices: list[Notice] | Unset = UNSET 206 if _notices is not UNSET: 207 notices = [] 208 for notices_item_data in _notices: 209 notices_item = Notice.from_dict(notices_item_data) 210 211 notices.append(notices_item) 212 213 notices_truncated = d.pop("noticesTruncated", UNSET) 214 215 dry_run_incomplete = d.pop("dryRunIncomplete", UNSET) 216 217 validation_stalled = d.pop("validationStalled", UNSET) 218 219 _field_links = d.pop("_links", UNSET) 220 field_links: StrategyLinks | Unset 221 if isinstance(_field_links, Unset): 222 field_links = UNSET 223 else: 224 field_links = StrategyLinks.from_dict(_field_links) 225 226 strategy_state = cls( 227 strategy_id=strategy_id, 228 validation=validation, 229 compiled_at=compiled_at, 230 required_sources=required_sources, 231 validated_at=validated_at, 232 detail=detail, 233 notices=notices, 234 notices_truncated=notices_truncated, 235 dry_run_incomplete=dry_run_incomplete, 236 validation_stalled=validation_stalled, 237 field_links=field_links, 238 ) 239 240 strategy_state.additional_properties = d 241 return strategy_state
5class StrategyStateRequiredSourcesItem(str, Enum): 6 FUNDINGRATE = "FundingRate" 7 KLINE = "KLine" 8 TICKER = "Ticker" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class StrategyStateValidation(str, Enum): 6 FAILED = "failed" 7 NOT_VALIDATED = "not_validated" 8 PASSED = "passed" 9 PENDING = "pending" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class StrategySummary: 19 """One entry from `GET /strategies` — the same provenance a full `StrategyState` carries 20 (`compiledAt`, `requiredSources`), without its validation state, so listing stays cheap 21 regardless of how many strategies you have registered. Check a specific strategy's 22 validation with `GET /strategy/{strategyId}`. 23 24 Attributes: 25 strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code 26 always yields the same id, for every caller. How much formatting the id ignores depends on 27 the language — see `POST /strategy` for exactly which rewrites preserve it and which do 28 not. 29 Example: 6bsh31ikwkuivhtgcoa6s4. 30 compiled_at (datetime.datetime | Unset): When the live compilation was produced. 31 required_sources (list[str] | Unset): The market data this strategy needs. Absent, not empty, when it could 32 not be established without constructing the strategy. 33 deleted_at (datetime.datetime | Unset): When you deleted this strategy. Only ever present in `GET 34 /strategies?includeDeleted=true`, 35 and only on strategies you have deleted. 36 """ 37 38 strategy_id: str 39 compiled_at: datetime.datetime | Unset = UNSET 40 required_sources: list[str] | Unset = UNSET 41 deleted_at: datetime.datetime | Unset = UNSET 42 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 43 44 def to_dict(self) -> dict[str, Any]: 45 strategy_id = self.strategy_id 46 47 compiled_at: str | Unset = UNSET 48 if not isinstance(self.compiled_at, Unset): 49 compiled_at = self.compiled_at.isoformat() 50 51 required_sources: list[str] | Unset = UNSET 52 if not isinstance(self.required_sources, Unset): 53 required_sources = self.required_sources 54 55 deleted_at: str | Unset = UNSET 56 if not isinstance(self.deleted_at, Unset): 57 deleted_at = self.deleted_at.isoformat() 58 59 field_dict: dict[str, Any] = {} 60 field_dict.update(self.additional_properties) 61 field_dict.update( 62 { 63 "strategyId": strategy_id, 64 } 65 ) 66 if compiled_at is not UNSET: 67 field_dict["compiledAt"] = compiled_at 68 if required_sources is not UNSET: 69 field_dict["requiredSources"] = required_sources 70 if deleted_at is not UNSET: 71 field_dict["deletedAt"] = deleted_at 72 73 return field_dict 74 75 @classmethod 76 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 77 d = dict(src_dict) 78 strategy_id = d.pop("strategyId") 79 80 _compiled_at = d.pop("compiledAt", UNSET) 81 compiled_at: datetime.datetime | Unset 82 if isinstance(_compiled_at, Unset): 83 compiled_at = UNSET 84 else: 85 compiled_at = isoparse(_compiled_at) 86 87 required_sources = cast(list[str], d.pop("requiredSources", UNSET)) 88 89 _deleted_at = d.pop("deletedAt", UNSET) 90 deleted_at: datetime.datetime | Unset 91 if isinstance(_deleted_at, Unset): 92 deleted_at = UNSET 93 else: 94 deleted_at = isoparse(_deleted_at) 95 96 strategy_summary = cls( 97 strategy_id=strategy_id, 98 compiled_at=compiled_at, 99 required_sources=required_sources, 100 deleted_at=deleted_at, 101 ) 102 103 strategy_summary.additional_properties = d 104 return strategy_summary 105 106 @property 107 def additional_keys(self) -> list[str]: 108 return list(self.additional_properties.keys()) 109 110 def __getitem__(self, key: str) -> Any: 111 return self.additional_properties[key] 112 113 def __setitem__(self, key: str, value: Any) -> None: 114 self.additional_properties[key] = value 115 116 def __delitem__(self, key: str) -> None: 117 del self.additional_properties[key] 118 119 def __contains__(self, key: str) -> bool: 120 return key in self.additional_properties
One entry from GET /strategies — the same provenance a full StrategyState carries
(compiledAt, requiredSources), without its validation state, so listing stays cheap
regardless of how many strategies you have registered. Check a specific strategy's
validation with GET /strategy/{strategyId}.
Attributes:
strategy_id (str): Unique identifier for a compiled strategy, derived from the source itself: the same code
always yields the same id, for every caller. How much formatting the id ignores depends on
the language — see `POST /strategy` for exactly which rewrites preserve it and which do
not.
Example: 6bsh31ikwkuivhtgcoa6s4.
compiled_at (datetime.datetime | Unset): When the live compilation was produced.
required_sources (list[str] | Unset): The market data this strategy needs. Absent, not empty, when it could
not be established without constructing the strategy.
deleted_at (datetime.datetime | Unset): When you deleted this strategy. Only ever present in `GET
/strategies?includeDeleted=true`,
and only on strategies you have deleted.
27def __init__(self, strategy_id, compiled_at=attr_dict['compiled_at'].default, required_sources=attr_dict['required_sources'].default, deleted_at=attr_dict['deleted_at'].default): 28 self.strategy_id = strategy_id 29 self.compiled_at = compiled_at 30 self.required_sources = required_sources 31 self.deleted_at = deleted_at 32 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class StrategySummary.
44 def to_dict(self) -> dict[str, Any]: 45 strategy_id = self.strategy_id 46 47 compiled_at: str | Unset = UNSET 48 if not isinstance(self.compiled_at, Unset): 49 compiled_at = self.compiled_at.isoformat() 50 51 required_sources: list[str] | Unset = UNSET 52 if not isinstance(self.required_sources, Unset): 53 required_sources = self.required_sources 54 55 deleted_at: str | Unset = UNSET 56 if not isinstance(self.deleted_at, Unset): 57 deleted_at = self.deleted_at.isoformat() 58 59 field_dict: dict[str, Any] = {} 60 field_dict.update(self.additional_properties) 61 field_dict.update( 62 { 63 "strategyId": strategy_id, 64 } 65 ) 66 if compiled_at is not UNSET: 67 field_dict["compiledAt"] = compiled_at 68 if required_sources is not UNSET: 69 field_dict["requiredSources"] = required_sources 70 if deleted_at is not UNSET: 71 field_dict["deletedAt"] = deleted_at 72 73 return field_dict
75 @classmethod 76 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 77 d = dict(src_dict) 78 strategy_id = d.pop("strategyId") 79 80 _compiled_at = d.pop("compiledAt", UNSET) 81 compiled_at: datetime.datetime | Unset 82 if isinstance(_compiled_at, Unset): 83 compiled_at = UNSET 84 else: 85 compiled_at = isoparse(_compiled_at) 86 87 required_sources = cast(list[str], d.pop("requiredSources", UNSET)) 88 89 _deleted_at = d.pop("deletedAt", UNSET) 90 deleted_at: datetime.datetime | Unset 91 if isinstance(_deleted_at, Unset): 92 deleted_at = UNSET 93 else: 94 deleted_at = isoparse(_deleted_at) 95 96 strategy_summary = cls( 97 strategy_id=strategy_id, 98 compiled_at=compiled_at, 99 required_sources=required_sources, 100 deleted_at=deleted_at, 101 ) 102 103 strategy_summary.additional_properties = d 104 return strategy_summary
12@_attrs_define 13class SweepAxisType0: 14 """ 15 Attributes: 16 from_ (float): 17 to (float): 18 step (float): 19 """ 20 21 from_: float 22 to: float 23 step: float 24 25 def to_dict(self) -> dict[str, Any]: 26 from_ = self.from_ 27 28 to = self.to 29 30 step = self.step 31 32 field_dict: dict[str, Any] = {} 33 34 field_dict.update( 35 { 36 "from": from_, 37 "to": to, 38 "step": step, 39 } 40 ) 41 42 return field_dict 43 44 @classmethod 45 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 46 d = dict(src_dict) 47 from_ = d.pop("from") 48 49 to = d.pop("to") 50 51 step = d.pop("step") 52 53 sweep_axis_type_0 = cls( 54 from_=from_, 55 to=to, 56 step=step, 57 ) 58 59 return sweep_axis_type_0
Attributes: from_ (float): to (float): step (float):
Method generated by attrs for class SweepAxisType0.
12@_attrs_define 13class SweepAxisType1: 14 """ 15 Attributes: 16 values (list[bool | float]): 17 """ 18 19 values: list[bool | float] 20 21 def to_dict(self) -> dict[str, Any]: 22 values = [] 23 for values_item_data in self.values: 24 values_item: bool | float 25 values_item = values_item_data 26 values.append(values_item) 27 28 field_dict: dict[str, Any] = {} 29 30 field_dict.update( 31 { 32 "values": values, 33 } 34 ) 35 36 return field_dict 37 38 @classmethod 39 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 40 d = dict(src_dict) 41 values = [] 42 _values = d.pop("values") 43 for values_item_data in _values: 44 45 def _parse_values_item(data: object) -> bool | float: 46 return cast(bool | float, data) 47 48 values_item = _parse_values_item(values_item_data) 49 50 values.append(values_item) 51 52 sweep_axis_type_1 = cls( 53 values=values, 54 ) 55 56 return sweep_axis_type_1
Attributes: values (list[bool | float]):
21 def to_dict(self) -> dict[str, Any]: 22 values = [] 23 for values_item_data in self.values: 24 values_item: bool | float 25 values_item = values_item_data 26 values.append(values_item) 27 28 field_dict: dict[str, Any] = {} 29 30 field_dict.update( 31 { 32 "values": values, 33 } 34 ) 35 36 return field_dict
38 @classmethod 39 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 40 d = dict(src_dict) 41 values = [] 42 _values = d.pop("values") 43 for values_item_data in _values: 44 45 def _parse_values_item(data: object) -> bool | float: 46 return cast(bool | float, data) 47 48 values_item = _parse_values_item(values_item_data) 49 50 values.append(values_item) 51 52 sweep_axis_type_1 = cls( 53 values=values, 54 ) 55 56 return sweep_axis_type_1
16@_attrs_define 17class SweepBaseConfig: 18 """ 19 Attributes: 20 initial_funding (float | Unset): Default: 100.0. 21 fee_rate (float | Unset): Default: 0.001. 22 buy_fee_rate (float | Unset): 23 sell_fee_rate (float | Unset): 24 fee_leg (SweepBaseConfigFeeLeg | Unset): Default: SweepBaseConfigFeeLeg.RECEIVED. 25 percent_amount_to_lock (float | Unset): Share of the free balance each entry locks, in percent (0-100]. Omitted, 26 a backtest sizes every entry with everything available. 27 """ 28 29 initial_funding: float | Unset = 100.0 30 fee_rate: float | Unset = 0.001 31 buy_fee_rate: float | Unset = UNSET 32 sell_fee_rate: float | Unset = UNSET 33 fee_leg: SweepBaseConfigFeeLeg | Unset = SweepBaseConfigFeeLeg.RECEIVED 34 percent_amount_to_lock: float | Unset = UNSET 35 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 36 37 def to_dict(self) -> dict[str, Any]: 38 initial_funding = self.initial_funding 39 40 fee_rate = self.fee_rate 41 42 buy_fee_rate = self.buy_fee_rate 43 44 sell_fee_rate = self.sell_fee_rate 45 46 fee_leg: str | Unset = UNSET 47 if not isinstance(self.fee_leg, Unset): 48 fee_leg = self.fee_leg.value 49 50 percent_amount_to_lock = self.percent_amount_to_lock 51 52 field_dict: dict[str, Any] = {} 53 field_dict.update(self.additional_properties) 54 field_dict.update({}) 55 if initial_funding is not UNSET: 56 field_dict["initialFunding"] = initial_funding 57 if fee_rate is not UNSET: 58 field_dict["feeRate"] = fee_rate 59 if buy_fee_rate is not UNSET: 60 field_dict["buyFeeRate"] = buy_fee_rate 61 if sell_fee_rate is not UNSET: 62 field_dict["sellFeeRate"] = sell_fee_rate 63 if fee_leg is not UNSET: 64 field_dict["feeLeg"] = fee_leg 65 if percent_amount_to_lock is not UNSET: 66 field_dict["percentAmountToLock"] = percent_amount_to_lock 67 68 return field_dict 69 70 @classmethod 71 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 72 d = dict(src_dict) 73 initial_funding = d.pop("initialFunding", UNSET) 74 75 fee_rate = d.pop("feeRate", UNSET) 76 77 buy_fee_rate = d.pop("buyFeeRate", UNSET) 78 79 sell_fee_rate = d.pop("sellFeeRate", UNSET) 80 81 _fee_leg = d.pop("feeLeg", UNSET) 82 fee_leg: SweepBaseConfigFeeLeg | Unset 83 if isinstance(_fee_leg, Unset): 84 fee_leg = UNSET 85 else: 86 fee_leg = SweepBaseConfigFeeLeg(_fee_leg) 87 88 percent_amount_to_lock = d.pop("percentAmountToLock", UNSET) 89 90 sweep_base_config = cls( 91 initial_funding=initial_funding, 92 fee_rate=fee_rate, 93 buy_fee_rate=buy_fee_rate, 94 sell_fee_rate=sell_fee_rate, 95 fee_leg=fee_leg, 96 percent_amount_to_lock=percent_amount_to_lock, 97 ) 98 99 sweep_base_config.additional_properties = d 100 return sweep_base_config 101 102 @property 103 def additional_keys(self) -> list[str]: 104 return list(self.additional_properties.keys()) 105 106 def __getitem__(self, key: str) -> Any: 107 return self.additional_properties[key] 108 109 def __setitem__(self, key: str, value: Any) -> None: 110 self.additional_properties[key] = value 111 112 def __delitem__(self, key: str) -> None: 113 del self.additional_properties[key] 114 115 def __contains__(self, key: str) -> bool: 116 return key in self.additional_properties
Attributes: initial_funding (float | Unset): Default: 100.0. fee_rate (float | Unset): Default: 0.001. buy_fee_rate (float | Unset): sell_fee_rate (float | Unset): fee_leg (SweepBaseConfigFeeLeg | Unset): Default: SweepBaseConfigFeeLeg.RECEIVED. percent_amount_to_lock (float | Unset): Share of the free balance each entry locks, in percent (0-100]. Omitted, a backtest sizes every entry with everything available.
29def __init__(self, initial_funding=attr_dict['initial_funding'].default, fee_rate=attr_dict['fee_rate'].default, buy_fee_rate=attr_dict['buy_fee_rate'].default, sell_fee_rate=attr_dict['sell_fee_rate'].default, fee_leg=attr_dict['fee_leg'].default, percent_amount_to_lock=attr_dict['percent_amount_to_lock'].default): 30 self.initial_funding = initial_funding 31 self.fee_rate = fee_rate 32 self.buy_fee_rate = buy_fee_rate 33 self.sell_fee_rate = sell_fee_rate 34 self.fee_leg = fee_leg 35 self.percent_amount_to_lock = percent_amount_to_lock 36 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepBaseConfig.
37 def to_dict(self) -> dict[str, Any]: 38 initial_funding = self.initial_funding 39 40 fee_rate = self.fee_rate 41 42 buy_fee_rate = self.buy_fee_rate 43 44 sell_fee_rate = self.sell_fee_rate 45 46 fee_leg: str | Unset = UNSET 47 if not isinstance(self.fee_leg, Unset): 48 fee_leg = self.fee_leg.value 49 50 percent_amount_to_lock = self.percent_amount_to_lock 51 52 field_dict: dict[str, Any] = {} 53 field_dict.update(self.additional_properties) 54 field_dict.update({}) 55 if initial_funding is not UNSET: 56 field_dict["initialFunding"] = initial_funding 57 if fee_rate is not UNSET: 58 field_dict["feeRate"] = fee_rate 59 if buy_fee_rate is not UNSET: 60 field_dict["buyFeeRate"] = buy_fee_rate 61 if sell_fee_rate is not UNSET: 62 field_dict["sellFeeRate"] = sell_fee_rate 63 if fee_leg is not UNSET: 64 field_dict["feeLeg"] = fee_leg 65 if percent_amount_to_lock is not UNSET: 66 field_dict["percentAmountToLock"] = percent_amount_to_lock 67 68 return field_dict
70 @classmethod 71 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 72 d = dict(src_dict) 73 initial_funding = d.pop("initialFunding", UNSET) 74 75 fee_rate = d.pop("feeRate", UNSET) 76 77 buy_fee_rate = d.pop("buyFeeRate", UNSET) 78 79 sell_fee_rate = d.pop("sellFeeRate", UNSET) 80 81 _fee_leg = d.pop("feeLeg", UNSET) 82 fee_leg: SweepBaseConfigFeeLeg | Unset 83 if isinstance(_fee_leg, Unset): 84 fee_leg = UNSET 85 else: 86 fee_leg = SweepBaseConfigFeeLeg(_fee_leg) 87 88 percent_amount_to_lock = d.pop("percentAmountToLock", UNSET) 89 90 sweep_base_config = cls( 91 initial_funding=initial_funding, 92 fee_rate=fee_rate, 93 buy_fee_rate=buy_fee_rate, 94 sell_fee_rate=sell_fee_rate, 95 fee_leg=fee_leg, 96 percent_amount_to_lock=percent_amount_to_lock, 97 ) 98 99 sweep_base_config.additional_properties = d 100 return sweep_base_config
5class SweepBaseConfigFeeLeg(str, Enum): 6 BASE = "BASE" 7 QUOTE = "QUOTE" 8 RECEIVED = "RECEIVED" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
19@_attrs_define 20class SweepHeatmap: 21 """The surface for one pair of axes, with all others collapsed away. 22 23 Attributes: 24 param_a (str | Unset): 25 param_b (str | Unset): 26 cells (list[SweepHeatmapCell] | Unset): 27 """ 28 29 param_a: str | Unset = UNSET 30 param_b: str | Unset = UNSET 31 cells: list[SweepHeatmapCell] | Unset = UNSET 32 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 33 34 def to_dict(self) -> dict[str, Any]: 35 param_a = self.param_a 36 37 param_b = self.param_b 38 39 cells: list[dict[str, Any]] | Unset = UNSET 40 if not isinstance(self.cells, Unset): 41 cells = [] 42 for cells_item_data in self.cells: 43 cells_item = cells_item_data.to_dict() 44 cells.append(cells_item) 45 46 field_dict: dict[str, Any] = {} 47 field_dict.update(self.additional_properties) 48 field_dict.update({}) 49 if param_a is not UNSET: 50 field_dict["paramA"] = param_a 51 if param_b is not UNSET: 52 field_dict["paramB"] = param_b 53 if cells is not UNSET: 54 field_dict["cells"] = cells 55 56 return field_dict 57 58 @classmethod 59 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 60 from ..models.sweep_heatmap_cell import SweepHeatmapCell 61 62 d = dict(src_dict) 63 param_a = d.pop("paramA", UNSET) 64 65 param_b = d.pop("paramB", UNSET) 66 67 _cells = d.pop("cells", UNSET) 68 cells: list[SweepHeatmapCell] | Unset = UNSET 69 if _cells is not UNSET: 70 cells = [] 71 for cells_item_data in _cells: 72 cells_item = SweepHeatmapCell.from_dict(cells_item_data) 73 74 cells.append(cells_item) 75 76 sweep_heatmap = cls( 77 param_a=param_a, 78 param_b=param_b, 79 cells=cells, 80 ) 81 82 sweep_heatmap.additional_properties = d 83 return sweep_heatmap 84 85 @property 86 def additional_keys(self) -> list[str]: 87 return list(self.additional_properties.keys()) 88 89 def __getitem__(self, key: str) -> Any: 90 return self.additional_properties[key] 91 92 def __setitem__(self, key: str, value: Any) -> None: 93 self.additional_properties[key] = value 94 95 def __delitem__(self, key: str) -> None: 96 del self.additional_properties[key] 97 98 def __contains__(self, key: str) -> bool: 99 return key in self.additional_properties
The surface for one pair of axes, with all others collapsed away.
Attributes: param_a (str | Unset): param_b (str | Unset): cells (list[SweepHeatmapCell] | Unset):
26def __init__(self, param_a=attr_dict['param_a'].default, param_b=attr_dict['param_b'].default, cells=attr_dict['cells'].default): 27 self.param_a = param_a 28 self.param_b = param_b 29 self.cells = cells 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepHeatmap.
34 def to_dict(self) -> dict[str, Any]: 35 param_a = self.param_a 36 37 param_b = self.param_b 38 39 cells: list[dict[str, Any]] | Unset = UNSET 40 if not isinstance(self.cells, Unset): 41 cells = [] 42 for cells_item_data in self.cells: 43 cells_item = cells_item_data.to_dict() 44 cells.append(cells_item) 45 46 field_dict: dict[str, Any] = {} 47 field_dict.update(self.additional_properties) 48 field_dict.update({}) 49 if param_a is not UNSET: 50 field_dict["paramA"] = param_a 51 if param_b is not UNSET: 52 field_dict["paramB"] = param_b 53 if cells is not UNSET: 54 field_dict["cells"] = cells 55 56 return field_dict
58 @classmethod 59 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 60 from ..models.sweep_heatmap_cell import SweepHeatmapCell 61 62 d = dict(src_dict) 63 param_a = d.pop("paramA", UNSET) 64 65 param_b = d.pop("paramB", UNSET) 66 67 _cells = d.pop("cells", UNSET) 68 cells: list[SweepHeatmapCell] | Unset = UNSET 69 if _cells is not UNSET: 70 cells = [] 71 for cells_item_data in _cells: 72 cells_item = SweepHeatmapCell.from_dict(cells_item_data) 73 74 cells.append(cells_item) 75 76 sweep_heatmap = cls( 77 param_a=param_a, 78 param_b=param_b, 79 cells=cells, 80 ) 81 82 sweep_heatmap.additional_properties = d 83 return sweep_heatmap
15@_attrs_define 16class SweepHeatmapCell: 17 """ 18 Attributes: 19 value_a (Any | Unset): 20 value_b (Any | Unset): 21 count (int | Unset): 22 best (float | Unset): 23 mean (float | Unset): 24 """ 25 26 value_a: Any | Unset = UNSET 27 value_b: Any | Unset = UNSET 28 count: int | Unset = UNSET 29 best: float | Unset = UNSET 30 mean: float | Unset = UNSET 31 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 32 33 def to_dict(self) -> dict[str, Any]: 34 value_a = self.value_a 35 36 value_b = self.value_b 37 38 count = self.count 39 40 best = self.best 41 42 mean = self.mean 43 44 field_dict: dict[str, Any] = {} 45 field_dict.update(self.additional_properties) 46 field_dict.update({}) 47 if value_a is not UNSET: 48 field_dict["valueA"] = value_a 49 if value_b is not UNSET: 50 field_dict["valueB"] = value_b 51 if count is not UNSET: 52 field_dict["count"] = count 53 if best is not UNSET: 54 field_dict["best"] = best 55 if mean is not UNSET: 56 field_dict["mean"] = mean 57 58 return field_dict 59 60 @classmethod 61 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 62 d = dict(src_dict) 63 value_a = d.pop("valueA", UNSET) 64 65 value_b = d.pop("valueB", UNSET) 66 67 count = d.pop("count", UNSET) 68 69 best = d.pop("best", UNSET) 70 71 mean = d.pop("mean", UNSET) 72 73 sweep_heatmap_cell = cls( 74 value_a=value_a, 75 value_b=value_b, 76 count=count, 77 best=best, 78 mean=mean, 79 ) 80 81 sweep_heatmap_cell.additional_properties = d 82 return sweep_heatmap_cell 83 84 @property 85 def additional_keys(self) -> list[str]: 86 return list(self.additional_properties.keys()) 87 88 def __getitem__(self, key: str) -> Any: 89 return self.additional_properties[key] 90 91 def __setitem__(self, key: str, value: Any) -> None: 92 self.additional_properties[key] = value 93 94 def __delitem__(self, key: str) -> None: 95 del self.additional_properties[key] 96 97 def __contains__(self, key: str) -> bool: 98 return key in self.additional_properties
Attributes: value_a (Any | Unset): value_b (Any | Unset): count (int | Unset): best (float | Unset): mean (float | Unset):
28def __init__(self, value_a=attr_dict['value_a'].default, value_b=attr_dict['value_b'].default, count=attr_dict['count'].default, best=attr_dict['best'].default, mean=attr_dict['mean'].default): 29 self.value_a = value_a 30 self.value_b = value_b 31 self.count = count 32 self.best = best 33 self.mean = mean 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepHeatmapCell.
33 def to_dict(self) -> dict[str, Any]: 34 value_a = self.value_a 35 36 value_b = self.value_b 37 38 count = self.count 39 40 best = self.best 41 42 mean = self.mean 43 44 field_dict: dict[str, Any] = {} 45 field_dict.update(self.additional_properties) 46 field_dict.update({}) 47 if value_a is not UNSET: 48 field_dict["valueA"] = value_a 49 if value_b is not UNSET: 50 field_dict["valueB"] = value_b 51 if count is not UNSET: 52 field_dict["count"] = count 53 if best is not UNSET: 54 field_dict["best"] = best 55 if mean is not UNSET: 56 field_dict["mean"] = mean 57 58 return field_dict
60 @classmethod 61 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 62 d = dict(src_dict) 63 value_a = d.pop("valueA", UNSET) 64 65 value_b = d.pop("valueB", UNSET) 66 67 count = d.pop("count", UNSET) 68 69 best = d.pop("best", UNSET) 70 71 mean = d.pop("mean", UNSET) 72 73 sweep_heatmap_cell = cls( 74 value_a=value_a, 75 value_b=value_b, 76 count=count, 77 best=best, 78 mean=mean, 79 ) 80 81 sweep_heatmap_cell.additional_properties = d 82 return sweep_heatmap_cell
19@_attrs_define 20class SweepMarginal: 21 """One axis, with every other axis collapsed away. 22 23 Attributes: 24 param (str | Unset): 25 points (list[SweepMarginalPoint] | Unset): 26 """ 27 28 param: str | Unset = UNSET 29 points: list[SweepMarginalPoint] | Unset = UNSET 30 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 31 32 def to_dict(self) -> dict[str, Any]: 33 param = self.param 34 35 points: list[dict[str, Any]] | Unset = UNSET 36 if not isinstance(self.points, Unset): 37 points = [] 38 for points_item_data in self.points: 39 points_item = points_item_data.to_dict() 40 points.append(points_item) 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update({}) 45 if param is not UNSET: 46 field_dict["param"] = param 47 if points is not UNSET: 48 field_dict["points"] = points 49 50 return field_dict 51 52 @classmethod 53 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 54 from ..models.sweep_marginal_point import SweepMarginalPoint 55 56 d = dict(src_dict) 57 param = d.pop("param", UNSET) 58 59 _points = d.pop("points", UNSET) 60 points: list[SweepMarginalPoint] | Unset = UNSET 61 if _points is not UNSET: 62 points = [] 63 for points_item_data in _points: 64 points_item = SweepMarginalPoint.from_dict(points_item_data) 65 66 points.append(points_item) 67 68 sweep_marginal = cls( 69 param=param, 70 points=points, 71 ) 72 73 sweep_marginal.additional_properties = d 74 return sweep_marginal 75 76 @property 77 def additional_keys(self) -> list[str]: 78 return list(self.additional_properties.keys()) 79 80 def __getitem__(self, key: str) -> Any: 81 return self.additional_properties[key] 82 83 def __setitem__(self, key: str, value: Any) -> None: 84 self.additional_properties[key] = value 85 86 def __delitem__(self, key: str) -> None: 87 del self.additional_properties[key] 88 89 def __contains__(self, key: str) -> bool: 90 return key in self.additional_properties
One axis, with every other axis collapsed away.
Attributes: param (str | Unset): points (list[SweepMarginalPoint] | Unset):
25def __init__(self, param=attr_dict['param'].default, points=attr_dict['points'].default): 26 self.param = param 27 self.points = points 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepMarginal.
32 def to_dict(self) -> dict[str, Any]: 33 param = self.param 34 35 points: list[dict[str, Any]] | Unset = UNSET 36 if not isinstance(self.points, Unset): 37 points = [] 38 for points_item_data in self.points: 39 points_item = points_item_data.to_dict() 40 points.append(points_item) 41 42 field_dict: dict[str, Any] = {} 43 field_dict.update(self.additional_properties) 44 field_dict.update({}) 45 if param is not UNSET: 46 field_dict["param"] = param 47 if points is not UNSET: 48 field_dict["points"] = points 49 50 return field_dict
52 @classmethod 53 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 54 from ..models.sweep_marginal_point import SweepMarginalPoint 55 56 d = dict(src_dict) 57 param = d.pop("param", UNSET) 58 59 _points = d.pop("points", UNSET) 60 points: list[SweepMarginalPoint] | Unset = UNSET 61 if _points is not UNSET: 62 points = [] 63 for points_item_data in _points: 64 points_item = SweepMarginalPoint.from_dict(points_item_data) 65 66 points.append(points_item) 67 68 sweep_marginal = cls( 69 param=param, 70 points=points, 71 ) 72 73 sweep_marginal.additional_properties = d 74 return sweep_marginal
15@_attrs_define 16class SweepMarginalPoint: 17 """How the objective behaved at one value of one axis. `best` and `mean` disagreeing is informative rather than noise: 18 a high `best` with a poor `mean` marks a value that only works alongside particular settings of the other axes. 19 20 Attributes: 21 value (Any | Unset): The axis value, as it appears in a run's parameters. 22 count (int | Unset): Non-aborted runs that used this value. 23 best (float | Unset): 24 mean (float | Unset): 25 worst (float | Unset): 26 """ 27 28 value: Any | Unset = UNSET 29 count: int | Unset = UNSET 30 best: float | Unset = UNSET 31 mean: float | Unset = UNSET 32 worst: float | Unset = UNSET 33 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 34 35 def to_dict(self) -> dict[str, Any]: 36 value = self.value 37 38 count = self.count 39 40 best = self.best 41 42 mean = self.mean 43 44 worst = self.worst 45 46 field_dict: dict[str, Any] = {} 47 field_dict.update(self.additional_properties) 48 field_dict.update({}) 49 if value is not UNSET: 50 field_dict["value"] = value 51 if count is not UNSET: 52 field_dict["count"] = count 53 if best is not UNSET: 54 field_dict["best"] = best 55 if mean is not UNSET: 56 field_dict["mean"] = mean 57 if worst is not UNSET: 58 field_dict["worst"] = worst 59 60 return field_dict 61 62 @classmethod 63 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 64 d = dict(src_dict) 65 value = d.pop("value", UNSET) 66 67 count = d.pop("count", UNSET) 68 69 best = d.pop("best", UNSET) 70 71 mean = d.pop("mean", UNSET) 72 73 worst = d.pop("worst", UNSET) 74 75 sweep_marginal_point = cls( 76 value=value, 77 count=count, 78 best=best, 79 mean=mean, 80 worst=worst, 81 ) 82 83 sweep_marginal_point.additional_properties = d 84 return sweep_marginal_point 85 86 @property 87 def additional_keys(self) -> list[str]: 88 return list(self.additional_properties.keys()) 89 90 def __getitem__(self, key: str) -> Any: 91 return self.additional_properties[key] 92 93 def __setitem__(self, key: str, value: Any) -> None: 94 self.additional_properties[key] = value 95 96 def __delitem__(self, key: str) -> None: 97 del self.additional_properties[key] 98 99 def __contains__(self, key: str) -> bool: 100 return key in self.additional_properties
How the objective behaved at one value of one axis. best and mean disagreeing is informative rather than noise:
a high best with a poor mean marks a value that only works alongside particular settings of the other axes.
Attributes:
value (Any | Unset): The axis value, as it appears in a run's parameters.
count (int | Unset): Non-aborted runs that used this value.
best (float | Unset):
mean (float | Unset):
worst (float | Unset):
28def __init__(self, value=attr_dict['value'].default, count=attr_dict['count'].default, best=attr_dict['best'].default, mean=attr_dict['mean'].default, worst=attr_dict['worst'].default): 29 self.value = value 30 self.count = count 31 self.best = best 32 self.mean = mean 33 self.worst = worst 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepMarginalPoint.
35 def to_dict(self) -> dict[str, Any]: 36 value = self.value 37 38 count = self.count 39 40 best = self.best 41 42 mean = self.mean 43 44 worst = self.worst 45 46 field_dict: dict[str, Any] = {} 47 field_dict.update(self.additional_properties) 48 field_dict.update({}) 49 if value is not UNSET: 50 field_dict["value"] = value 51 if count is not UNSET: 52 field_dict["count"] = count 53 if best is not UNSET: 54 field_dict["best"] = best 55 if mean is not UNSET: 56 field_dict["mean"] = mean 57 if worst is not UNSET: 58 field_dict["worst"] = worst 59 60 return field_dict
62 @classmethod 63 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 64 d = dict(src_dict) 65 value = d.pop("value", UNSET) 66 67 count = d.pop("count", UNSET) 68 69 best = d.pop("best", UNSET) 70 71 mean = d.pop("mean", UNSET) 72 73 worst = d.pop("worst", UNSET) 74 75 sweep_marginal_point = cls( 76 value=value, 77 count=count, 78 best=best, 79 mean=mean, 80 worst=worst, 81 ) 82 83 sweep_marginal_point.additional_properties = d 84 return sweep_marginal_point
15@_attrs_define 16class SweepProgress: 17 """How far along a sweep is, and — when the sweep is still running — enough to tell a healthy one from a stuck one. The 18 counts partition the shards (or, for a walk-forward sweep, the folds): every unit is either finished, failed, 19 waiting to be retried, or not yet started. 20 21 Attributes: 22 done (int): 23 total (int): 24 aborted (int): Individual runs that executed and aborted. A row-level count: a shard that fails before producing 25 any rows leaves this at 0, which is why `failedShards` exists alongside it. 26 shard_count (int): 27 pending_shards (int): Shards (or folds) that have not finished yet. On a cancelled sweep, `0` is what says every 28 run that was in flight has finished and the leaderboard is complete: `CANCELLED` is reported before that. 29 failed_shards (int): Shards (or folds) that failed and will not be retried. Distinct from `aborted`: this counts 30 whole units that never reported, not runs that ran badly. 31 retrying (int): Units whose last attempt failed on something transient — an I/O error, a worker that died mid- 32 read — and which are queued to be attempted again. Not counted as failures, because they have not failed yet; a 33 sweep with a non-zero value here is still expected to complete. 34 not_started (int): Units that have not reported anything yet. Covers both work still queued behind other work 35 and work claimed by a worker that stopped before it began, which is why a sweep with a persistent value here and 36 a rising `stalledSeconds` is worth looking at. 37 stalled_seconds (int | Unset): Seconds since anything last advanced. Omitted on a finished sweep, where it would 38 only measure how long ago it finished, and on sweeps submitted before this field existed. 39 eta_seconds (int | Unset): Rough seconds remaining, extrapolated from the rate observed so far and assuming 40 nothing else competes for workers. Runs conservative in practice — it has measured 2–5× long when a sweep spent 41 part of its life waiting to be retried, since that wait dilutes the observed rate. **Omitted, never zero, when 42 it cannot be computed**: a sweep with nothing finished yet has no rate to extrapolate from, and a zero would 43 read as "about to finish". Excludes queue wait entirely; `retrying` and `stalledSeconds` are where that shows 44 up. 45 """ 46 47 done: int 48 total: int 49 aborted: int 50 shard_count: int 51 pending_shards: int 52 failed_shards: int 53 retrying: int 54 not_started: int 55 stalled_seconds: int | Unset = UNSET 56 eta_seconds: int | Unset = UNSET 57 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 58 59 def to_dict(self) -> dict[str, Any]: 60 done = self.done 61 62 total = self.total 63 64 aborted = self.aborted 65 66 shard_count = self.shard_count 67 68 pending_shards = self.pending_shards 69 70 failed_shards = self.failed_shards 71 72 retrying = self.retrying 73 74 not_started = self.not_started 75 76 stalled_seconds = self.stalled_seconds 77 78 eta_seconds = self.eta_seconds 79 80 field_dict: dict[str, Any] = {} 81 field_dict.update(self.additional_properties) 82 field_dict.update( 83 { 84 "done": done, 85 "total": total, 86 "aborted": aborted, 87 "shardCount": shard_count, 88 "pendingShards": pending_shards, 89 "failedShards": failed_shards, 90 "retrying": retrying, 91 "notStarted": not_started, 92 } 93 ) 94 if stalled_seconds is not UNSET: 95 field_dict["stalledSeconds"] = stalled_seconds 96 if eta_seconds is not UNSET: 97 field_dict["etaSeconds"] = eta_seconds 98 99 return field_dict 100 101 @classmethod 102 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 103 d = dict(src_dict) 104 done = d.pop("done") 105 106 total = d.pop("total") 107 108 aborted = d.pop("aborted") 109 110 shard_count = d.pop("shardCount") 111 112 pending_shards = d.pop("pendingShards") 113 114 failed_shards = d.pop("failedShards") 115 116 retrying = d.pop("retrying") 117 118 not_started = d.pop("notStarted") 119 120 stalled_seconds = d.pop("stalledSeconds", UNSET) 121 122 eta_seconds = d.pop("etaSeconds", UNSET) 123 124 sweep_progress = cls( 125 done=done, 126 total=total, 127 aborted=aborted, 128 shard_count=shard_count, 129 pending_shards=pending_shards, 130 failed_shards=failed_shards, 131 retrying=retrying, 132 not_started=not_started, 133 stalled_seconds=stalled_seconds, 134 eta_seconds=eta_seconds, 135 ) 136 137 sweep_progress.additional_properties = d 138 return sweep_progress 139 140 @property 141 def additional_keys(self) -> list[str]: 142 return list(self.additional_properties.keys()) 143 144 def __getitem__(self, key: str) -> Any: 145 return self.additional_properties[key] 146 147 def __setitem__(self, key: str, value: Any) -> None: 148 self.additional_properties[key] = value 149 150 def __delitem__(self, key: str) -> None: 151 del self.additional_properties[key] 152 153 def __contains__(self, key: str) -> bool: 154 return key in self.additional_properties
How far along a sweep is, and — when the sweep is still running — enough to tell a healthy one from a stuck one. The counts partition the shards (or, for a walk-forward sweep, the folds): every unit is either finished, failed, waiting to be retried, or not yet started.
Attributes:
done (int):
total (int):
aborted (int): Individual runs that executed and aborted. A row-level count: a shard that fails before producing
any rows leaves this at 0, which is why `failedShards` exists alongside it.
shard_count (int):
pending_shards (int): Shards (or folds) that have not finished yet. On a cancelled sweep, `0` is what says every
run that was in flight has finished and the leaderboard is complete: `CANCELLED` is reported before that.
failed_shards (int): Shards (or folds) that failed and will not be retried. Distinct from `aborted`: this counts
whole units that never reported, not runs that ran badly.
retrying (int): Units whose last attempt failed on something transient — an I/O error, a worker that died mid-
read — and which are queued to be attempted again. Not counted as failures, because they have not failed yet; a
sweep with a non-zero value here is still expected to complete.
not_started (int): Units that have not reported anything yet. Covers both work still queued behind other work
and work claimed by a worker that stopped before it began, which is why a sweep with a persistent value here and
a rising `stalledSeconds` is worth looking at.
stalled_seconds (int | Unset): Seconds since anything last advanced. Omitted on a finished sweep, where it would
only measure how long ago it finished, and on sweeps submitted before this field existed.
eta_seconds (int | Unset): Rough seconds remaining, extrapolated from the rate observed so far and assuming
nothing else competes for workers. Runs conservative in practice — it has measured 2–5× long when a sweep spent
part of its life waiting to be retried, since that wait dilutes the observed rate. **Omitted, never zero, when
it cannot be computed**: a sweep with nothing finished yet has no rate to extrapolate from, and a zero would
read as "about to finish". Excludes queue wait entirely; `retrying` and `stalledSeconds` are where that shows
up.
33def __init__(self, done, total, aborted, shard_count, pending_shards, failed_shards, retrying, not_started, stalled_seconds=attr_dict['stalled_seconds'].default, eta_seconds=attr_dict['eta_seconds'].default): 34 self.done = done 35 self.total = total 36 self.aborted = aborted 37 self.shard_count = shard_count 38 self.pending_shards = pending_shards 39 self.failed_shards = failed_shards 40 self.retrying = retrying 41 self.not_started = not_started 42 self.stalled_seconds = stalled_seconds 43 self.eta_seconds = eta_seconds 44 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepProgress.
59 def to_dict(self) -> dict[str, Any]: 60 done = self.done 61 62 total = self.total 63 64 aborted = self.aborted 65 66 shard_count = self.shard_count 67 68 pending_shards = self.pending_shards 69 70 failed_shards = self.failed_shards 71 72 retrying = self.retrying 73 74 not_started = self.not_started 75 76 stalled_seconds = self.stalled_seconds 77 78 eta_seconds = self.eta_seconds 79 80 field_dict: dict[str, Any] = {} 81 field_dict.update(self.additional_properties) 82 field_dict.update( 83 { 84 "done": done, 85 "total": total, 86 "aborted": aborted, 87 "shardCount": shard_count, 88 "pendingShards": pending_shards, 89 "failedShards": failed_shards, 90 "retrying": retrying, 91 "notStarted": not_started, 92 } 93 ) 94 if stalled_seconds is not UNSET: 95 field_dict["stalledSeconds"] = stalled_seconds 96 if eta_seconds is not UNSET: 97 field_dict["etaSeconds"] = eta_seconds 98 99 return field_dict
101 @classmethod 102 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 103 d = dict(src_dict) 104 done = d.pop("done") 105 106 total = d.pop("total") 107 108 aborted = d.pop("aborted") 109 110 shard_count = d.pop("shardCount") 111 112 pending_shards = d.pop("pendingShards") 113 114 failed_shards = d.pop("failedShards") 115 116 retrying = d.pop("retrying") 117 118 not_started = d.pop("notStarted") 119 120 stalled_seconds = d.pop("stalledSeconds", UNSET) 121 122 eta_seconds = d.pop("etaSeconds", UNSET) 123 124 sweep_progress = cls( 125 done=done, 126 total=total, 127 aborted=aborted, 128 shard_count=shard_count, 129 pending_shards=pending_shards, 130 failed_shards=failed_shards, 131 retrying=retrying, 132 not_started=not_started, 133 stalled_seconds=stalled_seconds, 134 eta_seconds=eta_seconds, 135 ) 136 137 sweep_progress.additional_properties = d 138 return sweep_progress
20@_attrs_define 21class SweepRunRow: 22 """ 23 Attributes: 24 run_ix (int): Deterministic zero-based expansion index, stable across shards and ranking. 25 params (SweepRunRowParams): 26 sharpe (float): 27 sortino (float): 28 pnl (float): Absolute net PnL in the output currency. 29 pnl_pct (float): Same units as `pnlTotalPercent` on the single-run result — percent (0-100 scale). 30 cagr (float): Same units as `cagr` on the single-run result — a ratio, not a percent. 31 max_dd_pct (float): Same units as `maxDrawdownPercent` on the single-run result — percent (0-100 scale). 32 trades (int): 33 win_rate (float): Same units as `winRate` on the single-run result — a fraction, 0.0-1.0 (a rate, not a 34 percent). 35 below_trade_floor (bool): 36 aborted (bool): 37 runtime_ms (int): 38 rank (int | Unset): Present only in the `ranked` view. 39 plateau_score (float | Unset): The objective of the worst run in this point's immediate neighbourhood — how well 40 the region around it holds up, not how well it scored itself. Present only in the `ranked` view when plateau 41 ranking applied. Always read together with `neighbourCount`. 42 neighbour_count (int | Unset): How many neighbouring parameter points backed the `plateauScore`. Zero means the 43 point had no neighbours in the grid, so its score is unevidenced rather than confirmed — the value alone cannot 44 be distinguished from a genuinely robust one. 45 deflated_sharpe (float | Unset): Probability that this run's Sharpe reflects real edge rather than the best draw 46 from however many parameter vectors were tried. Above ~0.95 the result survives the multiple-testing correction; 47 near 0.5 or below it is indistinguishable from the best of a pile of coin flips. Absent on aborted runs, on 48 sweeps with too few trials to establish any dispersion to deflate against, on runs with fewer than 3 period 49 returns, and on a degenerate (near-constant) return series — all cases where the underlying statistic isn't 50 meaningfully computable, rather than genuinely zero. A present value is the computed probability, however small. 51 equity_curve (EquityCurveResult | Unset): An equity curve, shaped per `meta.outMode`: `points` when `ARRAY`, 52 `timestamps` + `equities` (parallel arrays) when `SHORT`. Used identically wherever a curve is returned — a 53 plain backtest's inline `equityCurve` and a sweep row's `equityCurve` are the same type. `url` is present 54 *instead of* any points when the curve is served by pointer rather than inline (a sweep row's top-N winners 55 only): `GET` it separately to fetch this exact same shape with the points populated. 56 """ 57 58 run_ix: int 59 params: SweepRunRowParams 60 sharpe: float 61 sortino: float 62 pnl: float 63 pnl_pct: float 64 cagr: float 65 max_dd_pct: float 66 trades: int 67 win_rate: float 68 below_trade_floor: bool 69 aborted: bool 70 runtime_ms: int 71 rank: int | Unset = UNSET 72 plateau_score: float | Unset = UNSET 73 neighbour_count: int | Unset = UNSET 74 deflated_sharpe: float | Unset = UNSET 75 equity_curve: EquityCurveResult | Unset = UNSET 76 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 77 78 def to_dict(self) -> dict[str, Any]: 79 run_ix = self.run_ix 80 81 params = self.params.to_dict() 82 83 sharpe = self.sharpe 84 85 sortino = self.sortino 86 87 pnl = self.pnl 88 89 pnl_pct = self.pnl_pct 90 91 cagr = self.cagr 92 93 max_dd_pct = self.max_dd_pct 94 95 trades = self.trades 96 97 win_rate = self.win_rate 98 99 below_trade_floor = self.below_trade_floor 100 101 aborted = self.aborted 102 103 runtime_ms = self.runtime_ms 104 105 rank = self.rank 106 107 plateau_score = self.plateau_score 108 109 neighbour_count = self.neighbour_count 110 111 deflated_sharpe = self.deflated_sharpe 112 113 equity_curve: dict[str, Any] | Unset = UNSET 114 if not isinstance(self.equity_curve, Unset): 115 equity_curve = self.equity_curve.to_dict() 116 117 field_dict: dict[str, Any] = {} 118 field_dict.update(self.additional_properties) 119 field_dict.update( 120 { 121 "runIx": run_ix, 122 "params": params, 123 "sharpe": sharpe, 124 "sortino": sortino, 125 "pnl": pnl, 126 "pnlPct": pnl_pct, 127 "cagr": cagr, 128 "maxDdPct": max_dd_pct, 129 "trades": trades, 130 "winRate": win_rate, 131 "belowTradeFloor": below_trade_floor, 132 "aborted": aborted, 133 "runtimeMs": runtime_ms, 134 } 135 ) 136 if rank is not UNSET: 137 field_dict["rank"] = rank 138 if plateau_score is not UNSET: 139 field_dict["plateauScore"] = plateau_score 140 if neighbour_count is not UNSET: 141 field_dict["neighbourCount"] = neighbour_count 142 if deflated_sharpe is not UNSET: 143 field_dict["deflatedSharpe"] = deflated_sharpe 144 if equity_curve is not UNSET: 145 field_dict["equityCurve"] = equity_curve 146 147 return field_dict 148 149 @classmethod 150 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 151 from ..models.equity_curve_result import EquityCurveResult 152 from ..models.sweep_run_row_params import SweepRunRowParams 153 154 d = dict(src_dict) 155 run_ix = d.pop("runIx") 156 157 params = SweepRunRowParams.from_dict(d.pop("params")) 158 159 sharpe = d.pop("sharpe") 160 161 sortino = d.pop("sortino") 162 163 pnl = d.pop("pnl") 164 165 pnl_pct = d.pop("pnlPct") 166 167 cagr = d.pop("cagr") 168 169 max_dd_pct = d.pop("maxDdPct") 170 171 trades = d.pop("trades") 172 173 win_rate = d.pop("winRate") 174 175 below_trade_floor = d.pop("belowTradeFloor") 176 177 aborted = d.pop("aborted") 178 179 runtime_ms = d.pop("runtimeMs") 180 181 rank = d.pop("rank", UNSET) 182 183 plateau_score = d.pop("plateauScore", UNSET) 184 185 neighbour_count = d.pop("neighbourCount", UNSET) 186 187 deflated_sharpe = d.pop("deflatedSharpe", UNSET) 188 189 _equity_curve = d.pop("equityCurve", UNSET) 190 equity_curve: EquityCurveResult | Unset 191 if isinstance(_equity_curve, Unset): 192 equity_curve = UNSET 193 else: 194 equity_curve = EquityCurveResult.from_dict(_equity_curve) 195 196 sweep_run_row = cls( 197 run_ix=run_ix, 198 params=params, 199 sharpe=sharpe, 200 sortino=sortino, 201 pnl=pnl, 202 pnl_pct=pnl_pct, 203 cagr=cagr, 204 max_dd_pct=max_dd_pct, 205 trades=trades, 206 win_rate=win_rate, 207 below_trade_floor=below_trade_floor, 208 aborted=aborted, 209 runtime_ms=runtime_ms, 210 rank=rank, 211 plateau_score=plateau_score, 212 neighbour_count=neighbour_count, 213 deflated_sharpe=deflated_sharpe, 214 equity_curve=equity_curve, 215 ) 216 217 sweep_run_row.additional_properties = d 218 return sweep_run_row 219 220 @property 221 def additional_keys(self) -> list[str]: 222 return list(self.additional_properties.keys()) 223 224 def __getitem__(self, key: str) -> Any: 225 return self.additional_properties[key] 226 227 def __setitem__(self, key: str, value: Any) -> None: 228 self.additional_properties[key] = value 229 230 def __delitem__(self, key: str) -> None: 231 del self.additional_properties[key] 232 233 def __contains__(self, key: str) -> bool: 234 return key in self.additional_properties
Attributes:
run_ix (int): Deterministic zero-based expansion index, stable across shards and ranking.
params (SweepRunRowParams):
sharpe (float):
sortino (float):
pnl (float): Absolute net PnL in the output currency.
pnl_pct (float): Same units as pnlTotalPercent on the single-run result — percent (0-100 scale).
cagr (float): Same units as cagr on the single-run result — a ratio, not a percent.
max_dd_pct (float): Same units as maxDrawdownPercent on the single-run result — percent (0-100 scale).
trades (int):
win_rate (float): Same units as winRate on the single-run result — a fraction, 0.0-1.0 (a rate, not a
percent).
below_trade_floor (bool):
aborted (bool):
runtime_ms (int):
rank (int | Unset): Present only in the ranked view.
plateau_score (float | Unset): The objective of the worst run in this point's immediate neighbourhood — how well
the region around it holds up, not how well it scored itself. Present only in the ranked view when plateau
ranking applied. Always read together with neighbourCount.
neighbour_count (int | Unset): How many neighbouring parameter points backed the plateauScore. Zero means the
point had no neighbours in the grid, so its score is unevidenced rather than confirmed — the value alone cannot
be distinguished from a genuinely robust one.
deflated_sharpe (float | Unset): Probability that this run's Sharpe reflects real edge rather than the best draw
from however many parameter vectors were tried. Above ~0.95 the result survives the multiple-testing correction;
near 0.5 or below it is indistinguishable from the best of a pile of coin flips. Absent on aborted runs, on
sweeps with too few trials to establish any dispersion to deflate against, on runs with fewer than 3 period
returns, and on a degenerate (near-constant) return series — all cases where the underlying statistic isn't
meaningfully computable, rather than genuinely zero. A present value is the computed probability, however small.
equity_curve (EquityCurveResult | Unset): An equity curve, shaped per meta.outMode: points when ARRAY,
timestamps + equities (parallel arrays) when SHORT. Used identically wherever a curve is returned — a
plain backtest's inline equityCurve and a sweep row's equityCurve are the same type. url is present
instead of any points when the curve is served by pointer rather than inline (a sweep row's top-N winners
only): GET it separately to fetch this exact same shape with the points populated.
41def __init__(self, run_ix, params, sharpe, sortino, pnl, pnl_pct, cagr, max_dd_pct, trades, win_rate, below_trade_floor, aborted, runtime_ms, rank=attr_dict['rank'].default, plateau_score=attr_dict['plateau_score'].default, neighbour_count=attr_dict['neighbour_count'].default, deflated_sharpe=attr_dict['deflated_sharpe'].default, equity_curve=attr_dict['equity_curve'].default): 42 self.run_ix = run_ix 43 self.params = params 44 self.sharpe = sharpe 45 self.sortino = sortino 46 self.pnl = pnl 47 self.pnl_pct = pnl_pct 48 self.cagr = cagr 49 self.max_dd_pct = max_dd_pct 50 self.trades = trades 51 self.win_rate = win_rate 52 self.below_trade_floor = below_trade_floor 53 self.aborted = aborted 54 self.runtime_ms = runtime_ms 55 self.rank = rank 56 self.plateau_score = plateau_score 57 self.neighbour_count = neighbour_count 58 self.deflated_sharpe = deflated_sharpe 59 self.equity_curve = equity_curve 60 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepRunRow.
78 def to_dict(self) -> dict[str, Any]: 79 run_ix = self.run_ix 80 81 params = self.params.to_dict() 82 83 sharpe = self.sharpe 84 85 sortino = self.sortino 86 87 pnl = self.pnl 88 89 pnl_pct = self.pnl_pct 90 91 cagr = self.cagr 92 93 max_dd_pct = self.max_dd_pct 94 95 trades = self.trades 96 97 win_rate = self.win_rate 98 99 below_trade_floor = self.below_trade_floor 100 101 aborted = self.aborted 102 103 runtime_ms = self.runtime_ms 104 105 rank = self.rank 106 107 plateau_score = self.plateau_score 108 109 neighbour_count = self.neighbour_count 110 111 deflated_sharpe = self.deflated_sharpe 112 113 equity_curve: dict[str, Any] | Unset = UNSET 114 if not isinstance(self.equity_curve, Unset): 115 equity_curve = self.equity_curve.to_dict() 116 117 field_dict: dict[str, Any] = {} 118 field_dict.update(self.additional_properties) 119 field_dict.update( 120 { 121 "runIx": run_ix, 122 "params": params, 123 "sharpe": sharpe, 124 "sortino": sortino, 125 "pnl": pnl, 126 "pnlPct": pnl_pct, 127 "cagr": cagr, 128 "maxDdPct": max_dd_pct, 129 "trades": trades, 130 "winRate": win_rate, 131 "belowTradeFloor": below_trade_floor, 132 "aborted": aborted, 133 "runtimeMs": runtime_ms, 134 } 135 ) 136 if rank is not UNSET: 137 field_dict["rank"] = rank 138 if plateau_score is not UNSET: 139 field_dict["plateauScore"] = plateau_score 140 if neighbour_count is not UNSET: 141 field_dict["neighbourCount"] = neighbour_count 142 if deflated_sharpe is not UNSET: 143 field_dict["deflatedSharpe"] = deflated_sharpe 144 if equity_curve is not UNSET: 145 field_dict["equityCurve"] = equity_curve 146 147 return field_dict
149 @classmethod 150 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 151 from ..models.equity_curve_result import EquityCurveResult 152 from ..models.sweep_run_row_params import SweepRunRowParams 153 154 d = dict(src_dict) 155 run_ix = d.pop("runIx") 156 157 params = SweepRunRowParams.from_dict(d.pop("params")) 158 159 sharpe = d.pop("sharpe") 160 161 sortino = d.pop("sortino") 162 163 pnl = d.pop("pnl") 164 165 pnl_pct = d.pop("pnlPct") 166 167 cagr = d.pop("cagr") 168 169 max_dd_pct = d.pop("maxDdPct") 170 171 trades = d.pop("trades") 172 173 win_rate = d.pop("winRate") 174 175 below_trade_floor = d.pop("belowTradeFloor") 176 177 aborted = d.pop("aborted") 178 179 runtime_ms = d.pop("runtimeMs") 180 181 rank = d.pop("rank", UNSET) 182 183 plateau_score = d.pop("plateauScore", UNSET) 184 185 neighbour_count = d.pop("neighbourCount", UNSET) 186 187 deflated_sharpe = d.pop("deflatedSharpe", UNSET) 188 189 _equity_curve = d.pop("equityCurve", UNSET) 190 equity_curve: EquityCurveResult | Unset 191 if isinstance(_equity_curve, Unset): 192 equity_curve = UNSET 193 else: 194 equity_curve = EquityCurveResult.from_dict(_equity_curve) 195 196 sweep_run_row = cls( 197 run_ix=run_ix, 198 params=params, 199 sharpe=sharpe, 200 sortino=sortino, 201 pnl=pnl, 202 pnl_pct=pnl_pct, 203 cagr=cagr, 204 max_dd_pct=max_dd_pct, 205 trades=trades, 206 win_rate=win_rate, 207 below_trade_floor=below_trade_floor, 208 aborted=aborted, 209 runtime_ms=runtime_ms, 210 rank=rank, 211 plateau_score=plateau_score, 212 neighbour_count=neighbour_count, 213 deflated_sharpe=deflated_sharpe, 214 equity_curve=equity_curve, 215 ) 216 217 sweep_run_row.additional_properties = d 218 return sweep_run_row
13@_attrs_define 14class SweepRunRowParams: 15 """ """ 16 17 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 18 19 def to_dict(self) -> dict[str, Any]: 20 21 field_dict: dict[str, Any] = {} 22 field_dict.update(self.additional_properties) 23 24 return field_dict 25 26 @classmethod 27 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 28 d = dict(src_dict) 29 sweep_run_row_params = cls() 30 31 sweep_run_row_params.additional_properties = d 32 return sweep_run_row_params 33 34 @property 35 def additional_keys(self) -> list[str]: 36 return list(self.additional_properties.keys()) 37 38 def __getitem__(self, key: str) -> Any: 39 return self.additional_properties[key] 40 41 def __setitem__(self, key: str, value: Any) -> None: 42 self.additional_properties[key] = value 43 44 def __delitem__(self, key: str) -> None: 45 del self.additional_properties[key] 46 47 def __contains__(self, key: str) -> bool: 48 return key in self.additional_properties
22@_attrs_define 23class SweepSensitivity: 24 """Sensitivity aggregates over a sweep's stored rows. Marginals are always complete; heatmaps may be capped, in which 25 case `heatmapsTruncated` is true. 26 27 Attributes: 28 sweep_id (str | Unset): 29 status (SweepSensitivityStatus | Unset): 30 objective (SweepSensitivityObjective | Unset): 31 rows_analysed (int | Unset): Rows available when this was computed. Grows while a sweep is still running. 32 marginals (list[SweepMarginal] | Unset): 33 heatmaps (list[SweepHeatmap] | Unset): 34 heatmaps_truncated (bool | Unset): True when at least one two-parameter surface was left out to stay inside the 35 response budget. Told explicitly because a silently short list would read as "these are all the interactions", 36 which is the wrong thing to conclude from a sensitivity view. 37 """ 38 39 sweep_id: str | Unset = UNSET 40 status: SweepSensitivityStatus | Unset = UNSET 41 objective: SweepSensitivityObjective | Unset = UNSET 42 rows_analysed: int | Unset = UNSET 43 marginals: list[SweepMarginal] | Unset = UNSET 44 heatmaps: list[SweepHeatmap] | Unset = UNSET 45 heatmaps_truncated: bool | Unset = UNSET 46 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 47 48 def to_dict(self) -> dict[str, Any]: 49 sweep_id = self.sweep_id 50 51 status: str | Unset = UNSET 52 if not isinstance(self.status, Unset): 53 status = self.status.value 54 55 objective: str | Unset = UNSET 56 if not isinstance(self.objective, Unset): 57 objective = self.objective.value 58 59 rows_analysed = self.rows_analysed 60 61 marginals: list[dict[str, Any]] | Unset = UNSET 62 if not isinstance(self.marginals, Unset): 63 marginals = [] 64 for marginals_item_data in self.marginals: 65 marginals_item = marginals_item_data.to_dict() 66 marginals.append(marginals_item) 67 68 heatmaps: list[dict[str, Any]] | Unset = UNSET 69 if not isinstance(self.heatmaps, Unset): 70 heatmaps = [] 71 for heatmaps_item_data in self.heatmaps: 72 heatmaps_item = heatmaps_item_data.to_dict() 73 heatmaps.append(heatmaps_item) 74 75 heatmaps_truncated = self.heatmaps_truncated 76 77 field_dict: dict[str, Any] = {} 78 field_dict.update(self.additional_properties) 79 field_dict.update({}) 80 if sweep_id is not UNSET: 81 field_dict["sweepId"] = sweep_id 82 if status is not UNSET: 83 field_dict["status"] = status 84 if objective is not UNSET: 85 field_dict["objective"] = objective 86 if rows_analysed is not UNSET: 87 field_dict["rowsAnalysed"] = rows_analysed 88 if marginals is not UNSET: 89 field_dict["marginals"] = marginals 90 if heatmaps is not UNSET: 91 field_dict["heatmaps"] = heatmaps 92 if heatmaps_truncated is not UNSET: 93 field_dict["heatmapsTruncated"] = heatmaps_truncated 94 95 return field_dict 96 97 @classmethod 98 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 99 from ..models.sweep_heatmap import SweepHeatmap 100 from ..models.sweep_marginal import SweepMarginal 101 102 d = dict(src_dict) 103 sweep_id = d.pop("sweepId", UNSET) 104 105 _status = d.pop("status", UNSET) 106 status: SweepSensitivityStatus | Unset 107 if isinstance(_status, Unset): 108 status = UNSET 109 else: 110 status = SweepSensitivityStatus(_status) 111 112 _objective = d.pop("objective", UNSET) 113 objective: SweepSensitivityObjective | Unset 114 if isinstance(_objective, Unset): 115 objective = UNSET 116 else: 117 objective = SweepSensitivityObjective(_objective) 118 119 rows_analysed = d.pop("rowsAnalysed", UNSET) 120 121 _marginals = d.pop("marginals", UNSET) 122 marginals: list[SweepMarginal] | Unset = UNSET 123 if _marginals is not UNSET: 124 marginals = [] 125 for marginals_item_data in _marginals: 126 marginals_item = SweepMarginal.from_dict(marginals_item_data) 127 128 marginals.append(marginals_item) 129 130 _heatmaps = d.pop("heatmaps", UNSET) 131 heatmaps: list[SweepHeatmap] | Unset = UNSET 132 if _heatmaps is not UNSET: 133 heatmaps = [] 134 for heatmaps_item_data in _heatmaps: 135 heatmaps_item = SweepHeatmap.from_dict(heatmaps_item_data) 136 137 heatmaps.append(heatmaps_item) 138 139 heatmaps_truncated = d.pop("heatmapsTruncated", UNSET) 140 141 sweep_sensitivity = cls( 142 sweep_id=sweep_id, 143 status=status, 144 objective=objective, 145 rows_analysed=rows_analysed, 146 marginals=marginals, 147 heatmaps=heatmaps, 148 heatmaps_truncated=heatmaps_truncated, 149 ) 150 151 sweep_sensitivity.additional_properties = d 152 return sweep_sensitivity 153 154 @property 155 def additional_keys(self) -> list[str]: 156 return list(self.additional_properties.keys()) 157 158 def __getitem__(self, key: str) -> Any: 159 return self.additional_properties[key] 160 161 def __setitem__(self, key: str, value: Any) -> None: 162 self.additional_properties[key] = value 163 164 def __delitem__(self, key: str) -> None: 165 del self.additional_properties[key] 166 167 def __contains__(self, key: str) -> bool: 168 return key in self.additional_properties
Sensitivity aggregates over a sweep's stored rows. Marginals are always complete; heatmaps may be capped, in which
case heatmapsTruncated is true.
Attributes:
sweep_id (str | Unset):
status (SweepSensitivityStatus | Unset):
objective (SweepSensitivityObjective | Unset):
rows_analysed (int | Unset): Rows available when this was computed. Grows while a sweep is still running.
marginals (list[SweepMarginal] | Unset):
heatmaps (list[SweepHeatmap] | Unset):
heatmaps_truncated (bool | Unset): True when at least one two-parameter surface was left out to stay inside the
response budget. Told explicitly because a silently short list would read as "these are all the interactions",
which is the wrong thing to conclude from a sensitivity view.
30def __init__(self, sweep_id=attr_dict['sweep_id'].default, status=attr_dict['status'].default, objective=attr_dict['objective'].default, rows_analysed=attr_dict['rows_analysed'].default, marginals=attr_dict['marginals'].default, heatmaps=attr_dict['heatmaps'].default, heatmaps_truncated=attr_dict['heatmaps_truncated'].default): 31 self.sweep_id = sweep_id 32 self.status = status 33 self.objective = objective 34 self.rows_analysed = rows_analysed 35 self.marginals = marginals 36 self.heatmaps = heatmaps 37 self.heatmaps_truncated = heatmaps_truncated 38 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepSensitivity.
48 def to_dict(self) -> dict[str, Any]: 49 sweep_id = self.sweep_id 50 51 status: str | Unset = UNSET 52 if not isinstance(self.status, Unset): 53 status = self.status.value 54 55 objective: str | Unset = UNSET 56 if not isinstance(self.objective, Unset): 57 objective = self.objective.value 58 59 rows_analysed = self.rows_analysed 60 61 marginals: list[dict[str, Any]] | Unset = UNSET 62 if not isinstance(self.marginals, Unset): 63 marginals = [] 64 for marginals_item_data in self.marginals: 65 marginals_item = marginals_item_data.to_dict() 66 marginals.append(marginals_item) 67 68 heatmaps: list[dict[str, Any]] | Unset = UNSET 69 if not isinstance(self.heatmaps, Unset): 70 heatmaps = [] 71 for heatmaps_item_data in self.heatmaps: 72 heatmaps_item = heatmaps_item_data.to_dict() 73 heatmaps.append(heatmaps_item) 74 75 heatmaps_truncated = self.heatmaps_truncated 76 77 field_dict: dict[str, Any] = {} 78 field_dict.update(self.additional_properties) 79 field_dict.update({}) 80 if sweep_id is not UNSET: 81 field_dict["sweepId"] = sweep_id 82 if status is not UNSET: 83 field_dict["status"] = status 84 if objective is not UNSET: 85 field_dict["objective"] = objective 86 if rows_analysed is not UNSET: 87 field_dict["rowsAnalysed"] = rows_analysed 88 if marginals is not UNSET: 89 field_dict["marginals"] = marginals 90 if heatmaps is not UNSET: 91 field_dict["heatmaps"] = heatmaps 92 if heatmaps_truncated is not UNSET: 93 field_dict["heatmapsTruncated"] = heatmaps_truncated 94 95 return field_dict
97 @classmethod 98 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 99 from ..models.sweep_heatmap import SweepHeatmap 100 from ..models.sweep_marginal import SweepMarginal 101 102 d = dict(src_dict) 103 sweep_id = d.pop("sweepId", UNSET) 104 105 _status = d.pop("status", UNSET) 106 status: SweepSensitivityStatus | Unset 107 if isinstance(_status, Unset): 108 status = UNSET 109 else: 110 status = SweepSensitivityStatus(_status) 111 112 _objective = d.pop("objective", UNSET) 113 objective: SweepSensitivityObjective | Unset 114 if isinstance(_objective, Unset): 115 objective = UNSET 116 else: 117 objective = SweepSensitivityObjective(_objective) 118 119 rows_analysed = d.pop("rowsAnalysed", UNSET) 120 121 _marginals = d.pop("marginals", UNSET) 122 marginals: list[SweepMarginal] | Unset = UNSET 123 if _marginals is not UNSET: 124 marginals = [] 125 for marginals_item_data in _marginals: 126 marginals_item = SweepMarginal.from_dict(marginals_item_data) 127 128 marginals.append(marginals_item) 129 130 _heatmaps = d.pop("heatmaps", UNSET) 131 heatmaps: list[SweepHeatmap] | Unset = UNSET 132 if _heatmaps is not UNSET: 133 heatmaps = [] 134 for heatmaps_item_data in _heatmaps: 135 heatmaps_item = SweepHeatmap.from_dict(heatmaps_item_data) 136 137 heatmaps.append(heatmaps_item) 138 139 heatmaps_truncated = d.pop("heatmapsTruncated", UNSET) 140 141 sweep_sensitivity = cls( 142 sweep_id=sweep_id, 143 status=status, 144 objective=objective, 145 rows_analysed=rows_analysed, 146 marginals=marginals, 147 heatmaps=heatmaps, 148 heatmaps_truncated=heatmaps_truncated, 149 ) 150 151 sweep_sensitivity.additional_properties = d 152 return sweep_sensitivity
5class SweepSensitivityObjective(str, Enum): 6 MAXDD = "maxdd" 7 PNL = "pnl" 8 SHARPE = "sharpe" 9 SORTINO = "sortino" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
5class SweepSensitivityStatus(str, Enum): 6 CANCELLED = "CANCELLED" 7 COMPLETED = "COMPLETED" 8 PARTIAL = "PARTIAL" 9 RUNNING = "RUNNING" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
21@_attrs_define 22class SweepSpecRequest: 23 """ 24 Example: 25 {'sampler': 'lhs', 'seed': 487221, 'samples': 100, 'objective': 'sharpe', 'params': {'rsiPeriod': {'from': 7, 26 'to': 28, 'step': 1}, 'useTrendFilter': {'values': [True, False]}}} 27 28 Attributes: 29 params (SweepSpecRequestParams): 30 sampler (SweepSpecRequestSampler | Unset): `grid` runs every combination of the axes and is held to your plan's 31 `maxSweepCartesian` (`GET /account`); `random` and `lhs` run `samples` combinations and are not. 32 Default: SweepSpecRequestSampler.GRID. 33 seed (int | Unset): Reproducibility seed. If omitted, the server generates one with Java's 34 `L64X128MixRandom` generator and returns the effective value. The range 35 is limited to JavaScript-safe integers so generated clients can replay it exactly. 36 samples (int | Unset): Number of samples for `random` and `lhs`; ignored by `grid`. 37 objective (SweepSpecRequestObjective | Unset): Default: SweepSpecRequestObjective.SHARPE. 38 """ 39 40 params: SweepSpecRequestParams 41 sampler: SweepSpecRequestSampler | Unset = SweepSpecRequestSampler.GRID 42 seed: int | Unset = UNSET 43 samples: int | Unset = UNSET 44 objective: SweepSpecRequestObjective | Unset = SweepSpecRequestObjective.SHARPE 45 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 46 47 def to_dict(self) -> dict[str, Any]: 48 params = self.params.to_dict() 49 50 sampler: str | Unset = UNSET 51 if not isinstance(self.sampler, Unset): 52 sampler = self.sampler.value 53 54 seed = self.seed 55 56 samples = self.samples 57 58 objective: str | Unset = UNSET 59 if not isinstance(self.objective, Unset): 60 objective = self.objective.value 61 62 field_dict: dict[str, Any] = {} 63 field_dict.update(self.additional_properties) 64 field_dict.update( 65 { 66 "params": params, 67 } 68 ) 69 if sampler is not UNSET: 70 field_dict["sampler"] = sampler 71 if seed is not UNSET: 72 field_dict["seed"] = seed 73 if samples is not UNSET: 74 field_dict["samples"] = samples 75 if objective is not UNSET: 76 field_dict["objective"] = objective 77 78 return field_dict 79 80 @classmethod 81 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 82 from ..models.sweep_spec_request_params import SweepSpecRequestParams 83 84 d = dict(src_dict) 85 params = SweepSpecRequestParams.from_dict(d.pop("params")) 86 87 _sampler = d.pop("sampler", UNSET) 88 sampler: SweepSpecRequestSampler | Unset 89 if isinstance(_sampler, Unset): 90 sampler = UNSET 91 else: 92 sampler = SweepSpecRequestSampler(_sampler) 93 94 seed = d.pop("seed", UNSET) 95 96 samples = d.pop("samples", UNSET) 97 98 _objective = d.pop("objective", UNSET) 99 objective: SweepSpecRequestObjective | Unset 100 if isinstance(_objective, Unset): 101 objective = UNSET 102 else: 103 objective = SweepSpecRequestObjective(_objective) 104 105 sweep_spec_request = cls( 106 params=params, 107 sampler=sampler, 108 seed=seed, 109 samples=samples, 110 objective=objective, 111 ) 112 113 sweep_spec_request.additional_properties = d 114 return sweep_spec_request 115 116 @property 117 def additional_keys(self) -> list[str]: 118 return list(self.additional_properties.keys()) 119 120 def __getitem__(self, key: str) -> Any: 121 return self.additional_properties[key] 122 123 def __setitem__(self, key: str, value: Any) -> None: 124 self.additional_properties[key] = value 125 126 def __delitem__(self, key: str) -> None: 127 del self.additional_properties[key] 128 129 def __contains__(self, key: str) -> bool: 130 return key in self.additional_properties
Example: {'sampler': 'lhs', 'seed': 487221, 'samples': 100, 'objective': 'sharpe', 'params': {'rsiPeriod': {'from': 7, 'to': 28, 'step': 1}, 'useTrendFilter': {'values': [True, False]}}}
Attributes:
params (SweepSpecRequestParams):
sampler (SweepSpecRequestSampler | Unset): grid runs every combination of the axes and is held to your plan's
maxSweepCartesian (GET /account); random and lhs run samples combinations and are not.
Default: SweepSpecRequestSampler.GRID.
seed (int | Unset): Reproducibility seed. If omitted, the server generates one with Java's
L64X128MixRandom generator and returns the effective value. The range
is limited to JavaScript-safe integers so generated clients can replay it exactly.
samples (int | Unset): Number of samples for random and lhs; ignored by grid.
objective (SweepSpecRequestObjective | Unset): Default: SweepSpecRequestObjective.SHARPE.
28def __init__(self, params, sampler=attr_dict['sampler'].default, seed=attr_dict['seed'].default, samples=attr_dict['samples'].default, objective=attr_dict['objective'].default): 29 self.params = params 30 self.sampler = sampler 31 self.seed = seed 32 self.samples = samples 33 self.objective = objective 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class SweepSpecRequest.
47 def to_dict(self) -> dict[str, Any]: 48 params = self.params.to_dict() 49 50 sampler: str | Unset = UNSET 51 if not isinstance(self.sampler, Unset): 52 sampler = self.sampler.value 53 54 seed = self.seed 55 56 samples = self.samples 57 58 objective: str | Unset = UNSET 59 if not isinstance(self.objective, Unset): 60 objective = self.objective.value 61 62 field_dict: dict[str, Any] = {} 63 field_dict.update(self.additional_properties) 64 field_dict.update( 65 { 66 "params": params, 67 } 68 ) 69 if sampler is not UNSET: 70 field_dict["sampler"] = sampler 71 if seed is not UNSET: 72 field_dict["seed"] = seed 73 if samples is not UNSET: 74 field_dict["samples"] = samples 75 if objective is not UNSET: 76 field_dict["objective"] = objective 77 78 return field_dict
80 @classmethod 81 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 82 from ..models.sweep_spec_request_params import SweepSpecRequestParams 83 84 d = dict(src_dict) 85 params = SweepSpecRequestParams.from_dict(d.pop("params")) 86 87 _sampler = d.pop("sampler", UNSET) 88 sampler: SweepSpecRequestSampler | Unset 89 if isinstance(_sampler, Unset): 90 sampler = UNSET 91 else: 92 sampler = SweepSpecRequestSampler(_sampler) 93 94 seed = d.pop("seed", UNSET) 95 96 samples = d.pop("samples", UNSET) 97 98 _objective = d.pop("objective", UNSET) 99 objective: SweepSpecRequestObjective | Unset 100 if isinstance(_objective, Unset): 101 objective = UNSET 102 else: 103 objective = SweepSpecRequestObjective(_objective) 104 105 sweep_spec_request = cls( 106 params=params, 107 sampler=sampler, 108 seed=seed, 109 samples=samples, 110 objective=objective, 111 ) 112 113 sweep_spec_request.additional_properties = d 114 return sweep_spec_request
5class SweepSpecRequestObjective(str, Enum): 6 MAXDD = "maxdd" 7 PNL = "pnl" 8 SHARPE = "sharpe" 9 SORTINO = "sortino" 10 11 def __str__(self) -> str: 12 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
18@_attrs_define 19class SweepSpecRequestParams: 20 """ """ 21 22 additional_properties: dict[str, SweepAxisType0 | SweepAxisType1] = _attrs_field(init=False, factory=dict) 23 24 def to_dict(self) -> dict[str, Any]: 25 from ..models.sweep_axis_type_0 import SweepAxisType0 26 27 field_dict: dict[str, Any] = {} 28 for prop_name, prop in self.additional_properties.items(): 29 if isinstance(prop, SweepAxisType0): 30 field_dict[prop_name] = prop.to_dict() 31 else: 32 field_dict[prop_name] = prop.to_dict() 33 34 return field_dict 35 36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 from ..models.sweep_axis_type_0 import SweepAxisType0 39 from ..models.sweep_axis_type_1 import SweepAxisType1 40 41 d = dict(src_dict) 42 sweep_spec_request_params = cls() 43 44 additional_properties = {} 45 for prop_name, prop_dict in d.items(): 46 47 def _parse_additional_property(data: object) -> SweepAxisType0 | SweepAxisType1: 48 try: 49 if not isinstance(data, dict): 50 raise TypeError() 51 componentsschemas_sweep_axis_type_0 = SweepAxisType0.from_dict(data) 52 53 return componentsschemas_sweep_axis_type_0 54 except (TypeError, ValueError, AttributeError, KeyError): 55 pass 56 if not isinstance(data, dict): 57 raise TypeError() 58 componentsschemas_sweep_axis_type_1 = SweepAxisType1.from_dict(data) 59 60 return componentsschemas_sweep_axis_type_1 61 62 additional_property = _parse_additional_property(prop_dict) 63 64 additional_properties[prop_name] = additional_property 65 66 sweep_spec_request_params.additional_properties = additional_properties 67 return sweep_spec_request_params 68 69 @property 70 def additional_keys(self) -> list[str]: 71 return list(self.additional_properties.keys()) 72 73 def __getitem__(self, key: str) -> SweepAxisType0 | SweepAxisType1: 74 return self.additional_properties[key] 75 76 def __setitem__(self, key: str, value: SweepAxisType0 | SweepAxisType1) -> None: 77 self.additional_properties[key] = value 78 79 def __delitem__(self, key: str) -> None: 80 del self.additional_properties[key] 81 82 def __contains__(self, key: str) -> bool: 83 return key in self.additional_properties
24 def to_dict(self) -> dict[str, Any]: 25 from ..models.sweep_axis_type_0 import SweepAxisType0 26 27 field_dict: dict[str, Any] = {} 28 for prop_name, prop in self.additional_properties.items(): 29 if isinstance(prop, SweepAxisType0): 30 field_dict[prop_name] = prop.to_dict() 31 else: 32 field_dict[prop_name] = prop.to_dict() 33 34 return field_dict
36 @classmethod 37 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 38 from ..models.sweep_axis_type_0 import SweepAxisType0 39 from ..models.sweep_axis_type_1 import SweepAxisType1 40 41 d = dict(src_dict) 42 sweep_spec_request_params = cls() 43 44 additional_properties = {} 45 for prop_name, prop_dict in d.items(): 46 47 def _parse_additional_property(data: object) -> SweepAxisType0 | SweepAxisType1: 48 try: 49 if not isinstance(data, dict): 50 raise TypeError() 51 componentsschemas_sweep_axis_type_0 = SweepAxisType0.from_dict(data) 52 53 return componentsschemas_sweep_axis_type_0 54 except (TypeError, ValueError, AttributeError, KeyError): 55 pass 56 if not isinstance(data, dict): 57 raise TypeError() 58 componentsschemas_sweep_axis_type_1 = SweepAxisType1.from_dict(data) 59 60 return componentsschemas_sweep_axis_type_1 61 62 additional_property = _parse_additional_property(prop_dict) 63 64 additional_properties[prop_name] = additional_property 65 66 sweep_spec_request_params.additional_properties = additional_properties 67 return sweep_spec_request_params
5class SweepSpecRequestSampler(str, Enum): 6 GRID = "grid" 7 LHS = "lhs" 8 RANDOM = "random" 9 10 def __str__(self) -> str: 11 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
17@_attrs_define 18class UpdateLiveParamsRequest: 19 """ 20 Attributes: 21 params (UpdateLiveParamsRequestParams): Must be non-empty; every key must be a property your strategy declares. 22 """ 23 24 params: UpdateLiveParamsRequestParams 25 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 26 27 def to_dict(self) -> dict[str, Any]: 28 params = self.params.to_dict() 29 30 field_dict: dict[str, Any] = {} 31 field_dict.update(self.additional_properties) 32 field_dict.update( 33 { 34 "params": params, 35 } 36 ) 37 38 return field_dict 39 40 @classmethod 41 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 42 from ..models.update_live_params_request_params import UpdateLiveParamsRequestParams 43 44 d = dict(src_dict) 45 params = UpdateLiveParamsRequestParams.from_dict(d.pop("params")) 46 47 update_live_params_request = cls( 48 params=params, 49 ) 50 51 update_live_params_request.additional_properties = d 52 return update_live_params_request 53 54 @property 55 def additional_keys(self) -> list[str]: 56 return list(self.additional_properties.keys()) 57 58 def __getitem__(self, key: str) -> Any: 59 return self.additional_properties[key] 60 61 def __setitem__(self, key: str, value: Any) -> None: 62 self.additional_properties[key] = value 63 64 def __delitem__(self, key: str) -> None: 65 del self.additional_properties[key] 66 67 def __contains__(self, key: str) -> bool: 68 return key in self.additional_properties
Attributes: params (UpdateLiveParamsRequestParams): Must be non-empty; every key must be a property your strategy declares.
24def __init__(self, params): 25 self.params = params 26 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class UpdateLiveParamsRequest.
40 @classmethod 41 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 42 from ..models.update_live_params_request_params import UpdateLiveParamsRequestParams 43 44 d = dict(src_dict) 45 params = UpdateLiveParamsRequestParams.from_dict(d.pop("params")) 46 47 update_live_params_request = cls( 48 params=params, 49 ) 50 51 update_live_params_request.additional_properties = d 52 return update_live_params_request
13@_attrs_define 14class UpdateLiveParamsRequestParams: 15 """Must be non-empty; every key must be a property your strategy declares.""" 16 17 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 18 19 def to_dict(self) -> dict[str, Any]: 20 21 field_dict: dict[str, Any] = {} 22 field_dict.update(self.additional_properties) 23 24 return field_dict 25 26 @classmethod 27 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 28 d = dict(src_dict) 29 update_live_params_request_params = cls() 30 31 update_live_params_request_params.additional_properties = d 32 return update_live_params_request_params 33 34 @property 35 def additional_keys(self) -> list[str]: 36 return list(self.additional_properties.keys()) 37 38 def __getitem__(self, key: str) -> Any: 39 return self.additional_properties[key] 40 41 def __setitem__(self, key: str, value: Any) -> None: 42 self.additional_properties[key] = value 43 44 def __delitem__(self, key: str) -> None: 45 del self.additional_properties[key] 46 47 def __contains__(self, key: str) -> bool: 48 return key in self.additional_properties
Must be non-empty; every key must be a property your strategy declares.
16@_attrs_define 17class UpdateLiveRequest: 18 """ 19 Attributes: 20 visibility (UpdateLiveRequestVisibility | Unset): 21 name (str | Unset): 22 description (str | Unset): 23 """ 24 25 visibility: UpdateLiveRequestVisibility | Unset = UNSET 26 name: str | Unset = UNSET 27 description: str | Unset = UNSET 28 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 29 30 def to_dict(self) -> dict[str, Any]: 31 visibility: str | Unset = UNSET 32 if not isinstance(self.visibility, Unset): 33 visibility = self.visibility.value 34 35 name = self.name 36 37 description = self.description 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update({}) 42 if visibility is not UNSET: 43 field_dict["visibility"] = visibility 44 if name is not UNSET: 45 field_dict["name"] = name 46 if description is not UNSET: 47 field_dict["description"] = description 48 49 return field_dict 50 51 @classmethod 52 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 53 d = dict(src_dict) 54 _visibility = d.pop("visibility", UNSET) 55 visibility: UpdateLiveRequestVisibility | Unset 56 if isinstance(_visibility, Unset): 57 visibility = UNSET 58 else: 59 visibility = UpdateLiveRequestVisibility(_visibility) 60 61 name = d.pop("name", UNSET) 62 63 description = d.pop("description", UNSET) 64 65 update_live_request = cls( 66 visibility=visibility, 67 name=name, 68 description=description, 69 ) 70 71 update_live_request.additional_properties = d 72 return update_live_request 73 74 @property 75 def additional_keys(self) -> list[str]: 76 return list(self.additional_properties.keys()) 77 78 def __getitem__(self, key: str) -> Any: 79 return self.additional_properties[key] 80 81 def __setitem__(self, key: str, value: Any) -> None: 82 self.additional_properties[key] = value 83 84 def __delitem__(self, key: str) -> None: 85 del self.additional_properties[key] 86 87 def __contains__(self, key: str) -> bool: 88 return key in self.additional_properties
Attributes: visibility (UpdateLiveRequestVisibility | Unset): name (str | Unset): description (str | Unset):
26def __init__(self, visibility=attr_dict['visibility'].default, name=attr_dict['name'].default, description=attr_dict['description'].default): 27 self.visibility = visibility 28 self.name = name 29 self.description = description 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class UpdateLiveRequest.
30 def to_dict(self) -> dict[str, Any]: 31 visibility: str | Unset = UNSET 32 if not isinstance(self.visibility, Unset): 33 visibility = self.visibility.value 34 35 name = self.name 36 37 description = self.description 38 39 field_dict: dict[str, Any] = {} 40 field_dict.update(self.additional_properties) 41 field_dict.update({}) 42 if visibility is not UNSET: 43 field_dict["visibility"] = visibility 44 if name is not UNSET: 45 field_dict["name"] = name 46 if description is not UNSET: 47 field_dict["description"] = description 48 49 return field_dict
51 @classmethod 52 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 53 d = dict(src_dict) 54 _visibility = d.pop("visibility", UNSET) 55 visibility: UpdateLiveRequestVisibility | Unset 56 if isinstance(_visibility, Unset): 57 visibility = UNSET 58 else: 59 visibility = UpdateLiveRequestVisibility(_visibility) 60 61 name = d.pop("name", UNSET) 62 63 description = d.pop("description", UNSET) 64 65 update_live_request = cls( 66 visibility=visibility, 67 name=name, 68 description=description, 69 ) 70 71 update_live_request.additional_properties = d 72 return update_live_request
5class UpdateLiveRequestVisibility(str, Enum): 6 PRIVATE = "private" 7 PUBLIC = "public" 8 9 def __str__(self) -> str: 10 return str(self.value)
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to 'strict'.
13@_attrs_define 14class WalkForwardAccepted: 15 """Echo of the accepted walk-forward configuration, present only when the submit carried one. `inSamplePct` is the 16 resolved value, so a request that omitted it can see what it got. 17 18 Attributes: 19 folds (int): 20 in_sample_pct (int): 21 total_runs (int): What this sweep actually costs, `folds × (grid size + 1)` — the in-sample runs for every fold 22 plus each fold's one out-of-sample run. Deliberately distinct from the top-level `totalRuns`, which stays the 23 size of the grid that was submitted. 24 """ 25 26 folds: int 27 in_sample_pct: int 28 total_runs: int 29 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 30 31 def to_dict(self) -> dict[str, Any]: 32 folds = self.folds 33 34 in_sample_pct = self.in_sample_pct 35 36 total_runs = self.total_runs 37 38 field_dict: dict[str, Any] = {} 39 field_dict.update(self.additional_properties) 40 field_dict.update( 41 { 42 "folds": folds, 43 "inSamplePct": in_sample_pct, 44 "totalRuns": total_runs, 45 } 46 ) 47 48 return field_dict 49 50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 d = dict(src_dict) 53 folds = d.pop("folds") 54 55 in_sample_pct = d.pop("inSamplePct") 56 57 total_runs = d.pop("totalRuns") 58 59 walk_forward_accepted = cls( 60 folds=folds, 61 in_sample_pct=in_sample_pct, 62 total_runs=total_runs, 63 ) 64 65 walk_forward_accepted.additional_properties = d 66 return walk_forward_accepted 67 68 @property 69 def additional_keys(self) -> list[str]: 70 return list(self.additional_properties.keys()) 71 72 def __getitem__(self, key: str) -> Any: 73 return self.additional_properties[key] 74 75 def __setitem__(self, key: str, value: Any) -> None: 76 self.additional_properties[key] = value 77 78 def __delitem__(self, key: str) -> None: 79 del self.additional_properties[key] 80 81 def __contains__(self, key: str) -> bool: 82 return key in self.additional_properties
Echo of the accepted walk-forward configuration, present only when the submit carried one. inSamplePct is the
resolved value, so a request that omitted it can see what it got.
Attributes:
folds (int):
in_sample_pct (int):
total_runs (int): What this sweep actually costs, `folds × (grid size + 1)` — the in-sample runs for every fold
plus each fold's one out-of-sample run. Deliberately distinct from the top-level `totalRuns`, which stays the
size of the grid that was submitted.
26def __init__(self, folds, in_sample_pct, total_runs): 27 self.folds = folds 28 self.in_sample_pct = in_sample_pct 29 self.total_runs = total_runs 30 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class WalkForwardAccepted.
31 def to_dict(self) -> dict[str, Any]: 32 folds = self.folds 33 34 in_sample_pct = self.in_sample_pct 35 36 total_runs = self.total_runs 37 38 field_dict: dict[str, Any] = {} 39 field_dict.update(self.additional_properties) 40 field_dict.update( 41 { 42 "folds": folds, 43 "inSamplePct": in_sample_pct, 44 "totalRuns": total_runs, 45 } 46 ) 47 48 return field_dict
50 @classmethod 51 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 52 d = dict(src_dict) 53 folds = d.pop("folds") 54 55 in_sample_pct = d.pop("inSamplePct") 56 57 total_runs = d.pop("totalRuns") 58 59 walk_forward_accepted = cls( 60 folds=folds, 61 in_sample_pct=in_sample_pct, 62 total_runs=total_runs, 63 ) 64 65 walk_forward_accepted.additional_properties = d 66 return walk_forward_accepted
18@_attrs_define 19class WalkForwardFold: 20 """What one fold concluded. The out-of-sample row is the answer; the in-sample figure is only there to be compared 21 against it, since any grid produces a flattering in-sample winner — that is what optimizing does. The gap between 22 them is the whole reading. 23 24 Attributes: 25 fold_ix (int): Position in the walk-forward sequence, oldest first. 26 in_sample_from (int): First index of the optimization window, into the prepared session. 27 in_sample_to (int): End of the optimization window, exclusive — and where scoring begins. 28 out_of_sample_to (int): End of the scoring window, exclusive. 29 params (WalkForwardFoldParams): The parameter vector that won this fold's optimization window. 30 in_sample_sharpe (float): How that winner scored on the window it was chosen on. 31 out_of_sample (SweepRunRow): 32 vectors_run (int): Vectors this fold evaluated in-sample before picking its winner. 33 """ 34 35 fold_ix: int 36 in_sample_from: int 37 in_sample_to: int 38 out_of_sample_to: int 39 params: WalkForwardFoldParams 40 in_sample_sharpe: float 41 out_of_sample: SweepRunRow 42 vectors_run: int 43 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 44 45 def to_dict(self) -> dict[str, Any]: 46 fold_ix = self.fold_ix 47 48 in_sample_from = self.in_sample_from 49 50 in_sample_to = self.in_sample_to 51 52 out_of_sample_to = self.out_of_sample_to 53 54 params = self.params.to_dict() 55 56 in_sample_sharpe = self.in_sample_sharpe 57 58 out_of_sample = self.out_of_sample.to_dict() 59 60 vectors_run = self.vectors_run 61 62 field_dict: dict[str, Any] = {} 63 field_dict.update(self.additional_properties) 64 field_dict.update( 65 { 66 "foldIx": fold_ix, 67 "inSampleFrom": in_sample_from, 68 "inSampleTo": in_sample_to, 69 "outOfSampleTo": out_of_sample_to, 70 "params": params, 71 "inSampleSharpe": in_sample_sharpe, 72 "outOfSample": out_of_sample, 73 "vectorsRun": vectors_run, 74 } 75 ) 76 77 return field_dict 78 79 @classmethod 80 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 81 from ..models.sweep_run_row import SweepRunRow 82 from ..models.walk_forward_fold_params import WalkForwardFoldParams 83 84 d = dict(src_dict) 85 fold_ix = d.pop("foldIx") 86 87 in_sample_from = d.pop("inSampleFrom") 88 89 in_sample_to = d.pop("inSampleTo") 90 91 out_of_sample_to = d.pop("outOfSampleTo") 92 93 params = WalkForwardFoldParams.from_dict(d.pop("params")) 94 95 in_sample_sharpe = d.pop("inSampleSharpe") 96 97 out_of_sample = SweepRunRow.from_dict(d.pop("outOfSample")) 98 99 vectors_run = d.pop("vectorsRun") 100 101 walk_forward_fold = cls( 102 fold_ix=fold_ix, 103 in_sample_from=in_sample_from, 104 in_sample_to=in_sample_to, 105 out_of_sample_to=out_of_sample_to, 106 params=params, 107 in_sample_sharpe=in_sample_sharpe, 108 out_of_sample=out_of_sample, 109 vectors_run=vectors_run, 110 ) 111 112 walk_forward_fold.additional_properties = d 113 return walk_forward_fold 114 115 @property 116 def additional_keys(self) -> list[str]: 117 return list(self.additional_properties.keys()) 118 119 def __getitem__(self, key: str) -> Any: 120 return self.additional_properties[key] 121 122 def __setitem__(self, key: str, value: Any) -> None: 123 self.additional_properties[key] = value 124 125 def __delitem__(self, key: str) -> None: 126 del self.additional_properties[key] 127 128 def __contains__(self, key: str) -> bool: 129 return key in self.additional_properties
What one fold concluded. The out-of-sample row is the answer; the in-sample figure is only there to be compared against it, since any grid produces a flattering in-sample winner — that is what optimizing does. The gap between them is the whole reading.
Attributes:
fold_ix (int): Position in the walk-forward sequence, oldest first.
in_sample_from (int): First index of the optimization window, into the prepared session.
in_sample_to (int): End of the optimization window, exclusive — and where scoring begins.
out_of_sample_to (int): End of the scoring window, exclusive.
params (WalkForwardFoldParams): The parameter vector that won this fold's optimization window.
in_sample_sharpe (float): How that winner scored on the window it was chosen on.
out_of_sample (SweepRunRow):
vectors_run (int): Vectors this fold evaluated in-sample before picking its winner.
31def __init__(self, fold_ix, in_sample_from, in_sample_to, out_of_sample_to, params, in_sample_sharpe, out_of_sample, vectors_run): 32 self.fold_ix = fold_ix 33 self.in_sample_from = in_sample_from 34 self.in_sample_to = in_sample_to 35 self.out_of_sample_to = out_of_sample_to 36 self.params = params 37 self.in_sample_sharpe = in_sample_sharpe 38 self.out_of_sample = out_of_sample 39 self.vectors_run = vectors_run 40 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class WalkForwardFold.
45 def to_dict(self) -> dict[str, Any]: 46 fold_ix = self.fold_ix 47 48 in_sample_from = self.in_sample_from 49 50 in_sample_to = self.in_sample_to 51 52 out_of_sample_to = self.out_of_sample_to 53 54 params = self.params.to_dict() 55 56 in_sample_sharpe = self.in_sample_sharpe 57 58 out_of_sample = self.out_of_sample.to_dict() 59 60 vectors_run = self.vectors_run 61 62 field_dict: dict[str, Any] = {} 63 field_dict.update(self.additional_properties) 64 field_dict.update( 65 { 66 "foldIx": fold_ix, 67 "inSampleFrom": in_sample_from, 68 "inSampleTo": in_sample_to, 69 "outOfSampleTo": out_of_sample_to, 70 "params": params, 71 "inSampleSharpe": in_sample_sharpe, 72 "outOfSample": out_of_sample, 73 "vectorsRun": vectors_run, 74 } 75 ) 76 77 return field_dict
79 @classmethod 80 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 81 from ..models.sweep_run_row import SweepRunRow 82 from ..models.walk_forward_fold_params import WalkForwardFoldParams 83 84 d = dict(src_dict) 85 fold_ix = d.pop("foldIx") 86 87 in_sample_from = d.pop("inSampleFrom") 88 89 in_sample_to = d.pop("inSampleTo") 90 91 out_of_sample_to = d.pop("outOfSampleTo") 92 93 params = WalkForwardFoldParams.from_dict(d.pop("params")) 94 95 in_sample_sharpe = d.pop("inSampleSharpe") 96 97 out_of_sample = SweepRunRow.from_dict(d.pop("outOfSample")) 98 99 vectors_run = d.pop("vectorsRun") 100 101 walk_forward_fold = cls( 102 fold_ix=fold_ix, 103 in_sample_from=in_sample_from, 104 in_sample_to=in_sample_to, 105 out_of_sample_to=out_of_sample_to, 106 params=params, 107 in_sample_sharpe=in_sample_sharpe, 108 out_of_sample=out_of_sample, 109 vectors_run=vectors_run, 110 ) 111 112 walk_forward_fold.additional_properties = d 113 return walk_forward_fold
13@_attrs_define 14class WalkForwardFoldParams: 15 """The parameter vector that won this fold's optimization window.""" 16 17 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 18 19 def to_dict(self) -> dict[str, Any]: 20 21 field_dict: dict[str, Any] = {} 22 field_dict.update(self.additional_properties) 23 24 return field_dict 25 26 @classmethod 27 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 28 d = dict(src_dict) 29 walk_forward_fold_params = cls() 30 31 walk_forward_fold_params.additional_properties = d 32 return walk_forward_fold_params 33 34 @property 35 def additional_keys(self) -> list[str]: 36 return list(self.additional_properties.keys()) 37 38 def __getitem__(self, key: str) -> Any: 39 return self.additional_properties[key] 40 41 def __setitem__(self, key: str, value: Any) -> None: 42 self.additional_properties[key] = value 43 44 def __delitem__(self, key: str) -> None: 45 del self.additional_properties[key] 46 47 def __contains__(self, key: str) -> bool: 48 return key in self.additional_properties
The parameter vector that won this fold's optimization window.
15@_attrs_define 16class WalkForwardRequest: 17 """Opt in to walk-forward validation. Present, the sweep runs as F sequential folds and the result gains a 18 `walkForward` section; absent, nothing about the sweep changes. Two requests that differ only in this block are two 19 different sweeps and do not deduplicate against each other. 20 21 Attributes: 22 folds (int): How many sequential optimize-then-score windows to run. Two is the minimum for a reason, and it is 23 structural rather than a tuning choice: parameter drift is measured between consecutive fold winners, and a 24 single fold — one train/test split with no sequence — has no consecutive pair to compare, so it would report the 25 strongest possible stability having measured nothing. 26 The upper bound is a server setting (12 by default) and is deliberately not pinned here, since a spec that 27 hardcodes a tunable limit lies the day it is raised. Exceeding it, or exceeding the sweep budget once multiplied 28 by the grid size, is a 400. 29 in_sample_pct (int | Unset): Share of the session each fold spends optimizing; the remainder is where its winner 30 is scored. Lower values leave more data to be scored on and, on short sessions, are also what lets the requested 31 fold count tile the data at all. Default: 66. 32 """ 33 34 folds: int 35 in_sample_pct: int | Unset = 66 36 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 37 38 def to_dict(self) -> dict[str, Any]: 39 folds = self.folds 40 41 in_sample_pct = self.in_sample_pct 42 43 field_dict: dict[str, Any] = {} 44 field_dict.update(self.additional_properties) 45 field_dict.update( 46 { 47 "folds": folds, 48 } 49 ) 50 if in_sample_pct is not UNSET: 51 field_dict["inSamplePct"] = in_sample_pct 52 53 return field_dict 54 55 @classmethod 56 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 57 d = dict(src_dict) 58 folds = d.pop("folds") 59 60 in_sample_pct = d.pop("inSamplePct", UNSET) 61 62 walk_forward_request = cls( 63 folds=folds, 64 in_sample_pct=in_sample_pct, 65 ) 66 67 walk_forward_request.additional_properties = d 68 return walk_forward_request 69 70 @property 71 def additional_keys(self) -> list[str]: 72 return list(self.additional_properties.keys()) 73 74 def __getitem__(self, key: str) -> Any: 75 return self.additional_properties[key] 76 77 def __setitem__(self, key: str, value: Any) -> None: 78 self.additional_properties[key] = value 79 80 def __delitem__(self, key: str) -> None: 81 del self.additional_properties[key] 82 83 def __contains__(self, key: str) -> bool: 84 return key in self.additional_properties
Opt in to walk-forward validation. Present, the sweep runs as F sequential folds and the result gains a
walkForward section; absent, nothing about the sweep changes. Two requests that differ only in this block are two
different sweeps and do not deduplicate against each other.
Attributes:
folds (int): How many sequential optimize-then-score windows to run. Two is the minimum for a reason, and it is
structural rather than a tuning choice: parameter drift is measured between consecutive fold winners, and a
single fold — one train/test split with no sequence — has no consecutive pair to compare, so it would report the
strongest possible stability having measured nothing.
The upper bound is a server setting (12 by default) and is deliberately not pinned here, since a spec that
hardcodes a tunable limit lies the day it is raised. Exceeding it, or exceeding the sweep budget once multiplied
by the grid size, is a 400.
in_sample_pct (int | Unset): Share of the session each fold spends optimizing; the remainder is where its winner
is scored. Lower values leave more data to be scored on and, on short sessions, are also what lets the requested
fold count tile the data at all. Default: 66.
25def __init__(self, folds, in_sample_pct=attr_dict['in_sample_pct'].default): 26 self.folds = folds 27 self.in_sample_pct = in_sample_pct 28 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class WalkForwardRequest.
38 def to_dict(self) -> dict[str, Any]: 39 folds = self.folds 40 41 in_sample_pct = self.in_sample_pct 42 43 field_dict: dict[str, Any] = {} 44 field_dict.update(self.additional_properties) 45 field_dict.update( 46 { 47 "folds": folds, 48 } 49 ) 50 if in_sample_pct is not UNSET: 51 field_dict["inSamplePct"] = in_sample_pct 52 53 return field_dict
55 @classmethod 56 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 57 d = dict(src_dict) 58 folds = d.pop("folds") 59 60 in_sample_pct = d.pop("inSamplePct", UNSET) 61 62 walk_forward_request = cls( 63 folds=folds, 64 in_sample_pct=in_sample_pct, 65 ) 66 67 walk_forward_request.additional_properties = d 68 return walk_forward_request
19@_attrs_define 20class WalkForwardResult: 21 """Present only on a sweep submitted with `walkForward`, and present from acceptance onward — its presence, not its 22 contents, is what identifies a walk-forward sweep. `completedFolds` is 0 while the first fold is still running. 23 24 Attributes: 25 folds (int): Folds requested at submit. 26 completed_folds (int): Folds that have finished and reported a winner. 27 results (list[WalkForwardFold]): One entry per completed fold, oldest first. 28 in_sample_pct (int | Unset): Resolved in-sample share each fold optimized on. 29 param_drift (float | Unset): Mean normalized lattice distance between consecutive fold winners. Low is good: 30 winners that stay in a tight band fold after fold are evidence the parameter means something, while winners that 31 jump across the grid every time are the sweep re-fitting noise, and that backtest will not survive contact with 32 live data. **Absent is not zero** — the field is omitted whenever the figure could not be computed (fewer than 33 two folds finished, no stored grid to place winners on), because zero is itself a meaningful reading here and a 34 placeholder would be indistinguishable from perfect stability. 35 """ 36 37 folds: int 38 completed_folds: int 39 results: list[WalkForwardFold] 40 in_sample_pct: int | Unset = UNSET 41 param_drift: float | Unset = UNSET 42 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) 43 44 def to_dict(self) -> dict[str, Any]: 45 folds = self.folds 46 47 completed_folds = self.completed_folds 48 49 results = [] 50 for results_item_data in self.results: 51 results_item = results_item_data.to_dict() 52 results.append(results_item) 53 54 in_sample_pct = self.in_sample_pct 55 56 param_drift = self.param_drift 57 58 field_dict: dict[str, Any] = {} 59 field_dict.update(self.additional_properties) 60 field_dict.update( 61 { 62 "folds": folds, 63 "completedFolds": completed_folds, 64 "results": results, 65 } 66 ) 67 if in_sample_pct is not UNSET: 68 field_dict["inSamplePct"] = in_sample_pct 69 if param_drift is not UNSET: 70 field_dict["paramDrift"] = param_drift 71 72 return field_dict 73 74 @classmethod 75 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 76 from ..models.walk_forward_fold import WalkForwardFold 77 78 d = dict(src_dict) 79 folds = d.pop("folds") 80 81 completed_folds = d.pop("completedFolds") 82 83 results = [] 84 _results = d.pop("results") 85 for results_item_data in _results: 86 results_item = WalkForwardFold.from_dict(results_item_data) 87 88 results.append(results_item) 89 90 in_sample_pct = d.pop("inSamplePct", UNSET) 91 92 param_drift = d.pop("paramDrift", UNSET) 93 94 walk_forward_result = cls( 95 folds=folds, 96 completed_folds=completed_folds, 97 results=results, 98 in_sample_pct=in_sample_pct, 99 param_drift=param_drift, 100 ) 101 102 walk_forward_result.additional_properties = d 103 return walk_forward_result 104 105 @property 106 def additional_keys(self) -> list[str]: 107 return list(self.additional_properties.keys()) 108 109 def __getitem__(self, key: str) -> Any: 110 return self.additional_properties[key] 111 112 def __setitem__(self, key: str, value: Any) -> None: 113 self.additional_properties[key] = value 114 115 def __delitem__(self, key: str) -> None: 116 del self.additional_properties[key] 117 118 def __contains__(self, key: str) -> bool: 119 return key in self.additional_properties
Present only on a sweep submitted with walkForward, and present from acceptance onward — its presence, not its
contents, is what identifies a walk-forward sweep. completedFolds is 0 while the first fold is still running.
Attributes:
folds (int): Folds requested at submit.
completed_folds (int): Folds that have finished and reported a winner.
results (list[WalkForwardFold]): One entry per completed fold, oldest first.
in_sample_pct (int | Unset): Resolved in-sample share each fold optimized on.
param_drift (float | Unset): Mean normalized lattice distance between consecutive fold winners. Low is good:
winners that stay in a tight band fold after fold are evidence the parameter means something, while winners that
jump across the grid every time are the sweep re-fitting noise, and that backtest will not survive contact with
live data. **Absent is not zero** — the field is omitted whenever the figure could not be computed (fewer than
two folds finished, no stored grid to place winners on), because zero is itself a meaningful reading here and a
placeholder would be indistinguishable from perfect stability.
28def __init__(self, folds, completed_folds, results, in_sample_pct=attr_dict['in_sample_pct'].default, param_drift=attr_dict['param_drift'].default): 29 self.folds = folds 30 self.completed_folds = completed_folds 31 self.results = results 32 self.in_sample_pct = in_sample_pct 33 self.param_drift = param_drift 34 self.additional_properties = __attr_factory_additional_properties()
Method generated by attrs for class WalkForwardResult.
44 def to_dict(self) -> dict[str, Any]: 45 folds = self.folds 46 47 completed_folds = self.completed_folds 48 49 results = [] 50 for results_item_data in self.results: 51 results_item = results_item_data.to_dict() 52 results.append(results_item) 53 54 in_sample_pct = self.in_sample_pct 55 56 param_drift = self.param_drift 57 58 field_dict: dict[str, Any] = {} 59 field_dict.update(self.additional_properties) 60 field_dict.update( 61 { 62 "folds": folds, 63 "completedFolds": completed_folds, 64 "results": results, 65 } 66 ) 67 if in_sample_pct is not UNSET: 68 field_dict["inSamplePct"] = in_sample_pct 69 if param_drift is not UNSET: 70 field_dict["paramDrift"] = param_drift 71 72 return field_dict
74 @classmethod 75 def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: 76 from ..models.walk_forward_fold import WalkForwardFold 77 78 d = dict(src_dict) 79 folds = d.pop("folds") 80 81 completed_folds = d.pop("completedFolds") 82 83 results = [] 84 _results = d.pop("results") 85 for results_item_data in _results: 86 results_item = WalkForwardFold.from_dict(results_item_data) 87 88 results.append(results_item) 89 90 in_sample_pct = d.pop("inSamplePct", UNSET) 91 92 param_drift = d.pop("paramDrift", UNSET) 93 94 walk_forward_result = cls( 95 folds=folds, 96 completed_folds=completed_folds, 97 results=results, 98 in_sample_pct=in_sample_pct, 99 param_drift=param_drift, 100 ) 101 102 walk_forward_result.additional_properties = d 103 return walk_forward_result