from typing import Literal from pydantic import BaseModel, Field Precision = Literal["realtime_exact", "close_final", "historical_exact", "unavailable"] MarketState = Literal["pre_open", "trading_am", "midday_break", "trading_pm", "finalizing", "closed"] PushStatus = Literal["pending", "sent", "failed", "skipped"] class HealthResponse(BaseModel): status: str class ValueWithStatus(BaseModel): amount_hkd_billion: float | None = None precision: Precision label: str class OverviewSnapshot(BaseModel): trade_date: str snapshot_time: str | None = None market_state: MarketState total_net_inflow: ValueWithStatus cumulative_net_inflow: ValueWithStatus shanghai_net_inflow: ValueWithStatus shenzhen_net_inflow: ValueWithStatus buy_amount: ValueWithStatus sell_amount: ValueWithStatus net_buy_amount: ValueWithStatus one_min_change: ValueWithStatus five_min_change: ValueWithStatus threshold_progress: float = Field(ge=0, le=1) next_threshold_hkd_billion: float source_name: str source_url: str | None = None updated_at: str | None = None unavailable_reason: str | None = None class TimelinePoint(BaseModel): timestamp: str amount_hkd_billion: float | None = None precision: Precision class BenchmarkTimelinePoint(BaseModel): timestamp: str value: float | None = None class BenchmarkTimelineSeries(BaseModel): key: str label: str unit: str detail_url: str | None = None points: list[BenchmarkTimelinePoint] class PushRecord(BaseModel): id: str triggered_at: str push_type: str rule_code: str trigger_value_hkd_billion: float | None = None description: str email_subject: str email_summary: str status: PushStatus error_message: str | None = None class PushRecordsResponse(BaseModel): records: list[PushRecord] class OverviewResponse(BaseModel): snapshot: OverviewSnapshot minute_timeline: list[TimelinePoint] benchmark_series: list[BenchmarkTimelineSeries] recent_push_records: list[PushRecord] class StatPoint(BaseModel): period: str amount_hkd_billion: float class RecentTradeDay(BaseModel): trade_date: str total_net_inflow_hkd_billion: float precision: Precision class HistorySummary(BaseModel): cumulative_net_inflow_hkd_billion: float trading_day_count: int max_single_day_inflow_hkd_billion: float max_single_day_outflow_hkd_billion: float longest_inflow_streak: int longest_outflow_streak: int class HistoryResponse(BaseModel): start_date: str daily: list[StatPoint] weekly: list[StatPoint] monthly: list[StatPoint] cumulative: list[StatPoint] benchmark_history: dict[str, list[StatPoint]] recent_trade_days: list[RecentTradeDay] summary: HistorySummary class RuleItem(BaseModel): key: str label: str value: str description: str class RulesResponse(BaseModel): items: list[RuleItem] class SourceDiagnosticsResponse(BaseModel): source_name: str realtime_available: bool historical_available: bool last_success_at: str | None = None last_failure_at: str | None = None last_error_reason: str | None = None last_success_url: str | None = None last_persisted_at: str | None = None class MetaResponse(BaseModel): product_name: str version: str timezone: str market_state: MarketState current_trade_date: str source_name: str source_strategy: str note: str class AShareFlowRecord(BaseModel): trade_date: str code: str name: str detail_url: str | None = None latest_price: float | None = None change_amount: float | None = None change_percent: float | None = None main_net_inflow: float | None = None main_net_inflow_ratio: float | None = None super_large_net_inflow: float | None = None super_large_net_inflow_ratio: float | None = None large_net_inflow: float | None = None large_net_inflow_ratio: float | None = None medium_net_inflow: float | None = None medium_net_inflow_ratio: float | None = None small_net_inflow: float | None = None small_net_inflow_ratio: float | None = None rolling_net_inflow_5d: float | None = None rolling_net_inflow_10d: float | None = None rolling_net_inflow_30d: float | None = None rolling_net_inflow_60d: float | None = None rolling_net_inflow_90d: float | None = None updated_at: str | None = None source_name: str source_url: str | None = None precision: Precision snapshot_time: str | None = None sector_type: str | None = None sector_type_label: str | None = None class AShareSectorGroup(BaseModel): label: str records: list[AShareFlowRecord] class AShareIndexFlowResponse(BaseModel): trade_date: str updated_at: str | None = None source_name: str source_url: str | None = None precision: Precision records: list[AShareFlowRecord] class AShareSectorFlowResponse(BaseModel): trade_date: str updated_at: str | None = None source_name: str source_url: str | None = None precision: Precision sector_types: dict[str, AShareSectorGroup]