diff --git a/stock-lab/app/screener/schemas.py b/stock-lab/app/screener/schemas.py new file mode 100644 index 0000000..b18835d --- /dev/null +++ b/stock-lab/app/screener/schemas.py @@ -0,0 +1,85 @@ +from __future__ import annotations +from typing import Literal, Optional +from pydantic import BaseModel, Field + + +class NodeMeta(BaseModel): + name: str + label: str + default_params: dict + param_schema: dict + + +class NodesResponse(BaseModel): + score_nodes: list[NodeMeta] + gate_nodes: list[NodeMeta] + + +class SettingsBody(BaseModel): + weights: dict[str, float] + node_params: dict[str, dict] = Field(default_factory=dict) + gate_params: dict + top_n: int = 20 + rr_ratio: float = 2.0 + atr_window: int = 14 + atr_stop_mult: float = 2.0 + + +class SettingsResponse(SettingsBody): + updated_at: str + + +class RunRequest(BaseModel): + mode: Literal["preview", "manual_save", "auto"] = "preview" + asof: Optional[str] = None + weights: Optional[dict[str, float]] = None + node_params: Optional[dict[str, dict]] = None + gate_params: Optional[dict] = None + top_n: Optional[int] = None + + +class ResultRow(BaseModel): + rank: int + ticker: str + name: str + total_score: float + scores: dict[str, float] + close: int + market_cap: int + entry_price: Optional[int] = None + stop_price: Optional[int] = None + target_price: Optional[int] = None + atr14: Optional[float] = None + r_pct: Optional[float] = None + + +class TelegramPayload(BaseModel): + chat_target: str + parse_mode: str + text: str + + +class RunResponse(BaseModel): + asof: str + mode: str + status: Literal["success", "failed", "skipped_holiday"] + run_id: Optional[int] = None + survivors_count: Optional[int] = None + weights: dict[str, float] + top_n: int + results: list[ResultRow] = Field(default_factory=list) + telegram_payload: Optional[TelegramPayload] = None + warnings: list[str] = Field(default_factory=list) + error: Optional[str] = None + + +class RunSummary(BaseModel): + id: int + asof: str + mode: str + status: str + started_at: str + finished_at: Optional[str] = None + top_n: int + survivors_count: Optional[int] = None + telegram_sent: bool