"""基金行情公共契约。内部使用稳定英文字段,不暴露供应商字段名。""" from datetime import date, datetime from decimal import Decimal from typing import Literal from pydantic import BaseModel, ConfigDict, Field, field_validator class FundQuoteQuery(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True) fund_codes: tuple[str, ...] = () fund_type: str | None = None target_date: date | None = None limit: int = Field(default=50, ge=1, le=1000) @field_validator("fund_codes") @classmethod def validate_codes(cls, value: tuple[str, ...]) -> tuple[str, ...]: for code in value: if len(code) != 6 or not code.isdigit(): raise ValueError("fund code must be a six-digit number") return tuple(dict.fromkeys(value)) class FundQuote(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True) fund_code: str fund_name: str fund_type: str | None = None nav: Decimal | None = None nav_date: date | None = None daily_change: Decimal | None = None half_year_return: Decimal | None = None one_year_return: Decimal | None = None year_to_date_return: Decimal | None = None since_inception_return: Decimal | None = None quote_time: datetime quote_source: Literal["eastmoney", "cache", "degraded"] is_intraday: bool degraded: bool = False