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
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
"""Monte Carlo Simulation Dashboard for Politician Trading Predictions
|
|
2
|
+
|
|
3
|
+
Inspired by best practices from:
|
|
4
|
+
- mesmith027/streamlit_webapps (Monte Carlo techniques)
|
|
5
|
+
- jumitti/tfinder (UI/UX patterns)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from datetime import datetime, timedelta
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
import pandas as pd
|
|
13
|
+
import plotly.graph_objects as go
|
|
14
|
+
import streamlit as st
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
# Try to import Monte Carlo simulator
|
|
19
|
+
HAS_MONTE_CARLO = True
|
|
20
|
+
try:
|
|
21
|
+
from mcli.ml.predictions.monte_carlo import (
|
|
22
|
+
MonteCarloTradingSimulator,
|
|
23
|
+
simulate_politician_trade_impact,
|
|
24
|
+
)
|
|
25
|
+
except ImportError:
|
|
26
|
+
HAS_MONTE_CARLO = False
|
|
27
|
+
MonteCarloTradingSimulator = None
|
|
28
|
+
|
|
29
|
+
# Try to import streamlit-extras
|
|
30
|
+
try:
|
|
31
|
+
from mcli.ml.dashboard.streamlit_extras_utils import (
|
|
32
|
+
section_header,
|
|
33
|
+
enhanced_metrics,
|
|
34
|
+
vertical_space,
|
|
35
|
+
)
|
|
36
|
+
HAS_EXTRAS = True
|
|
37
|
+
except ImportError:
|
|
38
|
+
HAS_EXTRAS = False
|
|
39
|
+
section_header = lambda *args, **kwargs: st.header(args[0])
|
|
40
|
+
enhanced_metrics = None
|
|
41
|
+
vertical_space = lambda x: st.write("")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def show_monte_carlo_predictions():
|
|
45
|
+
"""Main Monte Carlo predictions page"""
|
|
46
|
+
|
|
47
|
+
# Page header with custom styling
|
|
48
|
+
st.markdown(
|
|
49
|
+
"""
|
|
50
|
+
<style>
|
|
51
|
+
.main-header {
|
|
52
|
+
font-size: 2.5rem;
|
|
53
|
+
font-weight: bold;
|
|
54
|
+
color: #749BC2;
|
|
55
|
+
text-align: center;
|
|
56
|
+
padding: 1rem 0;
|
|
57
|
+
}
|
|
58
|
+
.sub-header {
|
|
59
|
+
font-size: 1.2rem;
|
|
60
|
+
color: #4A6FA5;
|
|
61
|
+
text-align: center;
|
|
62
|
+
margin-bottom: 2rem;
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
65
|
+
""",
|
|
66
|
+
unsafe_allow_html=True,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
st.markdown(
|
|
70
|
+
'<div class="main-header">🎲 Monte Carlo Trading Simulator</div>',
|
|
71
|
+
unsafe_allow_html=True,
|
|
72
|
+
)
|
|
73
|
+
st.markdown(
|
|
74
|
+
'<div class="sub-header">Simulate potential outcomes of politician trades using Monte Carlo methods</div>',
|
|
75
|
+
unsafe_allow_html=True,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if not HAS_MONTE_CARLO:
|
|
79
|
+
st.error("⚠️ Monte Carlo simulator not available. Please ensure all dependencies are installed.")
|
|
80
|
+
st.info(
|
|
81
|
+
"""
|
|
82
|
+
**Required:**
|
|
83
|
+
- numpy
|
|
84
|
+
- pandas
|
|
85
|
+
- plotly
|
|
86
|
+
|
|
87
|
+
Install with: `pip install numpy pandas plotly`
|
|
88
|
+
"""
|
|
89
|
+
)
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
# Sidebar configuration
|
|
93
|
+
with st.sidebar:
|
|
94
|
+
st.markdown("## ⚙️ Simulation Settings")
|
|
95
|
+
|
|
96
|
+
st.markdown("---")
|
|
97
|
+
st.markdown("### 📊 Parameters")
|
|
98
|
+
|
|
99
|
+
num_simulations = st.slider(
|
|
100
|
+
"Number of Simulations",
|
|
101
|
+
min_value=100,
|
|
102
|
+
max_value=10000,
|
|
103
|
+
value=1000,
|
|
104
|
+
step=100,
|
|
105
|
+
help="More simulations = better accuracy but slower performance",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
days_forward = st.slider(
|
|
109
|
+
"Days to Simulate",
|
|
110
|
+
min_value=30,
|
|
111
|
+
max_value=365,
|
|
112
|
+
value=90,
|
|
113
|
+
step=30,
|
|
114
|
+
help="How far into the future to project",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
confidence_level = st.select_slider(
|
|
118
|
+
"Confidence Level",
|
|
119
|
+
options=[0.90, 0.95, 0.99],
|
|
120
|
+
value=0.95,
|
|
121
|
+
format_func=lambda x: f"{x*100:.0f}%",
|
|
122
|
+
help="Confidence interval for predictions",
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
st.markdown("---")
|
|
126
|
+
st.markdown("### 📈 Display Options")
|
|
127
|
+
|
|
128
|
+
num_paths_display = st.slider(
|
|
129
|
+
"Paths to Display",
|
|
130
|
+
min_value=10,
|
|
131
|
+
max_value=500,
|
|
132
|
+
value=100,
|
|
133
|
+
step=10,
|
|
134
|
+
help="Number of individual simulation paths to show on chart",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
show_percentiles = st.checkbox(
|
|
138
|
+
"Show Confidence Bands",
|
|
139
|
+
value=True,
|
|
140
|
+
help="Display 50% and 90% confidence bands",
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
st.markdown("---")
|
|
144
|
+
st.markdown("### ℹ️ About")
|
|
145
|
+
st.info(
|
|
146
|
+
"""
|
|
147
|
+
**Monte Carlo Simulation** uses random sampling to model
|
|
148
|
+
possible future price movements based on historical volatility
|
|
149
|
+
and returns.
|
|
150
|
+
|
|
151
|
+
**Key Concepts:**
|
|
152
|
+
- Uses Geometric Brownian Motion (GBM)
|
|
153
|
+
- Assumes log-normal price distribution
|
|
154
|
+
- Estimates drift (μ) and volatility (σ) from historical data
|
|
155
|
+
"""
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Main content area with tabs
|
|
159
|
+
tab1, tab2, tab3, tab4 = st.tabs([
|
|
160
|
+
"🎯 Quick Simulation",
|
|
161
|
+
"📊 Advanced Analysis",
|
|
162
|
+
"📚 Learn More",
|
|
163
|
+
"⚙️ Custom Parameters"
|
|
164
|
+
])
|
|
165
|
+
|
|
166
|
+
with tab1:
|
|
167
|
+
show_quick_simulation(
|
|
168
|
+
num_simulations, days_forward, num_paths_display,
|
|
169
|
+
show_percentiles, confidence_level
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
with tab2:
|
|
173
|
+
show_advanced_analysis(num_simulations, days_forward, confidence_level)
|
|
174
|
+
|
|
175
|
+
with tab3:
|
|
176
|
+
show_educational_content()
|
|
177
|
+
|
|
178
|
+
with tab4:
|
|
179
|
+
show_custom_parameters(num_simulations, days_forward)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def show_quick_simulation(
|
|
183
|
+
num_simulations: int,
|
|
184
|
+
days_forward: int,
|
|
185
|
+
num_paths_display: int,
|
|
186
|
+
show_percentiles: bool,
|
|
187
|
+
confidence_level: float,
|
|
188
|
+
):
|
|
189
|
+
"""Quick simulation interface"""
|
|
190
|
+
|
|
191
|
+
section_header(
|
|
192
|
+
"🚀 Quick Start Simulation",
|
|
193
|
+
"Enter stock details and get instant Monte Carlo predictions",
|
|
194
|
+
divider="blue"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Input form
|
|
198
|
+
with st.form("quick_sim_form"):
|
|
199
|
+
col1, col2 = st.columns(2)
|
|
200
|
+
|
|
201
|
+
with col1:
|
|
202
|
+
stock_symbol = st.text_input(
|
|
203
|
+
"Stock Symbol",
|
|
204
|
+
value="AAPL",
|
|
205
|
+
placeholder="e.g., AAPL, TSLA, MSFT",
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
current_price = st.number_input(
|
|
209
|
+
"Current Price ($)",
|
|
210
|
+
min_value=0.01,
|
|
211
|
+
value=150.00,
|
|
212
|
+
step=0.01,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
with col2:
|
|
216
|
+
politician_name = st.text_input(
|
|
217
|
+
"Politician Name",
|
|
218
|
+
value="Nancy Pelosi",
|
|
219
|
+
placeholder="e.g., Nancy Pelosi",
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
transaction_amount = st.number_input(
|
|
223
|
+
"Transaction Amount ($)",
|
|
224
|
+
min_value=1000,
|
|
225
|
+
value=100000,
|
|
226
|
+
step=1000,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Historical parameters
|
|
230
|
+
col3, col4 = st.columns(2)
|
|
231
|
+
|
|
232
|
+
with col3:
|
|
233
|
+
annual_return = st.number_input(
|
|
234
|
+
"Expected Annual Return (%)",
|
|
235
|
+
min_value=-50.0,
|
|
236
|
+
max_value=100.0,
|
|
237
|
+
value=12.0,
|
|
238
|
+
step=0.5,
|
|
239
|
+
help="Historical average annual return",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
with col4:
|
|
243
|
+
annual_volatility = st.number_input(
|
|
244
|
+
"Annual Volatility (%)",
|
|
245
|
+
min_value=1.0,
|
|
246
|
+
max_value=100.0,
|
|
247
|
+
value=25.0,
|
|
248
|
+
step=1.0,
|
|
249
|
+
help="Historical standard deviation of returns",
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
submitted = st.form_submit_button(
|
|
253
|
+
"🎲 Run Simulation",
|
|
254
|
+
type="primary",
|
|
255
|
+
use_container_width=True,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if submitted:
|
|
259
|
+
run_simulation(
|
|
260
|
+
stock_symbol=stock_symbol,
|
|
261
|
+
politician_name=politician_name,
|
|
262
|
+
current_price=current_price,
|
|
263
|
+
transaction_amount=transaction_amount,
|
|
264
|
+
drift=annual_return / 100,
|
|
265
|
+
volatility=annual_volatility / 100,
|
|
266
|
+
num_simulations=num_simulations,
|
|
267
|
+
days_forward=days_forward,
|
|
268
|
+
num_paths_display=num_paths_display,
|
|
269
|
+
show_percentiles=show_percentiles,
|
|
270
|
+
confidence_level=confidence_level,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def run_simulation(
|
|
275
|
+
stock_symbol: str,
|
|
276
|
+
politician_name: str,
|
|
277
|
+
current_price: float,
|
|
278
|
+
transaction_amount: float,
|
|
279
|
+
drift: float,
|
|
280
|
+
volatility: float,
|
|
281
|
+
num_simulations: int,
|
|
282
|
+
days_forward: int,
|
|
283
|
+
num_paths_display: int,
|
|
284
|
+
show_percentiles: bool,
|
|
285
|
+
confidence_level: float,
|
|
286
|
+
):
|
|
287
|
+
"""Execute Monte Carlo simulation and display results"""
|
|
288
|
+
|
|
289
|
+
with st.spinner(f"Running {num_simulations:,} simulations..."):
|
|
290
|
+
# Initialize simulator
|
|
291
|
+
simulator = MonteCarloTradingSimulator(
|
|
292
|
+
initial_price=current_price,
|
|
293
|
+
days_to_simulate=days_forward,
|
|
294
|
+
num_simulations=num_simulations,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Run simulation
|
|
298
|
+
simulator.simulate_price_paths(drift, volatility)
|
|
299
|
+
|
|
300
|
+
# Calculate statistics
|
|
301
|
+
stats = simulator.calculate_statistics()
|
|
302
|
+
|
|
303
|
+
vertical_space(2)
|
|
304
|
+
|
|
305
|
+
# Display results header
|
|
306
|
+
section_header(
|
|
307
|
+
f"📈 Simulation Results: {stock_symbol}",
|
|
308
|
+
f"{politician_name} • {num_simulations:,} simulations • {days_forward} days",
|
|
309
|
+
divider="green"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# Key metrics
|
|
313
|
+
if HAS_EXTRAS and enhanced_metrics:
|
|
314
|
+
enhanced_metrics([
|
|
315
|
+
{
|
|
316
|
+
"label": "Expected Price",
|
|
317
|
+
"value": f"${stats['expected_final_price']:.2f}",
|
|
318
|
+
"delta": f"{stats['expected_return']:.1f}%"
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"label": "Probability of Profit",
|
|
322
|
+
"value": f"{stats['probability_profit']:.1f}%",
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"label": "Value at Risk (95%)",
|
|
326
|
+
"value": f"{stats['value_at_risk_95']:.1f}%",
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"label": "Best Case (95th %ile)",
|
|
330
|
+
"value": f"${stats['percentile_95']:.2f}",
|
|
331
|
+
"delta": f"+{((stats['percentile_95']/current_price - 1) * 100):.1f}%"
|
|
332
|
+
},
|
|
333
|
+
])
|
|
334
|
+
else:
|
|
335
|
+
col1, col2, col3, col4 = st.columns(4)
|
|
336
|
+
with col1:
|
|
337
|
+
st.metric("Expected Price", f"${stats['expected_final_price']:.2f}",
|
|
338
|
+
f"{stats['expected_return']:.1f}%")
|
|
339
|
+
with col2:
|
|
340
|
+
st.metric("Profit Probability", f"{stats['probability_profit']:.1f}%")
|
|
341
|
+
with col3:
|
|
342
|
+
st.metric("VaR (95%)", f"{stats['value_at_risk_95']:.1f}%")
|
|
343
|
+
with col4:
|
|
344
|
+
st.metric("Best Case", f"${stats['percentile_95']:.2f}")
|
|
345
|
+
|
|
346
|
+
vertical_space(2)
|
|
347
|
+
|
|
348
|
+
# Price path visualization
|
|
349
|
+
st.subheader("📊 Simulated Price Paths")
|
|
350
|
+
|
|
351
|
+
path_fig = simulator.create_path_visualization(
|
|
352
|
+
num_paths_to_plot=num_paths_display,
|
|
353
|
+
show_percentiles=show_percentiles
|
|
354
|
+
)
|
|
355
|
+
st.plotly_chart(path_fig, config={"displayModeBar": True}, use_container_width=True)
|
|
356
|
+
|
|
357
|
+
vertical_space(1)
|
|
358
|
+
|
|
359
|
+
# Distribution visualization
|
|
360
|
+
st.subheader("📉 Price & Return Distributions")
|
|
361
|
+
dist_fig = simulator.create_distribution_visualization()
|
|
362
|
+
st.plotly_chart(dist_fig, config={"displayModeBar": True}, use_container_width=True)
|
|
363
|
+
|
|
364
|
+
vertical_space(2)
|
|
365
|
+
|
|
366
|
+
# Detailed statistics
|
|
367
|
+
with st.expander("📊 Detailed Statistics", expanded=False):
|
|
368
|
+
col1, col2 = st.columns(2)
|
|
369
|
+
|
|
370
|
+
with col1:
|
|
371
|
+
st.markdown("**Price Statistics**")
|
|
372
|
+
st.markdown(f"- Current Price: ${current_price:.2f}")
|
|
373
|
+
st.markdown(f"- Expected Final: ${stats['expected_final_price']:.2f}")
|
|
374
|
+
st.markdown(f"- Median Final: ${stats['median_final_price']:.2f}")
|
|
375
|
+
st.markdown(f"- Standard Dev: ${stats['std_final_price']:.2f}")
|
|
376
|
+
st.markdown(f"- Min Price: ${stats['min_final_price']:.2f}")
|
|
377
|
+
st.markdown(f"- Max Price: ${stats['max_final_price']:.2f}")
|
|
378
|
+
|
|
379
|
+
with col2:
|
|
380
|
+
st.markdown("**Return Statistics**")
|
|
381
|
+
st.markdown(f"- Expected Return: {stats['expected_return']:.2f}%")
|
|
382
|
+
st.markdown(f"- Median Return: {stats['median_return']:.2f}%")
|
|
383
|
+
st.markdown(f"- Std Dev Return: {stats['std_return']:.2f}%")
|
|
384
|
+
st.markdown(f"- 5th Percentile: {stats['value_at_risk_95']:.2f}%")
|
|
385
|
+
st.markdown(f"- 95th Percentile: {((stats['percentile_95']/current_price - 1)*100):.2f}%")
|
|
386
|
+
|
|
387
|
+
# Confidence intervals
|
|
388
|
+
confidence_intervals = simulator.calculate_confidence_intervals([confidence_level])
|
|
389
|
+
lower, upper = confidence_intervals[confidence_level]
|
|
390
|
+
|
|
391
|
+
st.info(
|
|
392
|
+
f"**{confidence_level*100:.0f}% Confidence Interval:** "
|
|
393
|
+
f"${lower:.2f} - ${upper:.2f} "
|
|
394
|
+
f"({((lower/current_price - 1)*100):.1f}% to {((upper/current_price - 1)*100):.1f}%)"
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def show_advanced_analysis(num_simulations: int, days_forward: int, confidence_level: float):
|
|
399
|
+
"""Advanced analysis with historical data integration"""
|
|
400
|
+
|
|
401
|
+
section_header(
|
|
402
|
+
"🔬 Advanced Analysis",
|
|
403
|
+
"Use historical price data for more accurate simulations",
|
|
404
|
+
divider="violet"
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
st.info(
|
|
408
|
+
"""
|
|
409
|
+
**Coming Soon:**
|
|
410
|
+
- Integration with real-time market data APIs
|
|
411
|
+
- Historical politician trade correlation analysis
|
|
412
|
+
- Portfolio optimization using Monte Carlo
|
|
413
|
+
- Multi-stock scenario analysis
|
|
414
|
+
"""
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def show_educational_content():
|
|
419
|
+
"""Educational content about Monte Carlo methods"""
|
|
420
|
+
|
|
421
|
+
section_header(
|
|
422
|
+
"📚 Understanding Monte Carlo Simulation",
|
|
423
|
+
"Learn how probabilistic modeling predicts trading outcomes",
|
|
424
|
+
divider="orange"
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
st.markdown("""
|
|
428
|
+
## What is Monte Carlo Simulation?
|
|
429
|
+
|
|
430
|
+
Monte Carlo simulation is a computational technique that uses random sampling
|
|
431
|
+
to estimate possible outcomes of an uncertain event.
|
|
432
|
+
|
|
433
|
+
### How It Works for Stock Predictions
|
|
434
|
+
|
|
435
|
+
1. **Estimate Parameters**
|
|
436
|
+
- Calculate historical drift (μ): average return
|
|
437
|
+
- Calculate volatility (σ): standard deviation of returns
|
|
438
|
+
|
|
439
|
+
2. **Generate Random Paths**
|
|
440
|
+
- Use Geometric Brownian Motion (GBM)
|
|
441
|
+
- Formula: S(t+dt) = S(t) × exp((μ - σ²/2)dt + σ√dt × Z)
|
|
442
|
+
- Where Z is a random normal variable
|
|
443
|
+
|
|
444
|
+
3. **Analyze Results**
|
|
445
|
+
- Run thousands of simulations
|
|
446
|
+
- Calculate statistics on final prices
|
|
447
|
+
- Estimate probability distributions
|
|
448
|
+
|
|
449
|
+
### Key Advantages
|
|
450
|
+
|
|
451
|
+
- **Probabilistic**: Shows range of possible outcomes, not just one prediction
|
|
452
|
+
- **Visual**: Easy to understand probability distributions
|
|
453
|
+
- **Flexible**: Can incorporate different assumptions and scenarios
|
|
454
|
+
- **Risk Assessment**: Calculates Value at Risk (VaR) and confidence intervals
|
|
455
|
+
|
|
456
|
+
### Limitations
|
|
457
|
+
|
|
458
|
+
- Assumes log-normal distribution (may not capture extreme events)
|
|
459
|
+
- Based on historical data (past performance ≠ future results)
|
|
460
|
+
- Doesn't account for market structure changes
|
|
461
|
+
- Ignores transaction costs and liquidity constraints
|
|
462
|
+
|
|
463
|
+
### For Politician Trading Analysis
|
|
464
|
+
|
|
465
|
+
Monte Carlo is particularly useful for:
|
|
466
|
+
- **Following trades**: Estimate expected returns from mimicking politician trades
|
|
467
|
+
- **Risk management**: Understand downside risk before entering positions
|
|
468
|
+
- **Position sizing**: Determine appropriate investment amounts
|
|
469
|
+
- **Timing analysis**: Compare different holding periods
|
|
470
|
+
""")
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def show_custom_parameters(num_simulations: int, days_forward: int):
|
|
474
|
+
"""Custom parameter configuration"""
|
|
475
|
+
|
|
476
|
+
section_header(
|
|
477
|
+
"⚙️ Custom Parameters",
|
|
478
|
+
"Advanced configuration for power users",
|
|
479
|
+
divider="gray"
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
st.warning(
|
|
483
|
+
"⚠️ **Advanced Users Only** - Modifying these parameters requires "
|
|
484
|
+
"understanding of financial mathematics and Monte Carlo methods."
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
with st.form("custom_params_form"):
|
|
488
|
+
st.markdown("### Geometric Brownian Motion Parameters")
|
|
489
|
+
|
|
490
|
+
col1, col2 = st.columns(2)
|
|
491
|
+
|
|
492
|
+
with col1:
|
|
493
|
+
custom_drift = st.number_input(
|
|
494
|
+
"Drift (μ) - Annual",
|
|
495
|
+
min_value=-1.0,
|
|
496
|
+
max_value=1.0,
|
|
497
|
+
value=0.10,
|
|
498
|
+
step=0.01,
|
|
499
|
+
format="%.4f",
|
|
500
|
+
help="Expected return rate (e.g., 0.10 = 10% per year)",
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
custom_volatility = st.number_input(
|
|
504
|
+
"Volatility (σ) - Annual",
|
|
505
|
+
min_value=0.01,
|
|
506
|
+
max_value=2.0,
|
|
507
|
+
value=0.25,
|
|
508
|
+
step=0.01,
|
|
509
|
+
format="%.4f",
|
|
510
|
+
help="Standard deviation of returns (e.g., 0.25 = 25% volatility)",
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
with col2:
|
|
514
|
+
random_seed = st.number_input(
|
|
515
|
+
"Random Seed",
|
|
516
|
+
min_value=0,
|
|
517
|
+
max_value=999999,
|
|
518
|
+
value=42,
|
|
519
|
+
help="For reproducible results",
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
use_seed = st.checkbox("Use Random Seed", value=False)
|
|
523
|
+
|
|
524
|
+
st.markdown("### Time Parameters")
|
|
525
|
+
|
|
526
|
+
col3, col4 = st.columns(2)
|
|
527
|
+
|
|
528
|
+
with col3:
|
|
529
|
+
trading_days_per_year = st.number_input(
|
|
530
|
+
"Trading Days/Year",
|
|
531
|
+
min_value=200,
|
|
532
|
+
max_value=365,
|
|
533
|
+
value=252,
|
|
534
|
+
help="Standard is 252 for US markets",
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
with col4:
|
|
538
|
+
time_step = st.selectbox(
|
|
539
|
+
"Time Step",
|
|
540
|
+
["Daily", "Weekly", "Monthly"],
|
|
541
|
+
help="Granularity of simulation",
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
submitted = st.form_submit_button("Run Custom Simulation", type="primary")
|
|
545
|
+
|
|
546
|
+
if submitted:
|
|
547
|
+
st.success(
|
|
548
|
+
f"Custom simulation configured with μ={custom_drift:.4f}, "
|
|
549
|
+
f"σ={custom_volatility:.4f}"
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
# Module-level execution
|
|
554
|
+
if __name__ == "__main__":
|
|
555
|
+
show_monte_carlo_predictions()
|
|
@@ -310,7 +310,8 @@ def show_active_predictions(predictions_df: pd.DataFrame):
|
|
|
310
310
|
with st.container():
|
|
311
311
|
cols = st.columns([2, 1, 1, 1])
|
|
312
312
|
with cols[0]:
|
|
313
|
-
st.markdown(f"
|
|
313
|
+
st.markdown(f"### 📈 {row['ticker']}")
|
|
314
|
+
st.caption(f"{row['sector']}")
|
|
314
315
|
with cols[1]:
|
|
315
316
|
st.metric("Return", f"{row['predicted_return']*100:+.1f}%")
|
|
316
317
|
with cols[2]:
|
|
@@ -327,7 +328,8 @@ def show_active_predictions(predictions_df: pd.DataFrame):
|
|
|
327
328
|
with st.container():
|
|
328
329
|
cols = st.columns([2, 1, 1, 1])
|
|
329
330
|
with cols[0]:
|
|
330
|
-
st.markdown(f"
|
|
331
|
+
st.markdown(f"### 📈 {row['ticker']}")
|
|
332
|
+
st.caption(f"{row['sector']}")
|
|
331
333
|
with cols[1]:
|
|
332
334
|
st.metric("Return", f"{row['predicted_return']*100:+.1f}%")
|
|
333
335
|
with cols[2]:
|
|
@@ -32,6 +32,9 @@ logger = logging.getLogger(__name__)
|
|
|
32
32
|
def show_scrapers_and_logs():
|
|
33
33
|
"""Main function for scrapers and logs page"""
|
|
34
34
|
st.header("🔍 Data Scrapers & System Logs")
|
|
35
|
+
|
|
36
|
+
# Add a simple test to ensure the page is rendering
|
|
37
|
+
st.info("📋 Page loaded successfully - Scrapers & Logs functionality is available")
|
|
35
38
|
|
|
36
39
|
st.markdown("""
|
|
37
40
|
**Features:**
|
|
@@ -733,10 +736,10 @@ def run_senate_watcher_scraper(
|
|
|
733
736
|
st.markdown("#### Recent Trading Disclosures")
|
|
734
737
|
disc_df = pd.DataFrame([{
|
|
735
738
|
"Date": d.transaction_date.strftime("%Y-%m-%d") if hasattr(d.transaction_date, 'strftime') else str(d.transaction_date),
|
|
736
|
-
"
|
|
737
|
-
"Type": d.transaction_type,
|
|
739
|
+
"Ticker": d.asset_ticker or "—",
|
|
738
740
|
"Asset": d.asset_name[:50],
|
|
739
|
-
"
|
|
741
|
+
"Type": d.transaction_type,
|
|
742
|
+
"Politician": d.politician_bioguide_id,
|
|
740
743
|
"Min": f"${d.amount_range_min:,.0f}" if d.amount_range_min else "",
|
|
741
744
|
"Max": f"${d.amount_range_max:,.0f}" if d.amount_range_max else ""
|
|
742
745
|
} for d in disclosures[:100]]) # Limit to 100 for display
|
|
@@ -912,10 +915,18 @@ def show_system_logs():
|
|
|
912
915
|
except Exception as e:
|
|
913
916
|
st.error(f"Error reading log file: {e}")
|
|
914
917
|
else:
|
|
915
|
-
st.info(
|
|
918
|
+
st.info("📋 **No logs available yet**")
|
|
919
|
+
st.markdown("""
|
|
920
|
+
System logs will appear here automatically after scraping jobs run.
|
|
921
|
+
|
|
922
|
+
**To generate logs:**
|
|
923
|
+
- Use the "Manual Scrapers" section above to run a data pull
|
|
924
|
+
- Wait for automated jobs to execute
|
|
925
|
+
- Logs will be stored in: `/tmp/seed_database.log`
|
|
926
|
+
""")
|
|
916
927
|
|
|
917
928
|
# Create example logs display
|
|
918
|
-
st.markdown("### Example Log Output")
|
|
929
|
+
st.markdown("### 📝 Example Log Output")
|
|
919
930
|
st.code("""
|
|
920
931
|
2025-10-07 12:00:00 - INFO - Starting data pull job: senate_watcher_seed
|
|
921
932
|
2025-10-07 12:00:05 - INFO - Fetched 8350 Senate transactions
|
|
@@ -975,7 +986,7 @@ def show_job_history():
|
|
|
975
986
|
names=job_type_counts.index,
|
|
976
987
|
title="Jobs by Type"
|
|
977
988
|
)
|
|
978
|
-
st.plotly_chart(fig, use_container_width=True)
|
|
989
|
+
st.plotly_chart(fig, config={"displayModeBar": True}, use_container_width=True)
|
|
979
990
|
|
|
980
991
|
# Status breakdown
|
|
981
992
|
st.markdown("### Status Breakdown")
|
|
@@ -988,7 +999,7 @@ def show_job_history():
|
|
|
988
999
|
labels={'x': 'Status', 'y': 'Count'},
|
|
989
1000
|
title="Jobs by Status"
|
|
990
1001
|
)
|
|
991
|
-
st.plotly_chart(fig, use_container_width=True)
|
|
1002
|
+
st.plotly_chart(fig, config={"displayModeBar": True}, use_container_width=True)
|
|
992
1003
|
|
|
993
1004
|
# Timeline
|
|
994
1005
|
st.markdown("### Job Timeline")
|
|
@@ -1004,7 +1015,7 @@ def show_job_history():
|
|
|
1004
1015
|
color='status',
|
|
1005
1016
|
title="Jobs Over Time"
|
|
1006
1017
|
)
|
|
1007
|
-
st.plotly_chart(fig, use_container_width=True)
|
|
1018
|
+
st.plotly_chart(fig, config={"displayModeBar": True}, use_container_width=True)
|
|
1008
1019
|
|
|
1009
1020
|
# Records processed
|
|
1010
1021
|
st.markdown("### Records Processed")
|
|
@@ -1042,7 +1053,7 @@ def show_job_history():
|
|
|
1042
1053
|
hovermode='x unified'
|
|
1043
1054
|
)
|
|
1044
1055
|
|
|
1045
|
-
st.plotly_chart(fig, use_container_width=True)
|
|
1056
|
+
st.plotly_chart(fig, config={"displayModeBar": True}, use_container_width=True)
|
|
1046
1057
|
|
|
1047
1058
|
else:
|
|
1048
1059
|
st.info("No job history available yet. Run some scraping jobs to see statistics here.")
|
|
@@ -1058,3 +1069,8 @@ def show_job_history():
|
|
|
1058
1069
|
|
|
1059
1070
|
# Export for use in main dashboard
|
|
1060
1071
|
__all__ = ["show_scrapers_and_logs"]
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
# Module-level execution only when run directly (not when imported)
|
|
1075
|
+
if __name__ == "__main__":
|
|
1076
|
+
show_scrapers_and_logs()
|