""" 数据模型定义 — 与 TS data/types/base.ts 对齐的 Pydantic 模型 Ticker / Trade / OrderBook / Kline 是系统中流通的核心行情数据结构, 字段语义与 Binance/OKX/Bybit 通用概念对齐,时间戳统一使用 Unix 毫秒。 """ from typing import Literal from pydantic import BaseModel, Field, field_validator # ============================================================ # K 线周期类型 # ============================================================ KlineInterval = Literal["1m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "1d", "1w"] # ============================================================ # 行情数据模型 # ============================================================ class Ticker(BaseModel): """24 小时滚动行情统计 每笔成交触发推送,包含最近 24 小时的 OHLC、成交量、买卖盘口等统计信息。 """ exchange: str """交易所标识(如 binance)""" symbol: str """交易对符号(大写,如 BTCUSDT)""" # 24h 价格统计 last_price: float = Field(alias="lastPrice") """最新成交价""" open_price: float = Field(alias="openPrice") """24h 开盘价""" high_price: float = Field(alias="highPrice") """24h 最高价""" low_price: float = Field(alias="lowPrice") """24h 最低价""" # 24h 成交量统计 volume: float """24h 成交量(base 币种)""" quote_volume: float = Field(alias="quoteVolume") """24h 成交额(quote 币种)""" # 价格变化 price_change: float = Field(alias="priceChange") """24h 价格变化""" price_change_percent: float = Field(alias="priceChangePercent") """24h 价格变化百分比(0.05 = 5%)""" # 最优买卖盘口 bid_price: float = Field(alias="bidPrice") """买一价""" bid_qty: float = Field(alias="bidQty") """买一量""" ask_price: float = Field(alias="askPrice") """卖一价""" ask_qty: float = Field(alias="askQty") """卖一量""" # 时间戳 event_time: float = Field(alias="eventTime") """事件发生时间(Unix 毫秒)""" close_time: float = Field(alias="closeTime") """交易所收盘时间(Unix 毫秒,用于判断 K 线是否闭合)""" class Trade(BaseModel): """逐笔成交记录""" exchange: str """交易所标识""" symbol: str """交易对符号""" price: float """成交价""" amount: float """成交数量(base 币种)""" quote_amount: float = Field(alias="quoteAmount") """成交额(quote 币种 = price × amount)""" timestamp: float """成交时间(Unix 毫秒)""" is_buyer_maker: bool = Field(alias="isBuyerMaker") """买方是否为挂单方(true = 主动卖出 / taker sell)""" trade_id: str = Field(alias="tradeId") """交易所成交 ID""" class OrderBook(BaseModel): """订单簿深度快照""" exchange: str """交易所标识""" symbol: str """交易对符号""" bids: list[tuple[float, float]] """买单列表 [[price, qty], ...],按价格降序(买一在前)""" asks: list[tuple[float, float]] """卖单列表 [[price, qty], ...],按价格升序(卖一在前)""" last_update_id: int = Field(alias="lastUpdateId") """上次更新 ID""" event_time: float = Field(alias="eventTime") """事件发生时间(Unix 毫秒)""" class Kline(BaseModel): """标准化 K 线(OHLCV) K 线是最主要的行情输入,策略通过 on_kline() 接收此数据。 open/high/low/close/volume 字段在 TS 侧为字符串以保持精度, 模型在初始化时自动转换为 float。 """ exchange: str """交易所标识""" symbol: str """交易对符号""" interval: KlineInterval """K 线周期""" # 时间 open_time: float = Field(alias="openTime") """开盘时间(Unix 毫秒)""" close_time: float = Field(alias="closeTime") """收盘时间(Unix 毫秒)""" # OHLCV open: float """开盘价""" high: float """最高价""" low: float """最低价""" close: float """收盘价""" volume: float """成交量(base 币种)""" # 扩展字段 quote_volume: float = Field(default=0.0, alias="quoteVolume") """成交额(quote 币种)""" taker_buy_base_vol: float = Field(default=0.0, alias="takerBuyBaseVol") """主动买入成交量(base 币种)""" taker_buy_quote_vol: float = Field(default=0.0, alias="takerBuyQuoteVol") """主动买入成交额(quote 币种)""" trade_count: int = Field(default=0, alias="tradeCount") """成交笔数""" is_closed: bool = Field(alias="isClosed") """该 K 线是否已关闭(不再更新)""" # ── 字段校验:处理 TS 侧字符串 → float 转换 ── @field_validator( "open", "high", "low", "close", "volume", "quote_volume", "taker_buy_base_vol", "taker_buy_quote_vol", mode="before", ) @classmethod def _coerce_float(cls, v: object) -> float: """将字符串类型数值转为 float,兼容 TS 侧 MessagePack 序列化格式""" if isinstance(v, str): return float(v) return float(v) @field_validator("trade_count", mode="before") @classmethod def _coerce_int(cls, v: object) -> int: """将字符串类型数值转为 int""" if isinstance(v, str): return int(v) return int(v)