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.
- mcli/app/__init__.py +0 -2
- mcli/app/commands_cmd.py +30 -26
- mcli/app/completion_helpers.py +5 -5
- mcli/app/init_cmd.py +10 -10
- mcli/app/lock_cmd.py +29 -24
- mcli/app/main.py +2 -8
- mcli/app/model/model.py +5 -10
- mcli/app/store_cmd.py +8 -8
- mcli/app/video/__init__.py +0 -2
- mcli/app/video/video.py +1 -14
- mcli/chat/chat.py +90 -108
- mcli/chat/command_rag.py +0 -4
- mcli/chat/enhanced_chat.py +32 -41
- mcli/chat/system_controller.py +37 -37
- mcli/chat/system_integration.py +4 -5
- mcli/cli.py +2 -3
- mcli/lib/api/api.py +4 -9
- mcli/lib/api/daemon_client.py +19 -20
- mcli/lib/api/daemon_client_local.py +1 -3
- mcli/lib/api/daemon_decorator.py +6 -6
- mcli/lib/api/mcli_decorators.py +4 -8
- mcli/lib/auth/__init__.py +0 -1
- mcli/lib/auth/auth.py +4 -5
- mcli/lib/auth/mcli_manager.py +7 -12
- mcli/lib/auth/token_util.py +5 -5
- mcli/lib/config/__init__.py +29 -1
- mcli/lib/config/config.py +0 -1
- mcli/lib/custom_commands.py +1 -1
- mcli/lib/discovery/command_discovery.py +15 -15
- mcli/lib/erd/erd.py +7 -7
- mcli/lib/files/files.py +1 -1
- mcli/lib/fs/__init__.py +31 -1
- mcli/lib/fs/fs.py +12 -13
- mcli/lib/lib.py +0 -1
- mcli/lib/logger/logger.py +7 -10
- mcli/lib/performance/optimizer.py +25 -27
- mcli/lib/performance/rust_bridge.py +22 -27
- mcli/lib/performance/uvloop_config.py +0 -1
- mcli/lib/pickles/__init__.py +0 -1
- mcli/lib/pickles/pickles.py +0 -2
- mcli/lib/secrets/commands.py +0 -2
- mcli/lib/secrets/manager.py +0 -1
- mcli/lib/secrets/repl.py +2 -3
- mcli/lib/secrets/store.py +1 -2
- mcli/lib/services/data_pipeline.py +34 -34
- mcli/lib/services/lsh_client.py +38 -40
- mcli/lib/shell/shell.py +2 -2
- mcli/lib/toml/__init__.py +0 -1
- mcli/lib/ui/styling.py +0 -1
- mcli/lib/ui/visual_effects.py +33 -41
- mcli/lib/watcher/watcher.py +0 -1
- mcli/ml/__init__.py +1 -1
- mcli/ml/api/__init__.py +1 -1
- mcli/ml/api/app.py +8 -9
- mcli/ml/api/middleware.py +10 -10
- mcli/ml/api/routers/__init__.py +1 -1
- mcli/ml/api/routers/admin_router.py +3 -3
- mcli/ml/api/routers/auth_router.py +17 -18
- mcli/ml/api/routers/backtest_router.py +2 -2
- mcli/ml/api/routers/data_router.py +2 -2
- mcli/ml/api/routers/model_router.py +14 -15
- mcli/ml/api/routers/monitoring_router.py +2 -2
- mcli/ml/api/routers/portfolio_router.py +2 -2
- mcli/ml/api/routers/prediction_router.py +10 -9
- mcli/ml/api/routers/trade_router.py +2 -2
- mcli/ml/api/routers/websocket_router.py +6 -7
- mcli/ml/api/schemas.py +2 -2
- mcli/ml/auth/__init__.py +1 -1
- mcli/ml/auth/auth_manager.py +22 -23
- mcli/ml/auth/models.py +17 -17
- mcli/ml/auth/permissions.py +17 -17
- mcli/ml/backtesting/__init__.py +1 -1
- mcli/ml/backtesting/backtest_engine.py +31 -35
- mcli/ml/backtesting/performance_metrics.py +12 -14
- mcli/ml/backtesting/run.py +1 -2
- mcli/ml/cache.py +35 -36
- mcli/ml/cli/__init__.py +1 -1
- mcli/ml/cli/main.py +21 -24
- mcli/ml/config/__init__.py +1 -1
- mcli/ml/config/settings.py +28 -29
- mcli/ml/configs/__init__.py +1 -1
- mcli/ml/configs/dvc_config.py +14 -15
- mcli/ml/configs/mlflow_config.py +12 -13
- mcli/ml/configs/mlops_manager.py +19 -21
- mcli/ml/dashboard/__init__.py +4 -4
- mcli/ml/dashboard/app.py +20 -30
- mcli/ml/dashboard/app_supabase.py +16 -19
- mcli/ml/dashboard/app_training.py +11 -14
- mcli/ml/dashboard/cli.py +2 -2
- mcli/ml/dashboard/common.py +2 -3
- mcli/ml/dashboard/components/__init__.py +1 -1
- mcli/ml/dashboard/components/charts.py +13 -11
- mcli/ml/dashboard/components/metrics.py +7 -7
- mcli/ml/dashboard/components/tables.py +12 -9
- mcli/ml/dashboard/overview.py +2 -2
- mcli/ml/dashboard/pages/__init__.py +1 -1
- mcli/ml/dashboard/pages/cicd.py +15 -18
- mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
- mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
- mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
- mcli/ml/dashboard/pages/test_portfolio.py +3 -6
- mcli/ml/dashboard/pages/trading.py +16 -18
- mcli/ml/dashboard/pages/workflows.py +20 -30
- mcli/ml/dashboard/utils.py +9 -9
- mcli/ml/dashboard/warning_suppression.py +3 -3
- mcli/ml/data_ingestion/__init__.py +1 -1
- mcli/ml/data_ingestion/api_connectors.py +41 -46
- mcli/ml/data_ingestion/data_pipeline.py +36 -46
- mcli/ml/data_ingestion/stream_processor.py +43 -46
- mcli/ml/database/__init__.py +1 -1
- mcli/ml/database/migrations/env.py +2 -2
- mcli/ml/database/models.py +22 -24
- mcli/ml/database/session.py +14 -14
- mcli/ml/experimentation/__init__.py +1 -1
- mcli/ml/experimentation/ab_testing.py +45 -46
- mcli/ml/features/__init__.py +1 -1
- mcli/ml/features/ensemble_features.py +22 -27
- mcli/ml/features/recommendation_engine.py +30 -30
- mcli/ml/features/stock_features.py +29 -32
- mcli/ml/features/test_feature_engineering.py +10 -11
- mcli/ml/logging.py +4 -4
- mcli/ml/mlops/__init__.py +1 -1
- mcli/ml/mlops/data_versioning.py +29 -30
- mcli/ml/mlops/experiment_tracker.py +24 -24
- mcli/ml/mlops/model_serving.py +31 -34
- mcli/ml/mlops/pipeline_orchestrator.py +27 -35
- mcli/ml/models/__init__.py +5 -6
- mcli/ml/models/base_models.py +23 -23
- mcli/ml/models/ensemble_models.py +31 -31
- mcli/ml/models/recommendation_models.py +18 -19
- mcli/ml/models/test_models.py +14 -16
- mcli/ml/monitoring/__init__.py +1 -1
- mcli/ml/monitoring/drift_detection.py +32 -36
- mcli/ml/monitoring/metrics.py +2 -2
- mcli/ml/optimization/__init__.py +1 -1
- mcli/ml/optimization/optimize.py +1 -2
- mcli/ml/optimization/portfolio_optimizer.py +30 -32
- mcli/ml/predictions/__init__.py +1 -1
- mcli/ml/preprocessing/__init__.py +1 -1
- mcli/ml/preprocessing/data_cleaners.py +22 -23
- mcli/ml/preprocessing/feature_extractors.py +23 -26
- mcli/ml/preprocessing/ml_pipeline.py +23 -23
- mcli/ml/preprocessing/test_preprocessing.py +7 -8
- mcli/ml/scripts/populate_sample_data.py +0 -4
- mcli/ml/serving/serve.py +1 -2
- mcli/ml/tasks.py +17 -17
- mcli/ml/tests/test_integration.py +29 -30
- mcli/ml/tests/test_training_dashboard.py +21 -21
- mcli/ml/trading/__init__.py +1 -1
- mcli/ml/trading/migrations.py +5 -5
- mcli/ml/trading/models.py +21 -23
- mcli/ml/trading/paper_trading.py +16 -13
- mcli/ml/trading/risk_management.py +17 -18
- mcli/ml/trading/trading_service.py +25 -28
- mcli/ml/training/__init__.py +1 -1
- mcli/ml/training/train.py +0 -1
- mcli/public/oi/oi.py +1 -2
- mcli/self/completion_cmd.py +6 -10
- mcli/self/logs_cmd.py +19 -24
- mcli/self/migrate_cmd.py +22 -20
- mcli/self/redis_cmd.py +10 -11
- mcli/self/self_cmd.py +10 -18
- mcli/self/store_cmd.py +10 -12
- mcli/self/visual_cmd.py +9 -14
- mcli/self/zsh_cmd.py +2 -4
- mcli/workflow/daemon/async_command_database.py +23 -24
- mcli/workflow/daemon/async_process_manager.py +27 -29
- mcli/workflow/daemon/client.py +27 -33
- mcli/workflow/daemon/daemon.py +32 -36
- mcli/workflow/daemon/enhanced_daemon.py +24 -33
- mcli/workflow/daemon/process_cli.py +11 -12
- mcli/workflow/daemon/process_manager.py +23 -26
- mcli/workflow/daemon/test_daemon.py +4 -5
- mcli/workflow/dashboard/dashboard_cmd.py +0 -1
- mcli/workflow/doc_convert.py +15 -17
- mcli/workflow/gcloud/__init__.py +0 -1
- mcli/workflow/gcloud/gcloud.py +11 -8
- mcli/workflow/git_commit/ai_service.py +14 -15
- mcli/workflow/lsh_integration.py +9 -11
- mcli/workflow/model_service/client.py +26 -31
- mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
- mcli/workflow/model_service/lightweight_embedder.py +25 -35
- mcli/workflow/model_service/lightweight_model_server.py +26 -32
- mcli/workflow/model_service/lightweight_test.py +7 -10
- mcli/workflow/model_service/model_service.py +80 -91
- mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
- mcli/workflow/model_service/openai_adapter.py +23 -23
- mcli/workflow/model_service/pdf_processor.py +21 -26
- mcli/workflow/model_service/test_efficient_runner.py +12 -16
- mcli/workflow/model_service/test_example.py +11 -13
- mcli/workflow/model_service/test_integration.py +3 -5
- mcli/workflow/model_service/test_new_features.py +7 -8
- mcli/workflow/notebook/converter.py +1 -1
- mcli/workflow/notebook/notebook_cmd.py +5 -6
- mcli/workflow/notebook/schema.py +0 -1
- mcli/workflow/notebook/validator.py +7 -3
- mcli/workflow/openai/openai.py +1 -2
- mcli/workflow/registry/registry.py +4 -1
- mcli/workflow/repo/repo.py +6 -7
- mcli/workflow/scheduler/cron_parser.py +16 -19
- mcli/workflow/scheduler/job.py +10 -10
- mcli/workflow/scheduler/monitor.py +15 -15
- mcli/workflow/scheduler/persistence.py +17 -18
- mcli/workflow/scheduler/scheduler.py +37 -38
- mcli/workflow/secrets/__init__.py +1 -1
- mcli/workflow/sync/test_cmd.py +0 -1
- mcli/workflow/wakatime/__init__.py +5 -9
- mcli/workflow/wakatime/wakatime.py +1 -2
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/METADATA +1 -1
- mcli_framework-7.12.4.dist-info/RECORD +279 -0
- mcli_framework-7.12.2.dist-info/RECORD +0 -279
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/WHEEL +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"""Stock recommendation engine that combines all feature engineering components"""
|
|
1
|
+
"""Stock recommendation engine that combines all feature engineering components."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from dataclasses import
|
|
5
|
-
from datetime import datetime
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from datetime import datetime
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import
|
|
7
|
+
from typing import Dict, List, Optional, Tuple
|
|
8
8
|
|
|
9
9
|
import joblib
|
|
10
10
|
import numpy as np
|
|
@@ -31,7 +31,7 @@ logger = logging.getLogger(__name__)
|
|
|
31
31
|
|
|
32
32
|
@dataclass
|
|
33
33
|
class RecommendationConfig:
|
|
34
|
-
"""Configuration for stock recommendation engine"""
|
|
34
|
+
"""Configuration for stock recommendation engine."""
|
|
35
35
|
|
|
36
36
|
# Feature engineering components
|
|
37
37
|
enable_technical_features: bool = True
|
|
@@ -73,7 +73,7 @@ class RecommendationConfig:
|
|
|
73
73
|
|
|
74
74
|
@dataclass
|
|
75
75
|
class RecommendationResult:
|
|
76
|
-
"""Result from stock recommendation engine"""
|
|
76
|
+
"""Result from stock recommendation engine."""
|
|
77
77
|
|
|
78
78
|
# Basic information
|
|
79
79
|
ticker: str
|
|
@@ -105,7 +105,7 @@ class RecommendationResult:
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
class StockRecommendationEngine:
|
|
108
|
-
"""Comprehensive stock recommendation engine"""
|
|
108
|
+
"""Comprehensive stock recommendation engine."""
|
|
109
109
|
|
|
110
110
|
def __init__(self, config: Optional[RecommendationConfig] = None):
|
|
111
111
|
self.config = config or RecommendationConfig()
|
|
@@ -132,7 +132,7 @@ class StockRecommendationEngine:
|
|
|
132
132
|
politician_metadata: Optional[pd.DataFrame] = None,
|
|
133
133
|
market_data: Optional[Dict[str, pd.DataFrame]] = None,
|
|
134
134
|
) -> List[RecommendationResult]:
|
|
135
|
-
"""Generate stock recommendations based on politician trading data"""
|
|
135
|
+
"""Generate stock recommendations based on politician trading data."""
|
|
136
136
|
|
|
137
137
|
logger.info("Starting stock recommendation generation")
|
|
138
138
|
|
|
@@ -170,7 +170,7 @@ class StockRecommendationEngine:
|
|
|
170
170
|
politician_metadata: Optional[pd.DataFrame],
|
|
171
171
|
market_data: Optional[Dict[str, pd.DataFrame]],
|
|
172
172
|
) -> pd.DataFrame:
|
|
173
|
-
"""Extract all features for recommendation generation"""
|
|
173
|
+
"""Extract all features for recommendation generation."""
|
|
174
174
|
|
|
175
175
|
logger.info("Extracting comprehensive feature set")
|
|
176
176
|
df = trading_data.copy()
|
|
@@ -204,7 +204,7 @@ class StockRecommendationEngine:
|
|
|
204
204
|
def _add_technical_features(
|
|
205
205
|
self, df: pd.DataFrame, stock_price_data: pd.DataFrame
|
|
206
206
|
) -> pd.DataFrame:
|
|
207
|
-
"""Add technical analysis features"""
|
|
207
|
+
"""Add technical analysis features."""
|
|
208
208
|
logger.info("Adding technical features")
|
|
209
209
|
|
|
210
210
|
# Merge stock price data
|
|
@@ -254,7 +254,7 @@ class StockRecommendationEngine:
|
|
|
254
254
|
def _add_political_features(
|
|
255
255
|
self, df: pd.DataFrame, politician_metadata: Optional[pd.DataFrame]
|
|
256
256
|
) -> pd.DataFrame:
|
|
257
|
-
"""Add political influence features"""
|
|
257
|
+
"""Add political influence features."""
|
|
258
258
|
logger.info("Adding political features")
|
|
259
259
|
|
|
260
260
|
# Political influence features
|
|
@@ -275,7 +275,7 @@ class StockRecommendationEngine:
|
|
|
275
275
|
stock_price_data: pd.DataFrame,
|
|
276
276
|
market_data: Optional[Dict[str, pd.DataFrame]],
|
|
277
277
|
) -> pd.DataFrame:
|
|
278
|
-
"""Add market regime features"""
|
|
278
|
+
"""Add market regime features."""
|
|
279
279
|
logger.info("Adding market regime features")
|
|
280
280
|
|
|
281
281
|
# Add market regime features from stock price data
|
|
@@ -294,7 +294,7 @@ class StockRecommendationEngine:
|
|
|
294
294
|
return df
|
|
295
295
|
|
|
296
296
|
def _add_ensemble_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
297
|
-
"""Add ensemble features"""
|
|
297
|
+
"""Add ensemble features."""
|
|
298
298
|
logger.info("Adding ensemble features")
|
|
299
299
|
|
|
300
300
|
# Build ensemble features
|
|
@@ -309,7 +309,7 @@ class StockRecommendationEngine:
|
|
|
309
309
|
return df
|
|
310
310
|
|
|
311
311
|
def _add_interaction_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
312
|
-
"""Add feature interactions"""
|
|
312
|
+
"""Add feature interactions."""
|
|
313
313
|
logger.info("Adding interaction features")
|
|
314
314
|
|
|
315
315
|
# Get important feature pairs (mock implementation)
|
|
@@ -333,7 +333,7 @@ class StockRecommendationEngine:
|
|
|
333
333
|
return df
|
|
334
334
|
|
|
335
335
|
def _perform_feature_selection(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
336
|
-
"""Perform feature selection"""
|
|
336
|
+
"""Perform feature selection."""
|
|
337
337
|
logger.info("Performing feature selection")
|
|
338
338
|
|
|
339
339
|
# Create a synthetic target for feature selection if none exists
|
|
@@ -387,7 +387,7 @@ class StockRecommendationEngine:
|
|
|
387
387
|
def _generate_stock_recommendation(
|
|
388
388
|
self, stock_data: pd.DataFrame, ticker: str
|
|
389
389
|
) -> Optional[RecommendationResult]:
|
|
390
|
-
"""Generate recommendation for a specific stock"""
|
|
390
|
+
"""Generate recommendation for a specific stock."""
|
|
391
391
|
|
|
392
392
|
try:
|
|
393
393
|
# Calculate component scores
|
|
@@ -460,7 +460,7 @@ class StockRecommendationEngine:
|
|
|
460
460
|
return None
|
|
461
461
|
|
|
462
462
|
def _calculate_technical_score(self, stock_data: pd.DataFrame) -> float:
|
|
463
|
-
"""Calculate technical analysis score"""
|
|
463
|
+
"""Calculate technical analysis score."""
|
|
464
464
|
try:
|
|
465
465
|
technical_indicators = []
|
|
466
466
|
|
|
@@ -497,7 +497,7 @@ class StockRecommendationEngine:
|
|
|
497
497
|
return 0.5
|
|
498
498
|
|
|
499
499
|
def _calculate_political_score(self, stock_data: pd.DataFrame) -> float:
|
|
500
|
-
"""Calculate political influence score"""
|
|
500
|
+
"""Calculate political influence score."""
|
|
501
501
|
try:
|
|
502
502
|
political_factors = []
|
|
503
503
|
|
|
@@ -528,7 +528,7 @@ class StockRecommendationEngine:
|
|
|
528
528
|
return 0.5
|
|
529
529
|
|
|
530
530
|
def _calculate_regime_score(self, stock_data: pd.DataFrame) -> float:
|
|
531
|
-
"""Calculate market regime score"""
|
|
531
|
+
"""Calculate market regime score."""
|
|
532
532
|
try:
|
|
533
533
|
regime_factors = []
|
|
534
534
|
|
|
@@ -571,7 +571,7 @@ class StockRecommendationEngine:
|
|
|
571
571
|
return 0.5
|
|
572
572
|
|
|
573
573
|
def _calculate_ensemble_score(self, stock_data: pd.DataFrame) -> float:
|
|
574
|
-
"""Calculate ensemble model score"""
|
|
574
|
+
"""Calculate ensemble model score."""
|
|
575
575
|
try:
|
|
576
576
|
# Use cluster-based scoring as proxy for ensemble
|
|
577
577
|
ensemble_factors = []
|
|
@@ -596,7 +596,7 @@ class StockRecommendationEngine:
|
|
|
596
596
|
return 0.5
|
|
597
597
|
|
|
598
598
|
def _assess_risk_level(self, stock_data: pd.DataFrame) -> str:
|
|
599
|
-
"""Assess risk level for the stock"""
|
|
599
|
+
"""Assess risk level for the stock."""
|
|
600
600
|
try:
|
|
601
601
|
risk_factors = []
|
|
602
602
|
|
|
@@ -629,11 +629,11 @@ class StockRecommendationEngine:
|
|
|
629
629
|
return "medium"
|
|
630
630
|
|
|
631
631
|
def _risk_to_numeric(self, risk_level: str) -> float:
|
|
632
|
-
"""Convert risk level to numeric value"""
|
|
632
|
+
"""Convert risk level to numeric value."""
|
|
633
633
|
return {"low": 0.2, "medium": 0.5, "high": 0.8}.get(risk_level, 0.5)
|
|
634
634
|
|
|
635
635
|
def _calculate_confidence(self, stock_data: pd.DataFrame, final_score: float) -> float:
|
|
636
|
-
"""Calculate confidence in the recommendation"""
|
|
636
|
+
"""Calculate confidence in the recommendation."""
|
|
637
637
|
try:
|
|
638
638
|
confidence_factors = []
|
|
639
639
|
|
|
@@ -658,7 +658,7 @@ class StockRecommendationEngine:
|
|
|
658
658
|
def _generate_outlooks(
|
|
659
659
|
self, stock_data: pd.DataFrame, final_score: float
|
|
660
660
|
) -> Tuple[str, str, str]:
|
|
661
|
-
"""Generate short, medium, and long-term outlooks"""
|
|
661
|
+
"""Generate short, medium, and long-term outlooks."""
|
|
662
662
|
|
|
663
663
|
def score_to_outlook(score):
|
|
664
664
|
if score >= 0.7:
|
|
@@ -676,7 +676,7 @@ class StockRecommendationEngine:
|
|
|
676
676
|
return short_term, medium_term, long_term
|
|
677
677
|
|
|
678
678
|
def _get_key_features(self, stock_data: pd.DataFrame) -> Tuple[List[str], Dict[str, float]]:
|
|
679
|
-
"""Get key features and their importance"""
|
|
679
|
+
"""Get key features and their importance."""
|
|
680
680
|
try:
|
|
681
681
|
# Get numerical features
|
|
682
682
|
numerical_features = [
|
|
@@ -695,7 +695,7 @@ class StockRecommendationEngine:
|
|
|
695
695
|
variance = stock_data[feature].var()
|
|
696
696
|
importance = value * (1 + variance)
|
|
697
697
|
feature_importance[feature] = importance
|
|
698
|
-
except:
|
|
698
|
+
except Exception:
|
|
699
699
|
feature_importance[feature] = 0
|
|
700
700
|
|
|
701
701
|
# Sort by importance
|
|
@@ -715,7 +715,7 @@ class StockRecommendationEngine:
|
|
|
715
715
|
def _generate_explanation(
|
|
716
716
|
self, stock_data: pd.DataFrame, final_score: float, key_features: List[str]
|
|
717
717
|
) -> str:
|
|
718
|
-
"""Generate human-readable explanation for the recommendation"""
|
|
718
|
+
"""Generate human-readable explanation for the recommendation."""
|
|
719
719
|
|
|
720
720
|
try:
|
|
721
721
|
if final_score >= 0.7:
|
|
@@ -746,7 +746,7 @@ class StockRecommendationEngine:
|
|
|
746
746
|
return "Recommendation based on comprehensive analysis."
|
|
747
747
|
|
|
748
748
|
def _generate_warnings(self, stock_data: pd.DataFrame, final_score: float) -> List[str]:
|
|
749
|
-
"""Generate warnings for the recommendation"""
|
|
749
|
+
"""Generate warnings for the recommendation."""
|
|
750
750
|
|
|
751
751
|
warnings = []
|
|
752
752
|
|
|
@@ -777,7 +777,7 @@ class StockRecommendationEngine:
|
|
|
777
777
|
return warnings
|
|
778
778
|
|
|
779
779
|
def save_model_artifacts(self, artifacts_dir: Path):
|
|
780
|
-
"""Save model artifacts and configurations"""
|
|
780
|
+
"""Save model artifacts and configurations."""
|
|
781
781
|
artifacts_dir.mkdir(parents=True, exist_ok=True)
|
|
782
782
|
|
|
783
783
|
# Save configuration
|
|
@@ -792,7 +792,7 @@ class StockRecommendationEngine:
|
|
|
792
792
|
logger.info(f"Saved model artifacts to {artifacts_dir}")
|
|
793
793
|
|
|
794
794
|
def load_model_artifacts(self, artifacts_dir: Path):
|
|
795
|
-
"""Load model artifacts and configurations"""
|
|
795
|
+
"""Load model artifacts and configurations."""
|
|
796
796
|
try:
|
|
797
797
|
# Load configuration
|
|
798
798
|
config_path = artifacts_dir / "recommendation_config.joblib"
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
"""Stock-specific feature engineering for recommendation models"""
|
|
1
|
+
"""Stock-specific feature engineering for recommendation models."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import warnings
|
|
5
|
-
from collections import defaultdict
|
|
6
4
|
from dataclasses import dataclass
|
|
7
|
-
from
|
|
8
|
-
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
5
|
+
from typing import Dict, List, Optional, Tuple
|
|
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 StockFeatureConfig:
|
|
18
|
-
"""Configuration for stock feature extraction"""
|
|
15
|
+
"""Configuration for stock feature extraction."""
|
|
19
16
|
|
|
20
17
|
# Technical indicator periods
|
|
21
18
|
sma_periods: List[int] = None
|
|
@@ -50,13 +47,13 @@ class StockFeatureConfig:
|
|
|
50
47
|
|
|
51
48
|
|
|
52
49
|
class StockRecommendationFeatures:
|
|
53
|
-
"""Core stock recommendation feature extractor"""
|
|
50
|
+
"""Core stock recommendation feature extractor."""
|
|
54
51
|
|
|
55
52
|
def __init__(self, config: Optional[StockFeatureConfig] = None):
|
|
56
53
|
self.config = config or StockFeatureConfig()
|
|
57
54
|
|
|
58
55
|
def extract_features(self, stock_data: pd.DataFrame) -> pd.DataFrame:
|
|
59
|
-
"""Extract stock recommendation features"""
|
|
56
|
+
"""Extract stock recommendation features."""
|
|
60
57
|
logger.info("Extracting stock recommendation features")
|
|
61
58
|
|
|
62
59
|
df = stock_data.copy()
|
|
@@ -89,7 +86,7 @@ class StockRecommendationFeatures:
|
|
|
89
86
|
return df
|
|
90
87
|
|
|
91
88
|
def _extract_price_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
92
|
-
"""Extract price-based features"""
|
|
89
|
+
"""Extract price-based features."""
|
|
93
90
|
# Basic price relationships
|
|
94
91
|
df["hl_ratio"] = (df["high"] - df["low"]) / df["close"]
|
|
95
92
|
df["oc_ratio"] = (df["open"] - df["close"]) / df["close"]
|
|
@@ -125,7 +122,7 @@ class StockRecommendationFeatures:
|
|
|
125
122
|
return df
|
|
126
123
|
|
|
127
124
|
def _extract_volume_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
128
|
-
"""Extract volume-based features"""
|
|
125
|
+
"""Extract volume-based features."""
|
|
129
126
|
# Volume moving averages
|
|
130
127
|
for period in self.config.volume_ma_periods:
|
|
131
128
|
df[f"volume_ma_{period}"] = df["volume"].rolling(window=period).mean()
|
|
@@ -158,7 +155,7 @@ class StockRecommendationFeatures:
|
|
|
158
155
|
return df
|
|
159
156
|
|
|
160
157
|
def _extract_volatility_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
161
|
-
"""Extract volatility-based features"""
|
|
158
|
+
"""Extract volatility-based features."""
|
|
162
159
|
# Calculate returns
|
|
163
160
|
df["returns"] = df["close"].pct_change()
|
|
164
161
|
df["log_returns"] = np.log(df["close"] / df["close"].shift(1))
|
|
@@ -197,7 +194,7 @@ class StockRecommendationFeatures:
|
|
|
197
194
|
return df
|
|
198
195
|
|
|
199
196
|
def _extract_momentum_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
200
|
-
"""Extract momentum-based features"""
|
|
197
|
+
"""Extract momentum-based features."""
|
|
201
198
|
# RSI (Relative Strength Index)
|
|
202
199
|
delta = df["close"].diff()
|
|
203
200
|
gain = delta.where(delta > 0, 0).rolling(window=self.config.rsi_period).mean()
|
|
@@ -234,7 +231,7 @@ class StockRecommendationFeatures:
|
|
|
234
231
|
return df
|
|
235
232
|
|
|
236
233
|
def _extract_trend_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
237
|
-
"""Extract trend-based features"""
|
|
234
|
+
"""Extract trend-based features."""
|
|
238
235
|
# Trend strength
|
|
239
236
|
for window in [10, 20, 50]:
|
|
240
237
|
# Linear regression slope
|
|
@@ -255,7 +252,7 @@ class StockRecommendationFeatures:
|
|
|
255
252
|
ss_res = np.sum((prices - predicted) ** 2)
|
|
256
253
|
ss_tot = np.sum((prices - np.mean(prices)) ** 2)
|
|
257
254
|
return 1 - (ss_res / ss_tot) if ss_tot != 0 else 0
|
|
258
|
-
except:
|
|
255
|
+
except Exception:
|
|
259
256
|
return 0
|
|
260
257
|
|
|
261
258
|
df[f"trend_strength_{window}"] = (
|
|
@@ -283,13 +280,13 @@ class StockRecommendationFeatures:
|
|
|
283
280
|
|
|
284
281
|
|
|
285
282
|
class TechnicalIndicatorFeatures:
|
|
286
|
-
"""Advanced technical indicator features"""
|
|
283
|
+
"""Advanced technical indicator features."""
|
|
287
284
|
|
|
288
285
|
def __init__(self, config: Optional[StockFeatureConfig] = None):
|
|
289
286
|
self.config = config or StockFeatureConfig()
|
|
290
287
|
|
|
291
288
|
def extract_advanced_indicators(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
292
|
-
"""Extract advanced technical indicators"""
|
|
289
|
+
"""Extract advanced technical indicators."""
|
|
293
290
|
df = df.copy()
|
|
294
291
|
|
|
295
292
|
# Williams %R
|
|
@@ -315,13 +312,13 @@ class TechnicalIndicatorFeatures:
|
|
|
315
312
|
return df
|
|
316
313
|
|
|
317
314
|
def _williams_r(self, df: pd.DataFrame, period: int = 14) -> pd.Series:
|
|
318
|
-
"""Williams %R oscillator"""
|
|
315
|
+
"""Williams %R oscillator."""
|
|
319
316
|
highest_high = df["high"].rolling(window=period).max()
|
|
320
317
|
lowest_low = df["low"].rolling(window=period).min()
|
|
321
318
|
return -100 * (highest_high - df["close"]) / (highest_high - lowest_low)
|
|
322
319
|
|
|
323
320
|
def _commodity_channel_index(self, df: pd.DataFrame, period: int = 20) -> pd.Series:
|
|
324
|
-
"""Commodity Channel Index"""
|
|
321
|
+
"""Commodity Channel Index."""
|
|
325
322
|
typical_price = (df["high"] + df["low"] + df["close"]) / 3
|
|
326
323
|
sma_tp = typical_price.rolling(window=period).mean()
|
|
327
324
|
mad = typical_price.rolling(window=period).apply(
|
|
@@ -330,7 +327,7 @@ class TechnicalIndicatorFeatures:
|
|
|
330
327
|
return (typical_price - sma_tp) / (0.015 * mad)
|
|
331
328
|
|
|
332
329
|
def _money_flow_index(self, df: pd.DataFrame, period: int = 14) -> pd.Series:
|
|
333
|
-
"""Money Flow Index"""
|
|
330
|
+
"""Money Flow Index."""
|
|
334
331
|
typical_price = (df["high"] + df["low"] + df["close"]) / 3
|
|
335
332
|
money_flow = typical_price * df["volume"]
|
|
336
333
|
|
|
@@ -344,7 +341,7 @@ class TechnicalIndicatorFeatures:
|
|
|
344
341
|
return mfi
|
|
345
342
|
|
|
346
343
|
def _aroon_indicator(self, df: pd.DataFrame, period: int = 25) -> Tuple[pd.Series, pd.Series]:
|
|
347
|
-
"""Aroon Up and Aroon Down indicators"""
|
|
344
|
+
"""Aroon Up and Aroon Down indicators."""
|
|
348
345
|
aroon_up = (
|
|
349
346
|
100 * (period - df["high"].rolling(window=period).apply(np.argmax, raw=False)) / period
|
|
350
347
|
)
|
|
@@ -354,9 +351,9 @@ class TechnicalIndicatorFeatures:
|
|
|
354
351
|
return aroon_up, aroon_down
|
|
355
352
|
|
|
356
353
|
def _parabolic_sar(self, df: pd.DataFrame) -> pd.Series:
|
|
357
|
-
"""Parabolic SAR indicator (simplified version)"""
|
|
354
|
+
"""Parabolic SAR indicator (simplified version)."""
|
|
358
355
|
# Simplified PSAR implementation
|
|
359
|
-
|
|
356
|
+
df["high"].values
|
|
360
357
|
low = df["low"].values
|
|
361
358
|
close = df["close"].values
|
|
362
359
|
|
|
@@ -371,7 +368,7 @@ class TechnicalIndicatorFeatures:
|
|
|
371
368
|
return pd.Series(psar, index=df.index)
|
|
372
369
|
|
|
373
370
|
def _ichimoku_cloud(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
374
|
-
"""Ichimoku Cloud components"""
|
|
371
|
+
"""Ichimoku Cloud components."""
|
|
375
372
|
# Tenkan-sen (Conversion Line)
|
|
376
373
|
tenkan_high = df["high"].rolling(window=9).max()
|
|
377
374
|
tenkan_low = df["low"].rolling(window=9).min()
|
|
@@ -408,13 +405,13 @@ class TechnicalIndicatorFeatures:
|
|
|
408
405
|
|
|
409
406
|
|
|
410
407
|
class MarketRegimeFeatures:
|
|
411
|
-
"""Market regime detection features"""
|
|
408
|
+
"""Market regime detection features."""
|
|
412
409
|
|
|
413
410
|
def __init__(self, config: Optional[StockFeatureConfig] = None):
|
|
414
411
|
self.config = config or StockFeatureConfig()
|
|
415
412
|
|
|
416
413
|
def extract_regime_features(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
417
|
-
"""Extract market regime features"""
|
|
414
|
+
"""Extract market regime features."""
|
|
418
415
|
df = df.copy()
|
|
419
416
|
|
|
420
417
|
# Volatility regime
|
|
@@ -432,7 +429,7 @@ class MarketRegimeFeatures:
|
|
|
432
429
|
return df
|
|
433
430
|
|
|
434
431
|
def _volatility_regime(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
435
|
-
"""Identify volatility regimes"""
|
|
432
|
+
"""Identify volatility regimes."""
|
|
436
433
|
returns = df["close"].pct_change()
|
|
437
434
|
vol_20 = returns.rolling(window=20).std() * np.sqrt(252)
|
|
438
435
|
|
|
@@ -451,7 +448,7 @@ class MarketRegimeFeatures:
|
|
|
451
448
|
return df
|
|
452
449
|
|
|
453
450
|
def _trend_regime(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
454
|
-
"""Identify trend regimes"""
|
|
451
|
+
"""Identify trend regimes."""
|
|
455
452
|
# Multiple timeframe trend analysis
|
|
456
453
|
for window in [20, 50, 200]:
|
|
457
454
|
sma = df["close"].rolling(window=window).mean()
|
|
@@ -475,7 +472,7 @@ class MarketRegimeFeatures:
|
|
|
475
472
|
return df
|
|
476
473
|
|
|
477
474
|
def _volume_regime(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
478
|
-
"""Identify volume regimes"""
|
|
475
|
+
"""Identify volume regimes."""
|
|
479
476
|
volume_ma = df["volume"].rolling(window=20).mean()
|
|
480
477
|
volume_ratio = df["volume"] / volume_ma
|
|
481
478
|
|
|
@@ -497,7 +494,7 @@ class MarketRegimeFeatures:
|
|
|
497
494
|
return df
|
|
498
495
|
|
|
499
496
|
def _market_stress_indicators(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
500
|
-
"""Market stress and fear indicators"""
|
|
497
|
+
"""Market stress and fear indicators."""
|
|
501
498
|
returns = df["close"].pct_change()
|
|
502
499
|
|
|
503
500
|
# Maximum drawdown
|
|
@@ -524,7 +521,7 @@ class MarketRegimeFeatures:
|
|
|
524
521
|
|
|
525
522
|
|
|
526
523
|
class CrossAssetFeatures:
|
|
527
|
-
"""Cross-asset and correlation features"""
|
|
524
|
+
"""Cross-asset and correlation features."""
|
|
528
525
|
|
|
529
526
|
def __init__(self):
|
|
530
527
|
pass
|
|
@@ -532,7 +529,7 @@ class CrossAssetFeatures:
|
|
|
532
529
|
def extract_cross_asset_features(
|
|
533
530
|
self, primary_df: pd.DataFrame, market_data: Dict[str, pd.DataFrame]
|
|
534
531
|
) -> pd.DataFrame:
|
|
535
|
-
"""Extract features based on relationships with other assets"""
|
|
532
|
+
"""Extract features based on relationships with other assets."""
|
|
536
533
|
df = primary_df.copy()
|
|
537
534
|
|
|
538
535
|
# Correlation with market indices
|
|
@@ -554,7 +551,7 @@ class CrossAssetFeatures:
|
|
|
554
551
|
covariance = np.cov(stock_ret, market_ret)[0][1]
|
|
555
552
|
market_variance = np.var(market_ret)
|
|
556
553
|
return covariance / market_variance if market_variance != 0 else 1.0
|
|
557
|
-
except:
|
|
554
|
+
except Exception:
|
|
558
555
|
return 1.0
|
|
559
556
|
|
|
560
557
|
rolling_beta = pd.Series(index=df.index, dtype=float)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Test script for feature engineering system"""
|
|
1
|
+
"""Test script for feature engineering system."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
@@ -17,7 +17,7 @@ logger = logging.getLogger(__name__)
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def generate_mock_trading_data(n_records: int = 100) -> pd.DataFrame:
|
|
20
|
-
"""Generate mock politician trading data"""
|
|
20
|
+
"""Generate mock politician trading data."""
|
|
21
21
|
np.random.seed(42)
|
|
22
22
|
|
|
23
23
|
politicians = ["Nancy Pelosi", "Mitch McConnell", "Chuck Schumer", "Kevin McCarthy"]
|
|
@@ -36,7 +36,7 @@ def generate_mock_trading_data(n_records: int = 100) -> pd.DataFrame:
|
|
|
36
36
|
records = []
|
|
37
37
|
start_date = datetime.now() - timedelta(days=365)
|
|
38
38
|
|
|
39
|
-
for
|
|
39
|
+
for _i in range(n_records):
|
|
40
40
|
days_ago = np.random.randint(0, 365)
|
|
41
41
|
trade_date = start_date + timedelta(days=days_ago)
|
|
42
42
|
|
|
@@ -60,7 +60,7 @@ def generate_mock_trading_data(n_records: int = 100) -> pd.DataFrame:
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def generate_mock_stock_data(tickers: list, days: int = 365) -> pd.DataFrame:
|
|
63
|
-
"""Generate mock stock price data"""
|
|
63
|
+
"""Generate mock stock price data."""
|
|
64
64
|
np.random.seed(42)
|
|
65
65
|
|
|
66
66
|
stock_data = []
|
|
@@ -99,7 +99,7 @@ def generate_mock_stock_data(tickers: list, days: int = 365) -> pd.DataFrame:
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def test_stock_features():
|
|
102
|
-
"""Test stock feature extraction"""
|
|
102
|
+
"""Test stock feature extraction."""
|
|
103
103
|
logger.info("Testing stock features...")
|
|
104
104
|
|
|
105
105
|
from stock_features import StockRecommendationFeatures, TechnicalIndicatorFeatures
|
|
@@ -135,7 +135,7 @@ def test_stock_features():
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
def test_political_features():
|
|
138
|
-
"""Test political feature extraction"""
|
|
138
|
+
"""Test political feature extraction."""
|
|
139
139
|
logger.info("Testing political features...")
|
|
140
140
|
|
|
141
141
|
from political_features import PoliticalInfluenceFeatures
|
|
@@ -171,7 +171,7 @@ def test_political_features():
|
|
|
171
171
|
|
|
172
172
|
|
|
173
173
|
def test_ensemble_features():
|
|
174
|
-
"""Test ensemble feature engineering"""
|
|
174
|
+
"""Test ensemble feature engineering."""
|
|
175
175
|
logger.info("Testing ensemble features...")
|
|
176
176
|
|
|
177
177
|
from ensemble_features import EnsembleFeatureBuilder
|
|
@@ -207,7 +207,7 @@ def test_ensemble_features():
|
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
def test_recommendation_engine():
|
|
210
|
-
"""Test the full recommendation engine"""
|
|
210
|
+
"""Test the full recommendation engine."""
|
|
211
211
|
logger.info("Testing recommendation engine...")
|
|
212
212
|
|
|
213
213
|
from recommendation_engine import RecommendationConfig, StockRecommendationEngine
|
|
@@ -257,12 +257,11 @@ def test_recommendation_engine():
|
|
|
257
257
|
|
|
258
258
|
|
|
259
259
|
def test_feature_integration():
|
|
260
|
-
"""Test integration of all feature components"""
|
|
260
|
+
"""Test integration of all feature components."""
|
|
261
261
|
logger.info("Testing feature integration...")
|
|
262
262
|
|
|
263
263
|
from ensemble_features import EnsembleFeatureBuilder
|
|
264
264
|
from political_features import PoliticalInfluenceFeatures
|
|
265
|
-
from stock_features import StockRecommendationFeatures
|
|
266
265
|
|
|
267
266
|
# Generate test data
|
|
268
267
|
trading_data = generate_mock_trading_data(30)
|
|
@@ -304,7 +303,7 @@ def test_feature_integration():
|
|
|
304
303
|
|
|
305
304
|
|
|
306
305
|
def main():
|
|
307
|
-
"""Run all feature engineering tests"""
|
|
306
|
+
"""Run all feature engineering tests."""
|
|
308
307
|
logger.info("Starting feature engineering tests...")
|
|
309
308
|
|
|
310
309
|
try:
|
mcli/ml/logging.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Logging configuration for ML system"""
|
|
1
|
+
"""Logging configuration for ML system."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
@@ -11,7 +11,7 @@ from mcli.ml.config import settings
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class StructuredFormatter(logging.Formatter):
|
|
14
|
-
"""JSON structured logging formatter"""
|
|
14
|
+
"""JSON structured logging formatter."""
|
|
15
15
|
|
|
16
16
|
def format(self, record):
|
|
17
17
|
log_obj = {
|
|
@@ -34,7 +34,7 @@ class StructuredFormatter(logging.Formatter):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def setup_logging():
|
|
37
|
-
"""Configure logging for the application"""
|
|
37
|
+
"""Configure logging for the application."""
|
|
38
38
|
|
|
39
39
|
# Create logs directory
|
|
40
40
|
log_dir = Path("logs")
|
|
@@ -76,5 +76,5 @@ def setup_logging():
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def get_logger(name: str) -> logging.Logger:
|
|
79
|
-
"""Get a logger instance"""
|
|
79
|
+
"""Get a logger instance."""
|
|
80
80
|
return logging.getLogger(name)
|
mcli/ml/mlops/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""MLOps components for ML pipeline management"""
|
|
1
|
+
"""MLOps components for ML pipeline management."""
|
|
2
2
|
|
|
3
3
|
from .experiment_tracker import ExperimentRun, ExperimentTracker, MLflowConfig, ModelRegistry
|
|
4
4
|
from .model_serving import ModelEndpoint, ModelServer, PredictionService
|