mcli-framework 7.2.0__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.
- mcli/__init__.py +160 -0
- mcli/__main__.py +14 -0
- mcli/app/__init__.py +23 -0
- mcli/app/commands_cmd.py +741 -0
- mcli/app/model/__init__.py +0 -0
- 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/api/schemas.py +2 -2
- mcli/ml/auth/__init__.py +45 -0
- mcli/ml/auth/models.py +2 -2
- mcli/ml/backtesting/__init__.py +39 -0
- mcli/ml/cli/__init__.py +5 -0
- mcli/ml/cli/main.py +1 -1
- 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_integrated.py +296 -30
- mcli/ml/dashboard/app_training.py +1 -1
- mcli/ml/dashboard/components/__init__.py +7 -0
- mcli/ml/dashboard/pages/__init__.py +6 -0
- mcli/ml/dashboard/pages/cicd.py +1 -1
- mcli/ml/dashboard/pages/debug_dependencies.py +364 -0
- mcli/ml/dashboard/pages/gravity_viz.py +565 -0
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +555 -0
- mcli/ml/dashboard/pages/overview.py +378 -0
- mcli/ml/dashboard/pages/predictions_enhanced.py +20 -6
- mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -6
- mcli/ml/dashboard/pages/test_portfolio.py +423 -0
- mcli/ml/dashboard/pages/trading.py +768 -0
- mcli/ml/dashboard/streamlit_extras_utils.py +297 -0
- mcli/ml/dashboard/utils.py +161 -0
- mcli/ml/dashboard/warning_suppression.py +34 -0
- mcli/ml/data_ingestion/__init__.py +39 -0
- mcli/ml/database/__init__.py +47 -0
- mcli/ml/database/session.py +169 -16
- mcli/ml/experimentation/__init__.py +29 -0
- mcli/ml/features/__init__.py +39 -0
- mcli/ml/mlops/__init__.py +33 -0
- mcli/ml/models/__init__.py +94 -0
- mcli/ml/monitoring/__init__.py +25 -0
- mcli/ml/optimization/__init__.py +27 -0
- mcli/ml/predictions/__init__.py +5 -0
- mcli/ml/predictions/monte_carlo.py +428 -0
- mcli/ml/preprocessing/__init__.py +28 -0
- mcli/ml/scripts/__init__.py +1 -0
- mcli/ml/trading/__init__.py +66 -0
- mcli/ml/trading/alpaca_client.py +417 -0
- mcli/ml/trading/migrations.py +164 -0
- mcli/ml/trading/models.py +418 -0
- mcli/ml/trading/paper_trading.py +326 -0
- mcli/ml/trading/risk_management.py +370 -0
- mcli/ml/trading/trading_service.py +480 -0
- mcli/ml/training/__init__.py +10 -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 +514 -15
- mcli/workflow/__init__.py +0 -0
- mcli/workflow/daemon/__init__.py +15 -0
- mcli/workflow/daemon/daemon.py +21 -3
- mcli/workflow/dashboard/__init__.py +5 -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.2.0.dist-info → mcli_framework-7.4.0.dist-info}/METADATA +4 -1
- {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/RECORD +97 -18
- {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/WHEEL +0 -0
- {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
"""Monte Carlo simulation for politician trading predictions
|
|
2
|
+
|
|
3
|
+
Uses Monte Carlo methods to simulate possible price paths and estimate
|
|
4
|
+
expected returns based on politician trading patterns.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from datetime import datetime, timedelta
|
|
9
|
+
from typing import Dict, List, Optional, Tuple
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import pandas as pd
|
|
13
|
+
import plotly.express as px
|
|
14
|
+
import plotly.graph_objects as go
|
|
15
|
+
from plotly.subplots import make_subplots
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MonteCarloTradingSimulator:
|
|
21
|
+
"""Monte Carlo simulator for politician trading predictions"""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
initial_price: float,
|
|
26
|
+
days_to_simulate: int = 90,
|
|
27
|
+
num_simulations: int = 1000,
|
|
28
|
+
random_seed: Optional[int] = None,
|
|
29
|
+
):
|
|
30
|
+
"""
|
|
31
|
+
Initialize Monte Carlo simulator
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
initial_price: Starting stock price
|
|
35
|
+
days_to_simulate: Number of days to project forward
|
|
36
|
+
num_simulations: Number of Monte Carlo paths to generate
|
|
37
|
+
random_seed: Random seed for reproducibility
|
|
38
|
+
"""
|
|
39
|
+
self.initial_price = initial_price
|
|
40
|
+
self.days_to_simulate = days_to_simulate
|
|
41
|
+
self.num_simulations = num_simulations
|
|
42
|
+
self.random_seed = random_seed
|
|
43
|
+
|
|
44
|
+
if random_seed is not None:
|
|
45
|
+
np.random.seed(random_seed)
|
|
46
|
+
|
|
47
|
+
# Store simulation results
|
|
48
|
+
self.simulated_paths: Optional[np.ndarray] = None
|
|
49
|
+
self.final_prices: Optional[np.ndarray] = None
|
|
50
|
+
self.returns: Optional[np.ndarray] = None
|
|
51
|
+
|
|
52
|
+
def estimate_parameters(
|
|
53
|
+
self, historical_prices: pd.Series
|
|
54
|
+
) -> Tuple[float, float]:
|
|
55
|
+
"""
|
|
56
|
+
Estimate drift (μ) and volatility (σ) from historical data
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
historical_prices: Series of historical prices
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Tuple of (drift, volatility)
|
|
63
|
+
"""
|
|
64
|
+
# Calculate daily returns
|
|
65
|
+
returns = historical_prices.pct_change().dropna()
|
|
66
|
+
|
|
67
|
+
# Estimate parameters
|
|
68
|
+
daily_return = returns.mean()
|
|
69
|
+
daily_volatility = returns.std()
|
|
70
|
+
|
|
71
|
+
# Annualize (assuming 252 trading days)
|
|
72
|
+
annual_return = daily_return * 252
|
|
73
|
+
annual_volatility = daily_volatility * np.sqrt(252)
|
|
74
|
+
|
|
75
|
+
logger.info(
|
|
76
|
+
f"Estimated parameters: drift={annual_return:.4f}, "
|
|
77
|
+
f"volatility={annual_volatility:.4f}"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return annual_return, annual_volatility
|
|
81
|
+
|
|
82
|
+
def simulate_price_paths(
|
|
83
|
+
self, drift: float, volatility: float
|
|
84
|
+
) -> np.ndarray:
|
|
85
|
+
"""
|
|
86
|
+
Generate Monte Carlo price paths using Geometric Brownian Motion
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
drift: Expected return (μ)
|
|
90
|
+
volatility: Standard deviation (σ)
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Array of shape (num_simulations, days_to_simulate + 1) with price paths
|
|
94
|
+
"""
|
|
95
|
+
# Time step (assuming daily)
|
|
96
|
+
dt = 1 / 252 # Daily time step in years
|
|
97
|
+
|
|
98
|
+
# Initialize price paths matrix
|
|
99
|
+
paths = np.zeros((self.num_simulations, self.days_to_simulate + 1))
|
|
100
|
+
paths[:, 0] = self.initial_price
|
|
101
|
+
|
|
102
|
+
# Generate random shocks
|
|
103
|
+
random_shocks = np.random.normal(
|
|
104
|
+
0, 1, size=(self.num_simulations, self.days_to_simulate)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Simulate paths using Geometric Brownian Motion
|
|
108
|
+
# S(t+dt) = S(t) * exp((μ - σ²/2)dt + σ√dt * Z)
|
|
109
|
+
for t in range(1, self.days_to_simulate + 1):
|
|
110
|
+
drift_component = (drift - 0.5 * volatility**2) * dt
|
|
111
|
+
shock_component = volatility * np.sqrt(dt) * random_shocks[:, t - 1]
|
|
112
|
+
|
|
113
|
+
paths[:, t] = paths[:, t - 1] * np.exp(
|
|
114
|
+
drift_component + shock_component
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
self.simulated_paths = paths
|
|
118
|
+
self.final_prices = paths[:, -1]
|
|
119
|
+
self.returns = (self.final_prices - self.initial_price) / self.initial_price
|
|
120
|
+
|
|
121
|
+
logger.info(
|
|
122
|
+
f"Simulated {self.num_simulations} price paths over {self.days_to_simulate} days"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return paths
|
|
126
|
+
|
|
127
|
+
def calculate_statistics(self) -> Dict[str, float]:
|
|
128
|
+
"""
|
|
129
|
+
Calculate statistics from simulation results
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Dictionary with statistical measures
|
|
133
|
+
"""
|
|
134
|
+
if self.final_prices is None:
|
|
135
|
+
raise ValueError("Must run simulation first")
|
|
136
|
+
|
|
137
|
+
stats = {
|
|
138
|
+
"expected_final_price": np.mean(self.final_prices),
|
|
139
|
+
"median_final_price": np.median(self.final_prices),
|
|
140
|
+
"std_final_price": np.std(self.final_prices),
|
|
141
|
+
"min_final_price": np.min(self.final_prices),
|
|
142
|
+
"max_final_price": np.max(self.final_prices),
|
|
143
|
+
"expected_return": np.mean(self.returns) * 100,
|
|
144
|
+
"median_return": np.median(self.returns) * 100,
|
|
145
|
+
"std_return": np.std(self.returns) * 100,
|
|
146
|
+
"probability_profit": np.sum(self.returns > 0) / len(self.returns) * 100,
|
|
147
|
+
"value_at_risk_95": np.percentile(self.returns, 5) * 100, # 95% VaR
|
|
148
|
+
"percentile_5": np.percentile(self.final_prices, 5),
|
|
149
|
+
"percentile_25": np.percentile(self.final_prices, 25),
|
|
150
|
+
"percentile_75": np.percentile(self.final_prices, 75),
|
|
151
|
+
"percentile_95": np.percentile(self.final_prices, 95),
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return stats
|
|
155
|
+
|
|
156
|
+
def create_path_visualization(
|
|
157
|
+
self, num_paths_to_plot: int = 100, show_percentiles: bool = True
|
|
158
|
+
) -> go.Figure:
|
|
159
|
+
"""
|
|
160
|
+
Create visualization of simulated price paths
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
num_paths_to_plot: Number of individual paths to display
|
|
164
|
+
show_percentiles: Whether to show percentile bands
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Plotly figure object
|
|
168
|
+
"""
|
|
169
|
+
if self.simulated_paths is None:
|
|
170
|
+
raise ValueError("Must run simulation first")
|
|
171
|
+
|
|
172
|
+
fig = go.Figure()
|
|
173
|
+
|
|
174
|
+
# Plot sample paths
|
|
175
|
+
num_to_plot = min(num_paths_to_plot, self.num_simulations)
|
|
176
|
+
sample_indices = np.random.choice(
|
|
177
|
+
self.num_simulations, num_to_plot, replace=False
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
for idx in sample_indices:
|
|
181
|
+
fig.add_trace(
|
|
182
|
+
go.Scatter(
|
|
183
|
+
x=list(range(self.days_to_simulate + 1)),
|
|
184
|
+
y=self.simulated_paths[idx],
|
|
185
|
+
mode="lines",
|
|
186
|
+
line=dict(color="lightblue", width=0.5),
|
|
187
|
+
opacity=0.3,
|
|
188
|
+
showlegend=False,
|
|
189
|
+
hoverinfo="skip",
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Add mean path
|
|
194
|
+
mean_path = np.mean(self.simulated_paths, axis=0)
|
|
195
|
+
fig.add_trace(
|
|
196
|
+
go.Scatter(
|
|
197
|
+
x=list(range(self.days_to_simulate + 1)),
|
|
198
|
+
y=mean_path,
|
|
199
|
+
mode="lines",
|
|
200
|
+
line=dict(color="blue", width=3),
|
|
201
|
+
name="Expected Path",
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if show_percentiles:
|
|
206
|
+
# Add percentile bands
|
|
207
|
+
percentile_5 = np.percentile(self.simulated_paths, 5, axis=0)
|
|
208
|
+
percentile_25 = np.percentile(self.simulated_paths, 25, axis=0)
|
|
209
|
+
percentile_75 = np.percentile(self.simulated_paths, 75, axis=0)
|
|
210
|
+
percentile_95 = np.percentile(self.simulated_paths, 95, axis=0)
|
|
211
|
+
|
|
212
|
+
x_vals = list(range(self.days_to_simulate + 1))
|
|
213
|
+
|
|
214
|
+
# 90% confidence band (5th to 95th percentile)
|
|
215
|
+
fig.add_trace(
|
|
216
|
+
go.Scatter(
|
|
217
|
+
x=x_vals + x_vals[::-1],
|
|
218
|
+
y=list(percentile_95) + list(percentile_5[::-1]),
|
|
219
|
+
fill="toself",
|
|
220
|
+
fillcolor="rgba(255, 0, 0, 0.1)",
|
|
221
|
+
line=dict(color="rgba(255, 0, 0, 0)"),
|
|
222
|
+
name="90% Confidence",
|
|
223
|
+
hoverinfo="skip",
|
|
224
|
+
)
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# 50% confidence band (25th to 75th percentile)
|
|
228
|
+
fig.add_trace(
|
|
229
|
+
go.Scatter(
|
|
230
|
+
x=x_vals + x_vals[::-1],
|
|
231
|
+
y=list(percentile_75) + list(percentile_25[::-1]),
|
|
232
|
+
fill="toself",
|
|
233
|
+
fillcolor="rgba(0, 255, 0, 0.2)",
|
|
234
|
+
line=dict(color="rgba(0, 255, 0, 0)"),
|
|
235
|
+
name="50% Confidence",
|
|
236
|
+
hoverinfo="skip",
|
|
237
|
+
)
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
fig.update_layout(
|
|
241
|
+
title=f"Monte Carlo Simulation: {self.num_simulations:,} Price Paths",
|
|
242
|
+
xaxis_title="Days",
|
|
243
|
+
yaxis_title="Price ($)",
|
|
244
|
+
hovermode="x unified",
|
|
245
|
+
template="plotly_white",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
return fig
|
|
249
|
+
|
|
250
|
+
def create_distribution_visualization(self) -> go.Figure:
|
|
251
|
+
"""
|
|
252
|
+
Create histogram of final price distribution
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
Plotly figure object
|
|
256
|
+
"""
|
|
257
|
+
if self.final_prices is None:
|
|
258
|
+
raise ValueError("Must run simulation first")
|
|
259
|
+
|
|
260
|
+
stats = self.calculate_statistics()
|
|
261
|
+
|
|
262
|
+
fig = make_subplots(
|
|
263
|
+
rows=1,
|
|
264
|
+
cols=2,
|
|
265
|
+
subplot_titles=("Final Price Distribution", "Return Distribution"),
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Price distribution
|
|
269
|
+
fig.add_trace(
|
|
270
|
+
go.Histogram(
|
|
271
|
+
x=self.final_prices,
|
|
272
|
+
nbinsx=50,
|
|
273
|
+
name="Final Price",
|
|
274
|
+
marker_color="lightblue",
|
|
275
|
+
showlegend=False,
|
|
276
|
+
),
|
|
277
|
+
row=1,
|
|
278
|
+
col=1,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Add vertical lines for statistics
|
|
282
|
+
fig.add_vline(
|
|
283
|
+
x=stats["expected_final_price"],
|
|
284
|
+
line_dash="dash",
|
|
285
|
+
line_color="blue",
|
|
286
|
+
annotation_text="Mean",
|
|
287
|
+
row=1,
|
|
288
|
+
col=1,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
fig.add_vline(
|
|
292
|
+
x=self.initial_price,
|
|
293
|
+
line_dash="solid",
|
|
294
|
+
line_color="red",
|
|
295
|
+
annotation_text="Current",
|
|
296
|
+
row=1,
|
|
297
|
+
col=1,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Return distribution
|
|
301
|
+
fig.add_trace(
|
|
302
|
+
go.Histogram(
|
|
303
|
+
x=self.returns * 100,
|
|
304
|
+
nbinsx=50,
|
|
305
|
+
name="Returns",
|
|
306
|
+
marker_color="lightgreen",
|
|
307
|
+
showlegend=False,
|
|
308
|
+
),
|
|
309
|
+
row=1,
|
|
310
|
+
col=2,
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Add vertical line at 0% return
|
|
314
|
+
fig.add_vline(
|
|
315
|
+
x=0, line_dash="dash", line_color="red", annotation_text="0%", row=1, col=2
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
fig.update_xaxes(title_text="Price ($)", row=1, col=1)
|
|
319
|
+
fig.update_xaxes(title_text="Return (%)", row=1, col=2)
|
|
320
|
+
fig.update_yaxes(title_text="Frequency", row=1, col=1)
|
|
321
|
+
fig.update_yaxes(title_text="Frequency", row=1, col=2)
|
|
322
|
+
|
|
323
|
+
fig.update_layout(
|
|
324
|
+
title="Monte Carlo Simulation Results",
|
|
325
|
+
template="plotly_white",
|
|
326
|
+
height=400,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
return fig
|
|
330
|
+
|
|
331
|
+
def calculate_confidence_intervals(
|
|
332
|
+
self, confidence_levels: List[float] = [0.90, 0.95, 0.99]
|
|
333
|
+
) -> Dict[float, Tuple[float, float]]:
|
|
334
|
+
"""
|
|
335
|
+
Calculate confidence intervals for final price
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
confidence_levels: List of confidence levels (e.g., [0.90, 0.95])
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
Dictionary mapping confidence level to (lower, upper) bounds
|
|
342
|
+
"""
|
|
343
|
+
if self.final_prices is None:
|
|
344
|
+
raise ValueError("Must run simulation first")
|
|
345
|
+
|
|
346
|
+
intervals = {}
|
|
347
|
+
for level in confidence_levels:
|
|
348
|
+
alpha = 1 - level
|
|
349
|
+
lower = np.percentile(self.final_prices, alpha / 2 * 100)
|
|
350
|
+
upper = np.percentile(self.final_prices, (1 - alpha / 2) * 100)
|
|
351
|
+
intervals[level] = (lower, upper)
|
|
352
|
+
|
|
353
|
+
return intervals
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def simulate_politician_trade_impact(
|
|
357
|
+
stock_symbol: str,
|
|
358
|
+
politician_name: str,
|
|
359
|
+
transaction_amount: float,
|
|
360
|
+
historical_prices: pd.Series,
|
|
361
|
+
days_forward: int = 90,
|
|
362
|
+
num_simulations: int = 1000,
|
|
363
|
+
) -> Dict:
|
|
364
|
+
"""
|
|
365
|
+
Simulate potential outcomes of following a politician's trade
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
stock_symbol: Stock ticker symbol
|
|
369
|
+
politician_name: Name of politician
|
|
370
|
+
transaction_amount: Dollar amount of politician's trade
|
|
371
|
+
historical_prices: Historical price data
|
|
372
|
+
days_forward: Days to simulate forward
|
|
373
|
+
num_simulations: Number of Monte Carlo simulations
|
|
374
|
+
|
|
375
|
+
Returns:
|
|
376
|
+
Dictionary with simulation results and statistics
|
|
377
|
+
"""
|
|
378
|
+
if len(historical_prices) < 30:
|
|
379
|
+
logger.warning(f"Insufficient historical data for {stock_symbol}")
|
|
380
|
+
return None
|
|
381
|
+
|
|
382
|
+
current_price = historical_prices.iloc[-1]
|
|
383
|
+
|
|
384
|
+
# Initialize simulator
|
|
385
|
+
simulator = MonteCarloTradingSimulator(
|
|
386
|
+
initial_price=current_price,
|
|
387
|
+
days_to_simulate=days_forward,
|
|
388
|
+
num_simulations=num_simulations,
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
# Estimate parameters from historical data
|
|
392
|
+
drift, volatility = simulator.estimate_parameters(historical_prices)
|
|
393
|
+
|
|
394
|
+
# Run simulation
|
|
395
|
+
simulator.simulate_price_paths(drift, volatility)
|
|
396
|
+
|
|
397
|
+
# Calculate statistics
|
|
398
|
+
stats = simulator.calculate_statistics()
|
|
399
|
+
|
|
400
|
+
# Create visualizations
|
|
401
|
+
path_fig = simulator.create_path_visualization(num_paths_to_plot=100)
|
|
402
|
+
dist_fig = simulator.create_distribution_visualization()
|
|
403
|
+
|
|
404
|
+
# Calculate confidence intervals
|
|
405
|
+
confidence_intervals = simulator.calculate_confidence_intervals()
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
"stock_symbol": stock_symbol,
|
|
409
|
+
"politician_name": politician_name,
|
|
410
|
+
"transaction_amount": transaction_amount,
|
|
411
|
+
"current_price": current_price,
|
|
412
|
+
"simulation_days": days_forward,
|
|
413
|
+
"num_simulations": num_simulations,
|
|
414
|
+
"drift": drift,
|
|
415
|
+
"volatility": volatility,
|
|
416
|
+
"statistics": stats,
|
|
417
|
+
"confidence_intervals": confidence_intervals,
|
|
418
|
+
"path_visualization": path_fig,
|
|
419
|
+
"distribution_visualization": dist_fig,
|
|
420
|
+
"simulated_paths": simulator.simulated_paths,
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
# Export main classes and functions
|
|
425
|
+
__all__ = [
|
|
426
|
+
"MonteCarloTradingSimulator",
|
|
427
|
+
"simulate_politician_trade_impact",
|
|
428
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""ML Data Preprocessing Module"""
|
|
2
|
+
|
|
3
|
+
from .data_cleaners import (
|
|
4
|
+
MissingValueHandler,
|
|
5
|
+
OutlierDetector,
|
|
6
|
+
TradingDataCleaner,
|
|
7
|
+
)
|
|
8
|
+
from .feature_extractors import (
|
|
9
|
+
MarketFeatureExtractor,
|
|
10
|
+
PoliticianFeatureExtractor,
|
|
11
|
+
SentimentFeatureExtractor,
|
|
12
|
+
TemporalFeatureExtractor,
|
|
13
|
+
)
|
|
14
|
+
from .ml_pipeline import MLDataPipeline, MLDataPipelineConfig
|
|
15
|
+
from .politician_trading_preprocessor import PoliticianTradingPreprocessor
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"PoliticianTradingPreprocessor",
|
|
19
|
+
"PoliticianFeatureExtractor",
|
|
20
|
+
"MarketFeatureExtractor",
|
|
21
|
+
"TemporalFeatureExtractor",
|
|
22
|
+
"SentimentFeatureExtractor",
|
|
23
|
+
"TradingDataCleaner",
|
|
24
|
+
"OutlierDetector",
|
|
25
|
+
"MissingValueHandler",
|
|
26
|
+
"MLDataPipeline",
|
|
27
|
+
"MLDataPipelineConfig",
|
|
28
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""ML scripts module."""
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Trading module for portfolio management and trade execution"""
|
|
2
|
+
|
|
3
|
+
from mcli.ml.trading.models import (
|
|
4
|
+
# Enums
|
|
5
|
+
OrderStatus,
|
|
6
|
+
OrderType,
|
|
7
|
+
OrderSide,
|
|
8
|
+
PositionSide,
|
|
9
|
+
PortfolioType,
|
|
10
|
+
RiskLevel,
|
|
11
|
+
# Database models
|
|
12
|
+
TradingAccount,
|
|
13
|
+
Portfolio,
|
|
14
|
+
Position,
|
|
15
|
+
TradingOrder,
|
|
16
|
+
PortfolioPerformanceSnapshot,
|
|
17
|
+
TradingSignal,
|
|
18
|
+
# Pydantic models
|
|
19
|
+
TradingAccountCreate,
|
|
20
|
+
PortfolioCreate,
|
|
21
|
+
OrderCreate,
|
|
22
|
+
PositionResponse,
|
|
23
|
+
OrderResponse,
|
|
24
|
+
PortfolioResponse,
|
|
25
|
+
TradingSignalResponse,
|
|
26
|
+
)
|
|
27
|
+
from mcli.ml.trading.trading_service import TradingService
|
|
28
|
+
from mcli.ml.trading.alpaca_client import (
|
|
29
|
+
AlpacaTradingClient,
|
|
30
|
+
create_trading_client,
|
|
31
|
+
get_alpaca_config_from_env,
|
|
32
|
+
)
|
|
33
|
+
from mcli.ml.trading.risk_management import RiskManager
|
|
34
|
+
from mcli.ml.trading.paper_trading import PaperTradingEngine
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
# Enums
|
|
38
|
+
"OrderStatus",
|
|
39
|
+
"OrderType",
|
|
40
|
+
"OrderSide",
|
|
41
|
+
"PositionSide",
|
|
42
|
+
"PortfolioType",
|
|
43
|
+
"RiskLevel",
|
|
44
|
+
# Database models
|
|
45
|
+
"TradingAccount",
|
|
46
|
+
"Portfolio",
|
|
47
|
+
"Position",
|
|
48
|
+
"TradingOrder",
|
|
49
|
+
"PortfolioPerformanceSnapshot",
|
|
50
|
+
"TradingSignal",
|
|
51
|
+
# Pydantic models
|
|
52
|
+
"TradingAccountCreate",
|
|
53
|
+
"PortfolioCreate",
|
|
54
|
+
"OrderCreate",
|
|
55
|
+
"PositionResponse",
|
|
56
|
+
"OrderResponse",
|
|
57
|
+
"PortfolioResponse",
|
|
58
|
+
"TradingSignalResponse",
|
|
59
|
+
# Services
|
|
60
|
+
"TradingService",
|
|
61
|
+
"AlpacaTradingClient",
|
|
62
|
+
"create_trading_client",
|
|
63
|
+
"get_alpaca_config_from_env",
|
|
64
|
+
"RiskManager",
|
|
65
|
+
"PaperTradingEngine",
|
|
66
|
+
]
|