mcli-framework 7.3.1__py3-none-any.whl → 7.4.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.

@@ -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()