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,19 +1,18 @@
1
- """Advanced portfolio optimization for stock recommendations"""
1
+ """Advanced portfolio optimization for stock recommendations."""
2
2
 
3
3
  import logging
4
4
  from abc import ABC, abstractmethod
5
5
  from dataclasses import dataclass, field
6
- from datetime import datetime, timedelta
6
+ from datetime import datetime
7
7
  from enum import Enum
8
8
  from pathlib import Path
9
- from typing import Any, Dict, List, Optional, Tuple, Union
9
+ from typing import Any, Dict, List, Optional, Tuple
10
10
 
11
11
  # Optimization libraries
12
12
  import cvxpy as cp
13
13
  import matplotlib.pyplot as plt
14
14
  import numpy as np
15
15
  import pandas as pd
16
- import seaborn as sns
17
16
  from scipy.optimize import minimize
18
17
  from scipy.stats import norm
19
18
 
@@ -21,7 +20,7 @@ logger = logging.getLogger(__name__)
21
20
 
22
21
 
23
22
  class OptimizationObjective(Enum):
24
- """Portfolio optimization objectives"""
23
+ """Portfolio optimization objectives."""
25
24
 
26
25
  MEAN_VARIANCE = "mean_variance"
27
26
  RISK_PARITY = "risk_parity"
@@ -35,7 +34,7 @@ class OptimizationObjective(Enum):
35
34
 
36
35
  @dataclass
37
36
  class OptimizationConstraints:
38
- """Portfolio optimization constraints"""
37
+ """Portfolio optimization constraints."""
39
38
 
40
39
  # Weight constraints
41
40
  min_weight: float = 0.0
@@ -66,7 +65,7 @@ class OptimizationConstraints:
66
65
 
67
66
  @dataclass
68
67
  class PortfolioAllocation:
69
- """Portfolio allocation result"""
68
+ """Portfolio allocation result."""
70
69
 
71
70
  weights: Dict[str, float]
72
71
  expected_return: float
@@ -93,7 +92,7 @@ class PortfolioAllocation:
93
92
 
94
93
 
95
94
  class BaseOptimizer(ABC):
96
- """Base class for portfolio optimizers"""
95
+ """Base class for portfolio optimizers."""
97
96
 
98
97
  def __init__(self, constraints: OptimizationConstraints):
99
98
  self.constraints = constraints
@@ -102,8 +101,7 @@ class BaseOptimizer(ABC):
102
101
  def optimize(
103
102
  self, expected_returns: pd.Series, covariance_matrix: pd.DataFrame, **kwargs
104
103
  ) -> PortfolioAllocation:
105
- """Optimize portfolio allocation"""
106
- pass
104
+ """Optimize portfolio allocation."""
107
105
 
108
106
  def _calculate_portfolio_metrics(
109
107
  self,
@@ -112,7 +110,7 @@ class BaseOptimizer(ABC):
112
110
  covariance_matrix: pd.DataFrame,
113
111
  risk_free_rate: float = 0.02,
114
112
  ) -> Tuple[float, float, float]:
115
- """Calculate portfolio return, volatility, and Sharpe ratio"""
113
+ """Calculate portfolio return, volatility, and Sharpe ratio."""
116
114
  portfolio_return = np.dot(weights, expected_returns)
117
115
  portfolio_variance = np.dot(weights.T, np.dot(covariance_matrix, weights))
118
116
  portfolio_volatility = np.sqrt(portfolio_variance)
@@ -132,7 +130,7 @@ class BaseOptimizer(ABC):
132
130
  covariance_matrix: pd.DataFrame,
133
131
  confidence_level: float = 0.95,
134
132
  ) -> Tuple[float, float]:
135
- """Calculate Value at Risk and Conditional Value at Risk"""
133
+ """Calculate Value at Risk and Conditional Value at Risk."""
136
134
  portfolio_return = np.dot(weights, expected_returns)
137
135
  portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(covariance_matrix, weights)))
138
136
 
@@ -147,7 +145,7 @@ class BaseOptimizer(ABC):
147
145
 
148
146
 
149
147
  class MeanVarianceOptimizer(BaseOptimizer):
150
- """Modern Portfolio Theory mean-variance optimizer"""
148
+ """Modern Portfolio Theory mean-variance optimizer."""
151
149
 
