mcli-framework 7.12.2__py3-none-any.whl → 7.12.4__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.

Potentially problematic release.


This version of mcli-framework might be problematic. Click here for more details.

Files changed (216) hide show
  1. mcli/app/__init__.py +0 -2
  2. mcli/app/commands_cmd.py +30 -26
  3. mcli/app/completion_helpers.py +5 -5
  4. mcli/app/init_cmd.py +10 -10
  5. mcli/app/lock_cmd.py +29 -24
  6. mcli/app/main.py +2 -8
  7. mcli/app/model/model.py +5 -10
  8. mcli/app/store_cmd.py +8 -8
  9. mcli/app/video/__init__.py +0 -2
  10. mcli/app/video/video.py +1 -14
  11. mcli/chat/chat.py +90 -108
  12. mcli/chat/command_rag.py +0 -4
  13. mcli/chat/enhanced_chat.py +32 -41
  14. mcli/chat/system_controller.py +37 -37
  15. mcli/chat/system_integration.py +4 -5
  16. mcli/cli.py +2 -3
  17. mcli/lib/api/api.py +4 -9
  18. mcli/lib/api/daemon_client.py +19 -20
  19. mcli/lib/api/daemon_client_local.py +1 -3
  20. mcli/lib/api/daemon_decorator.py +6 -6
  21. mcli/lib/api/mcli_decorators.py +4 -8
  22. mcli/lib/auth/__init__.py +0 -1
  23. mcli/lib/auth/auth.py +4 -5
  24. mcli/lib/auth/mcli_manager.py +7 -12
  25. mcli/lib/auth/token_util.py +5 -5
  26. mcli/lib/config/__init__.py +29 -1
  27. mcli/lib/config/config.py +0 -1
  28. mcli/lib/custom_commands.py +1 -1
  29. mcli/lib/discovery/command_discovery.py +15 -15
  30. mcli/lib/erd/erd.py +7 -7
  31. mcli/lib/files/files.py +1 -1
  32. mcli/lib/fs/__init__.py +31 -1
  33. mcli/lib/fs/fs.py +12 -13
  34. mcli/lib/lib.py +0 -1
  35. mcli/lib/logger/logger.py +7 -10
  36. mcli/lib/performance/optimizer.py +25 -27
  37. mcli/lib/performance/rust_bridge.py +22 -27
  38. mcli/lib/performance/uvloop_config.py +0 -1
  39. mcli/lib/pickles/__init__.py +0 -1
  40. mcli/lib/pickles/pickles.py +0 -2
  41. mcli/lib/secrets/commands.py +0 -2
  42. mcli/lib/secrets/manager.py +0 -1
  43. mcli/lib/secrets/repl.py +2 -3
  44. mcli/lib/secrets/store.py +1 -2
  45. mcli/lib/services/data_pipeline.py +34 -34
  46. mcli/lib/services/lsh_client.py +38 -40
  47. mcli/lib/shell/shell.py +2 -2
  48. mcli/lib/toml/__init__.py +0 -1
  49. mcli/lib/ui/styling.py +0 -1
  50. mcli/lib/ui/visual_effects.py +33 -41
  51. mcli/lib/watcher/watcher.py +0 -1
  52. mcli/ml/__init__.py +1 -1
  53. mcli/ml/api/__init__.py +1 -1
  54. mcli/ml/api/app.py +8 -9
  55. mcli/ml/api/middleware.py +10 -10
  56. mcli/ml/api/routers/__init__.py +1 -1
  57. mcli/ml/api/routers/admin_router.py +3 -3
  58. mcli/ml/api/routers/auth_router.py +17 -18
  59. mcli/ml/api/routers/backtest_router.py +2 -2
  60. mcli/ml/api/routers/data_router.py +2 -2
  61. mcli/ml/api/routers/model_router.py +14 -15
  62. mcli/ml/api/routers/monitoring_router.py +2 -2
  63. mcli/ml/api/routers/portfolio_router.py +2 -2
  64. mcli/ml/api/routers/prediction_router.py +10 -9
  65. mcli/ml/api/routers/trade_router.py +2 -2
  66. mcli/ml/api/routers/websocket_router.py +6 -7
  67. mcli/ml/api/schemas.py +2 -2
  68. mcli/ml/auth/__init__.py +1 -1
  69. mcli/ml/auth/auth_manager.py +22 -23
  70. mcli/ml/auth/models.py +17 -17
  71. mcli/ml/auth/permissions.py +17 -17
  72. mcli/ml/backtesting/__init__.py +1 -1
  73. mcli/ml/backtesting/backtest_engine.py +31 -35
  74. mcli/ml/backtesting/performance_metrics.py +12 -14
  75. mcli/ml/backtesting/run.py +1 -2
  76. mcli/ml/cache.py +35 -36
  77. mcli/ml/cli/__init__.py +1 -1
  78. mcli/ml/cli/main.py +21 -24
  79. mcli/ml/config/__init__.py +1 -1
  80. mcli/ml/config/settings.py +28 -29
  81. mcli/ml/configs/__init__.py +1 -1
  82. mcli/ml/configs/dvc_config.py +14 -15
  83. mcli/ml/configs/mlflow_config.py +12 -13
  84. mcli/ml/configs/mlops_manager.py +19 -21
  85. mcli/ml/dashboard/__init__.py +4 -4
  86. mcli/ml/dashboard/app.py +20 -30
  87. mcli/ml/dashboard/app_supabase.py +16 -19
  88. mcli/ml/dashboard/app_training.py +11 -14
  89. mcli/ml/dashboard/cli.py +2 -2
  90. mcli/ml/dashboard/common.py +2 -3
  91. mcli/ml/dashboard/components/__init__.py +1 -1
  92. mcli/ml/dashboard/components/charts.py +13 -11
  93. mcli/ml/dashboard/components/metrics.py +7 -7
  94. mcli/ml/dashboard/components/tables.py +12 -9
  95. mcli/ml/dashboard/overview.py +2 -2
  96. mcli/ml/dashboard/pages/__init__.py +1 -1
  97. mcli/ml/dashboard/pages/cicd.py +15 -18
  98. mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
  99. mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
  100. mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
  101. mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
  102. mcli/ml/dashboard/pages/test_portfolio.py +3 -6
  103. mcli/ml/dashboard/pages/trading.py +16 -18
  104. mcli/ml/dashboard/pages/workflows.py +20 -30
  105. mcli/ml/dashboard/utils.py +9 -9
  106. mcli/ml/dashboard/warning_suppression.py +3 -3
  107. mcli/ml/data_ingestion/__init__.py +1 -1
  108. mcli/ml/data_ingestion/api_connectors.py +41 -46
  109. mcli/ml/data_ingestion/data_pipeline.py +36 -46
  110. mcli/ml/data_ingestion/stream_processor.py +43 -46
  111. mcli/ml/database/__init__.py +1 -1
  112. mcli/ml/database/migrations/env.py +2 -2
  113. mcli/ml/database/models.py +22 -24
  114. mcli/ml/database/session.py +14 -14
  115. mcli/ml/experimentation/__init__.py +1 -1
  116. mcli/ml/experimentation/ab_testing.py +45 -46
  117. mcli/ml/features/__init__.py +1 -1
  118. mcli/ml/features/ensemble_features.py +22 -27
  119. mcli/ml/features/recommendation_engine.py +30 -30
  120. mcli/ml/features/stock_features.py +29 -32
  121. mcli/ml/features/test_feature_engineering.py +10 -11
  122. mcli/ml/logging.py +4 -4
  123. mcli/ml/mlops/__init__.py +1 -1
  124. mcli/ml/mlops/data_versioning.py +29 -30
  125. mcli/ml/mlops/experiment_tracker.py +24 -24
  126. mcli/ml/mlops/model_serving.py +31 -34
  127. mcli/ml/mlops/pipeline_orchestrator.py +27 -35
  128. mcli/ml/models/__init__.py +5 -6
  129. mcli/ml/models/base_models.py +23 -23
  130. mcli/ml/models/ensemble_models.py +31 -31
  131. mcli/ml/models/recommendation_models.py +18 -19
  132. mcli/ml/models/test_models.py +14 -16
  133. mcli/ml/monitoring/__init__.py +1 -1
  134. mcli/ml/monitoring/drift_detection.py +32 -36
  135. mcli/ml/monitoring/metrics.py +2 -2
  136. mcli/ml/optimization/__init__.py +1 -1
  137. mcli/ml/optimization/optimize.py +1 -2
  138. mcli/ml/optimization/portfolio_optimizer.py +30 -32
  139. mcli/ml/predictions/__init__.py +1 -1
  140. mcli/ml/preprocessing/__init__.py +1 -1
  141. mcli/ml/preprocessing/data_cleaners.py +22 -23
  142. mcli/ml/preprocessing/feature_extractors.py +23 -26
  143. mcli/ml/preprocessing/ml_pipeline.py +23 -23
  144. mcli/ml/preprocessing/test_preprocessing.py +7 -8
  145. mcli/ml/scripts/populate_sample_data.py +0 -4
  146. mcli/ml/serving/serve.py +1 -2
  147. mcli/ml/tasks.py +17 -17
  148. mcli/ml/tests/test_integration.py +29 -30
  149. mcli/ml/tests/test_training_dashboard.py +21 -21
  150. mcli/ml/trading/__init__.py +1 -1
  151. mcli/ml/trading/migrations.py +5 -5
  152. mcli/ml/trading/models.py +21 -23
  153. mcli/ml/trading/paper_trading.py +16 -13
  154. mcli/ml/trading/risk_management.py +17 -18
  155. mcli/ml/trading/trading_service.py +25 -28
  156. mcli/ml/training/__init__.py +1 -1
  157. mcli/ml/training/train.py +0 -1
  158. mcli/public/oi/oi.py +1 -2
  159. mcli/self/completion_cmd.py +6 -10
  160. mcli/self/logs_cmd.py +19 -24
  161. mcli/self/migrate_cmd.py +22 -20
  162. mcli/self/redis_cmd.py +10 -11
  163. mcli/self/self_cmd.py +10 -18
  164. mcli/self/store_cmd.py +10 -12
  165. mcli/self/visual_cmd.py +9 -14
  166. mcli/self/zsh_cmd.py +2 -4
  167. mcli/workflow/daemon/async_command_database.py +23 -24
  168. mcli/workflow/daemon/async_process_manager.py +27 -29
  169. mcli/workflow/daemon/client.py +27 -33
  170. mcli/workflow/daemon/daemon.py +32 -36
  171. mcli/workflow/daemon/enhanced_daemon.py +24 -33
  172. mcli/workflow/daemon/process_cli.py +11 -12
  173. mcli/workflow/daemon/process_manager.py +23 -26
  174. mcli/workflow/daemon/test_daemon.py +4 -5
  175. mcli/workflow/dashboard/dashboard_cmd.py +0 -1
  176. mcli/workflow/doc_convert.py +15 -17
  177. mcli/workflow/gcloud/__init__.py +0 -1
  178. mcli/workflow/gcloud/gcloud.py +11 -8
  179. mcli/workflow/git_commit/ai_service.py +14 -15
  180. mcli/workflow/lsh_integration.py +9 -11
  181. mcli/workflow/model_service/client.py +26 -31
  182. mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
  183. mcli/workflow/model_service/lightweight_embedder.py +25 -35
  184. mcli/workflow/model_service/lightweight_model_server.py +26 -32
  185. mcli/workflow/model_service/lightweight_test.py +7 -10
  186. mcli/workflow/model_service/model_service.py +80 -91
  187. mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
  188. mcli/workflow/model_service/openai_adapter.py +23 -23
  189. mcli/workflow/model_service/pdf_processor.py +21 -26
  190. mcli/workflow/model_service/test_efficient_runner.py +12 -16
  191. mcli/workflow/model_service/test_example.py +11 -13
  192. mcli/workflow/model_service/test_integration.py +3 -5
  193. mcli/workflow/model_service/test_new_features.py +7 -8
  194. mcli/workflow/notebook/converter.py +1 -1
  195. mcli/workflow/notebook/notebook_cmd.py +5 -6
  196. mcli/workflow/notebook/schema.py +0 -1
  197. mcli/workflow/notebook/validator.py +7 -3
  198. mcli/workflow/openai/openai.py +1 -2
  199. mcli/workflow/registry/registry.py +4 -1
  200. mcli/workflow/repo/repo.py +6 -7
  201. mcli/workflow/scheduler/cron_parser.py +16 -19
  202. mcli/workflow/scheduler/job.py +10 -10
  203. mcli/workflow/scheduler/monitor.py +15 -15
  204. mcli/workflow/scheduler/persistence.py +17 -18
  205. mcli/workflow/scheduler/scheduler.py +37 -38
  206. mcli/workflow/secrets/__init__.py +1 -1
  207. mcli/workflow/sync/test_cmd.py +0 -1
  208. mcli/workflow/wakatime/__init__.py +5 -9
  209. mcli/workflow/wakatime/wakatime.py +1 -2
  210. {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/METADATA +1 -1
  211. mcli_framework-7.12.4.dist-info/RECORD +279 -0
  212. mcli_framework-7.12.2.dist-info/RECORD +0 -279
  213. {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/WHEEL +0 -0
  214. {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/entry_points.txt +0 -0
  215. {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/licenses/LICENSE +0 -0
  216. {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- """Test script for ensemble models"""
1
+ """Test script for ensemble models."""
2
2
 
3
3
  import os
4
4
  import sys
@@ -6,7 +6,6 @@ import sys
6
6
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../.."))
7
7
 
8
8
  import logging
9
- from datetime import datetime, timedelta
10
9
 
11
10
  import numpy as np
12
11
  import pandas as pd
@@ -18,7 +17,7 @@ logger = logging.getLogger(__name__)
18
17
 
19
18
 
20
19
  def generate_mock_features(n_samples: int = 500, n_features: int = 150) -> pd.DataFrame:
21
- """Generate mock feature data for testing"""
20
+ """Generate mock feature data for testing."""
22
21
  np.random.seed(42)
23
22
 
24
23
  # Create realistic feature names
@@ -50,7 +49,7 @@ def generate_mock_features(n_samples: int = 500, n_features: int = 150) -> pd.Da
50
49
 
51
50
  # Generate correlated features that simulate real market data
52
51
  features = []
53
- for i in range(n_samples):
52
+ for _i in range(n_samples):
54
53
  # Base market trend
55
54
  market_trend = np.random.normal(0, 1)
56
55
 
@@ -85,7 +84,7 @@ def generate_mock_features(n_samples: int = 500, n_features: int = 150) -> pd.Da
85
84
 
86
85
 
87
86
  def generate_mock_targets(n_samples: int) -> tuple:
88
- """Generate realistic target variables"""
87
+ """Generate realistic target variables."""
89
88
  np.random.seed(42)
90
89
 
91
90
  # Generate correlated targets
@@ -104,7 +103,7 @@ def generate_mock_targets(n_samples: int) -> tuple:
104
103
 
105
104
 
106
105
  def test_base_models():
107
- """Test base model functionality"""
106
+ """Test base model functionality."""
108
107
  logger.info("Testing base models...")
109
108
 
110
109
  from base_models import MLPBaseModel, ResNetModel
@@ -122,7 +121,7 @@ def test_base_models():
122
121
  logger.info(f"MLP output shape: {output.shape}")
123
122
 
124
123
  # Test prediction
125
- probas = mlp_model.predict_proba(X)
124
+ mlp_model.predict_proba(X)
126
125
  predictions = mlp_model.predict(X)
127
126
  logger.info(f"MLP predictions shape: {predictions.shape}")
128
127
 
@@ -140,7 +139,7 @@ def test_base_models():
140
139
 
141
140
 
142
141
  def test_ensemble_models():
143
- """Test ensemble model functionality"""
142
+ """Test ensemble model functionality."""
144
143
  logger.info("Testing ensemble models...")
145
144
 
146
145
  from ensemble_models import (
@@ -233,7 +232,7 @@ def test_ensemble_models():
233
232
  logger.info(f"Individual predictions: {len(individual_preds)} models")
234
233
 
235
234
  # Test prediction methods
236
- ensemble_probas = ensemble_model.predict_proba(X.values[:20])
235
+ _ensemble_probas = ensemble_model.predict_proba(X.values[:20]) # noqa: F841
237
236
  ensemble_preds = ensemble_model.predict(X.values[:20])
238
237
  logger.info(f"Ensemble predictions shape: {ensemble_preds.shape}")
239
238
 
@@ -241,14 +240,13 @@ def test_ensemble_models():
241
240
 
242
241
 
243
242
  def test_recommendation_model():
244
- """Test recommendation model"""
243
+ """Test recommendation model."""
245
244
  logger.info("Testing recommendation model...")
246
245
 
247
246
  from ensemble_models import EnsembleConfig, ModelConfig
248
247
  from recommendation_models import (
249
248
  PortfolioRecommendation,
250
249
  RecommendationConfig,
251
- RecommendationTrainer,
252
250
  StockRecommendationModel,
253
251
  )
254
252
 
@@ -329,7 +327,7 @@ def test_recommendation_model():
329
327
 
330
328
 
331
329
  def test_model_training():
332
- """Test model training functionality"""
330
+ """Test model training functionality."""
333
331
  logger.info("Testing model training...")
334
332
 
335
333
  from ensemble_models import EnsembleConfig, EnsembleTrainer, ModelConfig
@@ -376,7 +374,7 @@ def test_model_training():
376
374
  logger.info("Training ensemble model...")
377
375
  ensemble_result = ensemble_trainer.train(X_train.values, y_train, X_val.values, y_val)
378
376
 
379
- logger.info(f"Ensemble training metrics:")
377
+ logger.info("Ensemble training metrics:")
380
378
  logger.info(f" Train accuracy: {ensemble_result.train_metrics.accuracy:.3f}")
381
379
  logger.info(f" Val accuracy: {ensemble_result.val_metrics.accuracy:.3f}")
382
380
 
@@ -398,7 +396,7 @@ def test_model_training():
398
396
  batch_size=32,
399
397
  )
400
398
 
401
- logger.info(f"Recommendation training metrics:")
399
+ logger.info("Recommendation training metrics:")
402
400
  logger.info(f" Train accuracy: {rec_result.train_metrics.accuracy:.3f}")
403
401
  logger.info(f" Val accuracy: {rec_result.val_metrics.accuracy:.3f}")
404
402
 
@@ -413,7 +411,7 @@ def test_model_training():
413
411
 
414
412
 
415
413
  def test_model_persistence():
416
- """Test model saving and loading"""
414
+ """Test model saving and loading."""
417
415
  logger.info("Testing model persistence...")
418
416
 
419
417
  import tempfile
@@ -450,7 +448,7 @@ def test_model_persistence():
450
448
 
451
449
 
452
450
  def main():
453
- """Run all model tests"""
451
+ """Run all model tests."""
454
452
  logger.info("Starting ensemble model tests...")
455
453
 
456
454
  try:
@@ -1,4 +1,4 @@
1
- """ML Model Monitoring and Drift Detection"""
1
+ """ML Model Monitoring and Drift Detection."""
2
2
 
3
3
  from .drift_detection import (
4
4
  AlertSeverity,
@@ -1,22 +1,18 @@
1
- """Model monitoring and drift detection for ML systems"""
1
+ """Model monitoring and drift detection for ML systems."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  import logging
6
5
  import pickle
7
- import warnings
8
6
  from dataclasses import asdict, dataclass, field
9
7
  from datetime import datetime, timedelta
10
8
  from enum import Enum
11
9
  from pathlib import Path
12
- from typing import Any, Callable, Dict, List, Optional, Tuple, Union
10
+ from typing import Any, Callable, Dict, List, Optional
13
11
 
14
12
  import numpy as np
15
13
  import pandas as pd
16
- from scipy import stats
17
14
  from sklearn.ensemble import IsolationForest
18
15
  from sklearn.metrics import ks_2samp
19
- from sklearn.model_selection import train_test_split
20
16
 
21
17
  logger = logging.getLogger(__name__)
22
18
 
@@ -37,7 +33,7 @@ class AlertSeverity(Enum):
37
33
 
38
34
  @dataclass
39
35
  class DriftAlert:
40
- """Drift detection alert"""
36
+ """Drift detection alert."""
41
37
 
42
38
  timestamp: datetime
43
39
  drift_type: DriftType
@@ -51,7 +47,7 @@ class DriftAlert:
51
47
 
52
48
  @dataclass
53
49
  class ModelMetrics:
54
- """Model performance metrics"""
50
+ """Model performance metrics."""
55
51
 
56
52
  timestamp: datetime
57
53
  accuracy: float
@@ -67,7 +63,7 @@ class ModelMetrics:
67
63
 
68
64
  @dataclass
69
65
  class DataProfile:
70
- """Statistical profile of data"""
66
+ """Statistical profile of data."""
71
67
 
72
68
  feature_means: Dict[str, float]
73
69
  feature_stds: Dict[str, float]
@@ -79,7 +75,7 @@ class DataProfile:
79
75
 
80
76
 
81
77
  class StatisticalDriftDetector:
82
- """Detect statistical drift in data distributions"""
78
+ """Detect statistical drift in data distributions."""
83
79
 
84
80
  def __init__(
85
81
  self, reference_data: pd.DataFrame, significance_level: float = 0.05, min_samples: int = 100
@@ -90,7 +86,7 @@ class StatisticalDriftDetector:
90
86
  self.min_samples = min_samples
91
87
 
92
88
  def detect_drift(self, current_data: pd.DataFrame) -> Dict[str, Any]:
93
- """Detect drift between reference and current data"""
89
+ """Detect drift between reference and current data."""
94
90
  if len(current_data) < self.min_samples:
95
91
  return {"drift_detected": False, "message": "Insufficient samples"}
96
92
 
@@ -138,7 +134,7 @@ class StatisticalDriftDetector:
138
134
  return drift_results
139
135
 
140
136
  def _create_data_profile(self, data: pd.DataFrame) -> DataProfile:
141
- """Create statistical profile of data"""
137
+ """Create statistical profile of data."""
142
138
  numeric_data = data.select_dtypes(include=[np.number])
143
139
 
144
140
  return DataProfile(
@@ -156,7 +152,7 @@ class StatisticalDriftDetector:
156
152
  def _calculate_psi(
157
153
  self, reference_data: pd.DataFrame, current_data: pd.DataFrame
158
154
  ) -> Dict[str, float]:
159
- """Calculate Population Stability Index for each feature"""
155
+ """Calculate Population Stability Index for each feature."""
160
156
  psi_scores = {}
161
157
 
162
158
  for feature in reference_data.columns:
@@ -173,7 +169,7 @@ class StatisticalDriftDetector:
173
169
  return psi_scores
174
170
 
175
171
  def _psi_score(self, reference: pd.Series, current: pd.Series, bins: int = 10) -> float:
176
- """Calculate PSI score between two distributions"""
172
+ """Calculate PSI score between two distributions."""
177
173
  try:
178
174
  # Create bins based on reference data
179
175
  ref_min, ref_max = reference.min(), reference.max()
@@ -203,7 +199,7 @@ class StatisticalDriftDetector:
203
199
  def _compare_feature_distributions(
204
200
  self, ref_profile: DataProfile, curr_profile: DataProfile
205
201
  ) -> Dict[str, Dict[str, float]]:
206
- """Compare feature distributions between profiles"""
202
+ """Compare feature distributions between profiles."""
207
203
  comparisons = {}
208
204
 
209
205
  for feature in ref_profile.feature_means.keys():
@@ -231,7 +227,7 @@ class StatisticalDriftDetector:
231
227
 
232
228
 
233
229
  class ConceptDriftDetector:
234
- """Detect concept drift in model predictions"""
230
+ """Detect concept drift in model predictions."""
235
231
 
236
232
  def __init__(self, window_size: int = 1000, detection_threshold: float = 0.05):
237
233
  self.window_size = window_size
@@ -239,7 +235,7 @@ class ConceptDriftDetector:
239
235
  self.historical_metrics = []
240
236
 
241
237
  def add_batch_metrics(self, metrics: ModelMetrics):
242
- """Add batch metrics for drift detection"""
238
+ """Add batch metrics for drift detection."""
243
239
  self.historical_metrics.append(metrics)
244
240
 
245
241
  # Keep only recent metrics
@@ -247,7 +243,7 @@ class ConceptDriftDetector:
247
243
  self.historical_metrics = self.historical_metrics[-self.window_size :]
248
244
 
249
245
  def detect_concept_drift(self) -> Dict[str, Any]:
250
- """Detect concept drift using model performance degradation"""
246
+ """Detect concept drift using model performance degradation."""
251
247
  if len(self.historical_metrics) < self.window_size:
252
248
  return {"drift_detected": False, "message": "Insufficient historical data"}
253
249
 
@@ -292,7 +288,7 @@ class ConceptDriftDetector:
292
288
  }
293
289
 
294
290
  def _calculate_average_performance(self, metrics_list: List[ModelMetrics]) -> Dict[str, float]:
295
- """Calculate average performance metrics"""
291
+ """Calculate average performance metrics."""
296
292
  if not metrics_list:
297
293
  return {}
298
294
 
@@ -312,7 +308,7 @@ class ConceptDriftDetector:
312
308
 
313
309
 
314
310
  class OutlierDetector:
315
- """Detect outliers in incoming data"""
311
+ """Detect outliers in incoming data."""
316
312
 
317
313
  def __init__(self, contamination: float = 0.1):
318
314
  self.contamination = contamination
@@ -320,7 +316,7 @@ class OutlierDetector:
320
316
  self.is_fitted = False
321
317
 
322
318
  def fit(self, reference_data: pd.DataFrame):
323
- """Fit outlier detector on reference data"""
319
+ """Fit outlier detector on reference data."""
324
320
  numeric_data = reference_data.select_dtypes(include=[np.number])
325
321
 
326
322
  if numeric_data.empty:
@@ -332,7 +328,7 @@ class OutlierDetector:
332
328
  self.is_fitted = True
333
329
 
334
330
  def detect_outliers(self, data: pd.DataFrame) -> Dict[str, Any]:
335
- """Detect outliers in new data"""
331
+ """Detect outliers in new data."""
336
332
  if not self.is_fitted:
337
333
  return {"outliers_detected": False, "message": "Detector not fitted"}
338
334
 
@@ -358,7 +354,7 @@ class OutlierDetector:
358
354
 
359
355
 
360
356
  class ModelMonitor:
361
- """Comprehensive model monitoring system"""
357
+ """Comprehensive model monitoring system."""
362
358
 
363
359
  def __init__(self, model_name: str, storage_path: Path = Path("monitoring")):
364
360
  self.model_name = model_name
@@ -385,7 +381,7 @@ class ModelMonitor:
385
381
  self.monitoring_history = []
386
382
 
387
383
  def setup_reference_data(self, reference_data: pd.DataFrame):
388
- """Set up reference data for drift detection"""
384
+ """Set up reference data for drift detection."""
389
385
  self.statistical_detector = StatisticalDriftDetector(reference_data)
390
386
  self.outlier_detector.fit(reference_data)
391
387
 
@@ -398,7 +394,7 @@ class ModelMonitor:
398
394
  predictions: np.ndarray,
399
395
  true_labels: Optional[np.ndarray] = None,
400
396
  ) -> Dict[str, Any]:
401
- """Monitor a batch of data and predictions"""
397
+ """Monitor a batch of data and predictions."""
402
398
  monitoring_result = {
403
399
  "timestamp": datetime.now(),
404
400
  "batch_size": len(current_data),
@@ -480,11 +476,11 @@ class ModelMonitor:
480
476
  return monitoring_result
481
477
 
482
478
  def add_alert_handler(self, handler: Callable[[DriftAlert], None]):
483
- """Add alert handler function"""
479
+ """Add alert handler function."""
484
480
  self.alert_handlers.append(handler)
485
481
 
486
482
  def get_monitoring_summary(self, days: int = 7) -> Dict[str, Any]:
487
- """Get monitoring summary for the last N days"""
483
+ """Get monitoring summary for the last N days."""
488
484
  cutoff_date = datetime.now() - timedelta(days=days)
489
485
  recent_results = [
490
486
  result for result in self.monitoring_history if result["timestamp"] >= cutoff_date
@@ -521,7 +517,7 @@ class ModelMonitor:
521
517
  }
522
518
 
523
519
  def _analyze_predictions(self, predictions: np.ndarray) -> Dict[str, Any]:
524
- """Analyze prediction distribution"""
520
+ """Analyze prediction distribution."""
525
521
  return {
526
522
  "mean": float(np.mean(predictions)),
527
523
  "std": float(np.std(predictions)),
@@ -533,7 +529,7 @@ class ModelMonitor:
533
529
  def _calculate_performance_metrics(
534
530
  self, predictions: np.ndarray, true_labels: np.ndarray
535
531
  ) -> ModelMetrics:
536
- """Calculate model performance metrics"""
532
+ """Calculate model performance metrics."""
537
533
  # Convert to binary if needed
538
534
  if len(np.unique(true_labels)) == 2:
539
535
  # Binary classification
@@ -575,7 +571,7 @@ class ModelMonitor:
575
571
  )
576
572
 
577
573
  def _handle_alert(self, alert: DriftAlert):
578
- """Handle drift alert"""
574
+ """Handle drift alert."""
579
575
  logger.warning(
580
576
  f"DRIFT ALERT: {alert.description} "
581
577
  f"(Type: {alert.drift_type.value}, Severity: {alert.severity.value})"
@@ -589,7 +585,7 @@ class ModelMonitor:
589
585
  logger.error(f"Alert handler failed: {e}")
590
586
 
591
587
  def _save_monitoring_result(self, result: Dict[str, Any]):
592
- """Save monitoring result to storage"""
588
+ """Save monitoring result to storage."""
593
589
  timestamp_str = result["timestamp"].strftime("%Y%m%d_%H%M%S")
594
590
  filename = self.storage_path / f"monitoring_{timestamp_str}.json"
595
591
 
@@ -606,14 +602,14 @@ class ModelMonitor:
606
602
  self.monitoring_history = self.monitoring_history[-500:]
607
603
 
608
604
  def _save_reference_profile(self, reference_data: pd.DataFrame):
609
- """Save reference data profile"""
605
+ """Save reference data profile."""
610
606
  profile_file = self.storage_path / "reference_profile.pkl"
611
607
 
612
608
  with open(profile_file, "wb") as f:
613
609
  pickle.dump(reference_data, f)
614
610
 
615
611
  def _make_serializable(self, obj: Any) -> Any:
616
- """Convert object to JSON-serializable format"""
612
+ """Convert object to JSON-serializable format."""
617
613
  if isinstance(obj, np.ndarray):
618
614
  return obj.tolist()
619
615
  elif isinstance(obj, np.integer):
@@ -622,7 +618,7 @@ class ModelMonitor:
622
618
  return float(obj)
623
619
  elif isinstance(obj, datetime):
624
620
  return obj.isoformat()
625
- elif isinstance(obj, DriftAlert):
621
+ elif isinstance(obj, DriftAlert): # noqa: SIM114
626
622
  return asdict(obj)
627
623
  elif isinstance(obj, ModelMetrics):
628
624
  return asdict(obj)
@@ -638,13 +634,13 @@ class ModelMonitor:
638
634
 
639
635
  # Example alert handlers
640
636
  def email_alert_handler(alert: DriftAlert):
641
- """Example email alert handler"""
637
+ """Example email alert handler."""
642
638
  logger.info(f"EMAIL ALERT: {alert.description}")
643
639
  # In production, would send actual email
644
640
 
645
641
 
646
642
  def slack_alert_handler(alert: DriftAlert):
647
- """Example Slack alert handler"""
643
+ """Example Slack alert handler."""
648
644
  logger.info(f"SLACK ALERT: {alert.description}")
649
645
  # In production, would send to Slack
650
646
 
@@ -1,4 +1,4 @@
1
- """Prometheus metrics for monitoring"""
1
+ """Prometheus metrics for monitoring."""
2
2
 
3
3
  from prometheus_client import Counter, Gauge, Histogram, generate_latest
4
4
 
@@ -29,5 +29,5 @@ cache_hit_rate = Gauge("cache_hit_rate", "Cache hit rate")
29
29
 
30
30
 
31
31
  def get_metrics():
32
- """Get Prometheus metrics in text format"""
32
+ """Get Prometheus metrics in text format."""
33
33
  return generate_latest().decode("utf-8")
@@ -1,4 +1,4 @@
1
- """Advanced Portfolio Optimization"""
1
+ """Advanced Portfolio Optimization."""
2
2
 
3
3
  from .portfolio_optimizer import (
4
4
  AdvancedPortfolioOptimizer,
@@ -3,13 +3,12 @@
3
3
 
4
4
  import click
5
5
 
6
- from mcli.lib.ui.styling import error, info, success
6
+ from mcli.lib.ui.styling import error, info
7
7
 
8
8
 
9
9
  @click.group(name="mcli-optimize", help="Portfolio optimization CLI for MCLI trading system")
10
10
  def cli():
11
11
  """Main CLI group for portfolio optimization."""
12
- pass
13
12
 
14
13
 
15
14
  @cli.command(name="portfolio", help="Optimize portfolio allocation")