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,418 @@
1
+ """Trading and portfolio models for the ML system"""
2
+
3
+ from dataclasses import dataclass, field
4
+ from datetime import datetime
5
+ from decimal import Decimal
6
+ from enum import Enum
7
+ from typing import Any, Dict, List, Optional, Union
8
+ from uuid import UUID, uuid4
9
+
10
+ from sqlalchemy import (
11
+ Boolean, Column, DateTime, Enum as SQLEnum, Float, ForeignKey,
12
+ Integer, String, Text, JSON, Numeric, Index
13
+ )
14
+ from sqlalchemy.dialects.postgresql import UUID as PostgresUUID
15
+ from sqlalchemy.ext.declarative import declarative_base
16
+ from sqlalchemy.orm import relationship
17
+ from pydantic import BaseModel, Field
18
+
19
+ Base = declarative_base()
20
+
21
+
22
+ class OrderStatus(Enum):
23
+ """Order status enumeration"""
24
+ PENDING = "pending"
25
+ SUBMITTED = "submitted"
26
+ FILLED = "filled"
27
+ PARTIALLY_FILLED = "partially_filled"
28
+ CANCELLED = "cancelled"
29
+ REJECTED = "rejected"
30
+ EXPIRED = "expired"
31
+
32
+
33
+ class OrderType(Enum):
34
+ """Order type enumeration"""
35
+ MARKET = "market"
36
+ LIMIT = "limit"
37
+ STOP = "stop"
38
+ STOP_LIMIT = "stop_limit"
39
+ TRAILING_STOP = "trailing_stop"
40
+
41
+
42
+ class OrderSide(Enum):
43
+ """Order side enumeration"""
44
+ BUY = "buy"
45
+ SELL = "sell"
46
+
47
+
48
+ class PositionSide(Enum):
49
+ """Position side enumeration"""
50
+ LONG = "long"
51
+ SHORT = "short"
52
+
53
+
54
+ class PortfolioType(Enum):
55
+ """Portfolio type enumeration"""
56
+ TEST = "test"
57
+ LIVE = "live"
58
+ PAPER = "paper"
59
+
60
+
61
+ class RiskLevel(Enum):
62
+ """Risk level enumeration"""
63
+ CONSERVATIVE = "conservative"
64
+ MODERATE = "moderate"
65
+ AGGRESSIVE = "aggressive"
66
+
67
+
68
+ # Database Models
69
+ class TradingAccount(Base):
70
+ """Trading account information"""
71
+ __tablename__ = "trading_accounts"
72
+
73
+ id = Column(PostgresUUID(as_uuid=True), primary_key=True, default=uuid4)
74
+ user_id = Column(PostgresUUID(as_uuid=True), nullable=False) # Remove foreign key for now
75
+ account_name = Column(String(100), nullable=False)
76
+ account_type = Column(SQLEnum(PortfolioType), nullable=False, default=PortfolioType.TEST)
77
+
78
+ # Alpaca credentials (encrypted)
79
+ alpaca_api_key = Column(String(255), nullable=True)
80
+ alpaca_secret_key = Column(String(255), nullable=True)
81
+ alpaca_base_url = Column(String(255), nullable=True)
82
+
83
+ # Account settings
84
+ paper_trading = Column(Boolean, default=True)
85
+ risk_level = Column(SQLEnum(RiskLevel), default=RiskLevel.MODERATE)
86
+ max_position_size = Column(Float, default=0.1) # Max 10% per position
87
+ max_portfolio_risk = Column(Float, default=0.2) # Max 20% portfolio risk
88
+
89
+ # Metadata
90
+ created_at = Column(DateTime, default=datetime.utcnow)
91
+ updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
92
+ is_active = Column(Boolean, default=True)
93
+
94
+ # Relationships
95
+ portfolios = relationship("Portfolio", back_populates="trading_account")
96
+ orders = relationship("TradingOrder", back_populates="trading_account")
97
+
98
+
99
+ class Portfolio(Base):
100
+ """Portfolio information"""
101
+ __tablename__ = "portfolios"
102
+
103
+ id = Column(PostgresUUID(as_uuid=True), primary_key=True, default=uuid4)
104
+ trading_account_id = Column(PostgresUUID(as_uuid=True), ForeignKey("trading_accounts.id"), nullable=False)
105
+ name = Column(String(100), nullable=False)
106
+ description = Column(Text, nullable=True)
107
+
108
+ # Portfolio settings
109
+ initial_capital = Column(Numeric(15, 2), nullable=False, default=100000.00)
110
+ current_value = Column(Numeric(15, 2), nullable=False, default=100000.00)
111
+ cash_balance = Column(Numeric(15, 2), nullable=False, default=100000.00)
112
+
113
+ # Performance metrics
114
+ total_return = Column(Float, default=0.0)
115
+ total_return_pct = Column(Float, default=0.0)
116
+ daily_return = Column(Float, default=0.0)
117
+ daily_return_pct = Column(Float, default=0.0)
118
+ sharpe_ratio = Column(Float, default=0.0)
119
+ sortino_ratio = Column(Float, default=0.0)
120
+ max_drawdown = Column(Float, default=0.0)
121
+ max_drawdown_duration = Column(Integer, default=0)
122
+ volatility = Column(Float, default=0.0)
123
+
124
+ # Risk metrics
125
+ var_95 = Column(Float, default=0.0) # Value at Risk 95%
126
+ cvar_95 = Column(Float, default=0.0) # Conditional Value at Risk 95%
127
+ beta = Column(Float, default=1.0)
128
+
129
+ # Status
130
+ is_active = Column(Boolean, default=True)
131
+ created_at = Column(DateTime, default=datetime.utcnow)
132
+ updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
133
+
134
+ # Relationships
135
+ trading_account = relationship("TradingAccount", back_populates="portfolios")
136
+ positions = relationship("Position", back_populates="portfolio")
137
+ orders = relationship("TradingOrder", back_populates="portfolio")
138
+ performance_snapshots = relationship("PortfolioPerformanceSnapshot", back_populates="portfolio")
139
+
140
+
141
+ class Position(Base):
142
+ """Individual position in a portfolio"""
143
+ __tablename__ = "positions"
144
+
145
+ id = Column(PostgresUUID(as_uuid=True), primary_key=True, default=uuid4)
146
+ portfolio_id = Column(PostgresUUID(as_uuid=True), ForeignKey("portfolios.id"), nullable=False)
147
+ symbol = Column(String(10), nullable=False, index=True)
148
+
149
+ # Position details
150
+ quantity = Column(Integer, nullable=False)
151
+ side = Column(SQLEnum(PositionSide), nullable=False)
152
+ average_price = Column(Numeric(10, 4), nullable=False)
153
+ current_price = Column(Numeric(10, 4), nullable=False)
154
+
155
+ # Financial metrics
156
+ market_value = Column(Numeric(15, 2), nullable=False)
157
+ cost_basis = Column(Numeric(15, 2), nullable=False)
158
+ unrealized_pnl = Column(Numeric(15, 2), nullable=False, default=0.0)
159
+ unrealized_pnl_pct = Column(Float, nullable=False, default=0.0)
160
+ realized_pnl = Column(Numeric(15, 2), nullable=False, default=0.0)
161
+
162
+ # Position sizing
163
+ position_size_pct = Column(Float, nullable=False, default=0.0) # % of portfolio
164
+ weight = Column(Float, nullable=False, default=0.0) # Portfolio weight
165
+
166
+ # Metadata
167
+ created_at = Column(DateTime, default=datetime.utcnow)
168
+ updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
169
+
170
+ # Relationships
171
+ portfolio = relationship("Portfolio", back_populates="positions")
172
+ trades = relationship("TradingOrder", back_populates="position")
173
+
174
+ # Indexes
175
+ __table_args__ = (
176
+ Index('idx_position_portfolio_symbol', 'portfolio_id', 'symbol'),
177
+ )
178
+
179
+
180
+ class TradingOrder(Base):
181
+ """Trading order information"""
182
+ __tablename__ = "trading_orders"
183
+
184
+ id = Column(PostgresUUID(as_uuid=True), primary_key=True, default=uuid4)
185
+ trading_account_id = Column(PostgresUUID(as_uuid=True), ForeignKey("trading_accounts.id"), nullable=False)
186
+ portfolio_id = Column(PostgresUUID(as_uuid=True), ForeignKey("portfolios.id"), nullable=False)
187
+ position_id = Column(PostgresUUID(as_uuid=True), ForeignKey("positions.id"), nullable=True)
188
+
189
+ # Order details
190
+ symbol = Column(String(10), nullable=False, index=True)
191
+ side = Column(SQLEnum(OrderSide), nullable=False)
192
+ order_type = Column(SQLEnum(OrderType), nullable=False)
193
+ quantity = Column(Integer, nullable=False)
194
+
195
+ # Pricing
196
+ limit_price = Column(Numeric(10, 4), nullable=True)
197
+ stop_price = Column(Numeric(10, 4), nullable=True)
198
+ average_fill_price = Column(Numeric(10, 4), nullable=True)
199
+
200
+ # Status and execution
201
+ status = Column(SQLEnum(OrderStatus), nullable=False, default=OrderStatus.PENDING)
202
+ filled_quantity = Column(Integer, nullable=False, default=0)
203
+ remaining_quantity = Column(Integer, nullable=False)
204
+
205
+ # Timestamps
206
+ created_at = Column(DateTime, default=datetime.utcnow)
207
+ submitted_at = Column(DateTime, nullable=True)
208
+ filled_at = Column(DateTime, nullable=True)
209
+ cancelled_at = Column(DateTime, nullable=True)
210
+
211
+ # Additional info
212
+ time_in_force = Column(String(20), default="day")
213
+ extended_hours = Column(Boolean, default=False)
214
+ client_order_id = Column(String(100), nullable=True)
215
+ alpaca_order_id = Column(String(100), nullable=True, index=True)
216
+
217
+ # Relationships
218
+ trading_account = relationship("TradingAccount", back_populates="orders")
219
+ portfolio = relationship("Portfolio", back_populates="orders")
220
+ position = relationship("Position", back_populates="trades")
221
+
222
+ # Indexes
223
+ __table_args__ = (
224
+ Index('idx_order_portfolio_status', 'portfolio_id', 'status'),
225
+ Index('idx_order_symbol_status', 'symbol', 'status'),
226
+ )
227
+
228
+
229
+ class PortfolioPerformanceSnapshot(Base):
230
+ """Daily portfolio performance snapshots"""
231
+ __tablename__ = "portfolio_performance_snapshots"
232
+
233
+ id = Column(PostgresUUID(as_uuid=True), primary_key=True, default=uuid4)
234
+ portfolio_id = Column(PostgresUUID(as_uuid=True), ForeignKey("portfolios.id"), nullable=False)
235
+
236
+ # Snapshot data
237
+ snapshot_date = Column(DateTime, nullable=False, index=True)
238
+ portfolio_value = Column(Numeric(15, 2), nullable=False)
239
+ cash_balance = Column(Numeric(15, 2), nullable=False)
240
+
241
+ # Daily performance
242
+ daily_return = Column(Numeric(15, 2), nullable=False, default=0.0)
243
+ daily_return_pct = Column(Float, nullable=False, default=0.0)
244
+
245
+ # Cumulative performance
246
+ total_return = Column(Numeric(15, 2), nullable=False, default=0.0)
247
+ total_return_pct = Column(Float, nullable=False, default=0.0)
248
+
249
+ # Risk metrics
250
+ volatility = Column(Float, nullable=False, default=0.0)
251
+ sharpe_ratio = Column(Float, nullable=False, default=0.0)
252
+ max_drawdown = Column(Float, nullable=False, default=0.0)
253
+
254
+ # Position data (JSON)
255
+ positions_data = Column(JSON, nullable=True)
256
+
257
+ # Metadata
258
+ created_at = Column(DateTime, default=datetime.utcnow)
259
+
260
+ # Relationships
261
+ portfolio = relationship("Portfolio", back_populates="performance_snapshots")
262
+
263
+ # Indexes
264
+ __table_args__ = (
265
+ Index('idx_snapshot_portfolio_date', 'portfolio_id', 'snapshot_date'),
266
+ )
267
+
268
+
269
+ class TradingSignal(Base):
270
+ """Trading signals generated by ML models"""
271
+ __tablename__ = "trading_signals"
272
+
273
+ id = Column(PostgresUUID(as_uuid=True), primary_key=True, default=uuid4)
274
+ portfolio_id = Column(PostgresUUID(as_uuid=True), ForeignKey("portfolios.id"), nullable=False)
275
+
276
+ # Signal details
277
+ symbol = Column(String(10), nullable=False, index=True)
278
+ signal_type = Column(String(20), nullable=False) # "buy", "sell", "hold"
279
+ confidence = Column(Float, nullable=False)
280
+ strength = Column(Float, nullable=False) # Signal strength 0-1
281
+
282
+ # ML model info
283
+ model_id = Column(String(100), nullable=True)
284
+ model_version = Column(String(50), nullable=True)
285
+ prediction_id = Column(PostgresUUID(as_uuid=True), nullable=True)
286
+
287
+ # Signal parameters
288
+ target_price = Column(Numeric(10, 4), nullable=True)
289
+ stop_loss = Column(Numeric(10, 4), nullable=True)
290
+ take_profit = Column(Numeric(10, 4), nullable=True)
291
+ position_size = Column(Float, nullable=True) # Suggested position size as % of portfolio
292
+
293
+ # Metadata
294
+ created_at = Column(DateTime, default=datetime.utcnow)
295
+ expires_at = Column(DateTime, nullable=True)
296
+ is_active = Column(Boolean, default=True)
297
+
298
+ # Relationships
299
+ portfolio = relationship("Portfolio")
300
+
301
+ # Indexes
302
+ __table_args__ = (
303
+ Index('idx_signal_portfolio_symbol', 'portfolio_id', 'symbol'),
304
+ Index('idx_signal_created_active', 'created_at', 'is_active'),
305
+ )
306
+
307
+
308
+ # Pydantic Models for API
309
+ class TradingAccountCreate(BaseModel):
310
+ """Create trading account request"""
311
+ account_name: str = Field(..., min_length=1, max_length=100)
312
+ account_type: PortfolioType = Field(default=PortfolioType.TEST)
313
+ alpaca_api_key: Optional[str] = None
314
+ alpaca_secret_key: Optional[str] = None
315
+ paper_trading: bool = Field(default=True)
316
+ risk_level: RiskLevel = Field(default=RiskLevel.MODERATE)
317
+ max_position_size: float = Field(default=0.1, ge=0.01, le=1.0)
318
+ max_portfolio_risk: float = Field(default=0.2, ge=0.01, le=1.0)
319
+
320
+
321
+ class PortfolioCreate(BaseModel):
322
+ """Create portfolio request"""
323
+ name: str = Field(..., min_length=1, max_length=100)
324
+ description: Optional[str] = None
325
+ initial_capital: float = Field(default=100000.0, gt=0)
326
+
327
+
328
+ class OrderCreate(BaseModel):
329
+ """Create order request"""
330
+ symbol: str = Field(..., min_length=1, max_length=10)
331
+ side: OrderSide
332
+ order_type: OrderType
333
+ quantity: int = Field(..., gt=0)
334
+ limit_price: Optional[float] = Field(None, gt=0)
335
+ stop_price: Optional[float] = Field(None, gt=0)
336
+ time_in_force: str = Field(default="day")
337
+ extended_hours: bool = Field(default=False)
338
+
339
+
340
+ class PositionResponse(BaseModel):
341
+ """Position response model"""
342
+ id: UUID
343
+ symbol: str
344
+ quantity: int
345
+ side: PositionSide
346
+ average_price: float
347
+ current_price: float
348
+ market_value: float
349
+ cost_basis: float
350
+ unrealized_pnl: float
351
+ unrealized_pnl_pct: float
352
+ realized_pnl: float
353
+ position_size_pct: float
354
+ weight: float
355
+ created_at: datetime
356
+ updated_at: datetime
357
+
358
+
359
+ class OrderResponse(BaseModel):
360
+ """Order response model"""
361
+ id: UUID
362
+ symbol: str
363
+ side: OrderSide
364
+ order_type: OrderType
365
+ quantity: int
366
+ limit_price: Optional[float]
367
+ stop_price: Optional[float]
368
+ average_fill_price: Optional[float]
369
+ status: OrderStatus
370
+ filled_quantity: int
371
+ remaining_quantity: int
372
+ created_at: datetime
373
+ submitted_at: Optional[datetime]
374
+ filled_at: Optional[datetime]
375
+ cancelled_at: Optional[datetime]
376
+ time_in_force: str
377
+ extended_hours: bool
378
+ alpaca_order_id: Optional[str]
379
+
380
+
381
+ class PortfolioResponse(BaseModel):
382
+ """Portfolio response model"""
383
+ id: UUID
384
+ name: str
385
+ description: Optional[str]
386
+ initial_capital: float
387
+ current_value: float
388
+ cash_balance: float
389
+ total_return: float
390
+ total_return_pct: float
391
+ daily_return: float
392
+ daily_return_pct: float
393
+ sharpe_ratio: float
394
+ sortino_ratio: float
395
+ max_drawdown: float
396
+ volatility: float
397
+ is_active: bool
398
+ created_at: datetime
399
+ updated_at: datetime
400
+ positions: List[PositionResponse] = []
401
+
402
+
403
+ class TradingSignalResponse(BaseModel):
404
+ """Trading signal response model"""
405
+ id: UUID
406
+ symbol: str
407
+ signal_type: str
408
+ confidence: float
409
+ strength: float
410
+ model_id: Optional[str]
411
+ model_version: Optional[str]
412
+ target_price: Optional[float]
413
+ stop_loss: Optional[float]
414
+ take_profit: Optional[float]
415
+ position_size: Optional[float]
416
+ created_at: datetime
417
+ expires_at: Optional[datetime]
418
+ is_active: bool