152
150
  def optimize(
153
151
  self,
@@ -156,7 +154,7 @@ class MeanVarianceOptimizer(BaseOptimizer):
156
154
  risk_aversion: float = 1.0,
157
155
  **kwargs,
158
156
  ) -> PortfolioAllocation:
159
- """Optimize using mean-variance framework"""
157
+ """Optimize using mean-variance framework."""
160
158
  n_assets = len(expected_returns)
161
159
 
162
160
  # Decision variable: portfolio weights
@@ -213,15 +211,15 @@ class MeanVarianceOptimizer(BaseOptimizer):
213
211
 
214
212
 
215
213
  class RiskParityOptimizer(BaseOptimizer):
216
- """Risk parity portfolio optimizer"""
214
+ """Risk parity portfolio optimizer."""
217
215
 
218
216
  def optimize(
219
217
  self, expected_returns: pd.Series, covariance_matrix: pd.DataFrame, **kwargs
220
218
  ) -> PortfolioAllocation:
221
- """Optimize using risk parity approach"""
219
+ """Optimize using risk parity approach."""
222
220
 
223
221
  def risk_parity_objective(weights, cov_matrix):
224
- """Risk parity objective function"""
222
+ """Risk parity objective function."""
225
223
  portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
226
224
  marginal_contrib = np.dot(cov_matrix, weights) / portfolio_vol
227
225
  contrib = weights * marginal_contrib
@@ -282,7 +280,7 @@ class RiskParityOptimizer(BaseOptimizer):
282
280
 
283
281
 
284
282
  class BlackLittermanOptimizer(BaseOptimizer):
285
- """Black-Litterman portfolio optimizer"""
283
+ """Black-Litterman portfolio optimizer."""
286
284
 
287
285
  def optimize(
288
286
  self,
@@ -295,7 +293,7 @@ class BlackLittermanOptimizer(BaseOptimizer):
295
293
  risk_aversion: float = 3.0,
296
294
  **kwargs,
297
295
  ) -> PortfolioAllocation:
298
- """Optimize using Black-Litterman model"""
296
+ """Optimize using Black-Litterman model."""
299
297
 
300
298
  # Market capitalization weights (if not provided, use equal weights)
301
299
  if market_caps is None:
@@ -354,7 +352,7 @@ class BlackLittermanOptimizer(BaseOptimizer):
354
352
 
355
353
 
356
354
  class CVaROptimizer(BaseOptimizer):
357
- """Conditional Value at Risk optimizer"""
355
+ """Conditional Value at Risk optimizer."""
358
356
 
359
357
  def optimize(
360
358
  self,
@@ -364,7 +362,7 @@ class CVaROptimizer(BaseOptimizer):
364
362
  confidence_level: float = 0.95,
365
363
  **kwargs,
366
364
  ) -> PortfolioAllocation:
367
- """Optimize portfolio to minimize CVaR"""
365
+ """Optimize portfolio to minimize CVaR."""
368
366
 
369
367
  if scenarios is None:
370
368
  # Generate scenarios from normal distribution
@@ -434,12 +432,12 @@ class CVaROptimizer(BaseOptimizer):
434
432
 
435
433
 
436
434
  class KellyCriterionOptimizer(BaseOptimizer):
437
- """Kelly Criterion optimizer for growth-optimal portfolios"""
435
+ """Kelly Criterion optimizer for growth-optimal portfolios."""
438
436
 
439
437
  def optimize(
440
438
  self, expected_returns: pd.Series, covariance_matrix: pd.DataFrame, **kwargs
441
439
  ) -> PortfolioAllocation:
442
- """Optimize using Kelly Criterion"""
440
+ """Optimize using Kelly Criterion."""
443
441
 
444
442
  # Kelly optimal weights: w* = Σ^(-1) * μ
445
443
  # where μ is expected excess returns and Σ is covariance matrix
@@ -510,7 +508,7 @@ class KellyCriterionOptimizer(BaseOptimizer):
510
508
 
511
509
 
512
510
  class AdvancedPortfolioOptimizer:
513
- """Advanced portfolio optimization system"""
511
+ """Advanced portfolio optimization system."""
514
512
 
515
513
  def __init__(self, constraints: Optional[OptimizationConstraints] = None):
516
514
  self.constraints = constraints or OptimizationConstraints()
