from pydantic import BaseModel, Field from typing import List, Optional, Literal from datetime import datetime from enum import Enum class Stock(BaseModel): code: str = Field(..., description="股票代码") name: str = Field(..., description="股票名称") price: float = Field(..., description="当前价格") change: float = Field(..., description="涨跌额") change_percent: float = Field(..., description="涨跌幅%") volume: int = Field(..., description="成交量") market_cap: int = Field(..., description="市值") industry: str = Field(..., description="所属行业") class MarketOverview(BaseModel): up_count: int = Field(..., description="上涨家数") down_count: int = Field(..., description="下跌家数") flat_count: int = Field(..., description="平盘家数") limit_up_count: int = Field(..., description="涨停家数") limit_down_count: int = Field(..., description="跌停家数") update_time: str = Field(..., description="更新时间") class MarketIndex(BaseModel): code: str = Field(..., description="指数代码") name: str = Field(..., description="指数名称") price: float = Field(..., description="当前点位") change: float = Field(..., description="涨跌点数") change_percent: float = Field(..., description="涨跌幅%") volume: int = Field(..., description="成交量") up_count: int = Field(..., description="上涨家数") down_count: int = Field(..., description="下跌家数") flat_count: int = Field(..., description="平盘家数") class SentimentData(BaseModel): value: int = Field(..., ge=0, le=100, description="情绪值0-100") label: str = Field(..., description="状态标签") description: str = Field(..., description="描述") color: str = Field(..., description="颜色") class MomentumData(BaseModel): sector: str = Field(..., description="版块名称") change_percent: float = Field(..., description="涨跌幅") momentum: float = Field(..., description="动量值") stocks: List[str] = Field(default_factory=list, description="包含股票名称") up_count: int = Field(..., description="上涨家数") down_count: int = Field(..., description="下跌家数") flat_count: int = Field(..., description="平盘家数") top_stocks: List[Stock] = Field(default_factory=list, description="领涨股票") class HighLowStock(BaseModel): code: str = Field(..., description="股票代码") name: str = Field(..., description="股票名称") price: float = Field(..., description="当前价格") change_percent: float = Field(..., description="涨跌幅%") high_low_price: float = Field(..., description="新高/新低价格") industry: str = Field(..., description="所属行业") days_to_high_low: int = Field(..., description="距离新高/新低天数") class PriceDistribution(BaseModel): range: str = Field(..., description="涨跌幅区间") count: int = Field(..., description="股票数量") is_up: bool = Field(..., description="是否上涨区间") class RecommendationType(str, Enum): BUY = "buy" SELL = "sell" HOLD = "hold" class TrendType(str, Enum): UP = "up" DOWN = "down" SIDEWAYS = "sideways" class TargetPrice(BaseModel): ideal_buy: Optional[float] = Field(None, description="理想买入价") second_buy: Optional[float] = Field(None, description="次级买入价") stop_loss: Optional[float] = Field(None, description="止损价") take_profit: Optional[float] = Field(None, description="止盈价") class AIAnalysis(BaseModel): stock_code: str = Field(..., description="股票代码") stock_name: str = Field(..., description="股票名称") current_price: float = Field(..., description="当前价格") change_percent: float = Field(..., description="涨跌幅%") insights: str = Field(..., description="关键洞察") recommendation: RecommendationType = Field(..., description="推荐操作") recommendation_text: str = Field(..., description="推荐操作文本") trend: TrendType = Field(..., description="趋势判断") trend_text: str = Field(..., description="趋势文本") target_price: TargetPrice = Field(..., description="目标价位") confidence: int = Field(..., ge=0, le=100, description="置信度") class KLineData(BaseModel): date: str = Field(..., description="日期") open: float = Field(..., description="开盘价") high: float = Field(..., description="最高价") low: float = Field(..., description="最低价") close: float = Field(..., description="收盘价") volume: int = Field(..., description="成交量") class SentimentType(str, Enum): POSITIVE = "positive" NEGATIVE = "negative" NEUTRAL = "neutral" class NewsItem(BaseModel): id: str = Field(..., description="新闻ID") title: str = Field(..., description="标题") source: str = Field(..., description="来源") time: str = Field(..., description="时间") sentiment: SentimentType = Field(..., description="情感倾向") sentiment_text: str = Field(..., description="情感文本") is_hot: Optional[bool] = Field(None, description="是否热点") read_count: Optional[int] = Field(None, description="阅读数") class HotNews(BaseModel): id: str = Field(..., description="新闻ID") title: str = Field(..., description="标题") heat: int = Field(..., description="热度值") related_stocks: List[str] = Field(default_factory=list, description="相关股票") time: str = Field(..., description="时间") class DataSource(BaseModel): id: str = Field(..., description="数据源ID") name: str = Field(..., description="数据源名称") icon: str = Field(..., description="图标") is_available: bool = Field(..., description="是否可用") class SentimentTrend(BaseModel): date: str = Field(..., description="日期") value: int = Field(..., ge=0, le=100, description="情绪值") class SubscribeTopic(str, Enum): MARKET_OVERVIEW = "market_overview" STOCK_PRICE = "stock_price" SENTIMENT = "sentiment" MOMENTUM = "momentum" NEWS = "news" class WSMessage(BaseModel): topic: SubscribeTopic = Field(..., description="订阅主题") data: dict = Field(..., description="数据内容") timestamp: int = Field(..., description="时间戳") class ApiResponse(BaseModel): success: bool = Field(..., description="是否成功") data: Optional[dict] = Field(None, description="数据") message: Optional[str] = Field(None, description="消息") error: Optional[str] = Field(None, description="错误信息") class DataSourceType(str, Enum): EASTMONEY = "eastmoney" THS = "ths" XUEQIU = "xueqiu" TENCENT = "tencent"