""" 模拟交易数据模型 """ from enum import Enum from datetime import datetime from sqlalchemy import Column, Integer, String, Float, DateTime, JSON, Text, Enum as SQLEnum from app.models.database import Base class OrderStatus(str, Enum): """订单状态""" PENDING = "pending" # 等待入场 OPEN = "open" # 持仓中 CLOSED_TP = "closed_tp" # 止盈平仓 CLOSED_SL = "closed_sl" # 止损平仓 CLOSED_MANUAL = "closed_manual" # 手动平仓 CANCELLED = "cancelled" # 已取消 class OrderSide(str, Enum): """订单方向""" LONG = "long" # 做多 SHORT = "short" # 做空 class SignalGrade(str, Enum): """信号等级""" A = "A" B = "B" C = "C" D = "D" class EntryType(str, Enum): """入场类型""" MARKET = "market" # 现价入场 LIMIT = "limit" # 挂单入场 class PaperOrder(Base): """模拟交易订单表""" __tablename__ = "paper_orders" id = Column(Integer, primary_key=True, index=True) # 订单标识 order_id = Column(String(64), unique=True, nullable=False, index=True) # 交易对信息 symbol = Column(String(20), nullable=False, index=True) side = Column(SQLEnum(OrderSide), nullable=False) # 价格信息 entry_price = Column(Float, nullable=False) # 目标入场价 stop_loss = Column(Float, nullable=False) # 止损价 take_profit = Column(Float, nullable=False) # 止盈价 filled_price = Column(Float, nullable=True) # 实际成交价 exit_price = Column(Float, nullable=True) # 出场价 # 仓位信息 quantity = Column(Float, default=1000) # 仓位大小 (USDT) # 信号信息 signal_grade = Column(SQLEnum(SignalGrade), default=SignalGrade.D) signal_type = Column(String(20), default="swing") # swing / short_term confidence = Column(Float, default=0) # 置信度 (0-100) trend = Column(String(20), nullable=True) # 趋势方向 entry_type = Column(SQLEnum(EntryType, values_callable=lambda x: [e.value for e in x]), default=EntryType.MARKET) # 入场类型 # 订单状态 status = Column(SQLEnum(OrderStatus), default=OrderStatus.PENDING, index=True) # 盈亏信息 pnl_amount = Column(Float, default=0) # 盈亏金额 (USDT) pnl_percent = Column(Float, default=0) # 盈亏百分比 # 风险指标 max_drawdown = Column(Float, default=0) # 持仓期间最大回撤 max_profit = Column(Float, default=0) # 持仓期间最大盈利 # 时间戳 created_at = Column(DateTime, default=datetime.utcnow) opened_at = Column(DateTime, nullable=True) # 开仓时间 closed_at = Column(DateTime, nullable=True) # 平仓时间 # 附加数据 entry_reasons = Column(JSON, nullable=True) # 入场原因 indicators = Column(JSON, nullable=True) # 技术指标快照 notes = Column(Text, nullable=True) # 备注 def to_dict(self): """转换为字典""" return { 'id': self.id, 'order_id': self.order_id, 'symbol': self.symbol, 'side': self.side.value if self.side else None, 'entry_price': self.entry_price, 'stop_loss': self.stop_loss, 'take_profit': self.take_profit, 'filled_price': self.filled_price, 'exit_price': self.exit_price, 'quantity': self.quantity, 'signal_grade': self.signal_grade.value if self.signal_grade else None, 'signal_type': self.signal_type, 'confidence': self.confidence, 'trend': self.trend, 'entry_type': self.entry_type.value if self.entry_type else 'market', 'status': self.status.value if self.status else None, 'pnl_amount': self.pnl_amount, 'pnl_percent': self.pnl_percent, 'max_drawdown': self.max_drawdown, 'max_profit': self.max_profit, 'created_at': self.created_at.isoformat() if self.created_at else None, 'opened_at': self.opened_at.isoformat() if self.opened_at else None, 'closed_at': self.closed_at.isoformat() if self.closed_at else None, 'entry_reasons': self.entry_reasons, }