@@ -533,7 +531,7 @@ class AdvancedPortfolioOptimizer:
533
531
  objective: OptimizationObjective = OptimizationObjective.MEAN_VARIANCE,
534
532
  **optimizer_kwargs,
535
533
  ) -> PortfolioAllocation:
536
- """Optimize portfolio using specified objective"""
534
+ """Optimize portfolio using specified objective."""
537
535
 
538
536
  if objective not in self.optimizers:
539
537
  raise ValueError(f"Unsupported optimization objective: {objective}")
@@ -558,7 +556,7 @@ class AdvancedPortfolioOptimizer:
558
556
  objectives: List[OptimizationObjective],
559
557
  weights: Optional[List[float]] = None,
560
558
  ) -> PortfolioAllocation:
561
- """Combine multiple optimization objectives"""
559
+ """Combine multiple optimization objectives."""
562
560
 
563
561
  if weights is None:
564
562
  weights = [1.0 / len(objectives)] * len(objectives)
@@ -608,7 +606,7 @@ class AdvancedPortfolioOptimizer:
608
606
  def efficient_frontier(
609
607
  self, expected_returns: pd.Series, covariance_matrix: pd.DataFrame, n_points: int = 20
610
608
  ) -> pd.DataFrame:
611
- """Generate efficient frontier"""
609
+ """Generate efficient frontier."""
612
610
 
613
611
  min_vol_allocation = self.optimize_portfolio(
614
612
  expected_returns,
@@ -676,7 +674,7 @@ class AdvancedPortfolioOptimizer:
676
674
  target_allocation: PortfolioAllocation,
677
675
  rebalance_threshold: float = 0.05,
678
676
  ) -> Dict[str, Any]:
679
- """Calculate rebalancing trades"""
677
+ """Calculate rebalancing trades."""
680
678
 
681
679
  trades = {}
682
680
  total_deviation = 0
@@ -709,9 +707,9 @@ class AdvancedPortfolioOptimizer:
709
707
  expected_returns: pd.Series,
710
708
  covariance_matrix: pd.DataFrame,
711
709
  ) -> PortfolioAllocation:
712
- """Add additional metrics to allocation"""
710
+ """Add additional metrics to allocation."""
713
711
 
714
- weights_array = np.array(
712
+ _weights_array = np.array( # noqa: F841
715
713
  [allocation.weights.get(asset, 0) for asset in expected_returns.index]
716
714
  )
717
715
 
@@ -727,7 +725,7 @@ class AdvancedPortfolioOptimizer:
727
725
  def plot_allocation(
728
726
  self, allocation: PortfolioAllocation, save_path: Optional[Path] = None
729
727
  ) -> None:
730
- """Plot portfolio allocation"""
728
+ """Plot portfolio allocation."""
731
729
 
732
730
  # Filter out zero weights
733
731
  non_zero_weights = {k: v for k, v in allocation.weights.items() if abs(v) > 0.001}
@@ -854,7 +852,7 @@ if __name__ == "__main__":
854
852
  weights=[0.7, 0.3],
855
853
  )
856
854
 
857
- print(f"\nMULTI-OBJECTIVE Optimization:")
855
+ print("\nMULTI-OBJECTIVE Optimization:")
858
856
  print(f"Expected Return: {multi_obj_allocation.expected_return:.3f}")
859
857
  print(f"Volatility: {multi_obj_allocation.expected_volatility:.3f}")
860
858
  print(f"Sharpe Ratio: {multi_obj_allocation.sharpe_ratio:.3f}")
@@ -1,4 +1,4 @@
1
- """ML Predictions Module"""
1
+ """ML Predictions Module."""
2
2
 
3
3
  from .prediction_engine import PoliticianTradingPredictor
4
4
 
@@ -1,4 +1,4 @@
1
- """ML Data Preprocessing Module"""
1
+ """ML Data Preprocessing Module."""
2
2
 
3
3
  from .data_cleaners import MissingValueHandler, OutlierDetector, TradingDataCleaner
