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.

Files changed (97) hide show
  1. mcli/__init__.py +160 -0
  2. mcli/__main__.py +14 -0
  3. mcli/app/__init__.py +23 -0
  4. mcli/app/commands_cmd.py +741 -0
  5. mcli/app/model/__init__.py +0 -0
  6. mcli/app/video/__init__.py +5 -0
  7. mcli/chat/__init__.py +34 -0
  8. mcli/lib/__init__.py +0 -0
  9. mcli/lib/api/__init__.py +0 -0
  10. mcli/lib/auth/__init__.py +1 -0
  11. mcli/lib/config/__init__.py +1 -0
  12. mcli/lib/erd/__init__.py +25 -0
  13. mcli/lib/files/__init__.py +0 -0
  14. mcli/lib/fs/__init__.py +1 -0
  15. mcli/lib/logger/__init__.py +3 -0
  16. mcli/lib/performance/__init__.py +17 -0
  17. mcli/lib/pickles/__init__.py +1 -0
  18. mcli/lib/shell/__init__.py +0 -0
  19. mcli/lib/toml/__init__.py +1 -0
  20. mcli/lib/watcher/__init__.py +0 -0
  21. mcli/ml/__init__.py +16 -0
  22. mcli/ml/api/__init__.py +30 -0
  23. mcli/ml/api/routers/__init__.py +27 -0
  24. mcli/ml/api/schemas.py +2 -2
  25. mcli/ml/auth/__init__.py +45 -0
  26. mcli/ml/auth/models.py +2 -2
  27. mcli/ml/backtesting/__init__.py +39 -0
  28. mcli/ml/cli/__init__.py +5 -0
  29. mcli/ml/cli/main.py +1 -1
  30. mcli/ml/config/__init__.py +33 -0
  31. mcli/ml/configs/__init__.py +16 -0
  32. mcli/ml/dashboard/__init__.py +12 -0
  33. mcli/ml/dashboard/app_integrated.py +296 -30
  34. mcli/ml/dashboard/app_training.py +1 -1
  35. mcli/ml/dashboard/components/__init__.py +7 -0
  36. mcli/ml/dashboard/pages/__init__.py +6 -0
  37. mcli/ml/dashboard/pages/cicd.py +1 -1
  38. mcli/ml/dashboard/pages/debug_dependencies.py +364 -0
  39. mcli/ml/dashboard/pages/gravity_viz.py +565 -0
  40. mcli/ml/dashboard/pages/monte_carlo_predictions.py +555 -0
  41. mcli/ml/dashboard/pages/overview.py +378 -0
  42. mcli/ml/dashboard/pages/predictions_enhanced.py +20 -6
  43. mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -6
  44. mcli/ml/dashboard/pages/test_portfolio.py +423 -0
  45. mcli/ml/dashboard/pages/trading.py +768 -0
  46. mcli/ml/dashboard/streamlit_extras_utils.py +297 -0
  47. mcli/ml/dashboard/utils.py +161 -0
  48. mcli/ml/dashboard/warning_suppression.py +34 -0
  49. mcli/ml/data_ingestion/__init__.py +39 -0
  50. mcli/ml/database/__init__.py +47 -0
  51. mcli/ml/database/session.py +169 -16
  52. mcli/ml/experimentation/__init__.py +29 -0
  53. mcli/ml/features/__init__.py +39 -0
  54. mcli/ml/mlops/__init__.py +33 -0
  55. mcli/ml/models/__init__.py +94 -0
  56. mcli/ml/monitoring/__init__.py +25 -0
  57. mcli/ml/optimization/__init__.py +27 -0
  58. mcli/ml/predictions/__init__.py +5 -0
  59. mcli/ml/predictions/monte_carlo.py +428 -0
  60. mcli/ml/preprocessing/__init__.py +28 -0
  61. mcli/ml/scripts/__init__.py +1 -0
  62. mcli/ml/trading/__init__.py +66 -0
  63. mcli/ml/trading/alpaca_client.py +417 -0
  64. mcli/ml/trading/migrations.py +164 -0
  65. mcli/ml/trading/models.py +418 -0
  66. mcli/ml/trading/paper_trading.py +326 -0
  67. mcli/ml/trading/risk_management.py +370 -0
  68. mcli/ml/trading/trading_service.py +480 -0
  69. mcli/ml/training/__init__.py +10 -0
  70. mcli/mygroup/__init__.py +3 -0
  71. mcli/public/__init__.py +1 -0
  72. mcli/public/commands/__init__.py +2 -0
  73. mcli/self/__init__.py +3 -0
  74. mcli/self/self_cmd.py +514 -15
  75. mcli/workflow/__init__.py +0 -0
  76. mcli/workflow/daemon/__init__.py +15 -0
  77. mcli/workflow/daemon/daemon.py +21 -3
  78. mcli/workflow/dashboard/__init__.py +5 -0
  79. mcli/workflow/docker/__init__.py +0 -0
  80. mcli/workflow/file/__init__.py +0 -0
  81. mcli/workflow/gcloud/__init__.py +1 -0
  82. mcli/workflow/git_commit/__init__.py +0 -0
  83. mcli/workflow/interview/__init__.py +0 -0
  84. mcli/workflow/politician_trading/__init__.py +4 -0
  85. mcli/workflow/registry/__init__.py +0 -0
  86. mcli/workflow/repo/__init__.py +0 -0
  87. mcli/workflow/scheduler/__init__.py +25 -0
  88. mcli/workflow/search/__init__.py +0 -0
  89. mcli/workflow/sync/__init__.py +5 -0
  90. mcli/workflow/videos/__init__.py +1 -0
  91. mcli/workflow/wakatime/__init__.py +80 -0
  92. {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/METADATA +4 -1
  93. {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/RECORD +97 -18
  94. {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/WHEEL +0 -0
  95. {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/entry_points.txt +0 -0
  96. {mcli_framework-7.2.0.dist-info → mcli_framework-7.4.0.dist-info}/licenses/LICENSE +0 -0
  97. {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
+ ]