Files
zjjk/backend/app/api/schemas.py

239 lines
6.1 KiB
Python
Raw Normal View History

2026-03-20 21:47:30 +08:00
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]
2026-04-08 20:04:40 +08:00
class EtfRealtimeRecord(BaseModel):
trade_date: str
code: str
name: str
fund_name: str | None = None
detail_url: str | None = None
source_url: str | None = None
latest_price: float | None = None
change_amount: float | None = None
change_percent: float | None = None
previous_close: float | None = None
open_price: float | None = None
high_price: float | None = None
low_price: float | None = None
volume: int | None = None
turnover_amount: float | None = None
turnover_rate: float | None = None
change_percent_1m: float | None = None
change_percent_3m: float | None = None
change_percent_4m: float | None = None
updated_at: str | None = None
snapshot_time: str | None = None
source_name: str
precision: Precision
is_trading: bool = False
class EtfRealtimeResponse(BaseModel):
trade_date: str
updated_at: str | None = None
source_name: str
source_url: str | None = None
precision: Precision
group: str
records: list[EtfRealtimeRecord]