4
4
  from .feature_extractors import (
@@ -1,10 +1,10 @@
1
- """Data cleaning utilities for ML preprocessing"""
1
+ """Data cleaning utilities for ML preprocessing."""
2
2
 
3
3
  import logging
4
4
  import re
5
5
  from dataclasses import dataclass
6
- from datetime import datetime, timedelta
7
- from typing import Any, Dict, List, Optional, Tuple, Union
6
+ from datetime import datetime
7
+ from typing import Any, Dict, List, Optional, Tuple
8
8
 
9
9
  import numpy as np
10
10
  import pandas as pd
@@ -14,7 +14,7 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
  @dataclass
16
16
  class CleaningStats:
17
- """Statistics about data cleaning operations"""
17
+ """Statistics about data cleaning operations."""
18
18
 
19
19
  total_records: int
20
20
  cleaned_records: int
@@ -25,7 +25,7 @@ class CleaningStats:
25
25
 
26
26
 
27
27
  class TradingDataCleaner:
28
- """Cleans and standardizes politician trading data for ML"""
28
+ """Cleans and standardizes politician trading data for ML."""
29
29
 
30
30
  def __init__(self, config: Optional[Dict[str, Any]] = None):
31
31
  self.config = config or {}
@@ -41,7 +41,7 @@ class TradingDataCleaner:
41
41
  def clean_trading_records(
42
42
  self, records: List[Dict[str, Any]]
43
43
  ) -> Tuple[List[Dict[str, Any]], CleaningStats]:
44
- """Clean a batch of trading records"""
44
+ """Clean a batch of trading records."""
45
45
  self.cleaning_stats.total_records = len(records)
46
46
  cleaned_records = []
47
47
 
@@ -56,7 +56,7 @@ class TradingDataCleaner:
56
56
  return cleaned_records, self.cleaning_stats
57
57
 
58
58
  def _clean_single_record(self, record: Dict[str, Any]) -> Optional[Dict[str, Any]]:
59
- """Clean a single trading record"""
59
+ """Clean a single trading record."""
60
60
  try:
61
61
  cleaned = record.copy()
62
62
 
@@ -86,7 +86,7 @@ class TradingDataCleaner:
86
86
  return None
87
87
 
88
88
  def _clean_politician_name(self, record: Dict[str, Any]) -> Dict[str, Any]:
89
- """Clean and standardize politician names"""
89
+ """Clean and standardize politician names."""
90
90
  name_fields = ["politician_name", "name", "representative_name", "senator_name"]
91
91
 
92
92
  for field in name_fields:
@@ -113,7 +113,7 @@ class TradingDataCleaner:
113
113
  return record
114
114
 
115
115
  def _clean_transaction_amount(self, record: Dict[str, Any]) -> Dict[str, Any]:
116
- """Clean and standardize transaction amounts"""
116
+ """Clean and standardize transaction amounts."""
117
117
  amount_fields = ["transaction_amount", "amount", "value", "transaction_value"]
118
118
 
119
119
  for field in amount_fields:
@@ -148,7 +148,7 @@ class TradingDataCleaner:
148
148
  return record
149
149
 
150
150
  def _clean_transaction_date(self, record: Dict[str, Any]) -> Dict[str, Any]:
151
- """Clean and standardize transaction dates"""
151
+ """Clean and standardize transaction dates."""
152
152
  date_fields = ["transaction_date", "date", "trade_date", "disclosure_date"]
153
153
 
154
154
  for field in date_fields:
@@ -183,7 +183,7 @@ class TradingDataCleaner:
183
183
  date_obj = pd.to_datetime(date_str)
184
184
  record["transaction_date_cleaned"] = date_obj.strftime("%Y-%m-%d")
185
185
  self._increment_cleaning_operation("transaction_date_cleaned")
186
- except:
186
+ except Exception:
187
187
  continue
188
188
 
189
189
  if "transaction_date_cleaned" in record:
@@ -192,8 +192,7 @@ class TradingDataCleaner:
192
192
  return record
193
193
 
194
194
  def _clean_asset_info(self, record: Dict[str, Any]) -> Dict[str, Any]:
195
- """Clean and standardize asset information"""
196
- asset_fields = ["asset_name", "stock_symbol", "ticker", "security_name"]
195
+ """Clean and standardize asset information."""
197
196
 
198
197
  # Clean ticker/symbol
199
198
  for field in ["stock_symbol", "ticker", "symbol"]:
@@ -230,7 +229,7 @@ class TradingDataCleaner:
230
229
  return record
231
230
 
232
231
  def _clean_transaction_type(self, record: Dict[str, Any]) -> Dict[str, Any]:
233
- """Clean and standardize transaction types"""
232
+ """Clean and standardize transaction types."""
234
233
  type_fields = ["transaction_type", "type", "action", "trade_type"]
235
234
 
236
235
  for field in type_fields:
@@ -254,7 +253,7 @@ class TradingDataCleaner:
254
253
  return record
255
254
 
256
255
  def _validate_required_fields(self, record: Dict[str, Any]) -> bool:
257
- """Validate that required fields exist after cleaning"""
256
+ """Validate that required fields exist after cleaning."""
258
257
  required_fields = [
259
258
  "politician_name_cleaned",
260
259
  "transaction_date_cleaned",
@@ -272,14 +271,14 @@ class TradingDataCleaner:
272
271
  return has_required and amount_or_asset
273
272
 
274
273
  def _increment_cleaning_operation(self, operation: str):
275
- """Track cleaning operations"""
274
+ """Track cleaning operations."""
276
275
  if operation not in self.cleaning_stats.cleaning_operations:
277
276
  self.cleaning_stats.cleaning_operations[operation] = 0
278
277
  self.cleaning_stats.cleaning_operations[operation] += 1
279
278
 
280
279
 
281
280
  class OutlierDetector:
282
- """Detects and handles outliers in trading data"""
281
+ """Detects and handles outliers in trading data."""
283
282
 
284
283
  def __init__(self, config: Optional[Dict[str, Any]] = None):
285
284
  self.config = config or {}
@@ -297,7 +296,7 @@ class OutlierDetector:
297
296
  }
298
297
 
299
298
  def detect_outliers(self, df: pd.DataFrame) -> Tuple[pd.DataFrame, Dict[str, Any]]:
300
- """Detect outliers in the dataset"""
299
+ """Detect outliers in the dataset."""
301
300
  outlier_info = {"total_outliers": 0, "outliers_by_field": {}, "outlier_indices": set()}
302
301
 
303
302
  # Amount-based outliers
@@ -328,7 +327,7 @@ class OutlierDetector:
328
327
  return df, outlier_info
329
328
 
330
329
  def _detect_amount_outliers(self, df: pd.DataFrame) -> List[int]:
331
- """Detect amount-based outliers"""
330
+ """Detect amount-based outliers."""
332
331
  outliers = []
333
332
  amount_col = "transaction_amount_cleaned"
334
333
 
@@ -344,7 +343,7 @@ class OutlierDetector:
344
343
  return list(set(outliers))
345
344
 
346
345
  def _detect_date_outliers(self, df: pd.DataFrame) -> List[int]:
347
- """Detect date-based outliers"""
346
+ """Detect date-based outliers."""
348
347
  outliers = []
349
348
  date_col = "transaction_date_cleaned"
350
349
 
@@ -365,7 +364,7 @@ class OutlierDetector:
365
364
  return list(set(outliers))
366
365
 
367
366
  def _detect_statistical_outliers(self, df: pd.DataFrame, column: str) -> List[int]:
368
- """Detect statistical outliers using Z-score"""
367
+ """Detect statistical outliers using Z-score."""
369
368
  outliers = []
370
369
 
371
370
  if column not in df.columns or df[column].dtype not in [np.number, "float64", "int64"]:
@@ -387,7 +386,7 @@ class OutlierDetector:
387
386
 
388
387
 
389
388
  class MissingValueHandler:
390
- """Handles missing values in trading data"""
389
+ """Handles missing values in trading data."""
391
390
 
392
391
  def __init__(self, config: Optional[Dict[str, Any]] = None):
393
392
  self.config = config or {}
@@ -401,7 +400,7 @@ class MissingValueHandler:
401
400
  }
