tsagentkit 1.0.2__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.
- tsagentkit/__init__.py +126 -0
- tsagentkit/anomaly/__init__.py +130 -0
- tsagentkit/backtest/__init__.py +48 -0
- tsagentkit/backtest/engine.py +788 -0
- tsagentkit/backtest/metrics.py +244 -0
- tsagentkit/backtest/report.py +342 -0
- tsagentkit/calibration/__init__.py +136 -0
- tsagentkit/contracts/__init__.py +133 -0
- tsagentkit/contracts/errors.py +275 -0
- tsagentkit/contracts/results.py +418 -0
- tsagentkit/contracts/schema.py +44 -0
- tsagentkit/contracts/task_spec.py +300 -0
- tsagentkit/covariates/__init__.py +340 -0
- tsagentkit/eval/__init__.py +285 -0
- tsagentkit/features/__init__.py +20 -0
- tsagentkit/features/covariates.py +328 -0
- tsagentkit/features/extra/__init__.py +5 -0
- tsagentkit/features/extra/native.py +179 -0
- tsagentkit/features/factory.py +187 -0
- tsagentkit/features/matrix.py +159 -0
- tsagentkit/features/tsfeatures_adapter.py +115 -0
- tsagentkit/features/versioning.py +203 -0
- tsagentkit/hierarchy/__init__.py +39 -0
- tsagentkit/hierarchy/aggregation.py +62 -0
- tsagentkit/hierarchy/evaluator.py +400 -0
- tsagentkit/hierarchy/reconciliation.py +232 -0
- tsagentkit/hierarchy/structure.py +453 -0
- tsagentkit/models/__init__.py +182 -0
- tsagentkit/models/adapters/__init__.py +83 -0
- tsagentkit/models/adapters/base.py +321 -0
- tsagentkit/models/adapters/chronos.py +387 -0
- tsagentkit/models/adapters/moirai.py +256 -0
- tsagentkit/models/adapters/registry.py +171 -0
- tsagentkit/models/adapters/timesfm.py +440 -0
- tsagentkit/models/baselines.py +207 -0
- tsagentkit/models/sktime.py +307 -0
- tsagentkit/monitoring/__init__.py +51 -0
- tsagentkit/monitoring/alerts.py +302 -0
- tsagentkit/monitoring/coverage.py +203 -0
- tsagentkit/monitoring/drift.py +330 -0
- tsagentkit/monitoring/report.py +214 -0
- tsagentkit/monitoring/stability.py +275 -0
- tsagentkit/monitoring/triggers.py +423 -0
- tsagentkit/qa/__init__.py +347 -0
- tsagentkit/router/__init__.py +37 -0
- tsagentkit/router/bucketing.py +489 -0
- tsagentkit/router/fallback.py +132 -0
- tsagentkit/router/plan.py +23 -0
- tsagentkit/router/router.py +271 -0
- tsagentkit/series/__init__.py +26 -0
- tsagentkit/series/alignment.py +206 -0
- tsagentkit/series/dataset.py +449 -0
- tsagentkit/series/sparsity.py +261 -0
- tsagentkit/series/validation.py +393 -0
- tsagentkit/serving/__init__.py +39 -0
- tsagentkit/serving/orchestration.py +943 -0
- tsagentkit/serving/packaging.py +73 -0
- tsagentkit/serving/provenance.py +317 -0
- tsagentkit/serving/tsfm_cache.py +214 -0
- tsagentkit/skill/README.md +135 -0
- tsagentkit/skill/__init__.py +8 -0
- tsagentkit/skill/recipes.md +429 -0
- tsagentkit/skill/tool_map.md +21 -0
- tsagentkit/time/__init__.py +134 -0
- tsagentkit/utils/__init__.py +20 -0
- tsagentkit/utils/quantiles.py +83 -0
- tsagentkit/utils/signature.py +47 -0
- tsagentkit/utils/temporal.py +41 -0
- tsagentkit-1.0.2.dist-info/METADATA +371 -0
- tsagentkit-1.0.2.dist-info/RECORD +72 -0
- tsagentkit-1.0.2.dist-info/WHEEL +4 -0
- tsagentkit-1.0.2.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Calibration utilities for forecast intervals and quantiles."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
from tsagentkit.contracts import ECalibrationFail
|
|
12
|
+
from tsagentkit.utils import extract_quantiles, quantile_col_name
|
|
13
|
+
|
|
14
|
+
CalibrationMethod = Literal["none", "conformal"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class CalibratorArtifact:
|
|
19
|
+
"""Serializable calibration artifact.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
method: Calibration method
|
|
23
|
+
level: Target coverage level (percent)
|
|
24
|
+
by: Calibration scope ("unique_id" or "global")
|
|
25
|
+
deltas: Mapping from unique_id to calibration delta
|
|
26
|
+
metadata: Additional metadata
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
method: CalibrationMethod
|
|
30
|
+
level: int
|
|
31
|
+
by: Literal["unique_id", "global"] = "unique_id"
|
|
32
|
+
deltas: dict[str, float] = field(default_factory=dict)
|
|
33
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
34
|
+
|
|
35
|
+
def get_delta(self, unique_id: str | None = None) -> float:
|
|
36
|
+
if self.by == "global":
|
|
37
|
+
return float(self.deltas.get("global", 0.0))
|
|
38
|
+
if unique_id is None:
|
|
39
|
+
return float(self.deltas.get("global", 0.0))
|
|
40
|
+
return float(self.deltas.get(unique_id, 0.0))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def fit_calibrator(
|
|
44
|
+
cv: pd.DataFrame,
|
|
45
|
+
method: CalibrationMethod = "conformal",
|
|
46
|
+
level: int = 99,
|
|
47
|
+
by: Literal["unique_id", "global"] = "unique_id",
|
|
48
|
+
id_col: str = "unique_id",
|
|
49
|
+
actual_col: str = "y",
|
|
50
|
+
pred_col: str = "yhat",
|
|
51
|
+
) -> CalibratorArtifact:
|
|
52
|
+
"""Fit calibration artifact using out-of-sample residuals."""
|
|
53
|
+
if method == "none":
|
|
54
|
+
return CalibratorArtifact(method=method, level=level, by=by, deltas={"global": 0.0})
|
|
55
|
+
|
|
56
|
+
if cv.empty:
|
|
57
|
+
raise ECalibrationFail("CV frame is empty.", context={"method": method})
|
|
58
|
+
|
|
59
|
+
if pred_col not in cv.columns or actual_col not in cv.columns:
|
|
60
|
+
raise ECalibrationFail(
|
|
61
|
+
"CV frame must include prediction and actual columns.",
|
|
62
|
+
context={"pred_col": pred_col, "actual_col": actual_col},
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
residuals = np.abs(cv[actual_col].to_numpy(dtype=float) - cv[pred_col].to_numpy(dtype=float))
|
|
66
|
+
if residuals.size == 0:
|
|
67
|
+
raise ECalibrationFail("No residuals available for calibration.")
|
|
68
|
+
|
|
69
|
+
alpha = level / 100.0
|
|
70
|
+
deltas: dict[str, float] = {}
|
|
71
|
+
|
|
72
|
+
if by == "global":
|
|
73
|
+
deltas["global"] = float(np.quantile(residuals, alpha))
|
|
74
|
+
else:
|
|
75
|
+
for uid, group in cv.groupby(id_col):
|
|
76
|
+
group_resid = np.abs(group[actual_col].to_numpy(dtype=float) - group[pred_col].to_numpy(dtype=float))
|
|
77
|
+
if group_resid.size == 0:
|
|
78
|
+
continue
|
|
79
|
+
deltas[str(uid)] = float(np.quantile(group_resid, alpha))
|
|
80
|
+
|
|
81
|
+
if not deltas:
|
|
82
|
+
deltas["global"] = float(np.quantile(residuals, alpha))
|
|
83
|
+
|
|
84
|
+
return CalibratorArtifact(
|
|
85
|
+
method=method,
|
|
86
|
+
level=level,
|
|
87
|
+
by=by,
|
|
88
|
+
deltas=deltas,
|
|
89
|
+
metadata={
|
|
90
|
+
"n_residuals": int(residuals.size),
|
|
91
|
+
"alpha": alpha,
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def apply_calibrator(
|
|
97
|
+
forecast: pd.DataFrame,
|
|
98
|
+
calibrator: CalibratorArtifact,
|
|
99
|
+
id_col: str = "unique_id",
|
|
100
|
+
pred_col: str = "yhat",
|
|
101
|
+
) -> pd.DataFrame:
|
|
102
|
+
"""Apply calibration artifact to a forecast frame."""
|
|
103
|
+
if calibrator.method == "none":
|
|
104
|
+
return forecast
|
|
105
|
+
|
|
106
|
+
if forecast.empty:
|
|
107
|
+
return forecast
|
|
108
|
+
|
|
109
|
+
df = forecast.copy()
|
|
110
|
+
level = calibrator.level
|
|
111
|
+
lo_col = f"yhat_lo_{level}"
|
|
112
|
+
hi_col = f"yhat_hi_{level}"
|
|
113
|
+
|
|
114
|
+
if id_col not in df.columns or pred_col not in df.columns:
|
|
115
|
+
raise ECalibrationFail(
|
|
116
|
+
"Forecast frame must include unique_id and yhat for calibration.",
|
|
117
|
+
context={"id_col": id_col, "pred_col": pred_col},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
deltas = df[id_col].map(lambda uid: calibrator.get_delta(str(uid))).to_numpy(dtype=float)
|
|
121
|
+
yhat = df[pred_col].to_numpy(dtype=float)
|
|
122
|
+
df[lo_col] = yhat - deltas
|
|
123
|
+
df[hi_col] = yhat + deltas
|
|
124
|
+
|
|
125
|
+
# If quantile columns exist, adjust symmetrically around yhat.
|
|
126
|
+
quantiles = extract_quantiles(df.columns)
|
|
127
|
+
if quantiles:
|
|
128
|
+
for q in quantiles:
|
|
129
|
+
col = quantile_col_name(q)
|
|
130
|
+
direction = -1.0 if q < 0.5 else 1.0
|
|
131
|
+
df[col] = yhat + direction * deltas
|
|
132
|
+
|
|
133
|
+
return df
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = ["CalibratorArtifact", "fit_calibrator", "apply_calibrator"]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Contracts module for tsagentkit."""
|
|
2
|
+
|
|
3
|
+
from .errors import (
|
|
4
|
+
EOOM,
|
|
5
|
+
EAdapterNotAvailable,
|
|
6
|
+
EAnomalyFail,
|
|
7
|
+
EBacktestFail,
|
|
8
|
+
EBacktestInsufficientData,
|
|
9
|
+
EBacktestInvalidWindow,
|
|
10
|
+
ECalibrationFail,
|
|
11
|
+
EContractDuplicateKey,
|
|
12
|
+
EContractInvalid,
|
|
13
|
+
EContractInvalidType,
|
|
14
|
+
EContractMissingColumn,
|
|
15
|
+
EContractUnsorted,
|
|
16
|
+
ECovariateIncompleteKnown,
|
|
17
|
+
ECovariateLeakage,
|
|
18
|
+
ECovariateStaticInvalid,
|
|
19
|
+
EDSNotMonotonic,
|
|
20
|
+
EFallbackExhausted,
|
|
21
|
+
EFreqInferFail,
|
|
22
|
+
EModelFitFailed,
|
|
23
|
+
EModelLoadFailed,
|
|
24
|
+
EModelPredictFailed,
|
|
25
|
+
EQACriticalIssue,
|
|
26
|
+
EQALeakageDetected,
|
|
27
|
+
EQAMinHistory,
|
|
28
|
+
EQARepairPeeksFuture,
|
|
29
|
+
ESplitRandomForbidden,
|
|
30
|
+
ETaskSpecIncompatible,
|
|
31
|
+
ETaskSpecInvalid,
|
|
32
|
+
TSAgentKitError,
|
|
33
|
+
get_error_class,
|
|
34
|
+
)
|
|
35
|
+
from .results import (
|
|
36
|
+
CVFrame,
|
|
37
|
+
ForecastFrame,
|
|
38
|
+
ForecastResult,
|
|
39
|
+
ModelArtifact,
|
|
40
|
+
Provenance,
|
|
41
|
+
RepairReport,
|
|
42
|
+
RunArtifact,
|
|
43
|
+
ValidationReport,
|
|
44
|
+
)
|
|
45
|
+
from .schema import validate_contract
|
|
46
|
+
from .task_spec import (
|
|
47
|
+
AggregationMode,
|
|
48
|
+
AnomalyMethod,
|
|
49
|
+
AnomalySpec,
|
|
50
|
+
BacktestSpec,
|
|
51
|
+
BaseSpec,
|
|
52
|
+
CalibratorSpec,
|
|
53
|
+
CovariatePolicy,
|
|
54
|
+
CovariateRole,
|
|
55
|
+
CovariateSpec,
|
|
56
|
+
ForecastContract,
|
|
57
|
+
IntervalMode,
|
|
58
|
+
MissingPolicy,
|
|
59
|
+
PanelContract,
|
|
60
|
+
PlanSpec,
|
|
61
|
+
RouteDecision,
|
|
62
|
+
RouterConfig,
|
|
63
|
+
RouterThresholds,
|
|
64
|
+
RunArtifactSpec,
|
|
65
|
+
SeasonalityMethod,
|
|
66
|
+
TaskSpec,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
__all__ = [
|
|
70
|
+
# Errors
|
|
71
|
+
"TSAgentKitError",
|
|
72
|
+
"EContractInvalid",
|
|
73
|
+
"EContractMissingColumn",
|
|
74
|
+
"EContractInvalidType",
|
|
75
|
+
"EContractDuplicateKey",
|
|
76
|
+
"EContractUnsorted",
|
|
77
|
+
"EFreqInferFail",
|
|
78
|
+
"EDSNotMonotonic",
|
|
79
|
+
"ESplitRandomForbidden",
|
|
80
|
+
"EQAMinHistory",
|
|
81
|
+
"EQARepairPeeksFuture",
|
|
82
|
+
"EQACriticalIssue",
|
|
83
|
+
"EQALeakageDetected",
|
|
84
|
+
"ECovariateLeakage",
|
|
85
|
+
"ECovariateIncompleteKnown",
|
|
86
|
+
"ECovariateStaticInvalid",
|
|
87
|
+
"EModelFitFailed",
|
|
88
|
+
"EModelPredictFailed",
|
|
89
|
+
"EModelLoadFailed",
|
|
90
|
+
"EAdapterNotAvailable",
|
|
91
|
+
"EFallbackExhausted",
|
|
92
|
+
"EOOM",
|
|
93
|
+
"ETaskSpecInvalid",
|
|
94
|
+
"ETaskSpecIncompatible",
|
|
95
|
+
"EBacktestFail",
|
|
96
|
+
"EBacktestInsufficientData",
|
|
97
|
+
"EBacktestInvalidWindow",
|
|
98
|
+
"ECalibrationFail",
|
|
99
|
+
"EAnomalyFail",
|
|
100
|
+
"get_error_class",
|
|
101
|
+
# Results
|
|
102
|
+
"CVFrame",
|
|
103
|
+
"ForecastFrame",
|
|
104
|
+
"ForecastResult",
|
|
105
|
+
"ModelArtifact",
|
|
106
|
+
"Provenance",
|
|
107
|
+
"RepairReport",
|
|
108
|
+
"RunArtifact",
|
|
109
|
+
"ValidationReport",
|
|
110
|
+
# Schema
|
|
111
|
+
"validate_contract",
|
|
112
|
+
# Specs
|
|
113
|
+
"AggregationMode",
|
|
114
|
+
"AnomalyMethod",
|
|
115
|
+
"AnomalySpec",
|
|
116
|
+
"BacktestSpec",
|
|
117
|
+
"BaseSpec",
|
|
118
|
+
"CalibratorSpec",
|
|
119
|
+
"CovariatePolicy",
|
|
120
|
+
"CovariateRole",
|
|
121
|
+
"CovariateSpec",
|
|
122
|
+
"ForecastContract",
|
|
123
|
+
"IntervalMode",
|
|
124
|
+
"MissingPolicy",
|
|
125
|
+
"PanelContract",
|
|
126
|
+
"PlanSpec",
|
|
127
|
+
"RouteDecision",
|
|
128
|
+
"RouterConfig",
|
|
129
|
+
"RouterThresholds",
|
|
130
|
+
"RunArtifactSpec",
|
|
131
|
+
"SeasonalityMethod",
|
|
132
|
+
"TaskSpec",
|
|
133
|
+
]
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""Error codes and exceptions for tsagentkit.
|
|
2
|
+
|
|
3
|
+
Defines structured error codes used throughout the pipeline.
|
|
4
|
+
Aligned to docs/PRD.md Section 6.1 with compatibility aliases.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# ruff: noqa: N818
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TSAgentKitError(Exception):
|
|
13
|
+
"""Base exception for all tsagentkit errors.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
error_code: Unique error code string for programmatic handling
|
|
17
|
+
message: Human-readable error message
|
|
18
|
+
context: Additional context data for debugging
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
error_code: str = "E_UNKNOWN"
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
message: str,
|
|
26
|
+
context: dict[str, Any] | None = None,
|
|
27
|
+
) -> None:
|
|
28
|
+
super().__init__(message)
|
|
29
|
+
self.message = message
|
|
30
|
+
self.context = context or {}
|
|
31
|
+
|
|
32
|
+
def __str__(self) -> str:
|
|
33
|
+
if self.context:
|
|
34
|
+
return f"[{self.error_code}] {self.message} (context: {self.context})"
|
|
35
|
+
return f"[{self.error_code}] {self.message}"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# ---------------------------
|
|
39
|
+
# Contract Errors
|
|
40
|
+
# ---------------------------
|
|
41
|
+
|
|
42
|
+
class EContractInvalid(TSAgentKitError):
|
|
43
|
+
"""Input schema/contract invalid."""
|
|
44
|
+
error_code = "E_CONTRACT_INVALID"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class EContractMissingColumn(TSAgentKitError):
|
|
48
|
+
"""Input data is missing required columns."""
|
|
49
|
+
error_code = "E_CONTRACT_MISSING_COLUMN"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class EContractInvalidType(TSAgentKitError):
|
|
53
|
+
"""Column has invalid data type."""
|
|
54
|
+
error_code = "E_CONTRACT_INVALID_TYPE"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class EContractDuplicateKey(TSAgentKitError):
|
|
58
|
+
"""Duplicate (unique_id, ds) pairs found in data."""
|
|
59
|
+
error_code = "E_CONTRACT_DUPLICATE_KEY"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class EFreqInferFail(TSAgentKitError):
|
|
63
|
+
"""Frequency cannot be inferred/validated."""
|
|
64
|
+
error_code = "E_FREQ_INFER_FAIL"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class EDSNotMonotonic(TSAgentKitError):
|
|
68
|
+
"""Time index not monotonic per series."""
|
|
69
|
+
error_code = "E_DS_NOT_MONOTONIC"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ESplitRandomForbidden(TSAgentKitError):
|
|
73
|
+
"""Random train/test splits are strictly forbidden."""
|
|
74
|
+
error_code = "E_SPLIT_RANDOM_FORBIDDEN"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class EContractUnsorted(EDSNotMonotonic):
|
|
78
|
+
"""Data is not sorted by (unique_id, ds)."""
|
|
79
|
+
error_code = "E_DS_NOT_MONOTONIC"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# ---------------------------
|
|
83
|
+
# QA Errors
|
|
84
|
+
# ---------------------------
|
|
85
|
+
|
|
86
|
+
class EQAMinHistory(TSAgentKitError):
|
|
87
|
+
"""Series history too short."""
|
|
88
|
+
error_code = "E_QA_MIN_HISTORY"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class EQARepairPeeksFuture(TSAgentKitError):
|
|
92
|
+
"""Repair strategy violates PIT safety."""
|
|
93
|
+
error_code = "E_QA_REPAIR_PEEKS_FUTURE"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class EQACriticalIssue(TSAgentKitError):
|
|
97
|
+
"""Critical data quality issue detected in strict mode."""
|
|
98
|
+
error_code = "E_QA_CRITICAL_ISSUE"
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class EQALeakageDetected(TSAgentKitError):
|
|
102
|
+
"""Data leakage detected in strict mode."""
|
|
103
|
+
error_code = "E_QA_LEAKAGE_DETECTED"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# ---------------------------
|
|
107
|
+
# Covariate Errors
|
|
108
|
+
# ---------------------------
|
|
109
|
+
|
|
110
|
+
class ECovariateLeakage(TSAgentKitError):
|
|
111
|
+
"""Past/observed covariate leaks into future."""
|
|
112
|
+
error_code = "E_COVARIATE_LEAKAGE"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class ECovariateIncompleteKnown(TSAgentKitError):
|
|
116
|
+
"""Future-known covariate missing in horizon."""
|
|
117
|
+
error_code = "E_COVARIATE_INCOMPLETE_KNOWN"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class ECovariateStaticInvalid(TSAgentKitError):
|
|
121
|
+
"""Static covariate invalid cardinality."""
|
|
122
|
+
error_code = "E_COVARIATE_STATIC_INVALID"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# ---------------------------
|
|
126
|
+
# Model Errors
|
|
127
|
+
# ---------------------------
|
|
128
|
+
|
|
129
|
+
class EModelFitFailed(TSAgentKitError):
|
|
130
|
+
"""Model fitting failed."""
|
|
131
|
+
error_code = "E_MODEL_FIT_FAIL"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class EModelPredictFailed(TSAgentKitError):
|
|
135
|
+
"""Model prediction failed."""
|
|
136
|
+
error_code = "E_MODEL_PREDICT_FAIL"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class EModelLoadFailed(TSAgentKitError):
|
|
140
|
+
"""Model loading failed."""
|
|
141
|
+
error_code = "E_MODEL_LOAD_FAILED"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class EAdapterNotAvailable(TSAgentKitError):
|
|
145
|
+
"""TSFM adapter not available."""
|
|
146
|
+
error_code = "E_ADAPTER_NOT_AVAILABLE"
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class EFallbackExhausted(TSAgentKitError):
|
|
150
|
+
"""All models in the fallback ladder failed."""
|
|
151
|
+
error_code = "E_FALLBACK_EXHAUSTED"
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class EOOM(TSAgentKitError):
|
|
155
|
+
"""Out-of-memory during fit/predict."""
|
|
156
|
+
error_code = "E_OOM"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# ---------------------------
|
|
160
|
+
# Task Spec Errors
|
|
161
|
+
# ---------------------------
|
|
162
|
+
|
|
163
|
+
class ETaskSpecInvalid(TSAgentKitError):
|
|
164
|
+
"""Task specification is invalid or incomplete."""
|
|
165
|
+
error_code = "E_TASK_SPEC_INVALID"
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class ETaskSpecIncompatible(TSAgentKitError):
|
|
169
|
+
"""Task spec is incompatible with data."""
|
|
170
|
+
error_code = "E_TASK_SPEC_INCOMPATIBLE"
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# ---------------------------
|
|
174
|
+
# Backtest Errors
|
|
175
|
+
# ---------------------------
|
|
176
|
+
|
|
177
|
+
class EBacktestFail(TSAgentKitError):
|
|
178
|
+
"""Backtest execution failed."""
|
|
179
|
+
error_code = "E_BACKTEST_FAIL"
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class EBacktestInsufficientData(TSAgentKitError):
|
|
183
|
+
"""Not enough data for requested backtest windows."""
|
|
184
|
+
error_code = "E_BACKTEST_INSUFFICIENT_DATA"
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class EBacktestInvalidWindow(TSAgentKitError):
|
|
188
|
+
"""Invalid backtest window configuration."""
|
|
189
|
+
error_code = "E_BACKTEST_INVALID_WINDOW"
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# ---------------------------
|
|
193
|
+
# Calibration / Anomaly Errors
|
|
194
|
+
# ---------------------------
|
|
195
|
+
|
|
196
|
+
class ECalibrationFail(TSAgentKitError):
|
|
197
|
+
"""Calibration failed."""
|
|
198
|
+
error_code = "E_CALIBRATION_FAIL"
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class EAnomalyFail(TSAgentKitError):
|
|
202
|
+
"""Anomaly detection failed."""
|
|
203
|
+
error_code = "E_ANOMALY_FAIL"
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# Registry for lookup
|
|
207
|
+
ERROR_REGISTRY: dict[str, type[TSAgentKitError]] = {
|
|
208
|
+
"E_CONTRACT_INVALID": EContractInvalid,
|
|
209
|
+
"E_CONTRACT_MISSING_COLUMN": EContractMissingColumn,
|
|
210
|
+
"E_CONTRACT_INVALID_TYPE": EContractInvalidType,
|
|
211
|
+
"E_CONTRACT_DUPLICATE_KEY": EContractDuplicateKey,
|
|
212
|
+
"E_FREQ_INFER_FAIL": EFreqInferFail,
|
|
213
|
+
"E_DS_NOT_MONOTONIC": EDSNotMonotonic,
|
|
214
|
+
"E_SPLIT_RANDOM_FORBIDDEN": ESplitRandomForbidden,
|
|
215
|
+
"E_CONTRACT_UNSORTED": EContractUnsorted,
|
|
216
|
+
"E_QA_MIN_HISTORY": EQAMinHistory,
|
|
217
|
+
"E_QA_REPAIR_PEEKS_FUTURE": EQARepairPeeksFuture,
|
|
218
|
+
"E_QA_CRITICAL_ISSUE": EQACriticalIssue,
|
|
219
|
+
"E_QA_LEAKAGE_DETECTED": EQALeakageDetected,
|
|
220
|
+
"E_COVARIATE_LEAKAGE": ECovariateLeakage,
|
|
221
|
+
"E_COVARIATE_INCOMPLETE_KNOWN": ECovariateIncompleteKnown,
|
|
222
|
+
"E_COVARIATE_STATIC_INVALID": ECovariateStaticInvalid,
|
|
223
|
+
"E_MODEL_FIT_FAIL": EModelFitFailed,
|
|
224
|
+
"E_MODEL_PREDICT_FAIL": EModelPredictFailed,
|
|
225
|
+
"E_MODEL_LOAD_FAILED": EModelLoadFailed,
|
|
226
|
+
"E_ADAPTER_NOT_AVAILABLE": EAdapterNotAvailable,
|
|
227
|
+
"E_FALLBACK_EXHAUSTED": EFallbackExhausted,
|
|
228
|
+
"E_OOM": EOOM,
|
|
229
|
+
"E_TASK_SPEC_INVALID": ETaskSpecInvalid,
|
|
230
|
+
"E_TASK_SPEC_INCOMPATIBLE": ETaskSpecIncompatible,
|
|
231
|
+
"E_BACKTEST_FAIL": EBacktestFail,
|
|
232
|
+
"E_BACKTEST_INSUFFICIENT_DATA": EBacktestInsufficientData,
|
|
233
|
+
"E_BACKTEST_INVALID_WINDOW": EBacktestInvalidWindow,
|
|
234
|
+
"E_CALIBRATION_FAIL": ECalibrationFail,
|
|
235
|
+
"E_ANOMALY_FAIL": EAnomalyFail,
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def get_error_class(error_code: str) -> type[TSAgentKitError]:
|
|
240
|
+
"""Get error class by error code."""
|
|
241
|
+
return ERROR_REGISTRY.get(error_code, TSAgentKitError)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
__all__ = [
|
|
245
|
+
"TSAgentKitError",
|
|
246
|
+
"EContractInvalid",
|
|
247
|
+
"EContractMissingColumn",
|
|
248
|
+
"EContractInvalidType",
|
|
249
|
+
"EContractDuplicateKey",
|
|
250
|
+
"EFreqInferFail",
|
|
251
|
+
"EDSNotMonotonic",
|
|
252
|
+
"ESplitRandomForbidden",
|
|
253
|
+
"EContractUnsorted",
|
|
254
|
+
"EQAMinHistory",
|
|
255
|
+
"EQARepairPeeksFuture",
|
|
256
|
+
"EQACriticalIssue",
|
|
257
|
+
"EQALeakageDetected",
|
|
258
|
+
"ECovariateLeakage",
|
|
259
|
+
"ECovariateIncompleteKnown",
|
|
260
|
+
"ECovariateStaticInvalid",
|
|
261
|
+
"EModelFitFailed",
|
|
262
|
+
"EModelPredictFailed",
|
|
263
|
+
"EModelLoadFailed",
|
|
264
|
+
"EAdapterNotAvailable",
|
|
265
|
+
"EFallbackExhausted",
|
|
266
|
+
"EOOM",
|
|
267
|
+
"ETaskSpecInvalid",
|
|
268
|
+
"ETaskSpecIncompatible",
|
|
269
|
+
"EBacktestFail",
|
|
270
|
+
"EBacktestInsufficientData",
|
|
271
|
+
"EBacktestInvalidWindow",
|
|
272
|
+
"ECalibrationFail",
|
|
273
|
+
"EAnomalyFail",
|
|
274
|
+
"get_error_class",
|
|
275
|
+
]
|