from datetime import datetime from sqlalchemy import DateTime, Float, ForeignKey, String from sqlalchemy.orm import Mapped, mapped_column from app.database import Base class PaperTrade(Base): """A simulated ('taken') trade for paper trading. Captured from a setup at the moment the user marks it taken: direction, entry, size, stop and target. Open trades are marked-to-market against the latest close; closing records the exit price and time. """ __tablename__ = "paper_trades" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column( ForeignKey("users.id", ondelete="CASCADE"), nullable=False ) ticker_id: Mapped[int] = mapped_column( ForeignKey("tickers.id", ondelete="CASCADE"), nullable=False ) direction: Mapped[str] = mapped_column(String(10), nullable=False) entry_price: Mapped[float] = mapped_column(Float, nullable=False) shares: Mapped[float] = mapped_column(Float, nullable=False) stop_loss: Mapped[float] = mapped_column(Float, nullable=False) target: Mapped[float] = mapped_column(Float, nullable=False) status: Mapped[str] = mapped_column(String(10), nullable=False, default="open") opened_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=datetime.utcnow, nullable=False ) close_price: Mapped[float | None] = mapped_column(Float, nullable=True) closed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) # How the trade was closed: "trailing" | "stop" | "target" | "manual". close_reason: Mapped[str | None] = mapped_column(String(10), nullable=True)