Files
trade/engine/common/models.py
T
Rekey 039bfb5075 feat(engine): 添加核心基础设施 — engine/common 模块
- engine/__init__.py: 包入口,导出 Kline/KlineInterval/OrderBook/Ticker/Trade
- common/base.py: BaseStrategy 抽象基类,定义 on_kline/on_ticker/on_orderbook 回调
- common/models.py: Pydantic 数据模型,与 TS 侧 types 字段对齐,支持字段校验
- common/config.py: 全局配置加载(YAML),统一 engine/env.yaml 读取
- common/logger.py: 结构化日志,支持 JSON/pretty print 输出
2026-06-12 10:26:37 +08:00

179 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
数据模型定义 — 与 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", "4h", "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)