ml4t-diagnostic 0.1.0a1__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.
- ml4t/diagnostic/AGENT.md +25 -0
- ml4t/diagnostic/__init__.py +166 -0
- ml4t/diagnostic/backends/__init__.py +10 -0
- ml4t/diagnostic/backends/adapter.py +192 -0
- ml4t/diagnostic/backends/polars_backend.py +899 -0
- ml4t/diagnostic/caching/__init__.py +40 -0
- ml4t/diagnostic/caching/cache.py +331 -0
- ml4t/diagnostic/caching/decorators.py +131 -0
- ml4t/diagnostic/caching/smart_cache.py +339 -0
- ml4t/diagnostic/config/AGENT.md +24 -0
- ml4t/diagnostic/config/README.md +267 -0
- ml4t/diagnostic/config/__init__.py +219 -0
- ml4t/diagnostic/config/barrier_config.py +277 -0
- ml4t/diagnostic/config/base.py +301 -0
- ml4t/diagnostic/config/event_config.py +148 -0
- ml4t/diagnostic/config/feature_config.py +404 -0
- ml4t/diagnostic/config/multi_signal_config.py +55 -0
- ml4t/diagnostic/config/portfolio_config.py +215 -0
- ml4t/diagnostic/config/report_config.py +391 -0
- ml4t/diagnostic/config/sharpe_config.py +202 -0
- ml4t/diagnostic/config/signal_config.py +206 -0
- ml4t/diagnostic/config/trade_analysis_config.py +310 -0
- ml4t/diagnostic/config/validation.py +279 -0
- ml4t/diagnostic/core/__init__.py +29 -0
- ml4t/diagnostic/core/numba_utils.py +315 -0
- ml4t/diagnostic/core/purging.py +372 -0
- ml4t/diagnostic/core/sampling.py +471 -0
- ml4t/diagnostic/errors/__init__.py +205 -0
- ml4t/diagnostic/evaluation/AGENT.md +26 -0
- ml4t/diagnostic/evaluation/__init__.py +437 -0
- ml4t/diagnostic/evaluation/autocorrelation.py +531 -0
- ml4t/diagnostic/evaluation/barrier_analysis.py +1050 -0
- ml4t/diagnostic/evaluation/binary_metrics.py +910 -0
- ml4t/diagnostic/evaluation/dashboard.py +715 -0
- ml4t/diagnostic/evaluation/diagnostic_plots.py +1037 -0
- ml4t/diagnostic/evaluation/distribution/__init__.py +499 -0
- ml4t/diagnostic/evaluation/distribution/moments.py +299 -0
- ml4t/diagnostic/evaluation/distribution/tails.py +777 -0
- ml4t/diagnostic/evaluation/distribution/tests.py +470 -0
- ml4t/diagnostic/evaluation/drift/__init__.py +139 -0
- ml4t/diagnostic/evaluation/drift/analysis.py +432 -0
- ml4t/diagnostic/evaluation/drift/domain_classifier.py +517 -0
- ml4t/diagnostic/evaluation/drift/population_stability_index.py +310 -0
- ml4t/diagnostic/evaluation/drift/wasserstein.py +388 -0
- ml4t/diagnostic/evaluation/event_analysis.py +647 -0
- ml4t/diagnostic/evaluation/excursion.py +390 -0
- ml4t/diagnostic/evaluation/feature_diagnostics.py +873 -0
- ml4t/diagnostic/evaluation/feature_outcome.py +666 -0
- ml4t/diagnostic/evaluation/framework.py +935 -0
- ml4t/diagnostic/evaluation/metric_registry.py +255 -0
- ml4t/diagnostic/evaluation/metrics/AGENT.md +23 -0
- ml4t/diagnostic/evaluation/metrics/__init__.py +133 -0
- ml4t/diagnostic/evaluation/metrics/basic.py +160 -0
- ml4t/diagnostic/evaluation/metrics/conditional_ic.py +469 -0
- ml4t/diagnostic/evaluation/metrics/feature_outcome.py +475 -0
- ml4t/diagnostic/evaluation/metrics/ic_statistics.py +446 -0
- ml4t/diagnostic/evaluation/metrics/importance_analysis.py +338 -0
- ml4t/diagnostic/evaluation/metrics/importance_classical.py +375 -0
- ml4t/diagnostic/evaluation/metrics/importance_mda.py +371 -0
- ml4t/diagnostic/evaluation/metrics/importance_shap.py +715 -0
- ml4t/diagnostic/evaluation/metrics/information_coefficient.py +527 -0
- ml4t/diagnostic/evaluation/metrics/interactions.py +772 -0
- ml4t/diagnostic/evaluation/metrics/monotonicity.py +226 -0
- ml4t/diagnostic/evaluation/metrics/risk_adjusted.py +324 -0
- ml4t/diagnostic/evaluation/multi_signal.py +550 -0
- ml4t/diagnostic/evaluation/portfolio_analysis/__init__.py +83 -0
- ml4t/diagnostic/evaluation/portfolio_analysis/analysis.py +734 -0
- ml4t/diagnostic/evaluation/portfolio_analysis/metrics.py +589 -0
- ml4t/diagnostic/evaluation/portfolio_analysis/results.py +334 -0
- ml4t/diagnostic/evaluation/report_generation.py +824 -0
- ml4t/diagnostic/evaluation/signal_selector.py +452 -0
- ml4t/diagnostic/evaluation/stat_registry.py +139 -0
- ml4t/diagnostic/evaluation/stationarity/__init__.py +97 -0
- ml4t/diagnostic/evaluation/stationarity/analysis.py +518 -0
- ml4t/diagnostic/evaluation/stationarity/augmented_dickey_fuller.py +296 -0
- ml4t/diagnostic/evaluation/stationarity/kpss_test.py +308 -0
- ml4t/diagnostic/evaluation/stationarity/phillips_perron.py +365 -0
- ml4t/diagnostic/evaluation/stats/AGENT.md +43 -0
- ml4t/diagnostic/evaluation/stats/__init__.py +191 -0
- ml4t/diagnostic/evaluation/stats/backtest_overfitting.py +219 -0
- ml4t/diagnostic/evaluation/stats/bootstrap.py +228 -0
- ml4t/diagnostic/evaluation/stats/deflated_sharpe_ratio.py +591 -0
- ml4t/diagnostic/evaluation/stats/false_discovery_rate.py +295 -0
- ml4t/diagnostic/evaluation/stats/hac_standard_errors.py +108 -0
- ml4t/diagnostic/evaluation/stats/minimum_track_record.py +408 -0
- ml4t/diagnostic/evaluation/stats/moments.py +164 -0
- ml4t/diagnostic/evaluation/stats/rademacher_adjustment.py +436 -0
- ml4t/diagnostic/evaluation/stats/reality_check.py +155 -0
- ml4t/diagnostic/evaluation/stats/sharpe_inference.py +219 -0
- ml4t/diagnostic/evaluation/themes.py +330 -0
- ml4t/diagnostic/evaluation/threshold_analysis.py +957 -0
- ml4t/diagnostic/evaluation/trade_analysis.py +1136 -0
- ml4t/diagnostic/evaluation/trade_dashboard/__init__.py +32 -0
- ml4t/diagnostic/evaluation/trade_dashboard/app.py +315 -0
- ml4t/diagnostic/evaluation/trade_dashboard/export/__init__.py +18 -0
- ml4t/diagnostic/evaluation/trade_dashboard/export/csv.py +82 -0
- ml4t/diagnostic/evaluation/trade_dashboard/export/html.py +276 -0
- ml4t/diagnostic/evaluation/trade_dashboard/io.py +166 -0
- ml4t/diagnostic/evaluation/trade_dashboard/normalize.py +304 -0
- ml4t/diagnostic/evaluation/trade_dashboard/stats.py +386 -0
- ml4t/diagnostic/evaluation/trade_dashboard/style.py +79 -0
- ml4t/diagnostic/evaluation/trade_dashboard/tabs/__init__.py +21 -0
- ml4t/diagnostic/evaluation/trade_dashboard/tabs/patterns.py +354 -0
- ml4t/diagnostic/evaluation/trade_dashboard/tabs/shap_analysis.py +280 -0
- ml4t/diagnostic/evaluation/trade_dashboard/tabs/stat_validation.py +186 -0
- ml4t/diagnostic/evaluation/trade_dashboard/tabs/worst_trades.py +236 -0
- ml4t/diagnostic/evaluation/trade_dashboard/types.py +129 -0
- ml4t/diagnostic/evaluation/trade_shap/__init__.py +102 -0
- ml4t/diagnostic/evaluation/trade_shap/alignment.py +188 -0
- ml4t/diagnostic/evaluation/trade_shap/characterize.py +413 -0
- ml4t/diagnostic/evaluation/trade_shap/cluster.py +302 -0
- ml4t/diagnostic/evaluation/trade_shap/explain.py +208 -0
- ml4t/diagnostic/evaluation/trade_shap/hypotheses/__init__.py +23 -0
- ml4t/diagnostic/evaluation/trade_shap/hypotheses/generator.py +290 -0
- ml4t/diagnostic/evaluation/trade_shap/hypotheses/matcher.py +251 -0
- ml4t/diagnostic/evaluation/trade_shap/hypotheses/templates.yaml +467 -0
- ml4t/diagnostic/evaluation/trade_shap/models.py +386 -0
- ml4t/diagnostic/evaluation/trade_shap/normalize.py +116 -0
- ml4t/diagnostic/evaluation/trade_shap/pipeline.py +263 -0
- ml4t/diagnostic/evaluation/trade_shap_dashboard.py +283 -0
- ml4t/diagnostic/evaluation/trade_shap_diagnostics.py +588 -0
- ml4t/diagnostic/evaluation/validated_cv.py +535 -0
- ml4t/diagnostic/evaluation/visualization.py +1050 -0
- ml4t/diagnostic/evaluation/volatility/__init__.py +45 -0
- ml4t/diagnostic/evaluation/volatility/analysis.py +351 -0
- ml4t/diagnostic/evaluation/volatility/arch.py +258 -0
- ml4t/diagnostic/evaluation/volatility/garch.py +460 -0
- ml4t/diagnostic/integration/__init__.py +48 -0
- ml4t/diagnostic/integration/backtest_contract.py +671 -0
- ml4t/diagnostic/integration/data_contract.py +316 -0
- ml4t/diagnostic/integration/engineer_contract.py +226 -0
- ml4t/diagnostic/logging/__init__.py +77 -0
- ml4t/diagnostic/logging/logger.py +245 -0
- ml4t/diagnostic/logging/performance.py +234 -0
- ml4t/diagnostic/logging/progress.py +234 -0
- ml4t/diagnostic/logging/wandb.py +412 -0
- ml4t/diagnostic/metrics/__init__.py +9 -0
- ml4t/diagnostic/metrics/percentiles.py +128 -0
- ml4t/diagnostic/py.typed +1 -0
- ml4t/diagnostic/reporting/__init__.py +43 -0
- ml4t/diagnostic/reporting/base.py +130 -0
- ml4t/diagnostic/reporting/html_renderer.py +275 -0
- ml4t/diagnostic/reporting/json_renderer.py +51 -0
- ml4t/diagnostic/reporting/markdown_renderer.py +117 -0
- ml4t/diagnostic/results/AGENT.md +24 -0
- ml4t/diagnostic/results/__init__.py +105 -0
- ml4t/diagnostic/results/barrier_results/__init__.py +36 -0
- ml4t/diagnostic/results/barrier_results/hit_rate.py +304 -0
- ml4t/diagnostic/results/barrier_results/precision_recall.py +266 -0
- ml4t/diagnostic/results/barrier_results/profit_factor.py +297 -0
- ml4t/diagnostic/results/barrier_results/tearsheet.py +397 -0
- ml4t/diagnostic/results/barrier_results/time_to_target.py +305 -0
- ml4t/diagnostic/results/barrier_results/validation.py +38 -0
- ml4t/diagnostic/results/base.py +177 -0
- ml4t/diagnostic/results/event_results.py +349 -0
- ml4t/diagnostic/results/feature_results.py +787 -0
- ml4t/diagnostic/results/multi_signal_results.py +431 -0
- ml4t/diagnostic/results/portfolio_results.py +281 -0
- ml4t/diagnostic/results/sharpe_results.py +448 -0
- ml4t/diagnostic/results/signal_results/__init__.py +74 -0
- ml4t/diagnostic/results/signal_results/ic.py +581 -0
- ml4t/diagnostic/results/signal_results/irtc.py +110 -0
- ml4t/diagnostic/results/signal_results/quantile.py +392 -0
- ml4t/diagnostic/results/signal_results/tearsheet.py +456 -0
- ml4t/diagnostic/results/signal_results/turnover.py +213 -0
- ml4t/diagnostic/results/signal_results/validation.py +147 -0
- ml4t/diagnostic/signal/AGENT.md +17 -0
- ml4t/diagnostic/signal/__init__.py +69 -0
- ml4t/diagnostic/signal/_report.py +152 -0
- ml4t/diagnostic/signal/_utils.py +261 -0
- ml4t/diagnostic/signal/core.py +275 -0
- ml4t/diagnostic/signal/quantile.py +148 -0
- ml4t/diagnostic/signal/result.py +214 -0
- ml4t/diagnostic/signal/signal_ic.py +129 -0
- ml4t/diagnostic/signal/turnover.py +182 -0
- ml4t/diagnostic/splitters/AGENT.md +19 -0
- ml4t/diagnostic/splitters/__init__.py +36 -0
- ml4t/diagnostic/splitters/base.py +501 -0
- ml4t/diagnostic/splitters/calendar.py +421 -0
- ml4t/diagnostic/splitters/calendar_config.py +91 -0
- ml4t/diagnostic/splitters/combinatorial.py +1064 -0
- ml4t/diagnostic/splitters/config.py +322 -0
- ml4t/diagnostic/splitters/cpcv/__init__.py +57 -0
- ml4t/diagnostic/splitters/cpcv/combinations.py +119 -0
- ml4t/diagnostic/splitters/cpcv/partitioning.py +263 -0
- ml4t/diagnostic/splitters/cpcv/purge_engine.py +379 -0
- ml4t/diagnostic/splitters/cpcv/windows.py +190 -0
- ml4t/diagnostic/splitters/group_isolation.py +329 -0
- ml4t/diagnostic/splitters/persistence.py +316 -0
- ml4t/diagnostic/splitters/utils.py +207 -0
- ml4t/diagnostic/splitters/walk_forward.py +757 -0
- ml4t/diagnostic/utils/__init__.py +42 -0
- ml4t/diagnostic/utils/config.py +542 -0
- ml4t/diagnostic/utils/dependencies.py +318 -0
- ml4t/diagnostic/utils/sessions.py +127 -0
- ml4t/diagnostic/validation/__init__.py +54 -0
- ml4t/diagnostic/validation/dataframe.py +274 -0
- ml4t/diagnostic/validation/returns.py +280 -0
- ml4t/diagnostic/validation/timeseries.py +299 -0
- ml4t/diagnostic/visualization/AGENT.md +19 -0
- ml4t/diagnostic/visualization/__init__.py +223 -0
- ml4t/diagnostic/visualization/backtest/__init__.py +98 -0
- ml4t/diagnostic/visualization/backtest/cost_attribution.py +762 -0
- ml4t/diagnostic/visualization/backtest/executive_summary.py +895 -0
- ml4t/diagnostic/visualization/backtest/interactive_controls.py +673 -0
- ml4t/diagnostic/visualization/backtest/statistical_validity.py +874 -0
- ml4t/diagnostic/visualization/backtest/tearsheet.py +565 -0
- ml4t/diagnostic/visualization/backtest/template_system.py +373 -0
- ml4t/diagnostic/visualization/backtest/trade_plots.py +1172 -0
- ml4t/diagnostic/visualization/barrier_plots.py +782 -0
- ml4t/diagnostic/visualization/core.py +1060 -0
- ml4t/diagnostic/visualization/dashboards/__init__.py +36 -0
- ml4t/diagnostic/visualization/dashboards/base.py +582 -0
- ml4t/diagnostic/visualization/dashboards/importance.py +801 -0
- ml4t/diagnostic/visualization/dashboards/interaction.py +263 -0
- ml4t/diagnostic/visualization/dashboards.py +43 -0
- ml4t/diagnostic/visualization/data_extraction/__init__.py +48 -0
- ml4t/diagnostic/visualization/data_extraction/importance.py +649 -0
- ml4t/diagnostic/visualization/data_extraction/interaction.py +504 -0
- ml4t/diagnostic/visualization/data_extraction/types.py +113 -0
- ml4t/diagnostic/visualization/data_extraction/validation.py +66 -0
- ml4t/diagnostic/visualization/feature_plots.py +888 -0
- ml4t/diagnostic/visualization/interaction_plots.py +618 -0
- ml4t/diagnostic/visualization/portfolio/__init__.py +41 -0
- ml4t/diagnostic/visualization/portfolio/dashboard.py +514 -0
- ml4t/diagnostic/visualization/portfolio/drawdown_plots.py +341 -0
- ml4t/diagnostic/visualization/portfolio/returns_plots.py +487 -0
- ml4t/diagnostic/visualization/portfolio/risk_plots.py +301 -0
- ml4t/diagnostic/visualization/report_generation.py +1343 -0
- ml4t/diagnostic/visualization/signal/__init__.py +103 -0
- ml4t/diagnostic/visualization/signal/dashboard.py +911 -0
- ml4t/diagnostic/visualization/signal/event_plots.py +514 -0
- ml4t/diagnostic/visualization/signal/ic_plots.py +635 -0
- ml4t/diagnostic/visualization/signal/multi_signal_dashboard.py +974 -0
- ml4t/diagnostic/visualization/signal/multi_signal_plots.py +603 -0
- ml4t/diagnostic/visualization/signal/quantile_plots.py +625 -0
- ml4t/diagnostic/visualization/signal/turnover_plots.py +400 -0
- ml4t/diagnostic/visualization/trade_shap/__init__.py +90 -0
- ml4t_diagnostic-0.1.0a1.dist-info/METADATA +1044 -0
- ml4t_diagnostic-0.1.0a1.dist-info/RECORD +242 -0
- ml4t_diagnostic-0.1.0a1.dist-info/WHEEL +4 -0
- ml4t_diagnostic-0.1.0a1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""ML4T Data integration contract for data quality validation.
|
|
2
|
+
|
|
3
|
+
This module defines the API contract between ML4T Data and ML4T Diagnostic for
|
|
4
|
+
data quality assessment. ML4T Data can use these contracts to report data quality
|
|
5
|
+
to ML4T Diagnostic for validation before feature engineering.
|
|
6
|
+
|
|
7
|
+
Example workflow:
|
|
8
|
+
>>> from ml4t.data import DataManager
|
|
9
|
+
>>> from ml4t.diagnostic.integration import DataQualityReport, DataAnomaly
|
|
10
|
+
>>>
|
|
11
|
+
>>> # 1. Load data with quality report
|
|
12
|
+
>>> dm = DataManager(storage_config)
|
|
13
|
+
>>> data, quality = dm.load_with_quality("AAPL", start="2020-01-01")
|
|
14
|
+
>>>
|
|
15
|
+
>>> # 2. Check quality before proceeding
|
|
16
|
+
>>> if not quality.is_acceptable():
|
|
17
|
+
... print(quality.summary())
|
|
18
|
+
... raise DataQualityError(quality.recommendations)
|
|
19
|
+
>>>
|
|
20
|
+
>>> # 3. Proceed with feature engineering
|
|
21
|
+
>>> features = compute_features(data)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from datetime import datetime
|
|
27
|
+
from enum import Enum
|
|
28
|
+
|
|
29
|
+
from pydantic import BaseModel, Field
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AnomalyType(str, Enum):
|
|
33
|
+
"""Types of data anomalies that can be detected.
|
|
34
|
+
|
|
35
|
+
These anomaly types align with common data quality issues in financial data:
|
|
36
|
+
|
|
37
|
+
- MISSING_DATA: Gaps in the data (e.g., missing trading days)
|
|
38
|
+
- STALE_DATA: Same value repeated (stuck price feed)
|
|
39
|
+
- PRICE_SPIKE: Abnormal price movement (e.g., >10 std devs)
|
|
40
|
+
- NEGATIVE_PRICE: Invalid negative price (should be positive)
|
|
41
|
+
- ZERO_VOLUME: No trading activity (suspicious for liquid assets)
|
|
42
|
+
- OHLC_VIOLATION: High < Low or similar OHLC logic errors
|
|
43
|
+
- TIMESTAMP_GAP: Unexpected gap in timestamps
|
|
44
|
+
- DUPLICATE_TIMESTAMP: Same timestamp appears multiple times
|
|
45
|
+
- OUTLIER: Statistical outlier (not necessarily error)
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
MISSING_DATA = "missing_data"
|
|
49
|
+
STALE_DATA = "stale_data"
|
|
50
|
+
PRICE_SPIKE = "price_spike"
|
|
51
|
+
NEGATIVE_PRICE = "negative_price"
|
|
52
|
+
ZERO_VOLUME = "zero_volume"
|
|
53
|
+
OHLC_VIOLATION = "ohlc_violation"
|
|
54
|
+
TIMESTAMP_GAP = "timestamp_gap"
|
|
55
|
+
DUPLICATE_TIMESTAMP = "duplicate_timestamp"
|
|
56
|
+
OUTLIER = "outlier"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Severity(str, Enum):
|
|
60
|
+
"""Severity level of data anomalies.
|
|
61
|
+
|
|
62
|
+
- INFO: Informational, no action needed
|
|
63
|
+
- WARNING: Potential issue, review recommended
|
|
64
|
+
- ERROR: Definite issue, correction needed
|
|
65
|
+
- CRITICAL: Severe issue, data may be unusable
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
INFO = "info"
|
|
69
|
+
WARNING = "warning"
|
|
70
|
+
ERROR = "error"
|
|
71
|
+
CRITICAL = "critical"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class DataAnomaly(BaseModel):
|
|
75
|
+
"""Record of a single data anomaly detected.
|
|
76
|
+
|
|
77
|
+
Represents a specific data quality issue found during validation.
|
|
78
|
+
Used to communicate detailed findings from ML4T Data to ML4T Diagnostic.
|
|
79
|
+
|
|
80
|
+
Attributes:
|
|
81
|
+
anomaly_type: Type of anomaly detected
|
|
82
|
+
severity: Severity level
|
|
83
|
+
timestamp: When the anomaly occurred
|
|
84
|
+
symbol: Which asset (if multi-asset)
|
|
85
|
+
description: Human-readable description
|
|
86
|
+
value: The problematic value (if applicable)
|
|
87
|
+
expected_range: Expected value range (if applicable)
|
|
88
|
+
suggested_fix: Recommended correction
|
|
89
|
+
|
|
90
|
+
Example:
|
|
91
|
+
>>> anomaly = DataAnomaly(
|
|
92
|
+
... anomaly_type=AnomalyType.PRICE_SPIKE,
|
|
93
|
+
... severity=Severity.ERROR,
|
|
94
|
+
... timestamp=datetime(2024, 1, 15, 10, 30),
|
|
95
|
+
... symbol="AAPL",
|
|
96
|
+
... description="Price moved 15 std devs in 1 minute",
|
|
97
|
+
... value=999.99,
|
|
98
|
+
... expected_range=(150.0, 200.0),
|
|
99
|
+
... suggested_fix="Replace with interpolated value"
|
|
100
|
+
... )
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
anomaly_type: AnomalyType = Field(..., description="Type of anomaly")
|
|
104
|
+
severity: Severity = Field(..., description="Severity level")
|
|
105
|
+
timestamp: datetime = Field(..., description="When anomaly occurred")
|
|
106
|
+
symbol: str | None = Field(None, description="Asset symbol (if applicable)")
|
|
107
|
+
description: str = Field(..., description="Human-readable description")
|
|
108
|
+
value: float | None = Field(None, description="Problematic value")
|
|
109
|
+
expected_range: tuple[float, float] | None = Field(None, description="Expected value range")
|
|
110
|
+
suggested_fix: str | None = Field(None, description="Recommended correction")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class DataQualityMetrics(BaseModel):
|
|
114
|
+
"""Quantitative metrics for data quality assessment.
|
|
115
|
+
|
|
116
|
+
These metrics provide a numerical summary of data quality that can be
|
|
117
|
+
used for automated quality gates.
|
|
118
|
+
|
|
119
|
+
Attributes:
|
|
120
|
+
completeness: Fraction of expected data points present [0.0, 1.0]
|
|
121
|
+
timeliness: How up-to-date the data is (e.g., minutes since last update)
|
|
122
|
+
accuracy_score: Estimated data accuracy based on validation checks [0.0, 1.0]
|
|
123
|
+
consistency_score: How consistent the data is (no OHLC violations, etc.) [0.0, 1.0]
|
|
124
|
+
n_records: Total number of records
|
|
125
|
+
n_anomalies: Total anomalies detected
|
|
126
|
+
n_critical: Number of critical severity anomalies
|
|
127
|
+
n_error: Number of error severity anomalies
|
|
128
|
+
n_warning: Number of warning severity anomalies
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
>>> metrics = DataQualityMetrics(
|
|
132
|
+
... completeness=0.98,
|
|
133
|
+
... timeliness=5.0,
|
|
134
|
+
... accuracy_score=0.95,
|
|
135
|
+
... consistency_score=1.0,
|
|
136
|
+
... n_records=10000,
|
|
137
|
+
... n_anomalies=12,
|
|
138
|
+
... n_critical=0,
|
|
139
|
+
... n_error=2,
|
|
140
|
+
... n_warning=10
|
|
141
|
+
... )
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
completeness: float = Field(..., ge=0.0, le=1.0, description="Data completeness [0,1]")
|
|
145
|
+
timeliness: float = Field(..., ge=0.0, description="Minutes since last update")
|
|
146
|
+
accuracy_score: float = Field(..., ge=0.0, le=1.0, description="Accuracy score [0,1]")
|
|
147
|
+
consistency_score: float = Field(..., ge=0.0, le=1.0, description="Consistency score [0,1]")
|
|
148
|
+
n_records: int = Field(..., ge=0, description="Total records")
|
|
149
|
+
n_anomalies: int = Field(..., ge=0, description="Total anomalies")
|
|
150
|
+
n_critical: int = Field(default=0, ge=0, description="Critical anomalies")
|
|
151
|
+
n_error: int = Field(default=0, ge=0, description="Error anomalies")
|
|
152
|
+
n_warning: int = Field(default=0, ge=0, description="Warning anomalies")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class DataQualityReport(BaseModel):
|
|
156
|
+
"""Complete data quality report from ML4T Data.
|
|
157
|
+
|
|
158
|
+
This is the primary output format for data quality validation.
|
|
159
|
+
ML4T Data generates this report when loading data, and ML4T Diagnostic
|
|
160
|
+
can use it to decide whether to proceed with analysis.
|
|
161
|
+
|
|
162
|
+
Attributes:
|
|
163
|
+
symbol: Asset symbol or identifier
|
|
164
|
+
source: Data source/provider name
|
|
165
|
+
date_range: Start and end dates of the data
|
|
166
|
+
frequency: Data frequency (e.g., "1min", "1d", "tick")
|
|
167
|
+
metrics: Quantitative quality metrics
|
|
168
|
+
anomalies: List of detected anomalies
|
|
169
|
+
recommendations: Human-readable recommendations
|
|
170
|
+
is_production_ready: Whether data meets production quality standards
|
|
171
|
+
created_at: When this report was generated
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
>>> report = DataQualityReport(
|
|
175
|
+
... symbol="AAPL",
|
|
176
|
+
... source="databento",
|
|
177
|
+
... date_range=(datetime(2024, 1, 1), datetime(2024, 6, 30)),
|
|
178
|
+
... frequency="1min",
|
|
179
|
+
... metrics=DataQualityMetrics(
|
|
180
|
+
... completeness=0.995,
|
|
181
|
+
... timeliness=1.0,
|
|
182
|
+
... accuracy_score=0.99,
|
|
183
|
+
... consistency_score=1.0,
|
|
184
|
+
... n_records=100000,
|
|
185
|
+
... n_anomalies=3,
|
|
186
|
+
... ),
|
|
187
|
+
... anomalies=[],
|
|
188
|
+
... recommendations=["Data quality is excellent"],
|
|
189
|
+
... is_production_ready=True
|
|
190
|
+
... )
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
symbol: str = Field(..., description="Asset symbol")
|
|
194
|
+
source: str = Field(..., description="Data source/provider")
|
|
195
|
+
date_range: tuple[datetime, datetime] = Field(..., description="Data date range")
|
|
196
|
+
frequency: str = Field(..., description="Data frequency (1min, 1d, tick)")
|
|
197
|
+
metrics: DataQualityMetrics = Field(..., description="Quality metrics")
|
|
198
|
+
anomalies: list[DataAnomaly] = Field(default_factory=list, description="Detected anomalies")
|
|
199
|
+
recommendations: list[str] = Field(default_factory=list, description="Recommendations")
|
|
200
|
+
is_production_ready: bool = Field(..., description="Meets production standards")
|
|
201
|
+
created_at: datetime = Field(
|
|
202
|
+
default_factory=datetime.utcnow, description="Report generation time"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def is_acceptable(
|
|
206
|
+
self,
|
|
207
|
+
min_completeness: float = 0.95,
|
|
208
|
+
max_critical: int = 0,
|
|
209
|
+
max_errors: int = 5,
|
|
210
|
+
) -> bool:
|
|
211
|
+
"""Check if data quality meets acceptance criteria.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
min_completeness : float, default 0.95
|
|
216
|
+
Minimum acceptable completeness ratio
|
|
217
|
+
max_critical : int, default 0
|
|
218
|
+
Maximum allowed critical anomalies
|
|
219
|
+
max_errors : int, default 5
|
|
220
|
+
Maximum allowed error anomalies
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
bool
|
|
225
|
+
True if data meets all criteria
|
|
226
|
+
"""
|
|
227
|
+
return (
|
|
228
|
+
self.metrics.completeness >= min_completeness
|
|
229
|
+
and self.metrics.n_critical <= max_critical
|
|
230
|
+
and self.metrics.n_error <= max_errors
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
def summary(self) -> str:
|
|
234
|
+
"""Generate human-readable summary of data quality.
|
|
235
|
+
|
|
236
|
+
Returns
|
|
237
|
+
-------
|
|
238
|
+
str
|
|
239
|
+
Formatted summary string
|
|
240
|
+
"""
|
|
241
|
+
lines = [
|
|
242
|
+
"=" * 50,
|
|
243
|
+
f"Data Quality Report: {self.symbol}",
|
|
244
|
+
"=" * 50,
|
|
245
|
+
"",
|
|
246
|
+
f"Source: {self.source}",
|
|
247
|
+
f"Date range: {self.date_range[0].date()} to {self.date_range[1].date()}",
|
|
248
|
+
f"Frequency: {self.frequency}",
|
|
249
|
+
f"Records: {self.metrics.n_records:,}",
|
|
250
|
+
"",
|
|
251
|
+
"--- Quality Metrics ---",
|
|
252
|
+
f"Completeness: {self.metrics.completeness:.1%}",
|
|
253
|
+
f"Accuracy: {self.metrics.accuracy_score:.1%}",
|
|
254
|
+
f"Consistency: {self.metrics.consistency_score:.1%}",
|
|
255
|
+
"",
|
|
256
|
+
"--- Anomalies ---",
|
|
257
|
+
f"Critical: {self.metrics.n_critical}",
|
|
258
|
+
f"Errors: {self.metrics.n_error}",
|
|
259
|
+
f"Warnings: {self.metrics.n_warning}",
|
|
260
|
+
"",
|
|
261
|
+
f"Production Ready: {'YES' if self.is_production_ready else 'NO'}",
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
if self.recommendations:
|
|
265
|
+
lines.append("")
|
|
266
|
+
lines.append("--- Recommendations ---")
|
|
267
|
+
for rec in self.recommendations:
|
|
268
|
+
lines.append(f" - {rec}")
|
|
269
|
+
|
|
270
|
+
return "\n".join(lines)
|
|
271
|
+
|
|
272
|
+
def to_dict(self) -> dict:
|
|
273
|
+
"""Export to dictionary format.
|
|
274
|
+
|
|
275
|
+
Returns
|
|
276
|
+
-------
|
|
277
|
+
dict
|
|
278
|
+
Dictionary representation suitable for JSON serialization
|
|
279
|
+
"""
|
|
280
|
+
return self.model_dump(mode="json")
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class DataValidationRequest(BaseModel):
|
|
284
|
+
"""Request from ML4T Diagnostic to ML4T Data for validation.
|
|
285
|
+
|
|
286
|
+
Allows ML4T Diagnostic to specify what validation checks are needed.
|
|
287
|
+
ML4T Data can use this to customize the quality report.
|
|
288
|
+
|
|
289
|
+
Attributes:
|
|
290
|
+
symbol: Asset to validate
|
|
291
|
+
date_range: Date range to validate (optional)
|
|
292
|
+
checks: Specific checks to run
|
|
293
|
+
thresholds: Custom thresholds for validation
|
|
294
|
+
include_details: Whether to include detailed anomaly records
|
|
295
|
+
|
|
296
|
+
Example:
|
|
297
|
+
>>> request = DataValidationRequest(
|
|
298
|
+
... symbol="AAPL",
|
|
299
|
+
... checks=["completeness", "price_spikes", "ohlc_validation"],
|
|
300
|
+
... thresholds={"price_spike_std": 5.0},
|
|
301
|
+
... include_details=True
|
|
302
|
+
... )
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
symbol: str = Field(..., description="Asset to validate")
|
|
306
|
+
date_range: tuple[datetime, datetime] | None = Field(
|
|
307
|
+
None, description="Optional date range to validate"
|
|
308
|
+
)
|
|
309
|
+
checks: list[str] = Field(
|
|
310
|
+
default_factory=lambda: ["completeness", "stale_data", "price_spikes", "ohlc_validation"],
|
|
311
|
+
description="Validation checks to run",
|
|
312
|
+
)
|
|
313
|
+
thresholds: dict[str, float] = Field(
|
|
314
|
+
default_factory=dict, description="Custom thresholds for validation checks"
|
|
315
|
+
)
|
|
316
|
+
include_details: bool = Field(default=True, description="Include detailed anomaly records")
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""ML4T Engineer integration contract for preprocessing recommendations.
|
|
2
|
+
|
|
3
|
+
This module defines the API contract between ML4T Diagnostic and ML4T Engineer for feature
|
|
4
|
+
preprocessing recommendations. After evaluating features, ML4T Diagnostic can recommend
|
|
5
|
+
transforms that ML4T Engineer should apply.
|
|
6
|
+
|
|
7
|
+
Example workflow:
|
|
8
|
+
>>> from ml4t.diagnostic.evaluation import FeatureEvaluator
|
|
9
|
+
>>> from ml4t.diagnostic.integration import EngineerConfig
|
|
10
|
+
>>>
|
|
11
|
+
>>> # 1. Evaluate features
|
|
12
|
+
>>> evaluator = FeatureEvaluator(config)
|
|
13
|
+
>>> results = evaluator.evaluate(features_df)
|
|
14
|
+
>>>
|
|
15
|
+
>>> # 2. Get preprocessing recommendations
|
|
16
|
+
>>> eng_config = results.to_engineer_config()
|
|
17
|
+
>>>
|
|
18
|
+
>>> # 3. Export for ML4T Engineer
|
|
19
|
+
>>> preprocessing_dict = eng_config.to_dict()
|
|
20
|
+
>>>
|
|
21
|
+
>>> # 4. Use with ML4T Engineer
|
|
22
|
+
>>> # from ml4t.engineer import PreprocessingPipeline
|
|
23
|
+
>>> # pipeline = PreprocessingPipeline(preprocessing_dict)
|
|
24
|
+
>>> # transformed = pipeline.transform(features_df)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
from enum import Enum
|
|
30
|
+
|
|
31
|
+
from pydantic import BaseModel, Field
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TransformType(str, Enum):
|
|
35
|
+
"""Supported transform types matching ML4T Engineer API.
|
|
36
|
+
|
|
37
|
+
These transforms align with ML4T Engineer's PreprocessingPipeline.
|
|
38
|
+
Each transform addresses specific statistical issues:
|
|
39
|
+
|
|
40
|
+
- NONE: Feature is good as-is
|
|
41
|
+
- LOG: Reduce right skew, stabilize variance
|
|
42
|
+
- SQRT: Reduce right skew (milder than log)
|
|
43
|
+
- STANDARDIZE: Zero mean, unit variance (z-score)
|
|
44
|
+
- NORMALIZE: Scale to [0, 1] range
|
|
45
|
+
- WINSORIZE: Cap outliers at percentiles
|
|
46
|
+
- DIFF: First difference for non-stationary series
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
NONE = "none"
|
|
50
|
+
LOG = "log"
|
|
51
|
+
SQRT = "sqrt"
|
|
52
|
+
STANDARDIZE = "standardize"
|
|
53
|
+
NORMALIZE = "normalize"
|
|
54
|
+
WINSORIZE = "winsorize"
|
|
55
|
+
DIFF = "diff"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class PreprocessingRecommendation(BaseModel):
|
|
59
|
+
"""Recommendation for preprocessing a single feature.
|
|
60
|
+
|
|
61
|
+
ML4T Diagnostic generates these recommendations based on diagnostics:
|
|
62
|
+
- Stationarity tests → recommend differencing
|
|
63
|
+
- Distribution analysis → recommend transforms for skew
|
|
64
|
+
- Outlier detection → recommend winsorization
|
|
65
|
+
- Scale issues → recommend normalization
|
|
66
|
+
|
|
67
|
+
Attributes:
|
|
68
|
+
feature_name: Name of the feature
|
|
69
|
+
transform: Recommended transform type
|
|
70
|
+
reason: Human-readable explanation of why this transform
|
|
71
|
+
confidence: Confidence in recommendation [0.0, 1.0]
|
|
72
|
+
diagnostics: Optional diagnostic details that led to recommendation
|
|
73
|
+
|
|
74
|
+
Example:
|
|
75
|
+
>>> rec = PreprocessingRecommendation(
|
|
76
|
+
... feature_name="returns",
|
|
77
|
+
... transform=TransformType.DIFF,
|
|
78
|
+
... reason="Feature is non-stationary (ADF p=0.82)",
|
|
79
|
+
... confidence=0.95
|
|
80
|
+
... )
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
feature_name: str = Field(..., description="Feature name")
|
|
84
|
+
transform: TransformType = Field(..., description="Recommended transform")
|
|
85
|
+
reason: str = Field(..., description="Explanation for recommendation")
|
|
86
|
+
confidence: float = Field(..., ge=0.0, le=1.0, description="Confidence [0.0, 1.0]")
|
|
87
|
+
diagnostics: dict[str, float] | None = Field(
|
|
88
|
+
None, description="Optional diagnostic values (e.g., {'adf_pvalue': 0.82})"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class EngineerConfig(BaseModel):
|
|
93
|
+
"""Configuration for ML4T Engineer PreprocessingPipeline.
|
|
94
|
+
|
|
95
|
+
This is the output format that ML4T Engineer can consume.
|
|
96
|
+
Contains recommendations for all features that need preprocessing.
|
|
97
|
+
|
|
98
|
+
Attributes:
|
|
99
|
+
recommendations: List of feature preprocessing recommendations
|
|
100
|
+
metadata: Optional metadata about evaluation context
|
|
101
|
+
|
|
102
|
+
Example:
|
|
103
|
+
>>> config = EngineerConfig(recommendations=[
|
|
104
|
+
... PreprocessingRecommendation(
|
|
105
|
+
... feature_name="rsi_14",
|
|
106
|
+
... transform=TransformType.WINSORIZE,
|
|
107
|
+
... reason="Outliers detected at 1st and 99th percentile",
|
|
108
|
+
... confidence=0.85
|
|
109
|
+
... ),
|
|
110
|
+
... PreprocessingRecommendation(
|
|
111
|
+
... feature_name="log_returns",
|
|
112
|
+
... transform=TransformType.NONE,
|
|
113
|
+
... reason="Already stationary and normally distributed",
|
|
114
|
+
... confidence=0.90
|
|
115
|
+
... )
|
|
116
|
+
... ])
|
|
117
|
+
>>> eng_dict = config.to_dict()
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
recommendations: list[PreprocessingRecommendation] = Field(
|
|
121
|
+
..., description="Feature preprocessing recommendations"
|
|
122
|
+
)
|
|
123
|
+
metadata: dict[str, str] | None = Field(
|
|
124
|
+
None, description="Optional metadata (e.g., eval timestamp, config)"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def to_dict(self) -> dict[str, dict[str, str | float | dict[str, float]]]:
|
|
128
|
+
"""Export to ML4T Engineer-compatible format.
|
|
129
|
+
|
|
130
|
+
Returns dictionary mapping feature names to preprocessing configs:
|
|
131
|
+
{
|
|
132
|
+
"feature_name": {
|
|
133
|
+
"transform": "diff",
|
|
134
|
+
"reason": "Non-stationary",
|
|
135
|
+
"confidence": 0.95,
|
|
136
|
+
"diagnostics": {...}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Dictionary in ML4T Engineer PreprocessingPipeline format
|
|
142
|
+
|
|
143
|
+
Example:
|
|
144
|
+
>>> config.to_dict()
|
|
145
|
+
{
|
|
146
|
+
'rsi_14': {
|
|
147
|
+
'transform': 'winsorize',
|
|
148
|
+
'reason': 'Outliers detected',
|
|
149
|
+
'confidence': 0.85
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
"""
|
|
153
|
+
result: dict[str, dict[str, str | float | dict[str, float]]] = {}
|
|
154
|
+
for rec in self.recommendations:
|
|
155
|
+
feature_dict: dict[str, str | float | dict[str, float]] = {
|
|
156
|
+
"transform": rec.transform.value,
|
|
157
|
+
"reason": rec.reason,
|
|
158
|
+
"confidence": rec.confidence,
|
|
159
|
+
}
|
|
160
|
+
if rec.diagnostics:
|
|
161
|
+
feature_dict["diagnostics"] = rec.diagnostics
|
|
162
|
+
result[rec.feature_name] = feature_dict
|
|
163
|
+
return result
|
|
164
|
+
|
|
165
|
+
def get_recommendations_by_transform(
|
|
166
|
+
self, transform: TransformType
|
|
167
|
+
) -> list[PreprocessingRecommendation]:
|
|
168
|
+
"""Filter recommendations by transform type.
|
|
169
|
+
|
|
170
|
+
Useful for analyzing patterns in recommendations:
|
|
171
|
+
- How many features need differencing?
|
|
172
|
+
- Which features can stay unchanged?
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
transform: Transform type to filter by
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
List of recommendations with matching transform
|
|
179
|
+
|
|
180
|
+
Example:
|
|
181
|
+
>>> config.get_recommendations_by_transform(TransformType.DIFF)
|
|
182
|
+
[PreprocessingRecommendation(feature_name='returns', ...)]
|
|
183
|
+
"""
|
|
184
|
+
return [rec for rec in self.recommendations if rec.transform == transform]
|
|
185
|
+
|
|
186
|
+
def summary(self) -> str:
|
|
187
|
+
"""Human-readable summary of recommendations.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Formatted summary string
|
|
191
|
+
|
|
192
|
+
Example:
|
|
193
|
+
>>> print(config.summary())
|
|
194
|
+
ML4T Engineer Preprocessing Recommendations
|
|
195
|
+
==========================================
|
|
196
|
+
Total features: 5
|
|
197
|
+
- DIFF: 2 features
|
|
198
|
+
- WINSORIZE: 1 feature
|
|
199
|
+
- NONE: 2 features
|
|
200
|
+
"""
|
|
201
|
+
lines = ["ML4T Engineer Preprocessing Recommendations", "=" * 44]
|
|
202
|
+
lines.append(f"Total features: {len(self.recommendations)}")
|
|
203
|
+
lines.append("")
|
|
204
|
+
|
|
205
|
+
# Count by transform type
|
|
206
|
+
transform_counts: dict[TransformType, int] = {}
|
|
207
|
+
for rec in self.recommendations:
|
|
208
|
+
transform_counts[rec.transform] = transform_counts.get(rec.transform, 0) + 1
|
|
209
|
+
|
|
210
|
+
# Sort by count (descending)
|
|
211
|
+
for transform, count in sorted(transform_counts.items(), key=lambda x: x[1], reverse=True):
|
|
212
|
+
lines.append(f" {transform.value.upper()}: {count} features")
|
|
213
|
+
|
|
214
|
+
# Show high-confidence recommendations
|
|
215
|
+
high_conf = [rec for rec in self.recommendations if rec.confidence >= 0.9]
|
|
216
|
+
if high_conf:
|
|
217
|
+
lines.append("")
|
|
218
|
+
lines.append(f"High-confidence recommendations (≥0.9): {len(high_conf)}")
|
|
219
|
+
for rec in high_conf[:5]: # Show top 5
|
|
220
|
+
lines.append(
|
|
221
|
+
f" {rec.feature_name}: {rec.transform.value} (conf={rec.confidence:.2f})"
|
|
222
|
+
)
|
|
223
|
+
if len(high_conf) > 5:
|
|
224
|
+
lines.append(f" ... and {len(high_conf) - 5} more")
|
|
225
|
+
|
|
226
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ML4T Diagnostic Logging and Debugging Infrastructure
|
|
3
|
+
|
|
4
|
+
Provides structured logging with levels, progress tracking, debug mode,
|
|
5
|
+
and performance metrics for ML4T Diagnostic library operations.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Structured JSON logging
|
|
9
|
+
- Configurable log levels (DEBUG, INFO, WARNING, ERROR)
|
|
10
|
+
- Progress indicators for long-running operations
|
|
11
|
+
- Debug mode for intermediate results
|
|
12
|
+
- Performance metrics tracking
|
|
13
|
+
- Context-aware logging
|
|
14
|
+
- Weights & Biases integration
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
>>> from ml4t.diagnostic.logging import get_logger, set_log_level, LogLevel
|
|
18
|
+
>>> logger = get_logger(__name__)
|
|
19
|
+
>>> set_log_level(LogLevel.DEBUG)
|
|
20
|
+
>>> logger.info("Computing Sharpe ratio", n_samples=100)
|
|
21
|
+
>>> with logger.timed("sharpe_computation"):
|
|
22
|
+
... sharpe = compute_sharpe_ratio(returns)
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Structured logging
|
|
26
|
+
from ml4t.diagnostic.logging.logger import (
|
|
27
|
+
LogLevel,
|
|
28
|
+
QEvalLogger,
|
|
29
|
+
configure_logging,
|
|
30
|
+
get_log_level,
|
|
31
|
+
get_logger,
|
|
32
|
+
set_log_level,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Performance metrics
|
|
36
|
+
from ml4t.diagnostic.logging.performance import (
|
|
37
|
+
PerformanceMonitor,
|
|
38
|
+
PerformanceTracker,
|
|
39
|
+
get_performance_monitor,
|
|
40
|
+
measure_time,
|
|
41
|
+
timed,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Progress tracking
|
|
45
|
+
from ml4t.diagnostic.logging.progress import (
|
|
46
|
+
ProgressBar,
|
|
47
|
+
ProgressTracker,
|
|
48
|
+
progress_indicator,
|
|
49
|
+
spinner,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Experiment tracking (Weights & Biases)
|
|
53
|
+
from ml4t.diagnostic.logging.wandb import WandbLogger, log_experiment
|
|
54
|
+
|
|
55
|
+
__all__: list[str] = [
|
|
56
|
+
# Logger
|
|
57
|
+
"QEvalLogger",
|
|
58
|
+
"get_logger",
|
|
59
|
+
"set_log_level",
|
|
60
|
+
"get_log_level",
|
|
61
|
+
"configure_logging",
|
|
62
|
+
"LogLevel",
|
|
63
|
+
# Progress
|
|
64
|
+
"ProgressBar",
|
|
65
|
+
"progress_indicator",
|
|
66
|
+
"ProgressTracker",
|
|
67
|
+
"spinner",
|
|
68
|
+
# Performance
|
|
69
|
+
"PerformanceTracker",
|
|
70
|
+
"PerformanceMonitor",
|
|
71
|
+
"get_performance_monitor",
|
|
72
|
+
"timed",
|
|
73
|
+
"measure_time",
|
|
74
|
+
# WandB
|
|
75
|
+
"WandbLogger",
|
|
76
|
+
"log_experiment",
|
|
77
|
+
]
|