mcli-framework 7.8.3__py3-none-any.whl → 7.8.5__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/__init__.py +160 -0
- mcli/__main__.py +14 -0
- mcli/app/__init__.py +23 -0
- mcli/app/commands_cmd.py +942 -199
- mcli/app/main.py +5 -21
- mcli/app/model/__init__.py +0 -0
- mcli/app/model_cmd.py +57 -472
- mcli/app/video/__init__.py +5 -0
- mcli/chat/__init__.py +34 -0
- mcli/lib/__init__.py +0 -0
- mcli/lib/api/__init__.py +0 -0
- mcli/lib/auth/__init__.py +1 -0
- mcli/lib/config/__init__.py +1 -0
- mcli/lib/erd/__init__.py +25 -0
- mcli/lib/files/__init__.py +0 -0
- mcli/lib/fs/__init__.py +1 -0
- mcli/lib/logger/__init__.py +3 -0
- mcli/lib/performance/__init__.py +17 -0
- mcli/lib/pickles/__init__.py +1 -0
- mcli/lib/shell/__init__.py +0 -0
- mcli/lib/toml/__init__.py +1 -0
- mcli/lib/watcher/__init__.py +0 -0
- mcli/ml/__init__.py +16 -0
- mcli/ml/api/__init__.py +30 -0
- mcli/ml/api/routers/__init__.py +27 -0
- mcli/ml/auth/__init__.py +41 -0
- mcli/ml/backtesting/__init__.py +33 -0
- mcli/ml/cli/__init__.py +5 -0
- mcli/ml/config/__init__.py +33 -0
- mcli/ml/configs/__init__.py +16 -0
- mcli/ml/dashboard/__init__.py +12 -0
- mcli/ml/dashboard/app_supabase.py +57 -12
- mcli/ml/dashboard/components/__init__.py +7 -0
- mcli/ml/dashboard/pages/__init__.py +6 -0
- mcli/ml/dashboard/pages/predictions_enhanced.py +82 -38
- mcli/ml/dashboard/utils.py +39 -11
- mcli/ml/data_ingestion/__init__.py +29 -0
- mcli/ml/database/__init__.py +40 -0
- mcli/ml/experimentation/__init__.py +29 -0
- mcli/ml/features/__init__.py +39 -0
- mcli/ml/mlops/__init__.py +19 -0
- mcli/ml/models/__init__.py +90 -0
- mcli/ml/monitoring/__init__.py +25 -0
- mcli/ml/optimization/__init__.py +27 -0
- mcli/ml/predictions/__init__.py +5 -0
- mcli/ml/preprocessing/__init__.py +24 -0
- mcli/ml/scripts/__init__.py +1 -0
- mcli/ml/trading/__init__.py +63 -0
- mcli/ml/training/__init__.py +7 -0
- mcli/mygroup/__init__.py +3 -0
- mcli/public/__init__.py +1 -0
- mcli/public/commands/__init__.py +2 -0
- mcli/self/__init__.py +3 -0
- mcli/self/self_cmd.py +4 -253
- mcli/self/store_cmd.py +5 -3
- mcli/workflow/__init__.py +0 -0
- mcli/workflow/daemon/__init__.py +15 -0
- mcli/workflow/dashboard/__init__.py +5 -0
- mcli/workflow/dashboard/dashboard_cmd.py +1 -0
- mcli/workflow/docker/__init__.py +0 -0
- mcli/workflow/file/__init__.py +0 -0
- mcli/workflow/gcloud/__init__.py +1 -0
- mcli/workflow/git_commit/__init__.py +0 -0
- mcli/workflow/interview/__init__.py +0 -0
- mcli/workflow/politician_trading/__init__.py +4 -0
- mcli/workflow/registry/__init__.py +0 -0
- mcli/workflow/repo/__init__.py +0 -0
- mcli/workflow/scheduler/__init__.py +25 -0
- mcli/workflow/search/__init__.py +0 -0
- mcli/workflow/sync/__init__.py +5 -0
- mcli/workflow/videos/__init__.py +1 -0
- mcli/workflow/wakatime/__init__.py +80 -0
- {mcli_framework-7.8.3.dist-info → mcli_framework-7.8.5.dist-info}/METADATA +1 -1
- {mcli_framework-7.8.3.dist-info → mcli_framework-7.8.5.dist-info}/RECORD +78 -18
- mcli/app/chat_cmd.py +0 -42
- mcli/test/cron_test_cmd.py +0 -697
- mcli/test/test_cmd.py +0 -30
- {mcli_framework-7.8.3.dist-info → mcli_framework-7.8.5.dist-info}/WHEEL +0 -0
- {mcli_framework-7.8.3.dist-info → mcli_framework-7.8.5.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.8.3.dist-info → mcli_framework-7.8.5.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.8.3.dist-info → mcli_framework-7.8.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Performance optimization utilities for mcli
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .uvloop_config import (
|
|
6
|
+
configure_event_loop_for_performance,
|
|
7
|
+
get_event_loop_info,
|
|
8
|
+
install_uvloop,
|
|
9
|
+
should_use_uvloop,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"install_uvloop",
|
|
14
|
+
"should_use_uvloop",
|
|
15
|
+
"get_event_loop_info",
|
|
16
|
+
"configure_event_loop_for_performance",
|
|
17
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .pickles import ObjectCache
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .toml import read_from_toml
|
|
File without changes
|
mcli/ml/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""MCLI Machine Learning Module for Stock Recommendation System"""
|
|
2
|
+
|
|
3
|
+
from .configs.dvc_config import get_dvc_config, setup_dvc
|
|
4
|
+
from .configs.mlflow_config import get_mlflow_config, setup_mlflow
|
|
5
|
+
from .configs.mlops_manager import MLOpsManager, get_mlops_manager
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"get_mlops_manager",
|
|
11
|
+
"MLOpsManager",
|
|
12
|
+
"get_mlflow_config",
|
|
13
|
+
"setup_mlflow",
|
|
14
|
+
"get_dvc_config",
|
|
15
|
+
"setup_dvc",
|
|
16
|
+
]
|
mcli/ml/api/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""API routes and endpoints for ML system"""
|
|
2
|
+
|
|
3
|
+
from .app import create_app, get_application
|
|
4
|
+
from .routers import (
|
|
5
|
+
admin_router,
|
|
6
|
+
auth_router,
|
|
7
|
+
backtest_router,
|
|
8
|
+
data_router,
|
|
9
|
+
model_router,
|
|
10
|
+
monitoring_router,
|
|
11
|
+
portfolio_router,
|
|
12
|
+
prediction_router,
|
|
13
|
+
trade_router,
|
|
14
|
+
websocket_router,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"auth_router",
|
|
19
|
+
"model_router",
|
|
20
|
+
"prediction_router",
|
|
21
|
+
"portfolio_router",
|
|
22
|
+
"data_router",
|
|
23
|
+
"trade_router",
|
|
24
|
+
"backtest_router",
|
|
25
|
+
"monitoring_router",
|
|
26
|
+
"admin_router",
|
|
27
|
+
"websocket_router",
|
|
28
|
+
"create_app",
|
|
29
|
+
"get_application",
|
|
30
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""API routers"""
|
|
2
|
+
|
|
3
|
+
from . import (
|
|
4
|
+
admin_router,
|
|
5
|
+
auth_router,
|
|
6
|
+
backtest_router,
|
|
7
|
+
data_router,
|
|
8
|
+
model_router,
|
|
9
|
+
monitoring_router,
|
|
10
|
+
portfolio_router,
|
|
11
|
+
prediction_router,
|
|
12
|
+
trade_router,
|
|
13
|
+
websocket_router,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"auth_router",
|
|
18
|
+
"model_router",
|
|
19
|
+
"prediction_router",
|
|
20
|
+
"portfolio_router",
|
|
21
|
+
"data_router",
|
|
22
|
+
"trade_router",
|
|
23
|
+
"backtest_router",
|
|
24
|
+
"monitoring_router",
|
|
25
|
+
"admin_router",
|
|
26
|
+
"websocket_router",
|
|
27
|
+
]
|
mcli/ml/auth/__init__.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Authentication and authorization system"""
|
|
2
|
+
|
|
3
|
+
from .auth_manager import (
|
|
4
|
+
AuthManager,
|
|
5
|
+
create_access_token,
|
|
6
|
+
get_current_active_user,
|
|
7
|
+
get_current_user,
|
|
8
|
+
hash_password,
|
|
9
|
+
require_role,
|
|
10
|
+
verify_access_token,
|
|
11
|
+
verify_password,
|
|
12
|
+
)
|
|
13
|
+
from .models import (
|
|
14
|
+
PasswordChange,
|
|
15
|
+
PasswordReset,
|
|
16
|
+
TokenResponse,
|
|
17
|
+
UserCreate,
|
|
18
|
+
UserLogin,
|
|
19
|
+
UserResponse,
|
|
20
|
+
)
|
|
21
|
+
from .permissions import Permission, check_permission, has_permission
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"AuthManager",
|
|
25
|
+
"create_access_token",
|
|
26
|
+
"verify_access_token",
|
|
27
|
+
"get_current_user",
|
|
28
|
+
"get_current_active_user",
|
|
29
|
+
"require_role",
|
|
30
|
+
"hash_password",
|
|
31
|
+
"verify_password",
|
|
32
|
+
"UserCreate",
|
|
33
|
+
"UserLogin",
|
|
34
|
+
"UserResponse",
|
|
35
|
+
"TokenResponse",
|
|
36
|
+
"PasswordReset",
|
|
37
|
+
"PasswordChange",
|
|
38
|
+
"Permission",
|
|
39
|
+
"check_permission",
|
|
40
|
+
"has_permission",
|
|
41
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Backtesting framework for trading strategies"""
|
|
2
|
+
|
|
3
|
+
from .backtest_engine import (
|
|
4
|
+
BacktestConfig,
|
|
5
|
+
BacktestEngine,
|
|
6
|
+
BacktestResult,
|
|
7
|
+
PositionManager,
|
|
8
|
+
TradingStrategy,
|
|
9
|
+
)
|
|
10
|
+
from .performance_metrics import (
|
|
11
|
+
PerformanceAnalyzer,
|
|
12
|
+
PortfolioMetrics,
|
|
13
|
+
RiskMetrics,
|
|
14
|
+
plot_performance,
|
|
15
|
+
)
|
|
16
|
+
from .trading_simulator import MarketSimulator, Order, Portfolio, Position, TradingSimulator
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"BacktestEngine",
|
|
20
|
+
"BacktestConfig",
|
|
21
|
+
"BacktestResult",
|
|
22
|
+
"TradingStrategy",
|
|
23
|
+
"PositionManager",
|
|
24
|
+
"PerformanceAnalyzer",
|
|
25
|
+
"PortfolioMetrics",
|
|
26
|
+
"RiskMetrics",
|
|
27
|
+
"plot_performance",
|
|
28
|
+
"TradingSimulator",
|
|
29
|
+
"Order",
|
|
30
|
+
"Position",
|
|
31
|
+
"Portfolio",
|
|
32
|
+
"MarketSimulator",
|
|
33
|
+
]
|
mcli/ml/cli/__init__.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Configuration management for ML system"""
|
|
2
|
+
|
|
3
|
+
from .settings import (
|
|
4
|
+
APISettings,
|
|
5
|
+
DatabaseSettings,
|
|
6
|
+
DataSettings,
|
|
7
|
+
MLflowSettings,
|
|
8
|
+
ModelSettings,
|
|
9
|
+
MonitoringSettings,
|
|
10
|
+
RedisSettings,
|
|
11
|
+
SecuritySettings,
|
|
12
|
+
Settings,
|
|
13
|
+
create_settings,
|
|
14
|
+
get_settings,
|
|
15
|
+
settings,
|
|
16
|
+
update_settings,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"Settings",
|
|
21
|
+
"DatabaseSettings",
|
|
22
|
+
"RedisSettings",
|
|
23
|
+
"MLflowSettings",
|
|
24
|
+
"ModelSettings",
|
|
25
|
+
"DataSettings",
|
|
26
|
+
"APISettings",
|
|
27
|
+
"MonitoringSettings",
|
|
28
|
+
"SecuritySettings",
|
|
29
|
+
"settings",
|
|
30
|
+
"get_settings",
|
|
31
|
+
"update_settings",
|
|
32
|
+
"create_settings",
|
|
33
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""ML Configuration Module"""
|
|
2
|
+
|
|
3
|
+
from .dvc_config import DVCConfig, get_dvc_config, setup_dvc
|
|
4
|
+
from .mlflow_config import MLflowConfig, get_mlflow_config, setup_mlflow
|
|
5
|
+
from .mlops_manager import MLOpsManager, get_mlops_manager
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"MLflowConfig",
|
|
9
|
+
"get_mlflow_config",
|
|
10
|
+
"setup_mlflow",
|
|
11
|
+
"DVCConfig",
|
|
12
|
+
"get_dvc_config",
|
|
13
|
+
"setup_dvc",
|
|
14
|
+
"MLOpsManager",
|
|
15
|
+
"get_mlops_manager",
|
|
16
|
+
]
|
|
@@ -49,7 +49,7 @@ def get_politicians_data():
|
|
|
49
49
|
|
|
50
50
|
@st.cache_data(ttl=30)
|
|
51
51
|
def get_disclosures_data():
|
|
52
|
-
"""Get trading disclosures from Supabase"""
|
|
52
|
+
"""Get trading disclosures from Supabase with politician details"""
|
|
53
53
|
client = get_supabase_client()
|
|
54
54
|
if not client:
|
|
55
55
|
return pd.DataFrame()
|
|
@@ -65,6 +65,40 @@ def get_disclosures_data():
|
|
|
65
65
|
)
|
|
66
66
|
df = pd.DataFrame(response.data)
|
|
67
67
|
|
|
68
|
+
if df.empty:
|
|
69
|
+
return df
|
|
70
|
+
|
|
71
|
+
# Get all unique politician IDs
|
|
72
|
+
politician_ids = df["politician_id"].dropna().unique()
|
|
73
|
+
|
|
74
|
+
# Fetch politician details
|
|
75
|
+
politicians = {}
|
|
76
|
+
if len(politician_ids) > 0:
|
|
77
|
+
pol_response = (
|
|
78
|
+
client.table("politicians")
|
|
79
|
+
.select("id, full_name, party, state_or_country")
|
|
80
|
+
.in_("id", list(politician_ids))
|
|
81
|
+
.execute()
|
|
82
|
+
)
|
|
83
|
+
politicians = {p["id"]: p for p in pol_response.data}
|
|
84
|
+
|
|
85
|
+
# Add politician details to disclosures
|
|
86
|
+
df["politician_name"] = df["politician_id"].map(
|
|
87
|
+
lambda x: politicians.get(x, {}).get("full_name", "Unknown")
|
|
88
|
+
)
|
|
89
|
+
df["politician_party"] = df["politician_id"].map(
|
|
90
|
+
lambda x: politicians.get(x, {}).get("party", "Unknown")
|
|
91
|
+
)
|
|
92
|
+
df["politician_state"] = df["politician_id"].map(
|
|
93
|
+
lambda x: politicians.get(x, {}).get("state_or_country", "Unknown")
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Rename columns for compatibility
|
|
97
|
+
df["ticker_symbol"] = df["asset_ticker"]
|
|
98
|
+
df["amount"] = df["amount_exact"].fillna(
|
|
99
|
+
(df["amount_range_min"] + df["amount_range_max"]) / 2
|
|
100
|
+
)
|
|
101
|
+
|
|
68
102
|
# Convert datetime columns to proper datetime format
|
|
69
103
|
date_columns = ["transaction_date", "disclosure_date", "created_at", "updated_at"]
|
|
70
104
|
for col in date_columns:
|
|
@@ -347,21 +381,29 @@ def show_politicians():
|
|
|
347
381
|
)
|
|
348
382
|
with col2:
|
|
349
383
|
state_filter = st.multiselect(
|
|
350
|
-
"State",
|
|
351
|
-
options=
|
|
384
|
+
"State/Country",
|
|
385
|
+
options=(
|
|
386
|
+
politicians["state_or_country"].dropna().unique()
|
|
387
|
+
if "state_or_country" in politicians
|
|
388
|
+
else []
|
|
389
|
+
),
|
|
352
390
|
default=[],
|
|
353
391
|
)
|
|
354
392
|
with col3:
|
|
355
|
-
active_only = st.checkbox("Active Only", value=
|
|
393
|
+
active_only = st.checkbox("Active Only", value=False)
|
|
356
394
|
|
|
357
395
|
# Apply filters
|
|
358
396
|
filtered = politicians.copy()
|
|
359
397
|
if party_filter and "party" in filtered:
|
|
360
398
|
filtered = filtered[filtered["party"].isin(party_filter)]
|
|
361
|
-
if state_filter and "
|
|
362
|
-
filtered = filtered[filtered["
|
|
363
|
-
if active_only and "
|
|
364
|
-
|
|
399
|
+
if state_filter and "state_or_country" in filtered:
|
|
400
|
+
filtered = filtered[filtered["state_or_country"].isin(state_filter)]
|
|
401
|
+
if active_only and "term_end" in filtered:
|
|
402
|
+
# Filter for active (term_end is in the future or null)
|
|
403
|
+
filtered = filtered[
|
|
404
|
+
(filtered["term_end"].isna())
|
|
405
|
+
| (pd.to_datetime(filtered["term_end"]) > pd.Timestamp.now())
|
|
406
|
+
]
|
|
365
407
|
|
|
366
408
|
# Display data
|
|
367
409
|
st.dataframe(filtered, width="stretch")
|
|
@@ -369,17 +411,20 @@ def show_politicians():
|
|
|
369
411
|
# Stats
|
|
370
412
|
col1, col2 = st.columns(2)
|
|
371
413
|
with col1:
|
|
372
|
-
if "party" in filtered:
|
|
414
|
+
if "party" in filtered and not filtered["party"].dropna().empty:
|
|
373
415
|
party_dist = filtered["party"].value_counts()
|
|
374
416
|
fig = px.pie(
|
|
375
417
|
values=party_dist.values, names=party_dist.index, title="Party Distribution"
|
|
376
418
|
)
|
|
377
419
|
st.plotly_chart(fig, width="stretch", config={"responsive": True})
|
|
378
420
|
with col2:
|
|
379
|
-
if "
|
|
380
|
-
state_dist = filtered["
|
|
421
|
+
if "state_or_country" in filtered and not filtered["state_or_country"].dropna().empty:
|
|
422
|
+
state_dist = filtered["state_or_country"].value_counts().head(10)
|
|
381
423
|
fig = px.bar(
|
|
382
|
-
x=state_dist.values,
|
|
424
|
+
x=state_dist.values,
|
|
425
|
+
y=state_dist.index,
|
|
426
|
+
orientation="h",
|
|
427
|
+
title="Top States/Countries",
|
|
383
428
|
)
|
|
384
429
|
st.plotly_chart(fig, width="stretch", config={"responsive": True})
|
|
385
430
|
else:
|
|
@@ -158,54 +158,83 @@ def generate_mock_historical_performance() -> pd.DataFrame:
|
|
|
158
158
|
|
|
159
159
|
|
|
160
160
|
def get_real_predictions() -> pd.DataFrame:
|
|
161
|
-
"""Get real predictions from ML pipeline"""
|
|
161
|
+
"""Get real predictions from ML pipeline - REQUIRES SUPABASE CONNECTION"""
|
|
162
162
|
if not HAS_REAL_DATA:
|
|
163
|
-
st.
|
|
164
|
-
|
|
163
|
+
st.error("❌ **CONFIGURATION ERROR**: Real data functions not available!")
|
|
164
|
+
st.error(
|
|
165
|
+
"Cannot import Supabase utilities. Check that `src/mcli/ml/dashboard/utils.py` exists."
|
|
166
|
+
)
|
|
167
|
+
st.stop()
|
|
165
168
|
|
|
166
169
|
try:
|
|
167
170
|
# Get real disclosure data
|
|
168
171
|
disclosures = get_disclosures_data()
|
|
169
172
|
|
|
170
173
|
if disclosures.empty:
|
|
171
|
-
st.
|
|
172
|
-
|
|
174
|
+
st.error("❌ **DATABASE ERROR**: No trading disclosure data available!")
|
|
175
|
+
st.error("Supabase connection may not be configured. Check secrets configuration.")
|
|
176
|
+
st.code(
|
|
177
|
+
"""
|
|
178
|
+
# Required Streamlit Secrets:
|
|
179
|
+
SUPABASE_URL = "your_supabase_url"
|
|
180
|
+
SUPABASE_KEY = "your_supabase_key"
|
|
181
|
+
SUPABASE_SERVICE_ROLE_KEY = "your_service_role_key"
|
|
182
|
+
""",
|
|
183
|
+
language="toml",
|
|
184
|
+
)
|
|
185
|
+
st.stop()
|
|
186
|
+
|
|
187
|
+
# Check if we have enough data for ML
|
|
188
|
+
if len(disclosures) < 10:
|
|
189
|
+
st.error(
|
|
190
|
+
f"❌ **INSUFFICIENT DATA**: Found only {len(disclosures)} disclosures. "
|
|
191
|
+
f"Need at least 10 for ML predictions."
|
|
173
192
|
)
|
|
174
|
-
|
|
193
|
+
st.info("Please run data collection workflows to populate the database.")
|
|
194
|
+
st.stop()
|
|
175
195
|
|
|
176
196
|
# Run ML pipeline to generate predictions
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
197
|
+
st.success(f"✅ Loaded {len(disclosures)} real trading disclosures from database!")
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
_, _, predictions = run_ml_pipeline(disclosures)
|
|
201
|
+
|
|
202
|
+
if predictions is not None and not predictions.empty:
|
|
203
|
+
# Ensure all required columns exist
|
|
204
|
+
required_cols = [
|
|
205
|
+
"ticker",
|
|
206
|
+
"predicted_return",
|
|
207
|
+
"confidence",
|
|
208
|
+
"risk_score",
|
|
209
|
+
"recommendation",
|
|
210
|
+
"sector",
|
|
211
|
+
"politician",
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
for col in required_cols:
|
|
215
|
+
if col not in predictions.columns:
|
|
216
|
+
if col == "sector":
|
|
217
|
+
predictions[col] = "Technology" # Default
|
|
218
|
+
elif col == "politician":
|
|
219
|
+
predictions[col] = "Unknown"
|
|
220
|
+
elif col == "ticker":
|
|
221
|
+
predictions[col] = "UNK"
|
|
222
|
+
|
|
223
|
+
st.success("✅ Generated ML predictions from real data!")
|
|
224
|
+
return predictions
|
|
225
|
+
else:
|
|
226
|
+
st.error("❌ **ML PIPELINE ERROR**: Predictions returned empty!")
|
|
227
|
+
st.error("ML pipeline ran but produced no predictions.")
|
|
228
|
+
st.stop()
|
|
229
|
+
except Exception as ml_error:
|
|
230
|
+
st.error(f"❌ **ML PIPELINE ERROR**: {ml_error}")
|
|
231
|
+
st.exception(ml_error)
|
|
232
|
+
st.stop()
|
|
204
233
|
|
|
205
234
|
except Exception as e:
|
|
206
|
-
st.error(f"
|
|
207
|
-
st.
|
|
208
|
-
|
|
235
|
+
st.error(f"❌ **FATAL ERROR**: {e}")
|
|
236
|
+
st.exception(e)
|
|
237
|
+
st.stop()
|
|
209
238
|
|
|
210
239
|
|
|
211
240
|
def show_predictions_enhanced():
|
|
@@ -659,12 +688,27 @@ def show_prediction_generator():
|
|
|
659
688
|
|
|
660
689
|
|
|
661
690
|
def show_performance_tracker():
|
|
662
|
-
"""Show prediction performance over time"""
|
|
691
|
+
"""Show prediction performance over time - REQUIRES REAL ML PREDICTION HISTORY"""
|
|
663
692
|
|
|
664
693
|
st.subheader("📈 Prediction Performance Tracker")
|
|
665
694
|
st.markdown("Track the accuracy and ROI of our ML predictions over time")
|
|
666
695
|
|
|
667
|
-
#
|
|
696
|
+
# TODO: Implement real performance tracking from database
|
|
697
|
+
st.error(
|
|
698
|
+
"❌ **FEATURE NOT IMPLEMENTED**: Performance tracking requires ML prediction history database."
|
|
699
|
+
)
|
|
700
|
+
st.info(
|
|
701
|
+
"""
|
|
702
|
+
This feature requires:
|
|
703
|
+
1. A prediction_history table in Supabase
|
|
704
|
+
2. Automated prediction tracking and validation
|
|
705
|
+
3. Historical performance metrics calculation
|
|
706
|
+
|
|
707
|
+
Currently showing mock data for demonstration only.
|
|
708
|
+
"""
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
# Generate historical data (mock for now)
|
|
668
712
|
performance_df = generate_mock_historical_performance()
|
|
669
713
|
|
|
670
714
|
# KPIs
|
mcli/ml/dashboard/utils.py
CHANGED
|
@@ -69,17 +69,11 @@ def get_disclosures_data() -> pd.DataFrame:
|
|
|
69
69
|
"""Get trading disclosures from Supabase with proper schema mapping"""
|
|
70
70
|
client = get_supabase_client()
|
|
71
71
|
if not client:
|
|
72
|
-
|
|
72
|
+
st.warning("⚠️ Supabase connection not available. Configure SUPABASE_URL and SUPABASE_KEY.")
|
|
73
|
+
return pd.DataFrame() # Return empty instead of demo data
|
|
73
74
|
|
|
74
75
|
try:
|
|
75
|
-
#
|
|
76
|
-
count_response = client.table("trading_disclosures").select("*", count="exact").execute()
|
|
77
|
-
total_count = count_response.count
|
|
78
|
-
|
|
79
|
-
if total_count == 0:
|
|
80
|
-
return _generate_demo_disclosures()
|
|
81
|
-
|
|
82
|
-
# Get the data
|
|
76
|
+
# Get the data with politician details joined
|
|
83
77
|
response = (
|
|
84
78
|
client.table("trading_disclosures")
|
|
85
79
|
.select("*")
|
|
@@ -89,14 +83,48 @@ def get_disclosures_data() -> pd.DataFrame:
|
|
|
89
83
|
)
|
|
90
84
|
|
|
91
85
|
if not response.data:
|
|
92
|
-
|
|
86
|
+
st.info(
|
|
87
|
+
"📊 No trading disclosures found in database. Data collection may be in progress."
|
|
88
|
+
)
|
|
89
|
+
return pd.DataFrame()
|
|
93
90
|
|
|
94
91
|
df = pd.DataFrame(response.data)
|
|
92
|
+
|
|
93
|
+
# Get politician details and join
|
|
94
|
+
if not df.empty and "politician_id" in df.columns:
|
|
95
|
+
politician_ids = df["politician_id"].dropna().unique()
|
|
96
|
+
if len(politician_ids) > 0:
|
|
97
|
+
pol_response = (
|
|
98
|
+
client.table("politicians")
|
|
99
|
+
.select("id, full_name, party, state_or_country")
|
|
100
|
+
.in_("id", list(politician_ids))
|
|
101
|
+
.execute()
|
|
102
|
+
)
|
|
103
|
+
politicians = {p["id"]: p for p in pol_response.data}
|
|
104
|
+
|
|
105
|
+
# Add politician details
|
|
106
|
+
df["politician_name"] = df["politician_id"].map(
|
|
107
|
+
lambda x: politicians.get(x, {}).get("full_name", "Unknown")
|
|
108
|
+
)
|
|
109
|
+
df["politician_party"] = df["politician_id"].map(
|
|
110
|
+
lambda x: politicians.get(x, {}).get("party", "Unknown")
|
|
111
|
+
)
|
|
112
|
+
df["politician_state"] = df["politician_id"].map(
|
|
113
|
+
lambda x: politicians.get(x, {}).get("state_or_country", "Unknown")
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Map column names for compatibility
|
|
117
|
+
df["ticker_symbol"] = df["asset_ticker"]
|
|
118
|
+
df["amount"] = df["amount_exact"].fillna(
|
|
119
|
+
(df["amount_range_min"] + df["amount_range_max"]) / 2
|
|
120
|
+
)
|
|
121
|
+
|
|
95
122
|
return df
|
|
96
123
|
|
|
97
124
|
except Exception as e:
|
|
125
|
+
st.error(f"❌ Error fetching disclosures: {e}")
|
|
98
126
|
logger.error(f"Failed to fetch disclosures: {e}")
|
|
99
|
-
return
|
|
127
|
+
return pd.DataFrame()
|
|
100
128
|
|
|
101
129
|
|
|
102
130
|
def _generate_demo_disclosures() -> pd.DataFrame:
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Real-time data ingestion pipeline"""
|
|
2
|
+
|
|
3
|
+
from .api_connectors import (
|
|
4
|
+
AlphaVantageConnector,
|
|
5
|
+
CongressionalDataAPI,
|
|
6
|
+
PolygonIOConnector,
|
|
7
|
+
QuiverQuantConnector,
|
|
8
|
+
StockMarketAPI,
|
|
9
|
+
YahooFinanceConnector,
|
|
10
|
+
)
|
|
11
|
+
from .data_pipeline import DataLoader, DataTransformer, DataValidator, IngestionPipeline
|
|
12
|
+
from .stream_processor import DataStream, KafkaConsumer, StreamProcessor, WebSocketConsumer
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"StreamProcessor",
|
|
16
|
+
"DataStream",
|
|
17
|
+
"KafkaConsumer",
|
|
18
|
+
"WebSocketConsumer",
|
|
19
|
+
"CongressionalDataAPI",
|
|
20
|
+
"StockMarketAPI",
|
|
21
|
+
"AlphaVantageConnector",
|
|
22
|
+
"YahooFinanceConnector",
|
|
23
|
+
"PolygonIOConnector",
|
|
24
|
+
"QuiverQuantConnector",
|
|
25
|
+
"IngestionPipeline",
|
|
26
|
+
"DataValidator",
|
|
27
|
+
"DataTransformer",
|
|
28
|
+
"DataLoader",
|
|
29
|
+
]
|