第 3 章 · 01 object.py 的基类与行情数据类


文档摘要

第 3 章 · 01 object.py 的基类与行情数据类 本节摘要:本节精读 的基类设计(BaseData)与行情数据类(TickData/BarData)。BaseData 是所有数据类的根,只有两个成员:gatewayname(标记数据来源)和 extra(运行时挂载扩展数据)。TickData 字段最丰富——除常规 OHLC 外,还有国内标准的五档买卖盘(共 20 个字段)、涨停跌停、持仓量。最关键的设计是 自动生成 (symbol.exchange)这个全局唯一复合主键,使用者只需提供本地 symbol,框架自动拼接,避免手工出错。读完本节,你理解了 VeighNa 所有数据的"语法基础"。 内容来源:原项目源码 (L17-108),精读并套用体系化模板。

第 3 章 · 01 object.py 的基类与行情数据类

本节摘要:本节精读 vnpy/trader/object.py 的基类设计(BaseData)与行情数据类(TickData/BarData)。BaseData 是所有数据类的根,只有两个成员:gateway_name(标记数据来源)和 extra(运行时挂载扩展数据)。TickData 字段最丰富——除常规 OHLC 外,还有国内标准的五档买卖盘(共 20 个字段)、涨停跌停、持仓量。最关键的设计是 __post_init__ 自动生成 vt_symbol(symbol.exchange)这个全局唯一复合主键,使用者只需提供本地 symbol,框架自动拼接,避免手工出错。读完本节,你理解了 VeighNa 所有数据的"语法基础"。

内容来源:原项目源码 vnpy/trader/object.py(L17-108),精读并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 说清 BaseData 基类的两个字段及其设计意图。
  2. 列举 TickData 的字段分组(标识/静态/OHLC/五档/时间戳)。
  3. 理解 vt_symbol = f"{symbol}.{exchange.value}" 的拼接规则。
  4. 解释 BarData 与 TickData 的字段差异。
  5. 知道 datetime 别名 Datetime 实际就是标准库 datetime。

一、模块级常量

object.py:5-14:

5 from dataclasses import dataclass, field 6 from datetime import datetime as Datetime # 关键:把标准库 datetime 别名为 Datetime 8 from .constant import Direction, Exchange, Interval, Offset, Status, Product, OptionType, OrderType 11 INFO: int = 20 # 日志级别常量(LogData 默认级别) 14 ACTIVE_STATUSES = set([Status.SUBMITTING, Status.NOTTRADED, Status.PARTTRADED]) # "活跃订单"状态集合

两点:

  • from datetime import datetime as Datetime(第 6 行):所有字段标注的 Datetime 实际就是标准库 datetime.datetime(不是 date/time)。大写别名纯是命名习惯。所以 LogData.__post_init__ 里可直接 Datetime.now()
  • ACTIVE_STATUSES(第 14 行):把"提交中/未成交/部分成交"三个状态预定义为集合,用于 OrderData.is_active() 判断。集合查询 O(1)。

二、BaseData:所有数据类的根

object.py:17-26:

17 @dataclass 18 class BaseData: 24 gateway_name: str 26 extra: dict | None = field(default=None, init=False)

只有两个成员:

  • gateway_name: str:标记数据来源接口(如 "CTP""BITFINEX")。这是必填字段。因为是基类且 dataclass 继承时字段按 MRO 顺序排列,所有子类字段都排在 gateway_name 之后——这就是为什么子类构造时 gateway_name 总是用关键字传参。
  • extra: dict | None:用 field(init=False) 表示不参与 init 参数,默认 None。留给用户运行时挂载扩展数据,不污染 schema。

💡 核心心法:extra 字段是"dataclass 扩展性"的优雅设计。金融数据字段多且杂,核心包定义常用字段,用户有特殊需求(比如想给 TickData 加个"信号强度"标注)时,塞进 extra 即可,不必继承新类。注意 dataclass 规则:init=False 的字段必须放在所有 init=True 字段之后。

三、TickData:行情快照(字段最丰富)

object.py:30-85(字段分组):