402
401
 
403
402
  def handle_missing_values(self, df: pd.DataFrame) -> Tuple[pd.DataFrame, Dict[str, Any]]:
404
- """Handle missing values according to strategies"""
403
+ """Handle missing values according to strategies."""
405
404
  missing_info = {
406
405
  "original_shape": df.shape,
407
406
  "missing_counts": df.isnull().sum().to_dict(),
@@ -1,11 +1,8 @@
1
- """Feature extraction utilities for ML preprocessing"""
1
+ """Feature extraction utilities for ML preprocessing."""
2
2
 
3
3
  import logging
4
- import re
5
- from collections import Counter, defaultdict
6
4
  from dataclasses import dataclass
7
- from datetime import datetime, timedelta
8
- from typing import Any, Dict, List, Optional, Tuple, Union
5
+ from typing import Any, Dict, Optional
9
6
 
10
7
  import numpy as np
11
8
  import pandas as pd
@@ -15,7 +12,7 @@ logger = logging.getLogger(__name__)
15
12
 
16
13
  @dataclass
17
14
  class FeatureExtractionStats:
18
- """Statistics about feature extraction operations"""
15
+ """Statistics about feature extraction operations."""
19
16
 
20
17
  total_records: int
21
18
  features_extracted: int
@@ -25,7 +22,7 @@ class FeatureExtractionStats:
25
22
 
26
23
 
27
24
  class PoliticianFeatureExtractor:
28
- """Extracts features related to politicians"""
25
+ """Extracts features related to politicians."""
29
26
 
30
27
  def __init__(self, config: Optional[Dict[str, Any]] = None):
31
28
  self.config = config or {}
@@ -39,7 +36,7 @@ class PoliticianFeatureExtractor:
39
36
  }
