Move the only qualifying R:R scan to 15:30 ET with chained Telegram alerts, put outcome eval after a final-bar OHLCV fetch, enforce NY trading-day requalify semantics, stamp paper trades fill_mode=near_close, and migrate stored schedule_* keys to America/New_York.
56 lines
1.8 KiB
Python
56 lines
1.8 KiB
Python
"""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|atr_trailing|target)$")
|
|
trailing_pct: float | None = Field(default=None, ge=0.5, le=90)
|
|
atr_multiplier: float | None = Field(default=None, ge=0.5, le=10)
|
|
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
|
|
# Execution era: null = pre-cutover / unknown; "near_close" = post schedule cutover.
|
|
fill_mode: 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
|