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
mcli/ml/dashboard/app.py
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
"""Streamlit dashboard for ML system monitoring"""
|
|
2
|
+
|
|
3
|
+
import streamlit as st
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import plotly.express as px
|
|
6
|
+
import plotly.graph_objects as go
|
|
7
|
+
from plotly.subplots import make_subplots
|
|
8
|
+
import asyncio
|
|
9
|
+
import requests
|
|
10
|
+
import time
|
|
11
|
+
from datetime import datetime, timedelta
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from mcli.ml.database.session import SessionLocal
|
|
15
|
+
from mcli.ml.database.models import (
|
|
16
|
+
Model, Prediction, Portfolio, User, Trade,
|
|
17
|
+
StockData, BacktestResult, ModelStatus
|
|
18
|
+
)
|
|
19
|
+
from mcli.ml.cache import cache_manager
|
|
20
|
+
from mcli.ml.config import settings
|
|
21
|
+
|
|
22
|
+
# Page config
|
|
23
|
+
st.set_page_config(
|
|
24
|
+
page_title="MCLI ML Dashboard",
|
|
25
|
+
page_icon="📊",
|
|
26
|
+
layout="wide",
|
|
27
|
+
initial_sidebar_state="expanded"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Custom CSS
|
|
31
|
+
st.markdown("""
|
|
32
|
+
<style>
|
|
33
|
+
.metric-card {
|
|
34
|
+
background-color: #f0f2f6;
|
|
35
|
+
padding: 1rem;
|
|
36
|
+
border-radius: 0.5rem;
|
|
37
|
+
border-left: 4px solid #1f77b4;
|
|
38
|
+
}
|
|
39
|
+
.alert-success {
|
|
40
|
+
background-color: #d4edda;
|
|
41
|
+
border: 1px solid #c3e6cb;
|
|
42
|
+
color: #155724;
|
|
43
|
+
padding: 0.75rem;
|
|
44
|
+
border-radius: 0.25rem;
|
|
45
|
+
}
|
|
46
|
+
.alert-warning {
|
|
47
|
+
background-color: #fff3cd;
|
|
48
|
+
border: 1px solid #ffeaa7;
|
|
49
|
+
color: #856404;
|
|
50
|
+
padding: 0.75rem;
|
|
51
|
+
border-radius: 0.25rem;
|
|
52
|
+
}
|
|
53
|
+
.alert-danger {
|
|
54
|
+
background-color: #f8d7da;
|
|
55
|
+
border: 1px solid #f5c6cb;
|
|
56
|
+
color: #721c24;
|
|
57
|
+
padding: 0.75rem;
|
|
58
|
+
border-radius: 0.25rem;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
61
|
+
""", unsafe_allow_html=True)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@st.cache_data(ttl=30)
|
|
65
|
+
def get_system_metrics():
|
|
66
|
+
"""Get real-time system metrics"""
|
|
67
|
+
db = SessionLocal()
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
# Model metrics
|
|
71
|
+
total_models = db.query(Model).count()
|
|
72
|
+
deployed_models = db.query(Model).filter(Model.status == ModelStatus.DEPLOYED).count()
|
|
73
|
+
training_models = db.query(Model).filter(Model.status == ModelStatus.TRAINING).count()
|
|
74
|
+
|
|
75
|
+
# User metrics
|
|
76
|
+
total_users = db.query(User).count()
|
|
77
|
+
active_users = db.query(User).filter(
|
|
78
|
+
User.last_login_at >= datetime.utcnow() - timedelta(days=1)
|
|
79
|
+
).count()
|
|
80
|
+
|
|
81
|
+
# Prediction metrics
|
|
82
|
+
predictions_today = db.query(Prediction).filter(
|
|
83
|
+
Prediction.prediction_date >= datetime.utcnow().date()
|
|
84
|
+
).count()
|
|
85
|
+
|
|
86
|
+
# Portfolio metrics
|
|
87
|
+
active_portfolios = db.query(Portfolio).filter(Portfolio.is_active == True).count()
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
'total_models': total_models,
|
|
91
|
+
'deployed_models': deployed_models,
|
|
92
|
+
'training_models': training_models,
|
|
93
|
+
'total_users': total_users,
|
|
94
|
+
'active_users': active_users,
|
|
95
|
+
'predictions_today': predictions_today,
|
|
96
|
+
'active_portfolios': active_portfolios,
|
|
97
|
+
'timestamp': datetime.utcnow()
|
|
98
|
+
}
|
|
99
|
+
finally:
|
|
100
|
+
db.close()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@st.cache_data(ttl=60)
|
|
104
|
+
def get_model_performance():
|
|
105
|
+
"""Get model performance data"""
|
|
106
|
+
db = SessionLocal()
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
models = db.query(Model).filter(Model.status == ModelStatus.DEPLOYED).all()
|
|
110
|
+
|
|
111
|
+
data = []
|
|
112
|
+
for model in models:
|
|
113
|
+
data.append({
|
|
114
|
+
'name': model.name,
|
|
115
|
+
'accuracy': model.test_accuracy or 0,
|
|
116
|
+
'created_at': model.created_at,
|
|
117
|
+
'last_updated': model.updated_at
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return pd.DataFrame(data)
|
|
121
|
+
finally:
|
|
122
|
+
db.close()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@st.cache_data(ttl=30)
|
|
126
|
+
def get_recent_predictions():
|
|
127
|
+
"""Get recent predictions"""
|
|
128
|
+
db = SessionLocal()
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
predictions = db.query(Prediction).order_by(
|
|
132
|
+
Prediction.prediction_date.desc()
|
|
133
|
+
).limit(100).all()
|
|
134
|
+
|
|
135
|
+
data = []
|
|
136
|
+
for pred in predictions:
|
|
137
|
+
data.append({
|
|
138
|
+
'ticker': pred.ticker,
|
|
139
|
+
'predicted_return': pred.predicted_return,
|
|
140
|
+
'confidence': pred.confidence_score,
|
|
141
|
+
'prediction_date': pred.prediction_date,
|
|
142
|
+
'target_date': pred.target_date
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
return pd.DataFrame(data)
|
|
146
|
+
finally:
|
|
147
|
+
db.close()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@st.cache_data(ttl=60)
|
|
151
|
+
def get_portfolio_performance():
|
|
152
|
+
"""Get portfolio performance data"""
|
|
153
|
+
db = SessionLocal()
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
portfolios = db.query(Portfolio).filter(Portfolio.is_active == True).all()
|
|
157
|
+
|
|
158
|
+
data = []
|
|
159
|
+
for portfolio in portfolios:
|
|
160
|
+
data.append({
|
|
161
|
+
'name': portfolio.name,
|
|
162
|
+
'total_return': portfolio.total_return or 0,
|
|
163
|
+
'sharpe_ratio': portfolio.sharpe_ratio or 0,
|
|
164
|
+
'max_drawdown': portfolio.max_drawdown or 0,
|
|
165
|
+
'current_value': portfolio.current_value or 0
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
return pd.DataFrame(data)
|
|
169
|
+
finally:
|
|
170
|
+
db.close()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def check_api_health():
|
|
174
|
+
"""Check API health"""
|
|
175
|
+
try:
|
|
176
|
+
response = requests.get(f"http://localhost:{settings.api.port}/health", timeout=5)
|
|
177
|
+
return response.status_code == 200
|
|
178
|
+
except:
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def check_redis_health():
|
|
183
|
+
"""Check Redis health"""
|
|
184
|
+
try:
|
|
185
|
+
cache_manager.initialize()
|
|
186
|
+
return cache_manager.redis_client.ping() if cache_manager.redis_client else False
|
|
187
|
+
except:
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def main():
|
|
192
|
+
"""Main dashboard function"""
|
|
193
|
+
|
|
194
|
+
# Title and header
|
|
195
|
+
st.title("🤖 MCLI ML System Dashboard")
|
|
196
|
+
st.markdown("Real-time monitoring of ML models, predictions, and system health")
|
|
197
|
+
|
|
198
|
+
# Sidebar
|
|
199
|
+
st.sidebar.title("Navigation")
|
|
200
|
+
page = st.sidebar.selectbox(
|
|
201
|
+
"Choose a page",
|
|
202
|
+
["Overview", "Models", "Predictions", "Portfolios", "System Health", "Live Monitoring"]
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# Auto-refresh toggle
|
|
206
|
+
auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=True)
|
|
207
|
+
if auto_refresh:
|
|
208
|
+
time.sleep(30)
|
|
209
|
+
st.rerun()
|
|
210
|
+
|
|
211
|
+
# Manual refresh button
|
|
212
|
+
if st.sidebar.button("🔄 Refresh Now"):
|
|
213
|
+
st.cache_data.clear()
|
|
214
|
+
st.rerun()
|
|
215
|
+
|
|
216
|
+
# Main content based on selected page
|
|
217
|
+
if page == "Overview":
|
|
218
|
+
show_overview()
|
|
219
|
+
elif page == "Models":
|
|
220
|
+
show_models()
|
|
221
|
+
elif page == "Predictions":
|
|
222
|
+
show_predictions()
|
|
223
|
+
elif page == "Portfolios":
|
|
224
|
+
show_portfolios()
|
|
225
|
+
elif page == "System Health":
|
|
226
|
+
show_system_health()
|
|
227
|
+
elif page == "Live Monitoring":
|
|
228
|
+
show_live_monitoring()
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def show_overview():
|
|
232
|
+
"""Show overview dashboard"""
|
|
233
|
+
st.header("System Overview")
|
|
234
|
+
|
|
235
|
+
# Get metrics
|
|
236
|
+
metrics = get_system_metrics()
|
|
237
|
+
|
|
238
|
+
# Display key metrics
|
|
239
|
+
col1, col2, col3, col4 = st.columns(4)
|
|
240
|
+
|
|
241
|
+
with col1:
|
|
242
|
+
st.metric(
|
|
243
|
+
label="Deployed Models",
|
|
244
|
+
value=metrics['deployed_models'],
|
|
245
|
+
delta=f"{metrics['training_models']} training"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
with col2:
|
|
249
|
+
st.metric(
|
|
250
|
+
label="Active Users",
|
|
251
|
+
value=metrics['active_users'],
|
|
252
|
+
delta=f"{metrics['total_users']} total"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
with col3:
|
|
256
|
+
st.metric(
|
|
257
|
+
label="Predictions Today",
|
|
258
|
+
value=metrics['predictions_today']
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
with col4:
|
|
262
|
+
st.metric(
|
|
263
|
+
label="Active Portfolios",
|
|
264
|
+
value=metrics['active_portfolios']
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
# Charts
|
|
268
|
+
col1, col2 = st.columns(2)
|
|
269
|
+
|
|
270
|
+
with col1:
|
|
271
|
+
st.subheader("Model Performance")
|
|
272
|
+
model_data = get_model_performance()
|
|
273
|
+
if not model_data.empty:
|
|
274
|
+
fig = px.bar(
|
|
275
|
+
model_data,
|
|
276
|
+
x='name',
|
|
277
|
+
y='accuracy',
|
|
278
|
+
title="Model Accuracy Comparison"
|
|
279
|
+
)
|
|
280
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
281
|
+
else:
|
|
282
|
+
st.info("No model performance data available")
|
|
283
|
+
|
|
284
|
+
with col2:
|
|
285
|
+
st.subheader("Recent Predictions")
|
|
286
|
+
pred_data = get_recent_predictions()
|
|
287
|
+
if not pred_data.empty:
|
|
288
|
+
# Show confidence distribution
|
|
289
|
+
fig = px.histogram(
|
|
290
|
+
pred_data,
|
|
291
|
+
x='confidence',
|
|
292
|
+
title="Prediction Confidence Distribution"
|
|
293
|
+
)
|
|
294
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
295
|
+
else:
|
|
296
|
+
st.info("No recent predictions available")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def show_models():
|
|
300
|
+
"""Show models dashboard"""
|
|
301
|
+
st.header("Model Management")
|
|
302
|
+
|
|
303
|
+
# Model performance table
|
|
304
|
+
model_data = get_model_performance()
|
|
305
|
+
|
|
306
|
+
if not model_data.empty:
|
|
307
|
+
st.subheader("Model Performance")
|
|
308
|
+
st.dataframe(model_data, use_container_width=True)
|
|
309
|
+
|
|
310
|
+
# Model accuracy chart
|
|
311
|
+
fig = px.line(
|
|
312
|
+
model_data,
|
|
313
|
+
x='created_at',
|
|
314
|
+
y='accuracy',
|
|
315
|
+
color='name',
|
|
316
|
+
title="Model Accuracy Over Time"
|
|
317
|
+
)
|
|
318
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
319
|
+
else:
|
|
320
|
+
st.warning("No model data available")
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def show_predictions():
|
|
324
|
+
"""Show predictions dashboard"""
|
|
325
|
+
st.header("Predictions Analysis")
|
|
326
|
+
|
|
327
|
+
pred_data = get_recent_predictions()
|
|
328
|
+
|
|
329
|
+
if not pred_data.empty:
|
|
330
|
+
# Filters
|
|
331
|
+
col1, col2 = st.columns(2)
|
|
332
|
+
with col1:
|
|
333
|
+
selected_tickers = st.multiselect(
|
|
334
|
+
"Filter by Ticker",
|
|
335
|
+
options=pred_data['ticker'].unique(),
|
|
336
|
+
default=pred_data['ticker'].unique()[:5]
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
with col2:
|
|
340
|
+
confidence_threshold = st.slider(
|
|
341
|
+
"Minimum Confidence",
|
|
342
|
+
min_value=0.0,
|
|
343
|
+
max_value=1.0,
|
|
344
|
+
value=0.5,
|
|
345
|
+
step=0.1
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# Filter data
|
|
349
|
+
filtered_data = pred_data[
|
|
350
|
+
(pred_data['ticker'].isin(selected_tickers)) &
|
|
351
|
+
(pred_data['confidence'] >= confidence_threshold)
|
|
352
|
+
]
|
|
353
|
+
|
|
354
|
+
# Display filtered data
|
|
355
|
+
st.subheader("Filtered Predictions")
|
|
356
|
+
st.dataframe(filtered_data, use_container_width=True)
|
|
357
|
+
|
|
358
|
+
# Charts
|
|
359
|
+
col1, col2 = st.columns(2)
|
|
360
|
+
|
|
361
|
+
with col1:
|
|
362
|
+
fig = px.scatter(
|
|
363
|
+
filtered_data,
|
|
364
|
+
x='confidence',
|
|
365
|
+
y='predicted_return',
|
|
366
|
+
color='ticker',
|
|
367
|
+
title="Confidence vs Predicted Return"
|
|
368
|
+
)
|
|
369
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
370
|
+
|
|
371
|
+
with col2:
|
|
372
|
+
# Group by ticker and show average return
|
|
373
|
+
avg_returns = filtered_data.groupby('ticker')['predicted_return'].mean().reset_index()
|
|
374
|
+
fig = px.bar(
|
|
375
|
+
avg_returns,
|
|
376
|
+
x='ticker',
|
|
377
|
+
y='predicted_return',
|
|
378
|
+
title="Average Predicted Return by Ticker"
|
|
379
|
+
)
|
|
380
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
381
|
+
|
|
382
|
+
else:
|
|
383
|
+
st.warning("No prediction data available")
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def show_portfolios():
|
|
387
|
+
"""Show portfolios dashboard"""
|
|
388
|
+
st.header("Portfolio Performance")
|
|
389
|
+
|
|
390
|
+
portfolio_data = get_portfolio_performance()
|
|
391
|
+
|
|
392
|
+
if not portfolio_data.empty:
|
|
393
|
+
# Portfolio metrics
|
|
394
|
+
st.subheader("Portfolio Summary")
|
|
395
|
+
st.dataframe(portfolio_data, use_container_width=True)
|
|
396
|
+
|
|
397
|
+
# Performance charts
|
|
398
|
+
col1, col2 = st.columns(2)
|
|
399
|
+
|
|
400
|
+
with col1:
|
|
401
|
+
fig = px.bar(
|
|
402
|
+
portfolio_data,
|
|
403
|
+
x='name',
|
|
404
|
+
y='total_return',
|
|
405
|
+
title="Total Return by Portfolio"
|
|
406
|
+
)
|
|
407
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
408
|
+
|
|
409
|
+
with col2:
|
|
410
|
+
fig = px.scatter(
|
|
411
|
+
portfolio_data,
|
|
412
|
+
x='sharpe_ratio',
|
|
413
|
+
y='total_return',
|
|
414
|
+
size='current_value',
|
|
415
|
+
hover_data=['name'],
|
|
416
|
+
title="Risk-Return Analysis"
|
|
417
|
+
)
|
|
418
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
419
|
+
|
|
420
|
+
else:
|
|
421
|
+
st.warning("No portfolio data available")
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def show_system_health():
|
|
425
|
+
"""Show system health dashboard"""
|
|
426
|
+
st.header("System Health")
|
|
427
|
+
|
|
428
|
+
# Check various system components
|
|
429
|
+
api_healthy = check_api_health()
|
|
430
|
+
redis_healthy = check_redis_health()
|
|
431
|
+
|
|
432
|
+
col1, col2, col3 = st.columns(3)
|
|
433
|
+
|
|
434
|
+
with col1:
|
|
435
|
+
if api_healthy:
|
|
436
|
+
st.success("✅ API Server: Healthy")
|
|
437
|
+
else:
|
|
438
|
+
st.error("❌ API Server: Unhealthy")
|
|
439
|
+
|
|
440
|
+
with col2:
|
|
441
|
+
if redis_healthy:
|
|
442
|
+
st.success("✅ Redis Cache: Healthy")
|
|
443
|
+
else:
|
|
444
|
+
st.error("❌ Redis Cache: Unhealthy")
|
|
445
|
+
|
|
446
|
+
with col3:
|
|
447
|
+
# Database health (always assume healthy if we can query)
|
|
448
|
+
st.success("✅ Database: Healthy")
|
|
449
|
+
|
|
450
|
+
# System metrics over time (simulated)
|
|
451
|
+
st.subheader("System Metrics")
|
|
452
|
+
|
|
453
|
+
# Generate sample time series data
|
|
454
|
+
times = pd.date_range(start=datetime.now() - timedelta(hours=24), end=datetime.now(), freq='H')
|
|
455
|
+
cpu_usage = np.random.normal(45, 10, len(times))
|
|
456
|
+
memory_usage = np.random.normal(60, 15, len(times))
|
|
457
|
+
|
|
458
|
+
metrics_df = pd.DataFrame({
|
|
459
|
+
'time': times,
|
|
460
|
+
'cpu_usage': np.clip(cpu_usage, 0, 100),
|
|
461
|
+
'memory_usage': np.clip(memory_usage, 0, 100)
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
fig = make_subplots(
|
|
465
|
+
rows=2, cols=1,
|
|
466
|
+
subplot_titles=('CPU Usage (%)', 'Memory Usage (%)')
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
fig.add_trace(
|
|
470
|
+
go.Scatter(x=metrics_df['time'], y=metrics_df['cpu_usage'], name='CPU'),
|
|
471
|
+
row=1, col=1
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
fig.add_trace(
|
|
475
|
+
go.Scatter(x=metrics_df['time'], y=metrics_df['memory_usage'], name='Memory'),
|
|
476
|
+
row=2, col=1
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
fig.update_layout(height=500, title_text="System Resource Usage (24h)")
|
|
480
|
+
st.plotly_chart(fig, use_container_width=True)
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def show_live_monitoring():
|
|
484
|
+
"""Show live monitoring with real-time updates"""
|
|
485
|
+
st.header("Live Monitoring")
|
|
486
|
+
|
|
487
|
+
# Real-time metrics placeholder
|
|
488
|
+
metrics_placeholder = st.empty()
|
|
489
|
+
|
|
490
|
+
# Live prediction feed
|
|
491
|
+
st.subheader("Live Prediction Feed")
|
|
492
|
+
prediction_placeholder = st.empty()
|
|
493
|
+
|
|
494
|
+
# Live model status
|
|
495
|
+
st.subheader("Model Status")
|
|
496
|
+
model_placeholder = st.empty()
|
|
497
|
+
|
|
498
|
+
# Auto-update every 5 seconds
|
|
499
|
+
if st.button("Start Live Monitoring"):
|
|
500
|
+
for i in range(60): # Run for 5 minutes
|
|
501
|
+
# Update metrics
|
|
502
|
+
metrics = get_system_metrics()
|
|
503
|
+
with metrics_placeholder.container():
|
|
504
|
+
col1, col2, col3 = st.columns(3)
|
|
505
|
+
with col1:
|
|
506
|
+
st.metric("Predictions/min", np.random.randint(5, 20))
|
|
507
|
+
with col2:
|
|
508
|
+
st.metric("Avg Confidence", f"{np.random.uniform(0.7, 0.9):.3f}")
|
|
509
|
+
with col3:
|
|
510
|
+
st.metric("Active Models", metrics['deployed_models'])
|
|
511
|
+
|
|
512
|
+
# Simulate new predictions
|
|
513
|
+
with prediction_placeholder.container():
|
|
514
|
+
new_preds = pd.DataFrame({
|
|
515
|
+
'Ticker': np.random.choice(['AAPL', 'GOOGL', 'MSFT', 'TSLA'], 5),
|
|
516
|
+
'Prediction': np.random.uniform(-0.05, 0.05, 5),
|
|
517
|
+
'Confidence': np.random.uniform(0.6, 0.95, 5),
|
|
518
|
+
'Time': [datetime.now() - timedelta(seconds=x*10) for x in range(5)]
|
|
519
|
+
})
|
|
520
|
+
st.dataframe(new_preds, use_container_width=True)
|
|
521
|
+
|
|
522
|
+
# Model status
|
|
523
|
+
with model_placeholder.container():
|
|
524
|
+
model_data = get_model_performance()
|
|
525
|
+
if not model_data.empty:
|
|
526
|
+
st.dataframe(model_data[['name', 'accuracy']], use_container_width=True)
|
|
527
|
+
|
|
528
|
+
time.sleep(5)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
if __name__ == "__main__":
|
|
532
|
+
main()
|