mcli-framework 7.0.0__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/chat_cmd.py +42 -0
- mcli/app/commands_cmd.py +226 -0
- mcli/app/completion_cmd.py +216 -0
- mcli/app/completion_helpers.py +288 -0
- mcli/app/cron_test_cmd.py +697 -0
- mcli/app/logs_cmd.py +419 -0
- mcli/app/main.py +492 -0
- mcli/app/model/model.py +1060 -0
- mcli/app/model_cmd.py +227 -0
- mcli/app/redis_cmd.py +269 -0
- mcli/app/video/video.py +1114 -0
- mcli/app/visual_cmd.py +303 -0
- mcli/chat/chat.py +2409 -0
- mcli/chat/command_rag.py +514 -0
- mcli/chat/enhanced_chat.py +652 -0
- mcli/chat/system_controller.py +1010 -0
- mcli/chat/system_integration.py +1016 -0
- mcli/cli.py +25 -0
- mcli/config.toml +20 -0
- mcli/lib/api/api.py +586 -0
- mcli/lib/api/daemon_client.py +203 -0
- mcli/lib/api/daemon_client_local.py +44 -0
- mcli/lib/api/daemon_decorator.py +217 -0
- mcli/lib/api/mcli_decorators.py +1032 -0
- mcli/lib/auth/auth.py +85 -0
- mcli/lib/auth/aws_manager.py +85 -0
- mcli/lib/auth/azure_manager.py +91 -0
- mcli/lib/auth/credential_manager.py +192 -0
- mcli/lib/auth/gcp_manager.py +93 -0
- mcli/lib/auth/key_manager.py +117 -0
- mcli/lib/auth/mcli_manager.py +93 -0
- mcli/lib/auth/token_manager.py +75 -0
- mcli/lib/auth/token_util.py +1011 -0
- mcli/lib/config/config.py +47 -0
- mcli/lib/discovery/__init__.py +1 -0
- mcli/lib/discovery/command_discovery.py +274 -0
- mcli/lib/erd/erd.py +1345 -0
- mcli/lib/erd/generate_graph.py +453 -0
- mcli/lib/files/files.py +76 -0
- mcli/lib/fs/fs.py +109 -0
- mcli/lib/lib.py +29 -0
- mcli/lib/logger/logger.py +611 -0
- mcli/lib/performance/optimizer.py +409 -0
- mcli/lib/performance/rust_bridge.py +502 -0
- mcli/lib/performance/uvloop_config.py +154 -0
- mcli/lib/pickles/pickles.py +50 -0
- mcli/lib/search/cached_vectorizer.py +479 -0
- mcli/lib/services/data_pipeline.py +460 -0
- mcli/lib/services/lsh_client.py +441 -0
- mcli/lib/services/redis_service.py +387 -0
- mcli/lib/shell/shell.py +137 -0
- mcli/lib/toml/toml.py +33 -0
- mcli/lib/ui/styling.py +47 -0
- mcli/lib/ui/visual_effects.py +634 -0
- mcli/lib/watcher/watcher.py +185 -0
- mcli/ml/api/app.py +215 -0
- mcli/ml/api/middleware.py +224 -0
- mcli/ml/api/routers/admin_router.py +12 -0
- mcli/ml/api/routers/auth_router.py +244 -0
- mcli/ml/api/routers/backtest_router.py +12 -0
- mcli/ml/api/routers/data_router.py +12 -0
- mcli/ml/api/routers/model_router.py +302 -0
- mcli/ml/api/routers/monitoring_router.py +12 -0
- mcli/ml/api/routers/portfolio_router.py +12 -0
- mcli/ml/api/routers/prediction_router.py +267 -0
- mcli/ml/api/routers/trade_router.py +12 -0
- mcli/ml/api/routers/websocket_router.py +76 -0
- mcli/ml/api/schemas.py +64 -0
- mcli/ml/auth/auth_manager.py +425 -0
- mcli/ml/auth/models.py +154 -0
- mcli/ml/auth/permissions.py +302 -0
- mcli/ml/backtesting/backtest_engine.py +502 -0
- mcli/ml/backtesting/performance_metrics.py +393 -0
- mcli/ml/cache.py +400 -0
- mcli/ml/cli/main.py +398 -0
- mcli/ml/config/settings.py +394 -0
- mcli/ml/configs/dvc_config.py +230 -0
- mcli/ml/configs/mlflow_config.py +131 -0
- mcli/ml/configs/mlops_manager.py +293 -0
- mcli/ml/dashboard/app.py +532 -0
- mcli/ml/dashboard/app_integrated.py +738 -0
- mcli/ml/dashboard/app_supabase.py +560 -0
- mcli/ml/dashboard/app_training.py +615 -0
- mcli/ml/dashboard/cli.py +51 -0
- mcli/ml/data_ingestion/api_connectors.py +501 -0
- mcli/ml/data_ingestion/data_pipeline.py +567 -0
- mcli/ml/data_ingestion/stream_processor.py +512 -0
- mcli/ml/database/migrations/env.py +94 -0
- mcli/ml/database/models.py +667 -0
- mcli/ml/database/session.py +200 -0
- mcli/ml/experimentation/ab_testing.py +845 -0
- mcli/ml/features/ensemble_features.py +607 -0
- mcli/ml/features/political_features.py +676 -0
- mcli/ml/features/recommendation_engine.py +809 -0
- mcli/ml/features/stock_features.py +573 -0
- mcli/ml/features/test_feature_engineering.py +346 -0
- mcli/ml/logging.py +85 -0
- mcli/ml/mlops/data_versioning.py +518 -0
- mcli/ml/mlops/experiment_tracker.py +377 -0
- mcli/ml/mlops/model_serving.py +481 -0
- mcli/ml/mlops/pipeline_orchestrator.py +614 -0
- mcli/ml/models/base_models.py +324 -0
- mcli/ml/models/ensemble_models.py +675 -0
- mcli/ml/models/recommendation_models.py +474 -0
- mcli/ml/models/test_models.py +487 -0
- mcli/ml/monitoring/drift_detection.py +676 -0
- mcli/ml/monitoring/metrics.py +45 -0
- mcli/ml/optimization/portfolio_optimizer.py +834 -0
- mcli/ml/preprocessing/data_cleaners.py +451 -0
- mcli/ml/preprocessing/feature_extractors.py +491 -0
- mcli/ml/preprocessing/ml_pipeline.py +382 -0
- mcli/ml/preprocessing/politician_trading_preprocessor.py +569 -0
- mcli/ml/preprocessing/test_preprocessing.py +294 -0
- mcli/ml/scripts/populate_sample_data.py +200 -0
- mcli/ml/tasks.py +400 -0
- mcli/ml/tests/test_integration.py +429 -0
- mcli/ml/tests/test_training_dashboard.py +387 -0
- mcli/public/oi/oi.py +15 -0
- mcli/public/public.py +4 -0
- mcli/self/self_cmd.py +1246 -0
- mcli/workflow/daemon/api_daemon.py +800 -0
- mcli/workflow/daemon/async_command_database.py +681 -0
- mcli/workflow/daemon/async_process_manager.py +591 -0
- mcli/workflow/daemon/client.py +530 -0
- mcli/workflow/daemon/commands.py +1196 -0
- mcli/workflow/daemon/daemon.py +905 -0
- mcli/workflow/daemon/daemon_api.py +59 -0
- mcli/workflow/daemon/enhanced_daemon.py +571 -0
- mcli/workflow/daemon/process_cli.py +244 -0
- mcli/workflow/daemon/process_manager.py +439 -0
- mcli/workflow/daemon/test_daemon.py +275 -0
- mcli/workflow/dashboard/dashboard_cmd.py +113 -0
- mcli/workflow/docker/docker.py +0 -0
- mcli/workflow/file/file.py +100 -0
- mcli/workflow/gcloud/config.toml +21 -0
- mcli/workflow/gcloud/gcloud.py +58 -0
- mcli/workflow/git_commit/ai_service.py +328 -0
- mcli/workflow/git_commit/commands.py +430 -0
- mcli/workflow/lsh_integration.py +355 -0
- mcli/workflow/model_service/client.py +594 -0
- mcli/workflow/model_service/download_and_run_efficient_models.py +288 -0
- mcli/workflow/model_service/lightweight_embedder.py +397 -0
- mcli/workflow/model_service/lightweight_model_server.py +714 -0
- mcli/workflow/model_service/lightweight_test.py +241 -0
- mcli/workflow/model_service/model_service.py +1955 -0
- mcli/workflow/model_service/ollama_efficient_runner.py +425 -0
- mcli/workflow/model_service/pdf_processor.py +386 -0
- mcli/workflow/model_service/test_efficient_runner.py +234 -0
- mcli/workflow/model_service/test_example.py +315 -0
- mcli/workflow/model_service/test_integration.py +131 -0
- mcli/workflow/model_service/test_new_features.py +149 -0
- mcli/workflow/openai/openai.py +99 -0
- mcli/workflow/politician_trading/commands.py +1790 -0
- mcli/workflow/politician_trading/config.py +134 -0
- mcli/workflow/politician_trading/connectivity.py +490 -0
- mcli/workflow/politician_trading/data_sources.py +395 -0
- mcli/workflow/politician_trading/database.py +410 -0
- mcli/workflow/politician_trading/demo.py +248 -0
- mcli/workflow/politician_trading/models.py +165 -0
- mcli/workflow/politician_trading/monitoring.py +413 -0
- mcli/workflow/politician_trading/scrapers.py +966 -0
- mcli/workflow/politician_trading/scrapers_california.py +412 -0
- mcli/workflow/politician_trading/scrapers_eu.py +377 -0
- mcli/workflow/politician_trading/scrapers_uk.py +350 -0
- mcli/workflow/politician_trading/scrapers_us_states.py +438 -0
- mcli/workflow/politician_trading/supabase_functions.py +354 -0
- mcli/workflow/politician_trading/workflow.py +852 -0
- mcli/workflow/registry/registry.py +180 -0
- mcli/workflow/repo/repo.py +223 -0
- mcli/workflow/scheduler/commands.py +493 -0
- mcli/workflow/scheduler/cron_parser.py +238 -0
- mcli/workflow/scheduler/job.py +182 -0
- mcli/workflow/scheduler/monitor.py +139 -0
- mcli/workflow/scheduler/persistence.py +324 -0
- mcli/workflow/scheduler/scheduler.py +679 -0
- mcli/workflow/sync/sync_cmd.py +437 -0
- mcli/workflow/sync/test_cmd.py +314 -0
- mcli/workflow/videos/videos.py +242 -0
- mcli/workflow/wakatime/wakatime.py +11 -0
- mcli/workflow/workflow.py +37 -0
- mcli_framework-7.0.0.dist-info/METADATA +479 -0
- mcli_framework-7.0.0.dist-info/RECORD +186 -0
- mcli_framework-7.0.0.dist-info/WHEEL +5 -0
- mcli_framework-7.0.0.dist-info/entry_points.txt +7 -0
- mcli_framework-7.0.0.dist-info/licenses/LICENSE +21 -0
- mcli_framework-7.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
"""Integration tests for the complete ML pipeline"""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../.."))
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import numpy as np
|
|
10
|
+
from datetime import datetime, timedelta
|
|
11
|
+
import tempfile
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
import logging
|
|
14
|
+
|
|
15
|
+
# Import all components
|
|
16
|
+
from ml.preprocessing.data_processor import DataProcessor, ProcessingConfig
|
|
17
|
+
from ml.features.stock_features import StockRecommendationFeatures
|
|
18
|
+
from ml.features.political_features import PoliticalInfluenceFeatures
|
|
19
|
+
from ml.features.ensemble_features import EnsembleFeatureBuilder
|
|
20
|
+
from ml.models.ensemble_models import DeepEnsembleModel, EnsembleConfig, ModelConfig
|
|
21
|
+
from ml.models.recommendation_models import StockRecommendationModel, RecommendationConfig
|
|
22
|
+
from ml.mlops.pipeline_orchestrator import MLPipeline, PipelineConfig, PipelineExecutor
|
|
23
|
+
from ml.mlops.experiment_tracker import ExperimentTracker, MLflowConfig, ModelRegistry
|
|
24
|
+
from ml.backtesting.backtest_engine import BacktestEngine, BacktestConfig, TradingStrategy
|
|
25
|
+
from ml.backtesting.performance_metrics import PerformanceAnalyzer
|
|
26
|
+
|
|
27
|
+
logging.basicConfig(level=logging.INFO)
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TestDataIntegration:
|
|
32
|
+
"""Test data processing integration"""
|
|
33
|
+
|
|
34
|
+
def test_data_pipeline(self):
|
|
35
|
+
"""Test complete data processing pipeline"""
|
|
36
|
+
# Generate mock data
|
|
37
|
+
trading_data = self._generate_mock_trading_data()
|
|
38
|
+
stock_data = self._generate_mock_stock_data()
|
|
39
|
+
|
|
40
|
+
# Initialize processor
|
|
41
|
+
config = ProcessingConfig()
|
|
42
|
+
processor = DataProcessor(config)
|
|
43
|
+
|
|
44
|
+
# Process data
|
|
45
|
+
processed_trading = processor.process_politician_trades(trading_data)
|
|
46
|
+
assert len(processed_trading) > 0
|
|
47
|
+
assert 'transaction_amount_cleaned' in processed_trading.columns
|
|
48
|
+
|
|
49
|
+
# Clean data
|
|
50
|
+
cleaned_data = processor.clean_data(processed_trading)
|
|
51
|
+
assert cleaned_data.isnull().sum().sum() == 0 # No nulls
|
|
52
|
+
|
|
53
|
+
def test_feature_extraction_pipeline(self):
|
|
54
|
+
"""Test feature extraction pipeline"""
|
|
55
|
+
# Generate mock data
|
|
56
|
+
trading_data = self._generate_mock_trading_data()
|
|
57
|
+
stock_data = self._generate_mock_stock_data()
|
|
58
|
+
|
|
59
|
+
# Extract features
|
|
60
|
+
stock_extractor = StockRecommendationFeatures()
|
|
61
|
+
political_extractor = PoliticalInfluenceFeatures()
|
|
62
|
+
ensemble_builder = EnsembleFeatureBuilder()
|
|
63
|
+
|
|
64
|
+
# Stock features
|
|
65
|
+
stock_features = stock_extractor.extract_features(stock_data)
|
|
66
|
+
assert stock_features.shape[1] > 20 # Should have many features
|
|
67
|
+
|
|
68
|
+
# Political features
|
|
69
|
+
political_features = political_extractor.extract_influence_features(trading_data)
|
|
70
|
+
assert 'total_influence' in political_features.columns
|
|
71
|
+
|
|
72
|
+
# Ensemble features
|
|
73
|
+
combined = pd.concat([political_features, stock_features], axis=1)
|
|
74
|
+
ensemble_features = ensemble_builder.build_ensemble_features(combined)
|
|
75
|
+
assert ensemble_features.shape[1] > combined.shape[1] # More features
|
|
76
|
+
|
|
77
|
+
def _generate_mock_trading_data(self):
|
|
78
|
+
"""Generate mock trading data"""
|
|
79
|
+
n_records = 100
|
|
80
|
+
data = []
|
|
81
|
+
for _ in range(n_records):
|
|
82
|
+
data.append({
|
|
83
|
+
'politician_name_cleaned': np.random.choice(['Pelosi', 'McConnell']),
|
|
84
|
+
'transaction_date_cleaned': datetime.now() - timedelta(days=np.random.randint(1, 365)),
|
|
85
|
+
'transaction_amount_cleaned': np.random.uniform(1000, 500000),
|
|
86
|
+
'transaction_type_cleaned': np.random.choice(['buy', 'sell']),
|
|
87
|
+
'ticker_cleaned': np.random.choice(['AAPL', 'MSFT', 'GOOGL'])
|
|
88
|
+
})
|
|
89
|
+
return pd.DataFrame(data)
|
|
90
|
+
|
|
91
|
+
def _generate_mock_stock_data(self):
|
|
92
|
+
"""Generate mock stock data"""
|
|
93
|
+
dates = pd.date_range(end=datetime.now(), periods=100)
|
|
94
|
+
tickers = ['AAPL', 'MSFT', 'GOOGL']
|
|
95
|
+
data = []
|
|
96
|
+
|
|
97
|
+
for ticker in tickers:
|
|
98
|
+
base_price = np.random.uniform(100, 300)
|
|
99
|
+
for date in dates:
|
|
100
|
+
price = base_price * (1 + np.random.normal(0, 0.02))
|
|
101
|
+
data.append({
|
|
102
|
+
'symbol': ticker,
|
|
103
|
+
'date': date,
|
|
104
|
+
'close': price,
|
|
105
|
+
'volume': np.random.randint(1000000, 10000000),
|
|
106
|
+
'open': price * 0.99,
|
|
107
|
+
'high': price * 1.01,
|
|
108
|
+
'low': price * 0.98
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
return pd.DataFrame(data)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class TestModelIntegration:
|
|
115
|
+
"""Test model training and prediction integration"""
|
|
116
|
+
|
|
117
|
+
def test_model_training_pipeline(self):
|
|
118
|
+
"""Test complete model training pipeline"""
|
|
119
|
+
# Generate data
|
|
120
|
+
X = np.random.randn(200, 50)
|
|
121
|
+
y = np.random.randint(0, 2, 200)
|
|
122
|
+
returns = np.random.normal(0.05, 0.15, 200)
|
|
123
|
+
risk_labels = np.random.choice([0, 1, 2], 200)
|
|
124
|
+
|
|
125
|
+
# Configure model
|
|
126
|
+
model_configs = [
|
|
127
|
+
ModelConfig(
|
|
128
|
+
model_type="mlp",
|
|
129
|
+
hidden_dims=[64, 32],
|
|
130
|
+
dropout_rate=0.2,
|
|
131
|
+
learning_rate=0.001,
|
|
132
|
+
weight_decay=1e-4,
|
|
133
|
+
batch_size=32,
|
|
134
|
+
epochs=2
|
|
135
|
+
)
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
ensemble_config = EnsembleConfig(base_models=model_configs)
|
|
139
|
+
rec_config = RecommendationConfig(ensemble_config=ensemble_config)
|
|
140
|
+
|
|
141
|
+
# Train model
|
|
142
|
+
model = StockRecommendationModel(X.shape[1], rec_config)
|
|
143
|
+
assert model is not None
|
|
144
|
+
|
|
145
|
+
# Generate predictions
|
|
146
|
+
predictions = model.predict(X[:10])
|
|
147
|
+
assert len(predictions) == 10
|
|
148
|
+
|
|
149
|
+
def test_model_serving(self):
|
|
150
|
+
"""Test model serving capabilities"""
|
|
151
|
+
from ml.mlops.model_serving import ModelEndpoint, PredictionRequest
|
|
152
|
+
|
|
153
|
+
# Create endpoint
|
|
154
|
+
endpoint = ModelEndpoint()
|
|
155
|
+
|
|
156
|
+
# Create request
|
|
157
|
+
request = PredictionRequest(
|
|
158
|
+
trading_data={'politician': 'Test', 'amount': 10000},
|
|
159
|
+
tickers=['AAPL', 'MSFT']
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Generate prediction (async would need event loop)
|
|
163
|
+
# This is simplified testing
|
|
164
|
+
assert endpoint is not None
|
|
165
|
+
assert request is not None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class TestPipelineIntegration:
|
|
169
|
+
"""Test complete ML pipeline integration"""
|
|
170
|
+
|
|
171
|
+
def test_end_to_end_pipeline(self):
|
|
172
|
+
"""Test complete end-to-end pipeline"""
|
|
173
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
174
|
+
# Configure pipeline
|
|
175
|
+
config = PipelineConfig(
|
|
176
|
+
data_dir=Path(tmpdir) / "data",
|
|
177
|
+
model_dir=Path(tmpdir) / "models",
|
|
178
|
+
output_dir=Path(tmpdir) / "outputs",
|
|
179
|
+
enable_mlflow=False # Disable for testing
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Create pipeline
|
|
183
|
+
pipeline = MLPipeline(config)
|
|
184
|
+
|
|
185
|
+
# Run pipeline (with mock data)
|
|
186
|
+
result = pipeline.run()
|
|
187
|
+
|
|
188
|
+
assert 'model' in result
|
|
189
|
+
assert result['model'] is not None
|
|
190
|
+
|
|
191
|
+
def test_pipeline_with_mlflow(self):
|
|
192
|
+
"""Test pipeline with MLflow tracking"""
|
|
193
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
194
|
+
# Configure MLflow
|
|
195
|
+
mlflow_config = MLflowConfig(
|
|
196
|
+
tracking_uri=f"sqlite:///{tmpdir}/mlflow.db",
|
|
197
|
+
experiment_name="test_experiment"
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Configure pipeline
|
|
201
|
+
config = PipelineConfig(
|
|
202
|
+
data_dir=Path(tmpdir) / "data",
|
|
203
|
+
model_dir=Path(tmpdir) / "models",
|
|
204
|
+
enable_mlflow=True,
|
|
205
|
+
mlflow_config=mlflow_config
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Create and run pipeline
|
|
209
|
+
pipeline = MLPipeline(config)
|
|
210
|
+
result = pipeline.run()
|
|
211
|
+
|
|
212
|
+
assert result is not None
|
|
213
|
+
# MLflow should have logged the run
|
|
214
|
+
assert pipeline.experiment_tracker is not None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class TestBacktestIntegration:
|
|
218
|
+
"""Test backtesting framework integration"""
|
|
219
|
+
|
|
220
|
+
def test_backtesting_pipeline(self):
|
|
221
|
+
"""Test complete backtesting pipeline"""
|
|
222
|
+
# Generate mock price data
|
|
223
|
+
dates = pd.date_range(end=datetime.now(), periods=252)
|
|
224
|
+
price_data = []
|
|
225
|
+
|
|
226
|
+
for ticker in ['AAPL', 'MSFT', 'GOOGL', 'SPY']:
|
|
227
|
+
base_price = np.random.uniform(100, 300)
|
|
228
|
+
for date in dates:
|
|
229
|
+
price = base_price * (1 + np.random.normal(0, 0.02))
|
|
230
|
+
price_data.append({
|
|
231
|
+
'symbol': ticker,
|
|
232
|
+
'date': date,
|
|
233
|
+
'close': price,
|
|
234
|
+
'volume': np.random.randint(1000000, 10000000)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
price_df = pd.DataFrame(price_data)
|
|
238
|
+
|
|
239
|
+
# Configure backtest
|
|
240
|
+
config = BacktestConfig(
|
|
241
|
+
initial_capital=100000,
|
|
242
|
+
commission=0.001,
|
|
243
|
+
slippage=0.001,
|
|
244
|
+
max_positions=10,
|
|
245
|
+
benchmark='SPY'
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Create engine and strategy
|
|
249
|
+
engine = BacktestEngine(config)
|
|
250
|
+
strategy = TradingStrategy()
|
|
251
|
+
engine.set_strategy(strategy)
|
|
252
|
+
|
|
253
|
+
# Run backtest
|
|
254
|
+
result = engine.run(price_df)
|
|
255
|
+
|
|
256
|
+
assert result is not None
|
|
257
|
+
assert len(result.portfolio_value) > 0
|
|
258
|
+
assert result.metrics['total_return'] is not None
|
|
259
|
+
|
|
260
|
+
def test_performance_analysis(self):
|
|
261
|
+
"""Test performance analysis"""
|
|
262
|
+
# Generate mock returns
|
|
263
|
+
returns = pd.Series(np.random.normal(0.001, 0.02, 252))
|
|
264
|
+
benchmark_returns = pd.Series(np.random.normal(0.0008, 0.015, 252))
|
|
265
|
+
|
|
266
|
+
# Analyze performance
|
|
267
|
+
analyzer = PerformanceAnalyzer()
|
|
268
|
+
portfolio_metrics, risk_metrics = analyzer.calculate_metrics(
|
|
269
|
+
returns, benchmark_returns
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
assert portfolio_metrics.sharpe_ratio is not None
|
|
273
|
+
assert risk_metrics.value_at_risk_95 is not None
|
|
274
|
+
assert risk_metrics.beta is not None
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class TestSystemIntegration:
|
|
278
|
+
"""Test full system integration"""
|
|
279
|
+
|
|
280
|
+
def test_complete_workflow(self):
|
|
281
|
+
"""Test complete ML workflow from data to backtest"""
|
|
282
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
283
|
+
logger.info("Starting complete workflow test...")
|
|
284
|
+
|
|
285
|
+
# Step 1: Data Processing
|
|
286
|
+
logger.info("Step 1: Processing data...")
|
|
287
|
+
processor = DataProcessor(ProcessingConfig())
|
|
288
|
+
trading_data = self._generate_trading_data()
|
|
289
|
+
stock_data = self._generate_stock_data()
|
|
290
|
+
|
|
291
|
+
processed_trading = processor.process_politician_trades(trading_data)
|
|
292
|
+
assert len(processed_trading) > 0
|
|
293
|
+
|
|
294
|
+
# Step 2: Feature Engineering
|
|
295
|
+
logger.info("Step 2: Engineering features...")
|
|
296
|
+
political_extractor = PoliticalInfluenceFeatures()
|
|
297
|
+
features = political_extractor.extract_influence_features(processed_trading)
|
|
298
|
+
assert features.shape[1] > 5
|
|
299
|
+
|
|
300
|
+
# Step 3: Model Training
|
|
301
|
+
logger.info("Step 3: Training model...")
|
|
302
|
+
X = np.random.randn(100, 50)
|
|
303
|
+
y = np.random.randint(0, 2, 100)
|
|
304
|
+
|
|
305
|
+
model_configs = [
|
|
306
|
+
ModelConfig(
|
|
307
|
+
model_type="mlp",
|
|
308
|
+
hidden_dims=[32],
|
|
309
|
+
dropout_rate=0.2,
|
|
310
|
+
learning_rate=0.001,
|
|
311
|
+
weight_decay=1e-4,
|
|
312
|
+
batch_size=32,
|
|
313
|
+
epochs=1
|
|
314
|
+
)
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
ensemble_config = EnsembleConfig(base_models=model_configs)
|
|
318
|
+
rec_config = RecommendationConfig(ensemble_config=ensemble_config)
|
|
319
|
+
model = StockRecommendationModel(X.shape[1], rec_config)
|
|
320
|
+
|
|
321
|
+
# Step 4: Backtesting
|
|
322
|
+
logger.info("Step 4: Running backtest...")
|
|
323
|
+
backtest_config = BacktestConfig(initial_capital=100000)
|
|
324
|
+
engine = BacktestEngine(backtest_config)
|
|
325
|
+
strategy = TradingStrategy(model)
|
|
326
|
+
engine.set_strategy(strategy)
|
|
327
|
+
|
|
328
|
+
result = engine.run(stock_data)
|
|
329
|
+
assert result.metrics['total_return'] is not None
|
|
330
|
+
|
|
331
|
+
# Step 5: Performance Analysis
|
|
332
|
+
logger.info("Step 5: Analyzing performance...")
|
|
333
|
+
analyzer = PerformanceAnalyzer()
|
|
334
|
+
portfolio_metrics, risk_metrics = analyzer.calculate_metrics(result.returns)
|
|
335
|
+
|
|
336
|
+
assert portfolio_metrics.total_return is not None
|
|
337
|
+
assert risk_metrics.value_at_risk_95 is not None
|
|
338
|
+
|
|
339
|
+
logger.info("Complete workflow test successful!")
|
|
340
|
+
|
|
341
|
+
def _generate_trading_data(self):
|
|
342
|
+
"""Generate comprehensive trading data"""
|
|
343
|
+
n_records = 500
|
|
344
|
+
data = []
|
|
345
|
+
|
|
346
|
+
for _ in range(n_records):
|
|
347
|
+
data.append({
|
|
348
|
+
'politician_name_cleaned': np.random.choice(['Pelosi', 'McConnell', 'Schumer']),
|
|
349
|
+
'transaction_date_cleaned': datetime.now() - timedelta(days=np.random.randint(1, 365)),
|
|
350
|
+
'transaction_amount_cleaned': np.random.uniform(1000, 1000000),
|
|
351
|
+
'transaction_type_cleaned': np.random.choice(['buy', 'sell']),
|
|
352
|
+
'ticker_cleaned': np.random.choice(['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA']),
|
|
353
|
+
'disclosure_date': datetime.now() - timedelta(days=np.random.randint(0, 45))
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
return pd.DataFrame(data)
|
|
357
|
+
|
|
358
|
+
def _generate_stock_data(self):
|
|
359
|
+
"""Generate comprehensive stock data"""
|
|
360
|
+
dates = pd.date_range(end=datetime.now(), periods=365)
|
|
361
|
+
tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'SPY']
|
|
362
|
+
data = []
|
|
363
|
+
|
|
364
|
+
for ticker in tickers:
|
|
365
|
+
base_price = np.random.uniform(50, 500)
|
|
366
|
+
prices = [base_price]
|
|
367
|
+
|
|
368
|
+
for i, date in enumerate(dates):
|
|
369
|
+
# Random walk with momentum
|
|
370
|
+
change = np.random.normal(0.001, 0.02)
|
|
371
|
+
new_price = prices[-1] * (1 + change)
|
|
372
|
+
prices.append(new_price)
|
|
373
|
+
|
|
374
|
+
data.append({
|
|
375
|
+
'symbol': ticker,
|
|
376
|
+
'date': date,
|
|
377
|
+
'close': new_price,
|
|
378
|
+
'open': new_price * (1 + np.random.normal(0, 0.005)),
|
|
379
|
+
'high': new_price * (1 + abs(np.random.normal(0, 0.01))),
|
|
380
|
+
'low': new_price * (1 - abs(np.random.normal(0, 0.01))),
|
|
381
|
+
'volume': np.random.randint(1000000, 50000000)
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
return pd.DataFrame(data)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def test_smoke():
|
|
388
|
+
"""Smoke test to ensure all imports work"""
|
|
389
|
+
assert DataProcessor is not None
|
|
390
|
+
assert StockRecommendationFeatures is not None
|
|
391
|
+
assert DeepEnsembleModel is not None
|
|
392
|
+
assert MLPipeline is not None
|
|
393
|
+
assert BacktestEngine is not None
|
|
394
|
+
logger.info("Smoke test passed - all imports successful")
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
if __name__ == "__main__":
|
|
398
|
+
# Run integration tests
|
|
399
|
+
logger.info("Running integration tests...")
|
|
400
|
+
|
|
401
|
+
# Test data integration
|
|
402
|
+
data_tests = TestDataIntegration()
|
|
403
|
+
data_tests.test_data_pipeline()
|
|
404
|
+
data_tests.test_feature_extraction_pipeline()
|
|
405
|
+
logger.info("✅ Data integration tests passed")
|
|
406
|
+
|
|
407
|
+
# Test model integration
|
|
408
|
+
model_tests = TestModelIntegration()
|
|
409
|
+
model_tests.test_model_training_pipeline()
|
|
410
|
+
model_tests.test_model_serving()
|
|
411
|
+
logger.info("✅ Model integration tests passed")
|
|
412
|
+
|
|
413
|
+
# Test pipeline integration
|
|
414
|
+
pipeline_tests = TestPipelineIntegration()
|
|
415
|
+
pipeline_tests.test_end_to_end_pipeline()
|
|
416
|
+
logger.info("✅ Pipeline integration tests passed")
|
|
417
|
+
|
|
418
|
+
# Test backtest integration
|
|
419
|
+
backtest_tests = TestBacktestIntegration()
|
|
420
|
+
backtest_tests.test_backtesting_pipeline()
|
|
421
|
+
backtest_tests.test_performance_analysis()
|
|
422
|
+
logger.info("✅ Backtest integration tests passed")
|
|
423
|
+
|
|
424
|
+
# Test complete system
|
|
425
|
+
system_tests = TestSystemIntegration()
|
|
426
|
+
system_tests.test_complete_workflow()
|
|
427
|
+
logger.info("✅ System integration tests passed")
|
|
428
|
+
|
|
429
|
+
logger.info("🎉 All integration tests passed successfully!")
|