qtsurfer-api-client 0.98.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qtsurfer/__init__.py +0 -0
- qtsurfer/api/__init__.py +0 -0
- qtsurfer/api/client/__init__.py +38 -0
- qtsurfer/api/client/_generated/__init__.py +8 -0
- qtsurfer/api/client/_generated/api/__init__.py +1 -0
- qtsurfer/api/client/_generated/api/auth/__init__.py +1 -0
- qtsurfer/api/client/_generated/api/auth/auth.py +174 -0
- qtsurfer/api/client/_generated/api/backtesting/__init__.py +1 -0
- qtsurfer/api/client/_generated/api/backtesting/cancel_execution.py +214 -0
- qtsurfer/api/client/_generated/api/backtesting/execute_backtesting.py +251 -0
- qtsurfer/api/client/_generated/api/backtesting/get_execution_result.py +211 -0
- qtsurfer/api/client/_generated/api/backtesting/get_preparation_status.py +211 -0
- qtsurfer/api/client/_generated/api/backtesting/prepare_backtesting.py +235 -0
- qtsurfer/api/client/_generated/api/exchange/__init__.py +1 -0
- qtsurfer/api/client/_generated/api/exchange/get_exchange_klines_hour.py +269 -0
- qtsurfer/api/client/_generated/api/exchange/get_exchange_tickers_hour.py +349 -0
- qtsurfer/api/client/_generated/api/exchange/get_exchanges.py +129 -0
- qtsurfer/api/client/_generated/api/exchange/get_instruments.py +181 -0
- qtsurfer/api/client/_generated/api/exchange/get_segment_instruments.py +196 -0
- qtsurfer/api/client/_generated/api/strategy/__init__.py +1 -0
- qtsurfer/api/client/_generated/api/strategy/get_strategy_status.py +173 -0
- qtsurfer/api/client/_generated/client.py +268 -0
- qtsurfer/api/client/_generated/errors.py +16 -0
- qtsurfer/api/client/_generated/models/__init__.py +79 -0
- qtsurfer/api/client/_generated/models/accepted_job.py +66 -0
- qtsurfer/api/client/_generated/models/auth_token_error.py +72 -0
- qtsurfer/api/client/_generated/models/auth_token_error_code.py +10 -0
- qtsurfer/api/client/_generated/models/auth_token_response.py +101 -0
- qtsurfer/api/client/_generated/models/auth_token_response_tier.py +11 -0
- qtsurfer/api/client/_generated/models/auth_token_response_token_type.py +8 -0
- qtsurfer/api/client/_generated/models/backtest_job_result.py +80 -0
- qtsurfer/api/client/_generated/models/cancel_execution_response_200.py +78 -0
- qtsurfer/api/client/_generated/models/cancel_execution_response_200_status.py +8 -0
- qtsurfer/api/client/_generated/models/coverage_window.py +105 -0
- qtsurfer/api/client/_generated/models/data_source_type.py +8 -0
- qtsurfer/api/client/_generated/models/equity_point.py +71 -0
- qtsurfer/api/client/_generated/models/exchange.py +81 -0
- qtsurfer/api/client/_generated/models/execute_backtesting_body.py +83 -0
- qtsurfer/api/client/_generated/models/get_exchange_klines_hour_format.py +9 -0
- qtsurfer/api/client/_generated/models/get_exchange_tickers_hour_format.py +9 -0
- qtsurfer/api/client/_generated/models/get_segment_instruments_segment.py +9 -0
- qtsurfer/api/client/_generated/models/get_strategy_status_response_200.py +102 -0
- qtsurfer/api/client/_generated/models/get_strategy_status_response_200_status.py +12 -0
- qtsurfer/api/client/_generated/models/hal_link.py +74 -0
- qtsurfer/api/client/_generated/models/instrument_coverage.py +91 -0
- qtsurfer/api/client/_generated/models/instrument_detail.py +120 -0
- qtsurfer/api/client/_generated/models/instrument_links.py +102 -0
- qtsurfer/api/client/_generated/models/instrument_list_meta.py +82 -0
- qtsurfer/api/client/_generated/models/instrument_list_meta_segment.py +9 -0
- qtsurfer/api/client/_generated/models/instrument_list_response.py +96 -0
- qtsurfer/api/client/_generated/models/job_state.py +178 -0
- qtsurfer/api/client/_generated/models/job_state_status.py +12 -0
- qtsurfer/api/client/_generated/models/post_strategy_response_200.py +61 -0
- qtsurfer/api/client/_generated/models/prepare_backtesting_body.py +110 -0
- qtsurfer/api/client/_generated/models/prepare_backtesting_body_cadence.py +15 -0
- qtsurfer/api/client/_generated/models/prepare_job_state.py +302 -0
- qtsurfer/api/client/_generated/models/prepare_job_state_hours_without_data_item.py +101 -0
- qtsurfer/api/client/_generated/models/prepare_job_state_hours_without_data_item_rationale.py +10 -0
- qtsurfer/api/client/_generated/models/response_error.py +70 -0
- qtsurfer/api/client/_generated/models/result_map.py +286 -0
- qtsurfer/api/client/_generated/models/result_map_signals_upload.py +10 -0
- qtsurfer/api/client/_generated/py.typed +1 -0
- qtsurfer/api/client/_generated/types.py +54 -0
- qtsurfer/api/client/api/__init__.py +11 -0
- qtsurfer/api/client/api/auth.py +5 -0
- qtsurfer/api/client/api/backtesting.py +17 -0
- qtsurfer/api/client/api/exchange.py +15 -0
- qtsurfer/api/client/api/strategy.py +11 -0
- qtsurfer/api/client/models/__init__.py +9 -0
- qtsurfer/api/client/py.typed +0 -0
- qtsurfer_api_client-0.98.0.dist-info/METADATA +238 -0
- qtsurfer_api_client-0.98.0.dist-info/RECORD +74 -0
- qtsurfer_api_client-0.98.0.dist-info/WHEEL +4 -0
- qtsurfer_api_client-0.98.0.dist-info/licenses/LICENSE +201 -0
qtsurfer/__init__.py
ADDED
|
File without changes
|
qtsurfer/api/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""qtsurfer-api-client — auto-generated Python client for the QTSurfer API.
|
|
2
|
+
|
|
3
|
+
Low-level: one function per OpenAPI endpoint. For workflow orchestration
|
|
4
|
+
(``backtest = compile + prepare + execute + poll``), use
|
|
5
|
+
`qtsurfer-sdk <https://github.com/QTSurfer/sdk-python>`_ (coming soon).
|
|
6
|
+
|
|
7
|
+
Public surface (re-exported from the generated package):
|
|
8
|
+
|
|
9
|
+
* :class:`Client` — unauthenticated client (rarely useful in practice).
|
|
10
|
+
* :class:`AuthenticatedClient` — Bearer-token client; pass to every
|
|
11
|
+
endpoint function as ``client=...``.
|
|
12
|
+
* :mod:`qtsurfer.api.client.api` — endpoint modules grouped by tag.
|
|
13
|
+
* :mod:`qtsurfer.api.client.models` — request/response dataclasses.
|
|
14
|
+
|
|
15
|
+
Endpoint modules expose four entry points: ``sync``, ``sync_detailed``,
|
|
16
|
+
``asyncio``, ``asyncio_detailed``. See the README for examples.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
20
|
+
|
|
21
|
+
# Re-export the generated public types.
|
|
22
|
+
from qtsurfer.api.client._generated import api, errors, models, types
|
|
23
|
+
from qtsurfer.api.client._generated.client import AuthenticatedClient, Client
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
__version__ = version("qtsurfer-api-client")
|
|
27
|
+
except PackageNotFoundError: # pragma: no cover - editable installs in dev
|
|
28
|
+
__version__ = "0.0.0+unknown"
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"AuthenticatedClient",
|
|
32
|
+
"Client",
|
|
33
|
+
"__version__",
|
|
34
|
+
"api",
|
|
35
|
+
"errors",
|
|
36
|
+
"models",
|
|
37
|
+
"types",
|
|
38
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains methods for accessing the API"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains endpoint functions for accessing the API"""
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any, cast
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from ... import errors
|
|
7
|
+
from ...client import AuthenticatedClient, Client
|
|
8
|
+
from ...models.auth_token_error import AuthTokenError
|
|
9
|
+
from ...models.auth_token_response import AuthTokenResponse
|
|
10
|
+
from ...types import Response
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_kwargs() -> dict[str, Any]:
|
|
14
|
+
|
|
15
|
+
_kwargs: dict[str, Any] = {
|
|
16
|
+
"method": "post",
|
|
17
|
+
"url": "/auth/token",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return _kwargs
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _parse_response(
|
|
24
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
25
|
+
) -> Any | AuthTokenError | AuthTokenResponse | None:
|
|
26
|
+
if response.status_code == 200:
|
|
27
|
+
response_200 = AuthTokenResponse.from_dict(response.json())
|
|
28
|
+
|
|
29
|
+
return response_200
|
|
30
|
+
|
|
31
|
+
if response.status_code == 401:
|
|
32
|
+
response_401 = AuthTokenError.from_dict(response.json())
|
|
33
|
+
|
|
34
|
+
return response_401
|
|
35
|
+
|
|
36
|
+
if response.status_code == 429:
|
|
37
|
+
response_429 = cast(Any, None)
|
|
38
|
+
return response_429
|
|
39
|
+
|
|
40
|
+
if client.raise_on_unexpected_status:
|
|
41
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
42
|
+
else:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _build_response(
|
|
47
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
48
|
+
) -> Response[Any | AuthTokenError | AuthTokenResponse]:
|
|
49
|
+
return Response(
|
|
50
|
+
status_code=HTTPStatus(response.status_code),
|
|
51
|
+
content=response.content,
|
|
52
|
+
headers=response.headers,
|
|
53
|
+
parsed=_parse_response(client=client, response=response),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def sync_detailed(
|
|
58
|
+
*,
|
|
59
|
+
client: AuthenticatedClient,
|
|
60
|
+
) -> Response[Any | AuthTokenError | AuthTokenResponse]:
|
|
61
|
+
"""Exchange API key for a short-lived JWT
|
|
62
|
+
|
|
63
|
+
Exchanges a long-lived API key for a short-lived JWT used by every other
|
|
64
|
+
endpoint. This is the only endpoint that accepts an API key directly —
|
|
65
|
+
callers should obtain a JWT here, then send it as `Authorization: Bearer
|
|
66
|
+
<token>` to all other operations.
|
|
67
|
+
|
|
68
|
+
The returned JWT carries the caller's subscription `tier` as a claim and
|
|
69
|
+
expires after `expires_in` seconds. Callers should refresh the token
|
|
70
|
+
before expiry (or on a `401` response) by calling this endpoint again.
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
74
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Response[Any | AuthTokenError | AuthTokenResponse]
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
kwargs = _get_kwargs()
|
|
81
|
+
|
|
82
|
+
response = client.get_httpx_client().request(
|
|
83
|
+
**kwargs,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return _build_response(client=client, response=response)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def sync(
|
|
90
|
+
*,
|
|
91
|
+
client: AuthenticatedClient,
|
|
92
|
+
) -> Any | AuthTokenError | AuthTokenResponse | None:
|
|
93
|
+
"""Exchange API key for a short-lived JWT
|
|
94
|
+
|
|
95
|
+
Exchanges a long-lived API key for a short-lived JWT used by every other
|
|
96
|
+
endpoint. This is the only endpoint that accepts an API key directly —
|
|
97
|
+
callers should obtain a JWT here, then send it as `Authorization: Bearer
|
|
98
|
+
<token>` to all other operations.
|
|
99
|
+
|
|
100
|
+
The returned JWT carries the caller's subscription `tier` as a claim and
|
|
101
|
+
expires after `expires_in` seconds. Callers should refresh the token
|
|
102
|
+
before expiry (or on a `401` response) by calling this endpoint again.
|
|
103
|
+
|
|
104
|
+
Raises:
|
|
105
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
106
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Any | AuthTokenError | AuthTokenResponse
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
return sync_detailed(
|
|
113
|
+
client=client,
|
|
114
|
+
).parsed
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
async def asyncio_detailed(
|
|
118
|
+
*,
|
|
119
|
+
client: AuthenticatedClient,
|
|
120
|
+
) -> Response[Any | AuthTokenError | AuthTokenResponse]:
|
|
121
|
+
"""Exchange API key for a short-lived JWT
|
|
122
|
+
|
|
123
|
+
Exchanges a long-lived API key for a short-lived JWT used by every other
|
|
124
|
+
endpoint. This is the only endpoint that accepts an API key directly —
|
|
125
|
+
callers should obtain a JWT here, then send it as `Authorization: Bearer
|
|
126
|
+
<token>` to all other operations.
|
|
127
|
+
|
|
128
|
+
The returned JWT carries the caller's subscription `tier` as a claim and
|
|
129
|
+
expires after `expires_in` seconds. Callers should refresh the token
|
|
130
|
+
before expiry (or on a `401` response) by calling this endpoint again.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
134
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Response[Any | AuthTokenError | AuthTokenResponse]
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
kwargs = _get_kwargs()
|
|
141
|
+
|
|
142
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
143
|
+
|
|
144
|
+
return _build_response(client=client, response=response)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async def asyncio(
|
|
148
|
+
*,
|
|
149
|
+
client: AuthenticatedClient,
|
|
150
|
+
) -> Any | AuthTokenError | AuthTokenResponse | None:
|
|
151
|
+
"""Exchange API key for a short-lived JWT
|
|
152
|
+
|
|
153
|
+
Exchanges a long-lived API key for a short-lived JWT used by every other
|
|
154
|
+
endpoint. This is the only endpoint that accepts an API key directly —
|
|
155
|
+
callers should obtain a JWT here, then send it as `Authorization: Bearer
|
|
156
|
+
<token>` to all other operations.
|
|
157
|
+
|
|
158
|
+
The returned JWT carries the caller's subscription `tier` as a claim and
|
|
159
|
+
expires after `expires_in` seconds. Callers should refresh the token
|
|
160
|
+
before expiry (or on a `401` response) by calling this endpoint again.
|
|
161
|
+
|
|
162
|
+
Raises:
|
|
163
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
164
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Any | AuthTokenError | AuthTokenResponse
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
await asyncio_detailed(
|
|
172
|
+
client=client,
|
|
173
|
+
)
|
|
174
|
+
).parsed
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains endpoint functions for accessing the API"""
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any
|
|
3
|
+
from urllib.parse import quote
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from ... import errors
|
|
8
|
+
from ...client import AuthenticatedClient, Client
|
|
9
|
+
from ...models.cancel_execution_response_200 import CancelExecutionResponse200
|
|
10
|
+
from ...models.data_source_type import DataSourceType
|
|
11
|
+
from ...models.response_error import ResponseError
|
|
12
|
+
from ...types import Response
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_kwargs(
|
|
16
|
+
exchange_id: str,
|
|
17
|
+
type_: DataSourceType,
|
|
18
|
+
job_id: str,
|
|
19
|
+
) -> dict[str, Any]:
|
|
20
|
+
|
|
21
|
+
_kwargs: dict[str, Any] = {
|
|
22
|
+
"method": "delete",
|
|
23
|
+
"url": "/backtest/{exchange_id}/{type_}/execute/{job_id}".format(
|
|
24
|
+
exchange_id=quote(str(exchange_id), safe=""),
|
|
25
|
+
type_=quote(str(type_), safe=""),
|
|
26
|
+
job_id=quote(str(job_id), safe=""),
|
|
27
|
+
),
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return _kwargs
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _parse_response(
|
|
34
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
35
|
+
) -> CancelExecutionResponse200 | ResponseError | None:
|
|
36
|
+
if response.status_code == 200:
|
|
37
|
+
response_200 = CancelExecutionResponse200.from_dict(response.json())
|
|
38
|
+
|
|
39
|
+
return response_200
|
|
40
|
+
|
|
41
|
+
if response.status_code == 404:
|
|
42
|
+
response_404 = ResponseError.from_dict(response.json())
|
|
43
|
+
|
|
44
|
+
return response_404
|
|
45
|
+
|
|
46
|
+
if client.raise_on_unexpected_status:
|
|
47
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
48
|
+
else:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _build_response(
|
|
53
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
54
|
+
) -> Response[CancelExecutionResponse200 | ResponseError]:
|
|
55
|
+
return Response(
|
|
56
|
+
status_code=HTTPStatus(response.status_code),
|
|
57
|
+
content=response.content,
|
|
58
|
+
headers=response.headers,
|
|
59
|
+
parsed=_parse_response(client=client, response=response),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def sync_detailed(
|
|
64
|
+
exchange_id: str,
|
|
65
|
+
type_: DataSourceType,
|
|
66
|
+
job_id: str,
|
|
67
|
+
*,
|
|
68
|
+
client: AuthenticatedClient,
|
|
69
|
+
) -> Response[CancelExecutionResponse200 | ResponseError]:
|
|
70
|
+
"""Cancel a running backtest execution
|
|
71
|
+
|
|
72
|
+
Requests cancellation of the specified execution. The execution
|
|
73
|
+
status will transition to `Aborted` once the cancellation is
|
|
74
|
+
processed. Cancellation is asynchronous — poll the GET endpoint
|
|
75
|
+
to confirm the final status.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
exchange_id (str): Example: binance.
|
|
79
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
80
|
+
ticker.
|
|
81
|
+
job_id (str): Example: 13RBLGQlPnfDjO6wyKSX8i.
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
85
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Response[CancelExecutionResponse200 | ResponseError]
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
kwargs = _get_kwargs(
|
|
92
|
+
exchange_id=exchange_id,
|
|
93
|
+
type_=type_,
|
|
94
|
+
job_id=job_id,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
response = client.get_httpx_client().request(
|
|
98
|
+
**kwargs,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return _build_response(client=client, response=response)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def sync(
|
|
105
|
+
exchange_id: str,
|
|
106
|
+
type_: DataSourceType,
|
|
107
|
+
job_id: str,
|
|
108
|
+
*,
|
|
109
|
+
client: AuthenticatedClient,
|
|
110
|
+
) -> CancelExecutionResponse200 | ResponseError | None:
|
|
111
|
+
"""Cancel a running backtest execution
|
|
112
|
+
|
|
113
|
+
Requests cancellation of the specified execution. The execution
|
|
114
|
+
status will transition to `Aborted` once the cancellation is
|
|
115
|
+
processed. Cancellation is asynchronous — poll the GET endpoint
|
|
116
|
+
to confirm the final status.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
exchange_id (str): Example: binance.
|
|
120
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
121
|
+
ticker.
|
|
122
|
+
job_id (str): Example: 13RBLGQlPnfDjO6wyKSX8i.
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
126
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
CancelExecutionResponse200 | ResponseError
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
return sync_detailed(
|
|
133
|
+
exchange_id=exchange_id,
|
|
134
|
+
type_=type_,
|
|
135
|
+
job_id=job_id,
|
|
136
|
+
client=client,
|
|
137
|
+
).parsed
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
async def asyncio_detailed(
|
|
141
|
+
exchange_id: str,
|
|
142
|
+
type_: DataSourceType,
|
|
143
|
+
job_id: str,
|
|
144
|
+
*,
|
|
145
|
+
client: AuthenticatedClient,
|
|
146
|
+
) -> Response[CancelExecutionResponse200 | ResponseError]:
|
|
147
|
+
"""Cancel a running backtest execution
|
|
148
|
+
|
|
149
|
+
Requests cancellation of the specified execution. The execution
|
|
150
|
+
status will transition to `Aborted` once the cancellation is
|
|
151
|
+
processed. Cancellation is asynchronous — poll the GET endpoint
|
|
152
|
+
to confirm the final status.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
exchange_id (str): Example: binance.
|
|
156
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
157
|
+
ticker.
|
|
158
|
+
job_id (str): Example: 13RBLGQlPnfDjO6wyKSX8i.
|
|
159
|
+
|
|
160
|
+
Raises:
|
|
161
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
162
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Response[CancelExecutionResponse200 | ResponseError]
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
kwargs = _get_kwargs(
|
|
169
|
+
exchange_id=exchange_id,
|
|
170
|
+
type_=type_,
|
|
171
|
+
job_id=job_id,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
175
|
+
|
|
176
|
+
return _build_response(client=client, response=response)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
async def asyncio(
|
|
180
|
+
exchange_id: str,
|
|
181
|
+
type_: DataSourceType,
|
|
182
|
+
job_id: str,
|
|
183
|
+
*,
|
|
184
|
+
client: AuthenticatedClient,
|
|
185
|
+
) -> CancelExecutionResponse200 | ResponseError | None:
|
|
186
|
+
"""Cancel a running backtest execution
|
|
187
|
+
|
|
188
|
+
Requests cancellation of the specified execution. The execution
|
|
189
|
+
status will transition to `Aborted` once the cancellation is
|
|
190
|
+
processed. Cancellation is asynchronous — poll the GET endpoint
|
|
191
|
+
to confirm the final status.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
exchange_id (str): Example: binance.
|
|
195
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
196
|
+
ticker.
|
|
197
|
+
job_id (str): Example: 13RBLGQlPnfDjO6wyKSX8i.
|
|
198
|
+
|
|
199
|
+
Raises:
|
|
200
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
201
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
CancelExecutionResponse200 | ResponseError
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
await asyncio_detailed(
|
|
209
|
+
exchange_id=exchange_id,
|
|
210
|
+
type_=type_,
|
|
211
|
+
job_id=job_id,
|
|
212
|
+
client=client,
|
|
213
|
+
)
|
|
214
|
+
).parsed
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any
|
|
3
|
+
from urllib.parse import quote
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from ... import errors
|
|
8
|
+
from ...client import AuthenticatedClient, Client
|
|
9
|
+
from ...models.accepted_job import AcceptedJob
|
|
10
|
+
from ...models.data_source_type import DataSourceType
|
|
11
|
+
from ...models.execute_backtesting_body import ExecuteBacktestingBody
|
|
12
|
+
from ...models.response_error import ResponseError
|
|
13
|
+
from ...types import Response
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _get_kwargs(
|
|
17
|
+
exchange_id: str,
|
|
18
|
+
type_: DataSourceType,
|
|
19
|
+
*,
|
|
20
|
+
body: ExecuteBacktestingBody,
|
|
21
|
+
) -> dict[str, Any]:
|
|
22
|
+
headers: dict[str, Any] = {}
|
|
23
|
+
|
|
24
|
+
_kwargs: dict[str, Any] = {
|
|
25
|
+
"method": "post",
|
|
26
|
+
"url": "/backtest/{exchange_id}/{type_}/execute".format(
|
|
27
|
+
exchange_id=quote(str(exchange_id), safe=""),
|
|
28
|
+
type_=quote(str(type_), safe=""),
|
|
29
|
+
),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_kwargs["json"] = body.to_dict()
|
|
33
|
+
|
|
34
|
+
headers["Content-Type"] = "application/json"
|
|
35
|
+
|
|
36
|
+
_kwargs["headers"] = headers
|
|
37
|
+
return _kwargs
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _parse_response(
|
|
41
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
42
|
+
) -> AcceptedJob | ResponseError | None:
|
|
43
|
+
if response.status_code == 202:
|
|
44
|
+
response_202 = AcceptedJob.from_dict(response.json())
|
|
45
|
+
|
|
46
|
+
return response_202
|
|
47
|
+
|
|
48
|
+
if response.status_code == 400:
|
|
49
|
+
response_400 = ResponseError.from_dict(response.json())
|
|
50
|
+
|
|
51
|
+
return response_400
|
|
52
|
+
|
|
53
|
+
if response.status_code == 404:
|
|
54
|
+
response_404 = ResponseError.from_dict(response.json())
|
|
55
|
+
|
|
56
|
+
return response_404
|
|
57
|
+
|
|
58
|
+
if response.status_code == 429:
|
|
59
|
+
response_429 = ResponseError.from_dict(response.json())
|
|
60
|
+
|
|
61
|
+
return response_429
|
|
62
|
+
|
|
63
|
+
if client.raise_on_unexpected_status:
|
|
64
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
65
|
+
else:
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _build_response(
|
|
70
|
+
*, client: AuthenticatedClient | Client, response: httpx.Response
|
|
71
|
+
) -> Response[AcceptedJob | ResponseError]:
|
|
72
|
+
return Response(
|
|
73
|
+
status_code=HTTPStatus(response.status_code),
|
|
74
|
+
content=response.content,
|
|
75
|
+
headers=response.headers,
|
|
76
|
+
parsed=_parse_response(client=client, response=response),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def sync_detailed(
|
|
81
|
+
exchange_id: str,
|
|
82
|
+
type_: DataSourceType,
|
|
83
|
+
*,
|
|
84
|
+
client: AuthenticatedClient,
|
|
85
|
+
body: ExecuteBacktestingBody,
|
|
86
|
+
) -> Response[AcceptedJob | ResponseError]:
|
|
87
|
+
"""Execute a compiled strategy against a prepared dataset
|
|
88
|
+
|
|
89
|
+
Enqueues an execute task that runs the strategy identified by `strategyId` over the data
|
|
90
|
+
prepared by the prepare job identified by `prepareJobId`. The instrument and date range are
|
|
91
|
+
recovered from the prepare job — they do not need to be sent again.
|
|
92
|
+
|
|
93
|
+
Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`
|
|
94
|
+
for the result.
|
|
95
|
+
|
|
96
|
+
The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same
|
|
97
|
+
`jobId` (idempotent).
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
exchange_id (str): Example: binance.
|
|
101
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
102
|
+
ticker.
|
|
103
|
+
body (ExecuteBacktestingBody):
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
107
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Response[AcceptedJob | ResponseError]
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
kwargs = _get_kwargs(
|
|
114
|
+
exchange_id=exchange_id,
|
|
115
|
+
type_=type_,
|
|
116
|
+
body=body,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
response = client.get_httpx_client().request(
|
|
120
|
+
**kwargs,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
return _build_response(client=client, response=response)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def sync(
|
|
127
|
+
exchange_id: str,
|
|
128
|
+
type_: DataSourceType,
|
|
129
|
+
*,
|
|
130
|
+
client: AuthenticatedClient,
|
|
131
|
+
body: ExecuteBacktestingBody,
|
|
132
|
+
) -> AcceptedJob | ResponseError | None:
|
|
133
|
+
"""Execute a compiled strategy against a prepared dataset
|
|
134
|
+
|
|
135
|
+
Enqueues an execute task that runs the strategy identified by `strategyId` over the data
|
|
136
|
+
prepared by the prepare job identified by `prepareJobId`. The instrument and date range are
|
|
137
|
+
recovered from the prepare job — they do not need to be sent again.
|
|
138
|
+
|
|
139
|
+
Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`
|
|
140
|
+
for the result.
|
|
141
|
+
|
|
142
|
+
The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same
|
|
143
|
+
`jobId` (idempotent).
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
exchange_id (str): Example: binance.
|
|
147
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
148
|
+
ticker.
|
|
149
|
+
body (ExecuteBacktestingBody):
|
|
150
|
+
|
|
151
|
+
Raises:
|
|
152
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
153
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
AcceptedJob | ResponseError
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
return sync_detailed(
|
|
160
|
+
exchange_id=exchange_id,
|
|
161
|
+
type_=type_,
|
|
162
|
+
client=client,
|
|
163
|
+
body=body,
|
|
164
|
+
).parsed
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
async def asyncio_detailed(
|
|
168
|
+
exchange_id: str,
|
|
169
|
+
type_: DataSourceType,
|
|
170
|
+
*,
|
|
171
|
+
client: AuthenticatedClient,
|
|
172
|
+
body: ExecuteBacktestingBody,
|
|
173
|
+
) -> Response[AcceptedJob | ResponseError]:
|
|
174
|
+
"""Execute a compiled strategy against a prepared dataset
|
|
175
|
+
|
|
176
|
+
Enqueues an execute task that runs the strategy identified by `strategyId` over the data
|
|
177
|
+
prepared by the prepare job identified by `prepareJobId`. The instrument and date range are
|
|
178
|
+
recovered from the prepare job — they do not need to be sent again.
|
|
179
|
+
|
|
180
|
+
Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`
|
|
181
|
+
for the result.
|
|
182
|
+
|
|
183
|
+
The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same
|
|
184
|
+
`jobId` (idempotent).
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
exchange_id (str): Example: binance.
|
|
188
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
189
|
+
ticker.
|
|
190
|
+
body (ExecuteBacktestingBody):
|
|
191
|
+
|
|
192
|
+
Raises:
|
|
193
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
194
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Response[AcceptedJob | ResponseError]
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
kwargs = _get_kwargs(
|
|
201
|
+
exchange_id=exchange_id,
|
|
202
|
+
type_=type_,
|
|
203
|
+
body=body,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
207
|
+
|
|
208
|
+
return _build_response(client=client, response=response)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
async def asyncio(
|
|
212
|
+
exchange_id: str,
|
|
213
|
+
type_: DataSourceType,
|
|
214
|
+
*,
|
|
215
|
+
client: AuthenticatedClient,
|
|
216
|
+
body: ExecuteBacktestingBody,
|
|
217
|
+
) -> AcceptedJob | ResponseError | None:
|
|
218
|
+
"""Execute a compiled strategy against a prepared dataset
|
|
219
|
+
|
|
220
|
+
Enqueues an execute task that runs the strategy identified by `strategyId` over the data
|
|
221
|
+
prepared by the prepare job identified by `prepareJobId`. The instrument and date range are
|
|
222
|
+
recovered from the prepare job — they do not need to be sent again.
|
|
223
|
+
|
|
224
|
+
Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`
|
|
225
|
+
for the result.
|
|
226
|
+
|
|
227
|
+
The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same
|
|
228
|
+
`jobId` (idempotent).
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
exchange_id (str): Example: binance.
|
|
232
|
+
type_ (DataSourceType): Managed exchange data sources available for backtesting. Example:
|
|
233
|
+
ticker.
|
|
234
|
+
body (ExecuteBacktestingBody):
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
238
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
AcceptedJob | ResponseError
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
await asyncio_detailed(
|
|
246
|
+
exchange_id=exchange_id,
|
|
247
|
+
type_=type_,
|
|
248
|
+
client=client,
|
|
249
|
+
body=body,
|
|
250
|
+
)
|
|
251
|
+
).parsed
|