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,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
|