30 @dataclass 31 class TickData(BaseData): 32 symbol: str 33 exchange: Exchange 34 datetime: Datetime # 静态信息 name: str = "" volume: float = 0 # 当日累计成交量 turnover: float = 0 # 当日累计成交额 open_interest: float = 0 # 持仓量(期货特色) last_price: float = 0 # 最新成交价 last_volume: float = 0 limit_up: float = 0 # 涨停价 limit_down: float = 0 # 跌停价 # OHLC open_price: float = 0 high_price: float = 0 low_price: float = 0 pre_close: float = 0 # 五档买卖盘(国内标准) bid_price_1: float = 0 ... bid_price_5: float = 0 ask_price_1: float = 0 ... ask_price_5: float = 0 bid_volume_1: float = 0 ... bid_volume_5: float = 0 ask_volume_1: float = 0 ... ask_volume_5: float = 0 localtime: Datetime | None = None # 网关本地接收时间戳 82 def __post_init__(self) -> None: 84 self.vt_symbol: str = f"{self.symbol}.{self.exchange.value}"

TickData 字段分五大组:

  1. 标识:symbol/exchange/datetime(必填)。
  2. 静态信息:name/volume/turnover/open_interest/last_price/limit_up/limit_down。
  3. OHLC:open/high/low/pre_close。
  4. 五档买卖盘:bid/ask price/volume 各 5 档,共 20 个字段——这是国内期货/股票的标准深度行情。
  5. localtime:网关本地接收时间戳,用于对账延迟(交易所时间 vs 本地到达时间的差)。

四、vt_symbol:全局唯一复合主键

__post_init__(L82-84):

82 def __post_init__(self) -> None: 84 self.vt_symbol: str = f"{self.symbol}.{self.exchange.value}"

vt_symbol = "600000.SSE" 这种"全局限定符号" = 本地 symbol + "." + 交易所枚举值。

💡 核心心法:这是 VeighNa 最核心的命名约定。vt_ 前缀代表 "VeighNa Total"(全局)。为什么需要它?因为不同交易所可能有相同的本地 symbol(比如都有叫 "IF2401" 的合约,但一个在 CFFEX 一个在某海外所),光看本地 symbol 无法区分。拼接成 vt_symbol = symbol.exchange.value 后全局唯一,跨交易所不会冲突。

__post_init__ 是 dataclass 的钩子方法,在 __init__ 自动生成后调用。VeighNa 用它自动维护复合主键——使用者只需提供本地字段(symbol/exchange),框架自动拼 vt_symbol,避免上层手工拼接字符串出错。

五、BarData:K 线

object.py:87-108:

87 @dataclass 88 class BarData(BaseData): 93 symbol: str 94 exchange: Exchange 95 datetime: Datetime 97 interval: Interval | None = None # 周期:分钟/小时/日/周/tick volume / turnover / open_interest / open_price / high_price / low_price / close_price 106 def __post_init__(self): 108 self.vt_symbol = f"{self.symbol}.{self.exchange.value}"

标准 OHLCV + 持仓量 + 周期枚举(Interval.MINUTE/HOUR/DAILY/WEEKLY/TICK)。比 TickData 简洁——没有五档盘口(因为 K 线是聚合后的,不再保留逐笔深度)。

interval 的 value 是字符串简写("1m"/"1h"/"d"/"w"/"tick"),用于数据库存储与 UI 显示。第 6 章讲的 BarGenerator 合成的 Bar 就带 interval 字段。

六、行情数据类的使用示例

网关收到行情时构造 TickData:

tick = TickData( symbol="rb2401", exchange=Exchange.SHFE, datetime=datetime.now(), last_price=4200, bid_price_1=4199, bid_volume_1=10, ask_price_1=4201, ask_volume_1=8, gateway_name="CTP" ) # __post_init__ 自动生成:tick.vt_symbol == "rb2401.SHFE"

注意 gateway_name 用关键字传参(因为它来自基类,排在字段顺序最前)。构造后 tick.vt_symbol 自动可用,后续所有缓存/订阅/展示都用这个全局键。

本节要点回顾

  1. BaseData 是所有数据类根,只有 gateway_name(来源)+ extra(运行时扩展)。
  2. extra 用 field(init=False) 不参与构造,留作用户挂载扩展数据。
  3. TickData 字段分五组:标识/静态/OHLC/五档买卖盘(20 字段)/localtime。
  4. vt_symbol = f"{symbol}.{exchange.value}"post_init 自动生成,全局唯一复合主键。
  5. vt_ 前缀 = "VeighNa Total",是全书核心命名约定。
  6. BarData 比 TickData 简洁,带 interval 周期枚举。
  7. Datetime 别名就是标准库 datetime.datetime。

下一节,我们看交易相关的数据类——OrderData/TradeData/PositionData/AccountData,以及它们各自的 vt_ 主键规则。


发布者: 作者: 灏天文库 转发
评论区 (0)
U