"""Schemas for paper trades.""" from __future__ import annotations from datetime import datetime from pydantic import BaseModel, Field class PaperTradeCreate(BaseModel): symbol: str = Field(..., min_length=1, max_length=10) direction: str = Field(..., pattern=r"^(long|short)$") entry_price: float = Field(..., gt=0) shares: float = Field(..., gt=0) stop_loss: float = Field(..., gt=0) target: float = Field(..., gt=0) class PaperTradeClose(BaseModel): close_price: float | None = Field(default=None, gt=0) class ExitPolicyUpdate(BaseModel): """Auto-exit policy for open paper trades.""" mode: str | None = Field(default=None, pattern=r"^(time|trailing|target)$") trailing_pct: float | None = Field(default=None, ge=0.5, le=90) hold_days: int | None = Field(default=None, ge=2, le=250) class PaperTradeResponse(BaseModel): id: int symbol: str direction: str entry_price: float shares: float stop_loss: float target: float status: str opened_at: datetime close_price: float | None = None closed_at: datetime | None = None current_price: float | None = None # Alpha vs the S&P 500 (SPY) over the trade's holding period. None when the # benchmark series doesn't cover the trade's open date yet. benchmark_return_pct: float | None = None alpha_pct: float | None = None alpha_usd: float | None = None close_reason: str | None = None # Live trailing-stop level + how far price sits above it (% ), for open trades # when the trailing exit policy is active. trailing_stop: float | None = None trailing_distance_pct: float | None = None