"""Pydantic 数据模型""" from pydantic import BaseModel from datetime import datetime class StockQuote(BaseModel): ts_code: str name: str price: float pct_chg: float volume: float # 成交量(手) amount: float # 成交额(万元) turnover_rate: float # 换手率 % pe: float | None = None pb: float | None = None circ_mv: float | None = None # 流通市值(亿) total_mv: float | None = None # 总市值(亿) volume_ratio: float | None = None # 量比 high: float | None = None low: float | None = None open: float | None = None pre_close: float | None = None limit_up: float | None = None limit_down: float | None = None amplitude: float | None = None # 振幅 % class CapitalFlow(BaseModel): ts_code: str trade_date: str buy_elg_amount: float = 0 # 特大单买入(万) sell_elg_amount: float = 0 buy_lg_amount: float = 0 # 大单买入(万) sell_lg_amount: float = 0 buy_md_amount: float = 0 # 中单买入(万) sell_md_amount: float = 0 buy_sm_amount: float = 0 # 小单买入(万) sell_sm_amount: float = 0 net_mf_amount: float = 0 # 主力净流入(万) @property def main_net_inflow(self) -> float: """主力净流入 = 特大单净买 + 大单净买""" return (self.buy_elg_amount - self.sell_elg_amount + self.buy_lg_amount - self.sell_lg_amount) @property def total_amount(self) -> float: return (self.buy_elg_amount + self.sell_elg_amount + self.buy_lg_amount + self.sell_lg_amount + self.buy_md_amount + self.sell_md_amount + self.buy_sm_amount + self.sell_sm_amount) class SectorInfo(BaseModel): sector_code: str sector_name: str pct_change: float = 0 # 涨跌幅 % capital_inflow: float = 0 # 主力净流入(万元,原始数据来自Tushare亿元×10000) limit_up_count: int = 0 # 涨停数 days_continuous: int = 0 # 连续资金流入天数 heat_score: float = 0 # 热度综合评分 stage: str = "mid" # 板块阶段: early/mid/late/end # ── 板块分析增强字段 ── member_count: int = 0 # 成分股数量 leading_stocks: list[dict] = [] # 领涨股 [{ts_code, name, pct_chg, amount}] capital_trend: list[float] = [] # 近5日资金净流入趋势(万) pct_trend: list[float] = [] # 近5日涨跌幅趋势 turnover_avg: float = 0 # 板块平均换手率 main_force_ratio: float = 0 # 主力资金占比(主力净流入/总成交额) class MarketTemperature(BaseModel): trade_date: str up_count: int = 0 # 上涨家数 down_count: int = 0 # 下跌家数 limit_up_count: int = 0 # 涨停数(自然涨停) limit_down_count: int = 0 # 跌停数 max_streak: int = 0 # 最高连板 broken_rate: float = 0 # 炸板率 % index_above_ma20: bool = False # 上证在 MA20 上方 temperature: float = 0 # 综合温度 0-100 class TechnicalSignal(BaseModel): ts_code: str name: str = "" ma_bullish: bool = False # 均线多头排列 volume_breakout: bool = False # 放量突破 macd_golden: bool = False # MACD金叉 rsi_healthy: bool = False # RSI健康区间 pullback_support: bool = False # 缩量回踩支撑 big_yang: bool = False # 底部放量长阳 boll_support: bool = False # 布林带下轨支撑 score: float = 0 # 信号触发计数分 trend_score: float = 0 # 趋势评分(推荐体系用的技术面分数) signal_count: int = 0 # 满足的信号数量 # 位置安全评估(防追高) rally_pct_5d: float = 0 # 近5日累计涨幅 rally_pct_10d: float = 0 # 近10日累计涨幅 distance_from_high: float = 0 # 距离60日高点 %(负=已回调) position_score: float = 50 # 位置安全得分 0-100 # 价格参考 support_price: float | None = None # 支撑位 resist_price: float | None = None # 压力位 stop_loss_price: float | None = None # 止损价 class Recommendation(BaseModel): ts_code: str name: str sector: str score: float # 综合评分 market_temp_score: float sector_score: float capital_score: float technical_score: float supply_demand_score: float = 0 # 供需评分(主评分50%权重) price_action_score: float = 0 # 价格行为评分(主评分40%权重) position_score: float = 50 # 位置安全得分 valuation_score: float = 50 # 估值安全得分 signal: str # BUY / SELL / HOLD entry_price: float | None = None target_price: float | None = None stop_loss: float | None = None reasons: list[str] = [] risk_note: str = "" level: str = "" # 强烈推荐/推荐/观望/回避 strategy: str = "trend_breakout" # trend_breakout / momentum(旧) / potential(旧) entry_signal_type: str = "none" # breakout / pullback / launch / none entry_timing: str = "" # 进场时机建议(盘中适用) llm_analysis: str = "" # LLM 深度分析 llm_score: float | None = None # AI 评分 1-10 scan_session: str = "" created_at: datetime | None = None