mcli-framework 7.3.1__py3-none-any.whl → 7.5.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/commands_cmd.py +741 -0
- mcli/lib/auth/aws_manager.py +9 -64
- mcli/lib/auth/azure_manager.py +9 -64
- mcli/lib/auth/credential_manager.py +70 -1
- mcli/lib/auth/gcp_manager.py +11 -64
- mcli/ml/dashboard/app.py +6 -39
- mcli/ml/dashboard/app_integrated.py +288 -117
- mcli/ml/dashboard/app_supabase.py +8 -57
- mcli/ml/dashboard/app_training.py +10 -12
- mcli/ml/dashboard/common.py +167 -0
- mcli/ml/dashboard/overview.py +378 -0
- mcli/ml/dashboard/pages/cicd.py +4 -4
- mcli/ml/dashboard/pages/debug_dependencies.py +406 -0
- mcli/ml/dashboard/pages/gravity_viz.py +783 -0
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +555 -0
- mcli/ml/dashboard/pages/predictions_enhanced.py +4 -2
- mcli/ml/dashboard/pages/scrapers_and_logs.py +25 -9
- mcli/ml/dashboard/pages/test_portfolio.py +54 -4
- mcli/ml/dashboard/pages/trading.py +80 -26
- mcli/ml/dashboard/streamlit_extras_utils.py +297 -0
- mcli/ml/dashboard/styles.py +55 -0
- mcli/ml/dashboard/utils.py +7 -0
- mcli/ml/dashboard/warning_suppression.py +34 -0
- mcli/ml/database/session.py +169 -16
- mcli/ml/predictions/monte_carlo.py +428 -0
- mcli/ml/trading/alpaca_client.py +82 -18
- mcli/self/self_cmd.py +182 -737
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/METADATA +2 -3
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/RECORD +33 -87
- mcli/__init__.py +0 -160
- mcli/__main__.py +0 -14
- mcli/app/__init__.py +0 -23
- mcli/app/model/__init__.py +0 -0
- mcli/app/video/__init__.py +0 -5
- mcli/chat/__init__.py +0 -34
- mcli/lib/__init__.py +0 -0
- mcli/lib/api/__init__.py +0 -0
- mcli/lib/auth/__init__.py +0 -1
- mcli/lib/config/__init__.py +0 -1
- mcli/lib/erd/__init__.py +0 -25
- mcli/lib/files/__init__.py +0 -0
- mcli/lib/fs/__init__.py +0 -1
- mcli/lib/logger/__init__.py +0 -3
- mcli/lib/performance/__init__.py +0 -17
- mcli/lib/pickles/__init__.py +0 -1
- mcli/lib/shell/__init__.py +0 -0
- mcli/lib/toml/__init__.py +0 -1
- mcli/lib/watcher/__init__.py +0 -0
- mcli/ml/__init__.py +0 -16
- mcli/ml/api/__init__.py +0 -30
- mcli/ml/api/routers/__init__.py +0 -27
- mcli/ml/auth/__init__.py +0 -45
- mcli/ml/backtesting/__init__.py +0 -39
- mcli/ml/cli/__init__.py +0 -5
- mcli/ml/config/__init__.py +0 -33
- mcli/ml/configs/__init__.py +0 -16
- mcli/ml/dashboard/__init__.py +0 -12
- mcli/ml/dashboard/components/__init__.py +0 -7
- mcli/ml/dashboard/pages/__init__.py +0 -6
- mcli/ml/data_ingestion/__init__.py +0 -39
- mcli/ml/database/__init__.py +0 -47
- mcli/ml/experimentation/__init__.py +0 -29
- mcli/ml/features/__init__.py +0 -39
- mcli/ml/mlops/__init__.py +0 -33
- mcli/ml/models/__init__.py +0 -94
- mcli/ml/monitoring/__init__.py +0 -25
- mcli/ml/optimization/__init__.py +0 -27
- mcli/ml/predictions/__init__.py +0 -5
- mcli/ml/preprocessing/__init__.py +0 -28
- mcli/ml/scripts/__init__.py +0 -1
- mcli/ml/trading/__init__.py +0 -60
- mcli/ml/training/__init__.py +0 -10
- mcli/mygroup/__init__.py +0 -3
- mcli/public/__init__.py +0 -1
- mcli/public/commands/__init__.py +0 -2
- mcli/self/__init__.py +0 -3
- mcli/workflow/__init__.py +0 -0
- mcli/workflow/daemon/__init__.py +0 -15
- mcli/workflow/dashboard/__init__.py +0 -5
- mcli/workflow/docker/__init__.py +0 -0
- mcli/workflow/file/__init__.py +0 -0
- mcli/workflow/gcloud/__init__.py +0 -1
- mcli/workflow/git_commit/__init__.py +0 -0
- mcli/workflow/interview/__init__.py +0 -0
- mcli/workflow/politician_trading/__init__.py +0 -4
- mcli/workflow/registry/__init__.py +0 -0
- mcli/workflow/repo/__init__.py +0 -0
- mcli/workflow/scheduler/__init__.py +0 -25
- mcli/workflow/search/__init__.py +0 -0
- mcli/workflow/sync/__init__.py +0 -5
- mcli/workflow/videos/__init__.py +0 -1
- mcli/workflow/wakatime/__init__.py +0 -80
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/WHEEL +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/top_level.txt +0 -0
|
@@ -12,18 +12,51 @@ from typing import List
|
|
|
12
12
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
|
|
15
|
+
# Suppress warnings before other imports
|
|
16
|
+
from mcli.ml.dashboard.common import suppress_streamlit_warnings
|
|
17
|
+
|
|
18
|
+
suppress_streamlit_warnings()
|
|
19
|
+
|
|
15
20
|
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
16
22
|
import pandas as pd
|
|
17
23
|
import plotly.express as px
|
|
18
24
|
import plotly.graph_objects as go
|
|
19
25
|
import requests
|
|
20
26
|
import streamlit as st
|
|
21
|
-
from dotenv import load_dotenv
|
|
22
27
|
from plotly.subplots import make_subplots
|
|
23
|
-
from supabase import Client
|
|
28
|
+
from supabase import Client
|
|
29
|
+
|
|
30
|
+
# Import common dashboard utilities
|
|
31
|
+
from mcli.ml.dashboard.common import (
|
|
32
|
+
get_supabase_client,
|
|
33
|
+
load_environment_variables,
|
|
34
|
+
setup_page_config,
|
|
35
|
+
)
|
|
36
|
+
from mcli.ml.dashboard.styles import apply_dashboard_styles
|
|
24
37
|
|
|
25
|
-
# Load environment variables
|
|
26
|
-
|
|
38
|
+
# Load environment variables
|
|
39
|
+
load_environment_variables()
|
|
40
|
+
|
|
41
|
+
# Import streamlit-extras utilities
|
|
42
|
+
try:
|
|
43
|
+
from mcli.ml.dashboard.streamlit_extras_utils import (
|
|
44
|
+
enhanced_metrics,
|
|
45
|
+
section_header,
|
|
46
|
+
vertical_space,
|
|
47
|
+
data_quality_indicators,
|
|
48
|
+
trading_status_card,
|
|
49
|
+
)
|
|
50
|
+
HAS_STREAMLIT_EXTRAS = True
|
|
51
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
52
|
+
HAS_STREAMLIT_EXTRAS = False
|
|
53
|
+
enhanced_metrics = None
|
|
54
|
+
section_header = None
|
|
55
|
+
vertical_space = None
|
|
56
|
+
data_quality_indicators = None
|
|
57
|
+
trading_status_card = None
|
|
58
|
+
# Suppress warning for now - this is handled gracefully
|
|
59
|
+
# st.warning(f"Streamlit-extras utilities not available: {e}")
|
|
27
60
|
|
|
28
61
|
# Add ML pipeline imports
|
|
29
62
|
try:
|
|
@@ -46,45 +79,146 @@ except ImportError:
|
|
|
46
79
|
PoliticianTradingPredictor = None
|
|
47
80
|
|
|
48
81
|
# Add new dashboard pages
|
|
82
|
+
HAS_OVERVIEW_PAGE = False
|
|
83
|
+
HAS_PREDICTIONS_ENHANCED = False
|
|
84
|
+
HAS_SCRAPERS_PAGE = False
|
|
85
|
+
HAS_TRADING_PAGES = False
|
|
86
|
+
HAS_MONTE_CARLO_PAGE = False
|
|
87
|
+
HAS_CICD_PAGE = False
|
|
88
|
+
HAS_WORKFLOWS_PAGE = False
|
|
89
|
+
HAS_DEBUG_PAGE = False
|
|
90
|
+
|
|
91
|
+
show_overview = None
|
|
92
|
+
show_cicd_dashboard = None
|
|
93
|
+
show_workflows_dashboard = None
|
|
94
|
+
show_predictions_enhanced = None
|
|
95
|
+
show_scrapers_and_logs = None
|
|
96
|
+
show_trading_dashboard = None
|
|
97
|
+
show_test_portfolio = None
|
|
98
|
+
show_monte_carlo_predictions = None
|
|
99
|
+
show_debug_dependencies = None
|
|
100
|
+
|
|
101
|
+
# Import Overview page
|
|
102
|
+
try:
|
|
103
|
+
from mcli.ml.dashboard.overview import show_overview
|
|
104
|
+
HAS_OVERVIEW_PAGE = True
|
|
105
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
106
|
+
st.warning(f"Overview page not available: {e}")
|
|
107
|
+
|
|
49
108
|
try:
|
|
50
|
-
from mcli.ml.dashboard.pages.cicd import show_cicd_dashboard
|
|
51
|
-
from mcli.ml.dashboard.pages.workflows import show_workflows_dashboard
|
|
52
109
|
from mcli.ml.dashboard.pages.predictions_enhanced import show_predictions_enhanced
|
|
110
|
+
HAS_PREDICTIONS_ENHANCED = True
|
|
111
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
112
|
+
st.warning(f"Predictions Enhanced page not available: {e}")
|
|
113
|
+
|
|
114
|
+
try:
|
|
53
115
|
from mcli.ml.dashboard.pages.scrapers_and_logs import show_scrapers_and_logs
|
|
116
|
+
HAS_SCRAPERS_PAGE = True
|
|
117
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
118
|
+
st.warning(f"Scrapers & Logs page not available: {e}")
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
import sys
|
|
122
|
+
import traceback
|
|
123
|
+
|
|
124
|
+
# Verbose logging for alpaca-py debugging
|
|
125
|
+
st.info("🔍 Attempting to import trading pages (alpaca-py dependent)...")
|
|
126
|
+
|
|
127
|
+
# First, try importing alpaca directly to see the specific error
|
|
128
|
+
try:
|
|
129
|
+
import alpaca
|
|
130
|
+
st.success(f"✅ alpaca module imported successfully")
|
|
131
|
+
if hasattr(alpaca, "__version__"):
|
|
132
|
+
st.info(f"Alpaca version: {alpaca.__version__}")
|
|
133
|
+
if hasattr(alpaca, "__file__"):
|
|
134
|
+
st.caption(f"Alpaca location: {alpaca.__file__}")
|
|
135
|
+
except ImportError as alpaca_error:
|
|
136
|
+
st.error(f"❌ Failed to import alpaca module: {alpaca_error}")
|
|
137
|
+
with st.expander("🔬 Detailed alpaca import error"):
|
|
138
|
+
st.code(traceback.format_exc())
|
|
139
|
+
|
|
140
|
+
# Try to provide diagnostic info
|
|
141
|
+
st.warning("💡 Troubleshooting tips:")
|
|
142
|
+
st.markdown("""
|
|
143
|
+
- Check that `alpaca-py>=0.20.0` is in requirements.txt
|
|
144
|
+
- Verify Python version is 3.8+ (current: {}.{})
|
|
145
|
+
- Check Streamlit Cloud deployment logs for installation errors
|
|
146
|
+
- Visit the **Debug Dependencies** page for detailed diagnostics
|
|
147
|
+
""".format(sys.version_info.major, sys.version_info.minor))
|
|
148
|
+
|
|
149
|
+
# Now try importing the trading pages
|
|
54
150
|
from mcli.ml.dashboard.pages.trading import show_trading_dashboard
|
|
55
151
|
from mcli.ml.dashboard.pages.test_portfolio import show_test_portfolio
|
|
152
|
+
HAS_TRADING_PAGES = True
|
|
153
|
+
st.success("✅ Trading pages imported successfully!")
|
|
56
154
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
155
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
156
|
+
st.error(f"❌ Trading pages not available: {e}")
|
|
157
|
+
with st.expander("📋 Full error traceback"):
|
|
158
|
+
st.code(traceback.format_exc())
|
|
159
|
+
|
|
160
|
+
# Show installed packages related to alpaca
|
|
161
|
+
try:
|
|
162
|
+
import subprocess
|
|
163
|
+
result = subprocess.run(
|
|
164
|
+
["pip", "list"],
|
|
165
|
+
capture_output=True,
|
|
166
|
+
text=True,
|
|
167
|
+
timeout=5
|
|
168
|
+
)
|
|
169
|
+
alpaca_packages = [line for line in result.stdout.split("\n") if "alpaca" in line.lower()]
|
|
170
|
+
if alpaca_packages:
|
|
171
|
+
st.info("📦 Found alpaca-related packages:")
|
|
172
|
+
for pkg in alpaca_packages:
|
|
173
|
+
st.code(pkg)
|
|
174
|
+
else:
|
|
175
|
+
st.warning("⚠️ No alpaca-related packages found in pip list")
|
|
176
|
+
|
|
177
|
+
# Show full pip list for debugging
|
|
178
|
+
with st.expander("🔍 Full pip list (for debugging)"):
|
|
179
|
+
st.code(result.stdout, language="text")
|
|
180
|
+
except Exception as pip_error:
|
|
181
|
+
st.caption(f"Could not check installed packages: {pip_error}")
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
from mcli.ml.dashboard.pages.monte_carlo_predictions import show_monte_carlo_predictions
|
|
185
|
+
HAS_MONTE_CARLO_PAGE = True
|
|
186
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
187
|
+
HAS_MONTE_CARLO_PAGE = False
|
|
188
|
+
|
|
189
|
+
# Import CI/CD and Workflows pages
|
|
190
|
+
try:
|
|
191
|
+
from mcli.ml.dashboard.pages.cicd import show_cicd_dashboard
|
|
192
|
+
HAS_CICD_PAGE = True
|
|
193
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
194
|
+
st.warning(f"CI/CD page not available: {e}")
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
from mcli.ml.dashboard.pages.workflows import show_workflows_dashboard
|
|
198
|
+
HAS_WORKFLOWS_PAGE = True
|
|
199
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
200
|
+
st.warning(f"Workflows page not available: {e}")
|
|
201
|
+
|
|
202
|
+
# Import Debug Dependencies page (always available for troubleshooting)
|
|
203
|
+
try:
|
|
204
|
+
from mcli.ml.dashboard.pages.debug_dependencies import show_debug_dependencies
|
|
205
|
+
HAS_DEBUG_PAGE = True
|
|
206
|
+
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
207
|
+
st.warning(f"Debug Dependencies page not available: {e}")
|
|
208
|
+
|
|
209
|
+
# Page config - must be before other st commands
|
|
210
|
+
setup_page_config(
|
|
211
|
+
page_title="Politician Trading Tracker - MCLI",
|
|
212
|
+
page_icon="📊"
|
|
76
213
|
)
|
|
77
214
|
|
|
78
|
-
#
|
|
215
|
+
# Apply standard dashboard styles (includes metric-card, alert boxes)
|
|
216
|
+
apply_dashboard_styles()
|
|
217
|
+
|
|
218
|
+
# Add integrated dashboard-specific CSS
|
|
79
219
|
st.markdown(
|
|
80
220
|
"""
|
|
81
221
|
<style>
|
|
82
|
-
.metric-card {
|
|
83
|
-
background-color: #f0f2f6;
|
|
84
|
-
padding: 1rem;
|
|
85
|
-
border-radius: 0.5rem;
|
|
86
|
-
border-left: 4px solid #1f77b4;
|
|
87
|
-
}
|
|
88
222
|
.success-box {
|
|
89
223
|
background-color: #d4edda;
|
|
90
224
|
border: 1px solid #c3e6cb;
|
|
@@ -104,69 +238,7 @@ st.markdown(
|
|
|
104
238
|
unsafe_allow_html=True,
|
|
105
239
|
)
|
|
106
240
|
|
|
107
|
-
|
|
108
|
-
@st.cache_resource
|
|
109
|
-
def get_supabase_client() -> Client:
|
|
110
|
-
"""Get Supabase client with Streamlit Cloud secrets support"""
|
|
111
|
-
# Try Streamlit secrets first (for Streamlit Cloud), then fall back to environment variables (for local dev)
|
|
112
|
-
try:
|
|
113
|
-
url = st.secrets.get("SUPABASE_URL", "")
|
|
114
|
-
key = st.secrets.get("SUPABASE_KEY", "") or st.secrets.get("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
115
|
-
except (AttributeError, FileNotFoundError):
|
|
116
|
-
# Secrets not available, try environment variables
|
|
117
|
-
url = os.getenv("SUPABASE_URL", "")
|
|
118
|
-
key = os.getenv("SUPABASE_KEY", "") or os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
119
|
-
|
|
120
|
-
if not url or not key:
|
|
121
|
-
st.error(
|
|
122
|
-
"❌ Supabase credentials not configured"
|
|
123
|
-
)
|
|
124
|
-
with st.expander("🔧 Configuration Required"):
|
|
125
|
-
st.markdown("""
|
|
126
|
-
**Missing Supabase credentials:**
|
|
127
|
-
- `SUPABASE_URL`: {}
|
|
128
|
-
- `SUPABASE_KEY`: {}
|
|
129
|
-
|
|
130
|
-
**For Streamlit Cloud:**
|
|
131
|
-
1. Go to https://share.streamlit.io
|
|
132
|
-
2. Select your app → Settings → Secrets
|
|
133
|
-
3. Add:
|
|
134
|
-
```toml
|
|
135
|
-
SUPABASE_URL = "https://your-project.supabase.co"
|
|
136
|
-
SUPABASE_KEY = "your-anon-key"
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
**For local development:**
|
|
140
|
-
1. Create `.streamlit/secrets.toml` file
|
|
141
|
-
2. Add the same credentials as above
|
|
142
|
-
3. Restart the dashboard
|
|
143
|
-
|
|
144
|
-
**Using demo data** until configured.
|
|
145
|
-
""".format(
|
|
146
|
-
"✅ Set" if url else "❌ Missing",
|
|
147
|
-
"✅ Set" if key else "❌ Missing"
|
|
148
|
-
))
|
|
149
|
-
return None
|
|
150
|
-
|
|
151
|
-
try:
|
|
152
|
-
client = create_client(url, key)
|
|
153
|
-
# Test connection with a simple query
|
|
154
|
-
try:
|
|
155
|
-
test_result = client.table("politicians").select("id").limit(1).execute()
|
|
156
|
-
logger.info(f"✅ Supabase connection successful (URL: {url[:30]}...)")
|
|
157
|
-
return client
|
|
158
|
-
except Exception as conn_error:
|
|
159
|
-
st.error(f"❌ Supabase connection failed: {conn_error}")
|
|
160
|
-
with st.expander("🔍 Connection Details"):
|
|
161
|
-
st.write(f"**URL:** {url[:30]}...")
|
|
162
|
-
st.write(f"**Error:** {str(conn_error)}")
|
|
163
|
-
st.write("**Using demo data** until connection is restored.")
|
|
164
|
-
logger.error(f"Supabase connection test failed: {conn_error}")
|
|
165
|
-
return None
|
|
166
|
-
except Exception as e:
|
|
167
|
-
st.error(f"❌ Failed to create Supabase client: {e}")
|
|
168
|
-
logger.error(f"Failed to create Supabase client: {e}")
|
|
169
|
-
return None
|
|
241
|
+
# Note: get_supabase_client is now imported from common.py
|
|
170
242
|
|
|
171
243
|
|
|
172
244
|
@st.cache_data(ttl=300) # Cache for 5 minutes
|
|
@@ -811,15 +883,37 @@ def get_model_metrics():
|
|
|
811
883
|
|
|
812
884
|
def main():
|
|
813
885
|
"""Main dashboard function"""
|
|
886
|
+
|
|
887
|
+
# Clear any problematic session state that might cause media file errors
|
|
888
|
+
try:
|
|
889
|
+
# Remove any file-related session state that might be causing issues
|
|
890
|
+
keys_to_remove = []
|
|
891
|
+
for key in st.session_state.keys():
|
|
892
|
+
if 'file' in key.lower() or 'download' in key.lower() or 'media' in key.lower():
|
|
893
|
+
keys_to_remove.append(key)
|
|
894
|
+
|
|
895
|
+
for key in keys_to_remove:
|
|
896
|
+
if key in st.session_state:
|
|
897
|
+
del st.session_state[key]
|
|
898
|
+
except Exception:
|
|
899
|
+
# Ignore errors when clearing session state
|
|
900
|
+
pass
|
|
814
901
|
|
|
815
902
|
# Title and header
|
|
816
|
-
st.title("
|
|
817
|
-
st.markdown("
|
|
903
|
+
st.title("📊 Politician Trading Tracker")
|
|
904
|
+
st.markdown("Track, Analyze & Replicate Congressional Trading Patterns")
|
|
818
905
|
|
|
819
906
|
# Sidebar
|
|
820
907
|
st.sidebar.title("Navigation")
|
|
821
908
|
# Build page list
|
|
822
|
-
pages = [
|
|
909
|
+
pages = []
|
|
910
|
+
|
|
911
|
+
# Add Overview as first page if available
|
|
912
|
+
if HAS_OVERVIEW_PAGE:
|
|
913
|
+
pages.append("Overview")
|
|
914
|
+
|
|
915
|
+
# Add other pages
|
|
916
|
+
pages.extend([
|
|
823
917
|
"Pipeline Overview",
|
|
824
918
|
"ML Processing",
|
|
825
919
|
"Model Performance",
|
|
@@ -829,24 +923,37 @@ def main():
|
|
|
829
923
|
"Test Portfolio",
|
|
830
924
|
"LSH Jobs",
|
|
831
925
|
"System Health",
|
|
832
|
-
]
|
|
926
|
+
])
|
|
833
927
|
|
|
834
928
|
# Add scrapers and logs page
|
|
835
929
|
if HAS_SCRAPERS_PAGE:
|
|
836
930
|
pages.append("Scrapers & Logs")
|
|
837
931
|
|
|
838
|
-
# Add
|
|
839
|
-
if
|
|
840
|
-
pages.
|
|
841
|
-
|
|
932
|
+
# Add Monte Carlo predictions page
|
|
933
|
+
if HAS_MONTE_CARLO_PAGE:
|
|
934
|
+
pages.append("Monte Carlo Predictions")
|
|
935
|
+
|
|
936
|
+
# Add CI/CD page if available
|
|
937
|
+
if HAS_CICD_PAGE:
|
|
938
|
+
pages.append("CI/CD Pipelines")
|
|
939
|
+
|
|
940
|
+
# Add Workflows page if available
|
|
941
|
+
if HAS_WORKFLOWS_PAGE:
|
|
942
|
+
pages.append("Workflows")
|
|
943
|
+
|
|
944
|
+
# Add Debug Dependencies page (always useful for troubleshooting)
|
|
945
|
+
if HAS_DEBUG_PAGE:
|
|
946
|
+
pages.append("Debug Dependencies")
|
|
947
|
+
|
|
842
948
|
page = st.sidebar.selectbox(
|
|
843
949
|
"Choose a page",
|
|
844
950
|
pages,
|
|
845
951
|
index=0, # Default to Pipeline Overview
|
|
952
|
+
key="main_page_selector"
|
|
846
953
|
)
|
|
847
954
|
|
|
848
955
|
# Auto-refresh toggle (default off to prevent blocking)
|
|
849
|
-
auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=
|
|
956
|
+
auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=True)
|
|
850
957
|
if auto_refresh:
|
|
851
958
|
try:
|
|
852
959
|
from streamlit_autorefresh import st_autorefresh
|
|
@@ -873,7 +980,12 @@ def main():
|
|
|
873
980
|
|
|
874
981
|
# Main content with error handling
|
|
875
982
|
try:
|
|
876
|
-
if page == "
|
|
983
|
+
if page == "Overview":
|
|
984
|
+
if HAS_OVERVIEW_PAGE and show_overview:
|
|
985
|
+
show_overview()
|
|
986
|
+
else:
|
|
987
|
+
st.error("Overview page not available")
|
|
988
|
+
elif page == "Pipeline Overview":
|
|
877
989
|
show_pipeline_overview()
|
|
878
990
|
elif page == "ML Processing":
|
|
879
991
|
show_ml_processing()
|
|
@@ -883,30 +995,82 @@ def main():
|
|
|
883
995
|
show_model_training_evaluation()
|
|
884
996
|
elif page == "Predictions":
|
|
885
997
|
# Use enhanced predictions page if available, otherwise fallback
|
|
886
|
-
if
|
|
998
|
+
if HAS_PREDICTIONS_ENHANCED and show_predictions_enhanced:
|
|
887
999
|
show_predictions_enhanced()
|
|
888
1000
|
else:
|
|
889
1001
|
show_predictions()
|
|
890
1002
|
elif page == "Trading Dashboard":
|
|
891
|
-
if
|
|
892
|
-
|
|
1003
|
+
if HAS_TRADING_PAGES and show_trading_dashboard:
|
|
1004
|
+
try:
|
|
1005
|
+
show_trading_dashboard()
|
|
1006
|
+
except Exception as e:
|
|
1007
|
+
st.error(f"❌ Error in Trading Dashboard page: {e}")
|
|
1008
|
+
import traceback
|
|
1009
|
+
st.code(traceback.format_exc())
|
|
893
1010
|
else:
|
|
894
1011
|
st.warning("Trading dashboard not available")
|
|
895
1012
|
elif page == "Test Portfolio":
|
|
896
|
-
if
|
|
897
|
-
|
|
1013
|
+
if HAS_TRADING_PAGES and show_test_portfolio:
|
|
1014
|
+
try:
|
|
1015
|
+
show_test_portfolio()
|
|
1016
|
+
except Exception as e:
|
|
1017
|
+
st.error(f"❌ Error in Test Portfolio page: {e}")
|
|
1018
|
+
import traceback
|
|
1019
|
+
st.code(traceback.format_exc())
|
|
898
1020
|
else:
|
|
899
1021
|
st.warning("Test portfolio not available")
|
|
1022
|
+
elif page == "Monte Carlo Predictions":
|
|
1023
|
+
if HAS_MONTE_CARLO_PAGE and show_monte_carlo_predictions:
|
|
1024
|
+
try:
|
|
1025
|
+
show_monte_carlo_predictions()
|
|
1026
|
+
except Exception as e:
|
|
1027
|
+
st.error(f"❌ Error in Monte Carlo Predictions page: {e}")
|
|
1028
|
+
import traceback
|
|
1029
|
+
st.code(traceback.format_exc())
|
|
1030
|
+
else:
|
|
1031
|
+
st.warning("Monte Carlo predictions not available")
|
|
900
1032
|
elif page == "LSH Jobs":
|
|
901
1033
|
show_lsh_jobs()
|
|
902
1034
|
elif page == "System Health":
|
|
903
1035
|
show_system_health()
|
|
904
1036
|
elif page == "Scrapers & Logs" and HAS_SCRAPERS_PAGE:
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1037
|
+
try:
|
|
1038
|
+
show_scrapers_and_logs()
|
|
1039
|
+
except Exception as e:
|
|
1040
|
+
st.error(f"❌ Error in Scrapers & Logs page: {e}")
|
|
1041
|
+
import traceback
|
|
1042
|
+
st.code(traceback.format_exc())
|
|
1043
|
+
elif page == "CI/CD Pipelines":
|
|
1044
|
+
if show_cicd_dashboard is not None:
|
|
1045
|
+
try:
|
|
1046
|
+
show_cicd_dashboard()
|
|
1047
|
+
except Exception as e:
|
|
1048
|
+
st.error(f"❌ Error in CI/CD Pipelines page: {e}")
|
|
1049
|
+
import traceback
|
|
1050
|
+
st.code(traceback.format_exc())
|
|
1051
|
+
else:
|
|
1052
|
+
st.warning("CI/CD Pipelines page is not available. This page requires additional dependencies.")
|
|
1053
|
+
elif page == "Workflows":
|
|
1054
|
+
if show_workflows_dashboard is not None:
|
|
1055
|
+
try:
|
|
1056
|
+
show_workflows_dashboard()
|
|
1057
|
+
except Exception as e:
|
|
1058
|
+
st.error(f"❌ Error in Workflows page: {e}")
|
|
1059
|
+
import traceback
|
|
1060
|
+
st.code(traceback.format_exc())
|
|
1061
|
+
else:
|
|
1062
|
+
st.warning("Workflows page is not available. This page requires additional dependencies.")
|
|
1063
|
+
|
|
1064
|
+
elif page == "Debug Dependencies":
|
|
1065
|
+
if show_debug_dependencies is not None:
|
|
1066
|
+
try:
|
|
1067
|
+
show_debug_dependencies()
|
|
1068
|
+
except Exception as e:
|
|
1069
|
+
st.error(f"❌ Error in Debug Dependencies page: {e}")
|
|
1070
|
+
import traceback
|
|
1071
|
+
st.code(traceback.format_exc())
|
|
1072
|
+
else:
|
|
1073
|
+
st.warning("Debug Dependencies page is not available.")
|
|
910
1074
|
except Exception as e:
|
|
911
1075
|
st.error(f"❌ Error loading page '{page}': {e}")
|
|
912
1076
|
import traceback
|
|
@@ -2804,5 +2968,12 @@ def show_system_health():
|
|
|
2804
2968
|
st.plotly_chart(fig, width="stretch", config={"responsive": True})
|
|
2805
2969
|
|
|
2806
2970
|
|
|
2807
|
-
# Run the main dashboard function
|
|
2808
|
-
|
|
2971
|
+
# Run the main dashboard function with error handling
|
|
2972
|
+
try:
|
|
2973
|
+
main()
|
|
2974
|
+
except Exception as e:
|
|
2975
|
+
st.error(f"❌ Dashboard error: {e}")
|
|
2976
|
+
st.info("🔄 Please refresh the page to try again")
|
|
2977
|
+
import traceback
|
|
2978
|
+
with st.expander("Error details"):
|
|
2979
|
+
st.code(traceback.format_exc())
|
|
@@ -1,75 +1,26 @@
|
|
|
1
1
|
"""Streamlit dashboard for ML system monitoring - Supabase version"""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import os
|
|
5
4
|
from datetime import datetime, timedelta
|
|
6
|
-
from pathlib import Path
|
|
7
5
|
|
|
8
6
|
import numpy as np
|
|
9
7
|
import pandas as pd
|
|
10
8
|
import plotly.express as px
|
|
11
9
|
import plotly.graph_objects as go
|
|
12
10
|
import streamlit as st
|
|
13
|
-
from dotenv import load_dotenv
|
|
14
11
|
from plotly.subplots import make_subplots
|
|
15
|
-
|
|
12
|
+
|
|
13
|
+
from mcli.ml.dashboard.common import get_supabase_client, load_environment_variables, setup_page_config
|
|
14
|
+
from mcli.ml.dashboard.styles import apply_dashboard_styles
|
|
16
15
|
|
|
17
16
|
# Page config must come first
|
|
18
|
-
|
|
19
|
-
page_title="MCLI ML Dashboard", page_icon="📊", layout="wide", initial_sidebar_state="expanded"
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
# Load environment variables from supabase/.env.local
|
|
23
|
-
env_path = Path(__file__).parent.parent.parent.parent.parent / "supabase" / ".env.local"
|
|
24
|
-
if env_path.exists():
|
|
25
|
-
load_dotenv(env_path)
|
|
26
|
-
|
|
27
|
-
# Custom CSS
|
|
28
|
-
st.markdown(
|
|
29
|
-
"""
|
|
30
|
-
<style>
|
|
31
|
-
.metric-card {
|
|
32
|
-
background-color: #f0f2f6;
|
|
33
|
-
padding: 1rem;
|
|
34
|
-
border-radius: 0.5rem;
|
|
35
|
-
border-left: 4px solid #1f77b4;
|
|
36
|
-
}
|
|
37
|
-
</style>
|
|
38
|
-
""",
|
|
39
|
-
unsafe_allow_html=True,
|
|
40
|
-
)
|
|
17
|
+
setup_page_config(page_title="MCLI ML Dashboard")
|
|
41
18
|
|
|
19
|
+
# Load environment variables
|
|
20
|
+
load_environment_variables()
|
|
42
21
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"""Get Supabase client with Streamlit Cloud secrets support"""
|
|
46
|
-
# Try Streamlit secrets first (for Streamlit Cloud), then fall back to environment variables (for local dev)
|
|
47
|
-
try:
|
|
48
|
-
url = st.secrets.get("SUPABASE_URL", "")
|
|
49
|
-
key = st.secrets.get("SUPABASE_KEY", "") or st.secrets.get("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
50
|
-
except (AttributeError, FileNotFoundError):
|
|
51
|
-
# Secrets not available, try environment variables
|
|
52
|
-
url = os.getenv("SUPABASE_URL", "")
|
|
53
|
-
key = os.getenv("SUPABASE_KEY", "") or os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
54
|
-
|
|
55
|
-
if not url or not key:
|
|
56
|
-
st.warning(
|
|
57
|
-
"⚠️ Supabase credentials not found. Configure SUPABASE_URL and SUPABASE_KEY in Streamlit Cloud secrets or environment variables."
|
|
58
|
-
)
|
|
59
|
-
return None
|
|
60
|
-
|
|
61
|
-
try:
|
|
62
|
-
client = create_client(url, key)
|
|
63
|
-
# Test connection
|
|
64
|
-
try:
|
|
65
|
-
client.table("politicians").select("id").limit(1).execute()
|
|
66
|
-
return client
|
|
67
|
-
except Exception as e:
|
|
68
|
-
st.error(f"❌ Supabase connection test failed: {e}")
|
|
69
|
-
return None
|
|
70
|
-
except Exception as e:
|
|
71
|
-
st.error(f"❌ Failed to create Supabase client: {e}")
|
|
72
|
-
return None
|
|
22
|
+
# Apply standard dashboard styles
|
|
23
|
+
apply_dashboard_styles()
|
|
73
24
|
|
|
74
25
|
|
|
75
26
|
@st.cache_data(ttl=30)
|
|
@@ -12,24 +12,22 @@ from scipy import stats
|
|
|
12
12
|
|
|
13
13
|
from mcli.ml.database.models import Experiment, Model, ModelStatus
|
|
14
14
|
from mcli.ml.database.session import SessionLocal
|
|
15
|
+
from mcli.ml.dashboard.common import setup_page_config
|
|
16
|
+
from mcli.ml.dashboard.styles import apply_dashboard_styles
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
# Page config - must be first
|
|
19
|
+
setup_page_config(
|
|
17
20
|
page_title="MCLI Training Dashboard",
|
|
18
|
-
page_icon="🔬"
|
|
19
|
-
layout="wide",
|
|
20
|
-
initial_sidebar_state="expanded",
|
|
21
|
+
page_icon="🔬"
|
|
21
22
|
)
|
|
22
23
|
|
|
23
|
-
#
|
|
24
|
+
# Apply standard dashboard styles (includes metric-card)
|
|
25
|
+
apply_dashboard_styles()
|
|
26
|
+
|
|
27
|
+
# Add training-specific CSS
|
|
24
28
|
st.markdown(
|
|
25
29
|
"""
|
|
26
30
|
<style>
|
|
27
|
-
.metric-card {
|
|
28
|
-
background-color: #f0f2f6;
|
|
29
|
-
padding: 1rem;
|
|
30
|
-
border-radius: 0.5rem;
|
|
31
|
-
border-left: 4px solid #1f77b4;
|
|
32
|
-
}
|
|
33
31
|
.model-card {
|
|
34
32
|
background-color: #ffffff;
|
|
35
33
|
padding: 1.5rem;
|
|
@@ -594,7 +592,7 @@ def main():
|
|
|
594
592
|
)
|
|
595
593
|
|
|
596
594
|
# Auto-refresh toggle
|
|
597
|
-
auto_refresh = st.sidebar.checkbox("Auto-refresh (60s)", value=
|
|
595
|
+
auto_refresh = st.sidebar.checkbox("Auto-refresh (60s)", value=True)
|
|
598
596
|
if auto_refresh:
|
|
599
597
|
import time
|
|
600
598
|
|