edc50e8809
- 数据层: build_aggregates_sql 新增 2h/6h 聚合视图,默认起始时间调整为 2017-05 - 模型层: KlineInterval 类型扩展 2h/6h,DataService 新增对应表名和毫秒映射 - 指标层: 新增 incremental.py 增量指标模块 (EmaInc/AtrInc/RsiInc/BbInc),O(1) per bar - 策略重构: long_short.py 和 regime_all.py 从批量 ema/atr 迁移至增量指标,避免每 bar 重复全量计算 - regime 探测器: RegimeDetector3 改为增量 EMA200,detect() 接口简化 - 回测扩展: regime_timeframe_comparison 从 4h/1d 扩展至 2h/4h/6h/1d - 新增示例: multi_strategy_report, vol_break_compare/periods, intraday_explore, top3_trades 等分析脚本
179 lines
5.4 KiB
Python
179 lines
5.4 KiB
Python
"""
|
||
数据模型定义 — 与 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)
|