40
37
 
41
38
  def extract_politician_features(self, df: pd.DataFrame) -> pd.DataFrame:
42
- """Extract politician-related features"""
39
+ """Extract politician-related features."""
43
40
  df_features = df.copy()
44
41
 
45
42
  # Basic politician features
@@ -51,7 +48,7 @@ class PoliticianFeatureExtractor:
51
48
  return df_features
52
49
 
53
50
  def _extract_name_features(self, df: pd.DataFrame) -> pd.DataFrame:
54
- """Extract features from politician names"""
51
+ """Extract features from politician names."""
55
52
  if "politician_name_cleaned" not in df.columns:
56
53
  return df
57
54
 
@@ -72,7 +69,7 @@ class PoliticianFeatureExtractor:
72
69
  return df
73
70
 
74
71
  def _extract_trading_patterns(self, df: pd.DataFrame) -> pd.DataFrame:
75
- """Extract trading pattern features for each politician"""
72
+ """Extract trading pattern features for each politician."""
76
73
  if "politician_name_cleaned" not in df.columns:
77
74
  return df
78
75
 
@@ -147,7 +144,7 @@ class PoliticianFeatureExtractor:
147
144
  return df
148
145
 
149
146
  def _extract_frequency_features(self, df: pd.DataFrame) -> pd.DataFrame:
150
- """Extract trading frequency features"""
147
+ """Extract trading frequency features."""
151
148
  if not all(
152
149
  col in df.columns for col in ["politician_name_cleaned", "transaction_date_cleaned"]
153
150
  ):
@@ -189,7 +186,7 @@ class PoliticianFeatureExtractor:
189
186
  return df
190
187
 
191
188
  def _extract_timing_features(self, df: pd.DataFrame) -> pd.DataFrame:
192
- """Extract timing-related features"""
189
+ """Extract timing-related features."""
193
190
  if "transaction_date_dt" not in df.columns:
194
191
  return df
195
192
 
@@ -220,14 +217,14 @@ class PoliticianFeatureExtractor:
220
217
 
221
218
 
222
219
  class MarketFeatureExtractor:
223
- """Extracts market-related features"""
220
+ """Extracts market-related features."""
224
221
 
225
222
  def __init__(self, config: Optional[Dict[str, Any]] = None):
226
223
  self.config = config or {}
227
224
  self.sector_mapping = self._load_sector_mapping()
228
225
 
229
226
  def extract_market_features(self, df: pd.DataFrame) -> pd.DataFrame:
230
- """Extract market-related features"""
227
+ """Extract market-related features."""
231
228
  df_features = df.copy()
232
229
 
233
230
  # Asset features
@@ -238,7 +235,7 @@ class MarketFeatureExtractor:
238
235
  return df_features
239
236
 
240
237
  def _extract_asset_features(self, df: pd.DataFrame) -> pd.DataFrame:
241
- """Extract features from asset names"""
238
+ """Extract features from asset names."""
242
239
  if "asset_name_cleaned" not in df.columns:
243
240
  return df
244
241
 
@@ -270,7 +267,7 @@ class MarketFeatureExtractor:
270
267
  return df
271
268
 
272
269
  def _extract_ticker_features(self, df: pd.DataFrame) -> pd.DataFrame:
273
- """Extract features from stock tickers"""
270
+ """Extract features from stock tickers."""
274
271
  if "ticker_cleaned" not in df.columns:
