nlalpha-backtest 0.8.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.
- nlalpha_backtest/__init__.py +66 -0
- nlalpha_backtest/context.py +5 -0
- nlalpha_backtest/data.py +33 -0
- nlalpha_backtest/engine.py +254 -0
- nlalpha_backtest/execution/__init__.py +50 -0
- nlalpha_backtest/execution/backend.py +300 -0
- nlalpha_backtest/execution/backtest_executor.py +117 -0
- nlalpha_backtest/execution/batch_runtime.py +435 -0
- nlalpha_backtest/execution/event_data.py +173 -0
- nlalpha_backtest/execution/local_executor.py +471 -0
- nlalpha_backtest/execution/market_time.py +441 -0
- nlalpha_backtest/execution/result_integrity.py +41 -0
- nlalpha_backtest/execution/runner.py +365 -0
- nlalpha_backtest/execution/runtime.py +225 -0
- nlalpha_backtest/execution/validation.py +23 -0
- nlalpha_backtest/jobs/__init__.py +13 -0
- nlalpha_backtest/jobs/job_service.py +586 -0
- nlalpha_backtest/jobs/job_store.py +326 -0
- nlalpha_backtest/jobs/job_store_redis.py +255 -0
- nlalpha_backtest/knowledge/execution.md +33 -0
- nlalpha_backtest/reports.py +170 -0
- nlalpha_backtest/server.py +1669 -0
- nlalpha_backtest-0.8.0.dist-info/METADATA +272 -0
- nlalpha_backtest-0.8.0.dist-info/RECORD +27 -0
- nlalpha_backtest-0.8.0.dist-info/WHEEL +4 -0
- nlalpha_backtest-0.8.0.dist-info/entry_points.txt +2 -0
- nlalpha_backtest-0.8.0.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""nlalpha-backtest: Backtest execution MCP tool."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib.metadata import version as _distribution_version
|
|
6
|
+
|
|
7
|
+
from typing import Callable
|
|
8
|
+
|
|
9
|
+
from nlalpha.core.backtest import BacktestResult, BatchBacktestInput
|
|
10
|
+
from nlalpha.core.contracts.market import Bar
|
|
11
|
+
from nlalpha_backtest.execution import BacktestExecutor, run_batch_strategy_code
|
|
12
|
+
|
|
13
|
+
__version__ = _distribution_version("nlalpha-backtest")
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"run",
|
|
17
|
+
"run_batch",
|
|
18
|
+
"run_batch_strategy_code",
|
|
19
|
+
"BacktestExecutor",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def run(
|
|
24
|
+
job_id: str,
|
|
25
|
+
strategy,
|
|
26
|
+
data: list[Bar],
|
|
27
|
+
execution_config: dict | None = None,
|
|
28
|
+
capital_config: dict | None = None,
|
|
29
|
+
contract_config: dict | None = None,
|
|
30
|
+
progress_callback: Callable[[float, str], None] | None = None,
|
|
31
|
+
engine: str | None = None,
|
|
32
|
+
) -> BacktestResult:
|
|
33
|
+
"""Execute a backtest. Main entry point for backtest execution."""
|
|
34
|
+
service = BacktestExecutor()
|
|
35
|
+
return await service.run(
|
|
36
|
+
job_id=job_id,
|
|
37
|
+
strategy=strategy,
|
|
38
|
+
data=data,
|
|
39
|
+
execution_config=execution_config,
|
|
40
|
+
capital_config=capital_config,
|
|
41
|
+
contract_config=contract_config,
|
|
42
|
+
progress_callback=progress_callback,
|
|
43
|
+
engine=engine,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def run_batch(
|
|
48
|
+
job_id: str,
|
|
49
|
+
inputs: BatchBacktestInput,
|
|
50
|
+
execution_config: dict | None = None,
|
|
51
|
+
capital_config: dict | None = None,
|
|
52
|
+
contract_config: dict | None = None,
|
|
53
|
+
progress_callback: Callable[[float, str], None] | None = None,
|
|
54
|
+
engine: str | None = None,
|
|
55
|
+
) -> BacktestResult:
|
|
56
|
+
"""Execute one batch-signals run using an explicitly versioned input."""
|
|
57
|
+
service = BacktestExecutor()
|
|
58
|
+
return await service.run_batch(
|
|
59
|
+
job_id=job_id,
|
|
60
|
+
inputs=inputs,
|
|
61
|
+
execution_config=execution_config,
|
|
62
|
+
capital_config=capital_config,
|
|
63
|
+
contract_config=contract_config,
|
|
64
|
+
progress_callback=progress_callback,
|
|
65
|
+
engine=engine,
|
|
66
|
+
)
|
nlalpha_backtest/data.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Backtest data models: MarketContext and BacktestResult."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
|
|
8
|
+
from nlalpha.core.contracts.market import Bar, Position
|
|
9
|
+
from nlalpha.core.backtest import BacktestResult as BacktestResult
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class MarketContext:
|
|
13
|
+
"""Strategy input: a stable, branch-free data structure."""
|
|
14
|
+
|
|
15
|
+
bars: dict[str, Bar] = field(default_factory=dict)
|
|
16
|
+
series: dict[str, dict[str, list[float]]] = field(default_factory=dict)
|
|
17
|
+
positions: dict[str, Position] = field(default_factory=dict)
|
|
18
|
+
equity: float = 0.0
|
|
19
|
+
cash: float = 0.0
|
|
20
|
+
timestamp: datetime | None = None
|
|
21
|
+
step: int = 0
|
|
22
|
+
|
|
23
|
+
def get(self, symbol: str, field: str = "close") -> float | None:
|
|
24
|
+
"""Get current bar field for a symbol."""
|
|
25
|
+
bar = self.bars.get(symbol)
|
|
26
|
+
return getattr(bar, field, None) if bar else None
|
|
27
|
+
|
|
28
|
+
def get_series(self, symbol: str, field: str = "close") -> list[float]:
|
|
29
|
+
"""Get historical series for a symbol."""
|
|
30
|
+
return self.series.get(symbol, {}).get(field, [])
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = ["BacktestResult", "MarketContext"]
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Engine registry and compatibility imports for shared backtest contracts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import threading
|
|
7
|
+
from dataclasses import dataclass, replace
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from nlalpha_backtest.execution.backend import EngineCapability, EngineDiagnostic, ExecutionCapabilities
|
|
12
|
+
|
|
13
|
+
from nlalpha.core.backtest import (
|
|
14
|
+
BATCH_SIGNALS,
|
|
15
|
+
EVENT_DRIVEN,
|
|
16
|
+
BacktestContext as BacktestContext,
|
|
17
|
+
BacktestEngineProvider as BacktestEngineProvider,
|
|
18
|
+
BacktestResult as BacktestResult,
|
|
19
|
+
EngineManifest as EngineManifest,
|
|
20
|
+
)
|
|
21
|
+
from nlalpha.core.errors import StrategyRuntimeError
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger("nlalpha_backtest.engine")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class _EngineRecord:
|
|
28
|
+
"""One cached provider load and its manifest, guidance, or failure diagnostic."""
|
|
29
|
+
|
|
30
|
+
engine_id: str | None
|
|
31
|
+
provider: BacktestEngineProvider | None
|
|
32
|
+
manifest: EngineManifest | None
|
|
33
|
+
capability: EngineCapability | None
|
|
34
|
+
diagnostic: EngineDiagnostic | None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class EngineRegistry:
|
|
38
|
+
"""Discover each installed engine once and select only verified providers."""
|
|
39
|
+
|
|
40
|
+
_records: list[_EngineRecord] = []
|
|
41
|
+
_default_order: list[str] = ["nautilus", "vector"]
|
|
42
|
+
_DISCOVERY_DONE = False
|
|
43
|
+
_lock = threading.RLock()
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def register(cls, name: str, provider: BacktestEngineProvider) -> None:
|
|
47
|
+
"""Register an explicit provider after validating its identity and guidance."""
|
|
48
|
+
record = cls._provider_record(name, provider, None, None, f"registered:{name}")
|
|
49
|
+
with cls._lock:
|
|
50
|
+
cls._append(record)
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def _provider_record(cls, name, provider, package, version, entry_point):
|
|
54
|
+
"""Cache one provider manifest and its exact guidance after identity validation."""
|
|
55
|
+
from nlalpha_backtest.execution.backend import EngineCapability, EngineDiagnostic
|
|
56
|
+
|
|
57
|
+
manifest = provider.manifest()
|
|
58
|
+
if not isinstance(manifest, EngineManifest) or manifest.engine_id != name:
|
|
59
|
+
raise ValueError("provider manifest engine_id must match the registered engine identity")
|
|
60
|
+
if not manifest.available:
|
|
61
|
+
diagnostic = EngineDiagnostic("unavailable", manifest.unavailable_reason or "provider reports unavailable",
|
|
62
|
+
name, entry_point, package, version)
|
|
63
|
+
return _EngineRecord(name, provider, manifest, None, diagnostic)
|
|
64
|
+
confession = provider.confess()
|
|
65
|
+
capability = EngineCapability(manifest, package, version, confession, entry_point)
|
|
66
|
+
return _EngineRecord(name, provider, manifest, capability, None)
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def _append(cls, record: _EngineRecord) -> None:
|
|
70
|
+
"""Retain a load record and disable every conflicting engine identity."""
|
|
71
|
+
from nlalpha_backtest.execution.backend import EngineDiagnostic
|
|
72
|
+
|
|
73
|
+
duplicates = [index for index, item in enumerate(cls._records)
|
|
74
|
+
if record.engine_id is not None and item.engine_id == record.engine_id]
|
|
75
|
+
if duplicates:
|
|
76
|
+
reason = f"duplicate engine identity: {record.engine_id}"
|
|
77
|
+
for index in duplicates:
|
|
78
|
+
prior = cls._records[index]
|
|
79
|
+
origin = prior.capability or prior.diagnostic
|
|
80
|
+
diagnostic = EngineDiagnostic("load_failed", reason, record.engine_id,
|
|
81
|
+
origin.entry_point, origin.package, origin.version)
|
|
82
|
+
cls._records[index] = replace(prior, capability=None, diagnostic=diagnostic)
|
|
83
|
+
origin = record.capability or record.diagnostic
|
|
84
|
+
record = replace(record, capability=None, diagnostic=EngineDiagnostic(
|
|
85
|
+
"load_failed", reason, record.engine_id, origin.entry_point, origin.package, origin.version))
|
|
86
|
+
cls._records.append(record)
|
|
87
|
+
if record.diagnostic:
|
|
88
|
+
logger.warning("engine unavailable | engine_id=%s entry_point=%s package=%s status=%s reason=%s",
|
|
89
|
+
record.engine_id, record.diagnostic.entry_point, record.diagnostic.package,
|
|
90
|
+
record.diagnostic.status, record.diagnostic.reason)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def _record(cls, name: str) -> _EngineRecord | None:
|
|
94
|
+
"""Find the cached load record for an engine identity."""
|
|
95
|
+
return next((item for item in cls._records if item.engine_id == name), None)
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def get(cls, name: str) -> BacktestEngineProvider:
|
|
99
|
+
"""Return a provider whose cached discovery record is available."""
|
|
100
|
+
record = cls._record(name)
|
|
101
|
+
if record is None or record.capability is None:
|
|
102
|
+
raise KeyError(f"Engine {name!r} is not available. Available: {[item.engine_id for item in cls.list_available()]}")
|
|
103
|
+
return record.provider
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def get_default(cls, *, runtime_mode: str = EVENT_DRIVEN, input_schema: str | None = None) -> BacktestEngineProvider:
|
|
107
|
+
"""Select a verified compatible provider in the explicit preference order."""
|
|
108
|
+
cls._validate_request(runtime_mode, input_schema)
|
|
109
|
+
manifests = []
|
|
110
|
+
for name in dict.fromkeys(cls._default_order):
|
|
111
|
+
record = cls._record(name)
|
|
112
|
+
if record is None:
|
|
113
|
+
continue
|
|
114
|
+
if record.capability is not None and record.manifest.supports(runtime_mode, input_schema):
|
|
115
|
+
return record.provider
|
|
116
|
+
if record.manifest is not None:
|
|
117
|
+
manifests.append(record.manifest.to_dict())
|
|
118
|
+
raise StrategyRuntimeError(
|
|
119
|
+
f"No available backtest engine supports runtime mode {runtime_mode!r} with input schema {input_schema!r}.",
|
|
120
|
+
details={"reason": "no_compatible_engine", "runtime_mode": runtime_mode,
|
|
121
|
+
"input_schema": input_schema, "engines": manifests},
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def resolve(cls, engine_id: str | None = None, *, runtime_mode: str = EVENT_DRIVEN,
|
|
126
|
+
input_schema: str | None = None) -> BacktestEngineProvider:
|
|
127
|
+
"""Resolve an explicit verified provider or apply the configured preference order."""
|
|
128
|
+
cls._validate_request(runtime_mode, input_schema)
|
|
129
|
+
if engine_id is None:
|
|
130
|
+
return cls.get_default(runtime_mode=runtime_mode, input_schema=input_schema)
|
|
131
|
+
details = {"engine_id": engine_id, "runtime_mode": runtime_mode, "input_schema": input_schema}
|
|
132
|
+
record = cls._record(engine_id)
|
|
133
|
+
if record is None:
|
|
134
|
+
raise StrategyRuntimeError(f"Engine {engine_id!r} is not registered.", details={
|
|
135
|
+
**details, "reason": "engine_not_registered", "registered_engines": list(dict.fromkeys(
|
|
136
|
+
item.engine_id for item in cls._records if item.engine_id is not None))})
|
|
137
|
+
if record.manifest is not None:
|
|
138
|
+
details["manifest"] = record.manifest.to_dict()
|
|
139
|
+
if record.capability is None:
|
|
140
|
+
raise StrategyRuntimeError(f"Engine {engine_id!r} is unavailable: {record.diagnostic.reason}",
|
|
141
|
+
details={**details, "reason": "engine_unavailable",
|
|
142
|
+
"diagnostic": record.diagnostic.to_dict()})
|
|
143
|
+
if not record.manifest.supports(runtime_mode, input_schema):
|
|
144
|
+
raise StrategyRuntimeError(
|
|
145
|
+
f"Engine {engine_id!r} does not support runtime mode {runtime_mode!r} with input schema {input_schema!r}.",
|
|
146
|
+
details={**details, "reason": "engine_incompatible"})
|
|
147
|
+
return record.provider
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def _validate_request(runtime_mode: str, input_schema: str | None) -> None:
|
|
151
|
+
"""Reject invalid runtime and input-schema combinations before selection."""
|
|
152
|
+
details = {"runtime_mode": runtime_mode, "input_schema": input_schema}
|
|
153
|
+
if runtime_mode not in (EVENT_DRIVEN, BATCH_SIGNALS):
|
|
154
|
+
raise StrategyRuntimeError(
|
|
155
|
+
f"Unknown backtest runtime mode: {runtime_mode!r}.",
|
|
156
|
+
details={
|
|
157
|
+
**details,
|
|
158
|
+
"reason": "invalid_runtime_mode",
|
|
159
|
+
"supported_runtime_modes": [EVENT_DRIVEN, BATCH_SIGNALS],
|
|
160
|
+
},
|
|
161
|
+
)
|
|
162
|
+
if runtime_mode == BATCH_SIGNALS and (
|
|
163
|
+
not isinstance(input_schema, str) or not input_schema.strip()
|
|
164
|
+
):
|
|
165
|
+
raise StrategyRuntimeError(
|
|
166
|
+
"Batch signal execution requires a non-empty input schema.",
|
|
167
|
+
details={**details, "reason": "input_schema_required"},
|
|
168
|
+
)
|
|
169
|
+
if runtime_mode == EVENT_DRIVEN and input_schema is not None:
|
|
170
|
+
raise StrategyRuntimeError(
|
|
171
|
+
"Event-driven execution does not accept an input schema.",
|
|
172
|
+
details={**details, "reason": "unexpected_input_schema"},
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
@classmethod
|
|
176
|
+
def list_available(cls) -> list[EngineManifest]:
|
|
177
|
+
"""List manifests from the same verified records used for provider selection."""
|
|
178
|
+
return [record.manifest for record in cls._records if record.capability is not None]
|
|
179
|
+
|
|
180
|
+
@classmethod
|
|
181
|
+
def list_all(cls) -> list[EngineManifest]:
|
|
182
|
+
"""List every successfully read manifest with its effective availability."""
|
|
183
|
+
return [record.manifest if record.capability is not None else replace(
|
|
184
|
+
record.manifest, available=False, unavailable_reason=record.diagnostic.reason)
|
|
185
|
+
for record in cls._records if record.manifest is not None]
|
|
186
|
+
|
|
187
|
+
@classmethod
|
|
188
|
+
def capabilities(cls) -> ExecutionCapabilities:
|
|
189
|
+
"""Return the installed engine directory and retained load diagnostics."""
|
|
190
|
+
from nlalpha_backtest.execution.backend import ExecutionCapabilities
|
|
191
|
+
|
|
192
|
+
cls.discover_engines()
|
|
193
|
+
return ExecutionCapabilities(
|
|
194
|
+
tuple(record.capability for record in cls._records if record.capability is not None),
|
|
195
|
+
tuple(record.diagnostic for record in cls._records if record.diagnostic is not None),
|
|
196
|
+
{"kind": "local"},
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
@classmethod
|
|
200
|
+
def discover_engines(cls) -> None:
|
|
201
|
+
"""Load installed entry points once while retaining each plugin's failure evidence."""
|
|
202
|
+
from importlib.metadata import entry_points
|
|
203
|
+
from nlalpha_backtest.execution.backend import EngineDiagnostic
|
|
204
|
+
|
|
205
|
+
with cls._lock:
|
|
206
|
+
if cls._DISCOVERY_DONE:
|
|
207
|
+
return
|
|
208
|
+
entries = list(entry_points(group="nlalpha.engines"))
|
|
209
|
+
for entry in sorted(entries, key=lambda item: (item.name, item.value)):
|
|
210
|
+
package = version = engine_id = None
|
|
211
|
+
source = f"{entry.name}={entry.value}"
|
|
212
|
+
manifest = None
|
|
213
|
+
provider = None
|
|
214
|
+
try:
|
|
215
|
+
package = entry.dist.metadata["Name"]
|
|
216
|
+
version = entry.dist.version
|
|
217
|
+
plugin = entry.load()()
|
|
218
|
+
engine_id = plugin.engine_id
|
|
219
|
+
if not isinstance(engine_id, str) or not engine_id.strip() or engine_id != engine_id.strip():
|
|
220
|
+
raise ValueError("plugin engine_id must be a nonempty trimmed string")
|
|
221
|
+
available = plugin.is_available()
|
|
222
|
+
if not isinstance(available, bool):
|
|
223
|
+
raise TypeError("plugin is_available must return a boolean")
|
|
224
|
+
declared = plugin.get_manifest()
|
|
225
|
+
if not isinstance(declared, dict):
|
|
226
|
+
raise TypeError("plugin get_manifest must return a manifest object")
|
|
227
|
+
fields = {"engine_id", "engine_name", "available", "unavailable_reason", "runtime_modes", "input_schemas"}
|
|
228
|
+
if not fields.issubset(declared):
|
|
229
|
+
raise ValueError("plugin get_manifest is missing manifest fields")
|
|
230
|
+
manifest = EngineManifest(**{name: declared[name] for name in fields})
|
|
231
|
+
if manifest.engine_id != engine_id:
|
|
232
|
+
raise ValueError("plugin manifest engine_id does not match plugin identity")
|
|
233
|
+
if not available or not manifest.available:
|
|
234
|
+
diagnostic = EngineDiagnostic("unavailable", manifest.unavailable_reason or "plugin reports unavailable",
|
|
235
|
+
engine_id, source, package, version)
|
|
236
|
+
record = _EngineRecord(engine_id, None, manifest, None, diagnostic)
|
|
237
|
+
else:
|
|
238
|
+
provider = plugin.get_provider()
|
|
239
|
+
record = cls._provider_record(engine_id, provider, package, version, source)
|
|
240
|
+
if record.manifest != manifest:
|
|
241
|
+
raise ValueError("plugin and provider manifests disagree")
|
|
242
|
+
except Exception as exc:
|
|
243
|
+
if not isinstance(engine_id, str) or not engine_id.strip() or engine_id != engine_id.strip():
|
|
244
|
+
engine_id = None
|
|
245
|
+
if (not isinstance(package, str) or not package.strip() or package != package.strip()
|
|
246
|
+
or not isinstance(version, str) or not version.strip() or version != version.strip()):
|
|
247
|
+
package = version = None
|
|
248
|
+
diagnostic = EngineDiagnostic("load_failed", f"{type(exc).__name__}: {exc}".strip(),
|
|
249
|
+
engine_id, source, package, version)
|
|
250
|
+
record = _EngineRecord(engine_id, provider, manifest, None, diagnostic)
|
|
251
|
+
cls._append(record)
|
|
252
|
+
cls._DISCOVERY_DONE = True
|
|
253
|
+
logger.info("engine discovery completed | available=%d diagnostics=%d",
|
|
254
|
+
len(cls.list_available()), sum(item.diagnostic is not None for item in cls._records))
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Backtest execution contracts, local backend, runner, and runtime."""
|
|
2
|
+
|
|
3
|
+
from nlalpha_backtest.execution.backtest_executor import BacktestExecutor
|
|
4
|
+
from nlalpha_backtest.execution.backend import (
|
|
5
|
+
BatchBacktestRequest,
|
|
6
|
+
BacktestRequest,
|
|
7
|
+
CancelOutcome,
|
|
8
|
+
CancelStatus,
|
|
9
|
+
ExecutionBackend,
|
|
10
|
+
ExecutionCapabilities,
|
|
11
|
+
EngineCapability,
|
|
12
|
+
EngineDiagnostic,
|
|
13
|
+
ExecutionCancelled,
|
|
14
|
+
ExecutionError,
|
|
15
|
+
ExecutionFailed,
|
|
16
|
+
ExecutionObservation,
|
|
17
|
+
ExecutionOutcome,
|
|
18
|
+
ExecutionRequest,
|
|
19
|
+
ExecutionTimedOut,
|
|
20
|
+
OperationStatus,
|
|
21
|
+
)
|
|
22
|
+
from nlalpha_backtest.execution.local_executor import LocalExecutor
|
|
23
|
+
from nlalpha_backtest.execution.runner import BacktestRunner
|
|
24
|
+
from nlalpha_backtest.execution.runtime import run_batch_strategy_code, run_strategy_code
|
|
25
|
+
from nlalpha_backtest.execution.validation import validate_runtime_mode
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"BacktestExecutor",
|
|
29
|
+
"BacktestRequest",
|
|
30
|
+
"BatchBacktestRequest",
|
|
31
|
+
"BacktestRunner",
|
|
32
|
+
"CancelOutcome",
|
|
33
|
+
"CancelStatus",
|
|
34
|
+
"ExecutionBackend",
|
|
35
|
+
"ExecutionCapabilities",
|
|
36
|
+
"EngineCapability",
|
|
37
|
+
"EngineDiagnostic",
|
|
38
|
+
"ExecutionCancelled",
|
|
39
|
+
"ExecutionError",
|
|
40
|
+
"ExecutionFailed",
|
|
41
|
+
"ExecutionObservation",
|
|
42
|
+
"ExecutionOutcome",
|
|
43
|
+
"ExecutionRequest",
|
|
44
|
+
"ExecutionTimedOut",
|
|
45
|
+
"LocalExecutor",
|
|
46
|
+
"OperationStatus",
|
|
47
|
+
"run_batch_strategy_code",
|
|
48
|
+
"run_strategy_code",
|
|
49
|
+
"validate_runtime_mode",
|
|
50
|
+
]
|