275
272
  return df
276
273
 
@@ -288,7 +285,7 @@ class MarketFeatureExtractor:
288
285
  return df
289
286
 
290
287
  def _extract_market_cap_features(self, df: pd.DataFrame) -> pd.DataFrame:
291
- """Extract market cap related features (placeholder)"""
288
+ """Extract market cap related features (placeholder)."""
292
289
  # This would typically connect to external APIs
293
290
  # For now, create estimated features based on transaction amounts
294
291
 
@@ -311,7 +308,7 @@ class MarketFeatureExtractor:
311
308
  return df
312
309
 
313
310
  def _load_sector_mapping(self) -> Dict[str, str]:
314
- """Load ticker to sector mapping (simplified)"""
311
+ """Load ticker to sector mapping (simplified)."""
315
312
  # This would typically be loaded from a data file or API
316
313
  return {
317
314
  "AAPL": "technology",
@@ -333,14 +330,14 @@ class MarketFeatureExtractor:
333
330
 
334
331
 
335
332
  class TemporalFeatureExtractor:
336
- """Extracts temporal features for time series analysis"""
333
+ """Extracts temporal features for time series analysis."""
337
334
 
338
335
  def __init__(self, config: Optional[Dict[str, Any]] = None):
339
336
  self.config = config or {}
340
337
  self.lookback_periods = config.get("lookback_periods", [7, 30, 90, 365])
341
338
 
342
339
  def extract_temporal_features(self, df: pd.DataFrame) -> pd.DataFrame:
343
- """Extract temporal features"""
340
+ """Extract temporal features."""
344
341
  df_features = df.copy()
345
342
 
346
343
  if "transaction_date_dt" not in df.columns:
@@ -357,7 +354,7 @@ class TemporalFeatureExtractor:
357
354
  return df_features
358
355
 
359
356
  def _extract_rolling_features(self, df: pd.DataFrame) -> pd.DataFrame:
360
- """Extract rolling window features"""
357
+ """Extract rolling window features."""
361
358
  # Set date as index temporarily
362
359
  df_indexed = df.set_index("transaction_date_dt")
363
360
 
@@ -389,7 +386,7 @@ class TemporalFeatureExtractor:
389
386
  return df
390
387
 
391
388
  def _extract_lag_features(self, df: pd.DataFrame) -> pd.DataFrame:
392
- """Extract lagged features"""
389
+ """Extract lagged features."""
393
390
  lag_periods = [1, 7, 30]
394
391
 
395
392
  for lag in lag_periods:
@@ -406,7 +403,7 @@ class TemporalFeatureExtractor:
406
403
  return df
407
404
 
408
405
  def _extract_trend_features(self, df: pd.DataFrame) -> pd.DataFrame:
409
- """Extract trend features"""
406
+ """Extract trend features."""
410
407
  # Calculate percentage changes
411
408
  df["amount_pct_change_1d"] = df.groupby("politician_name_cleaned")[
412
409
  "transaction_amount_cleaned"
@@ -439,7 +436,7 @@ class TemporalFeatureExtractor:
439
436
 
440
437
 
441
438
  class SentimentFeatureExtractor:
442
- """Extracts sentiment and text-based features"""
439
+ """Extracts sentiment and text-based features."""
443
440
 
444
441
  def __init__(self, config: Optional[Dict[str, Any]] = None):
445
442
  self.config = config or {}
@@ -447,7 +444,7 @@ class SentimentFeatureExtractor:
447
444
  self.negative_words = ["loss", "down", "bear", "decline", "weak", "fall", "drop"]
448
445
 
449
446
  def extract_sentiment_features(self, df: pd.DataFrame) -> pd.DataFrame:
450
- """Extract sentiment features from text fields"""
447
+ """Extract sentiment features from text fields."""
451
448
  df_features = df.copy()
452
449
 
453
450
  # Asset name sentiment
@@ -465,7 +462,7 @@ class SentimentFeatureExtractor:
465
462
  def _extract_text_sentiment(
466
463
  self, df: pd.DataFrame, text_column: str, prefix: str
467
464
  ) -> pd.DataFrame:
468
- """Extract sentiment from text column"""
465
+ """Extract sentiment from text column."""
469
466
  if text_column not in df.columns:
470
467
  return df
471
468