Ptrade 框架的 data 对象解析

阿凡
阿凡 2025,大牛市快来了 V:flj99103681

1 人点赞了该文章 · 41 浏览

1. 什么是 data 对象

在 ptrade 量化交易框架中,handle_data(context, data) 是策略的核心回调函数之一。data 是一个 BarDict(字典容器)对象,包含了当前时间点的市场数据。

def handle_data(context, data):
    # data 是 BarDict 类型
    print(type(data))  # <class 'IQEngine.plugins.plugin_fly_data.local_variables.bar.BarDict'>

2. BarDict 对象结构

从调试输出可以看到:

BarDict 类的方法和属性:
- __class__        # 类类型
- __contains__     # 支持 'in' 操作符
- __delattr__      # 删除属性
- __dir__          # 列出所有可用属性
- __doc__          # 文档字符串
- __eq__           # 相等比较
- __format__       # 格式化
- __ge__           # 大于等于比较
- __getattribute__ # 获取属性
- __getitem__      # 支持 [] 访问,如 data[security]
- __getstate__     # 序列化状态
- __gt__           # 大于比较
- __hash____       # 哈希值
- __init__         # 初始化
- __le__           # 小于等于比较
- __len__          # 支持 len() 获取长度
- __lt__           # 小于比较
- __module__       # 模块信息
- __ne__           # 不等比较
- __new__          # 创建实例
- __reduce__       # 序列化
- __reduce_ex__    # 序列化
- __repr__         # 字符串表示
- __setattr__      # 设置属性
- __sizeof__       # 对象大小
- __str__          # 字符串转换
- _cache           # 内部缓存
- _dt              # 时间信息
- _engine          # 引擎引用
- _frequency       # 频率信息
- dt               # 当前bar的时间戳
- items            # 字典的 items() 方法
- keys             # 字典的 keys() 方法
- start_date_tmp   # 起始时间
- update_dt        # 更新时间
- values           # 字典的 values() 方法

3. BarData 对象(单个证券的数据)

当你通过 data[security] 访问单个证券时,得到的是 BarData 对象:

bar = data['600570.SS']
# bar 的类型: <class 'IQEngine.plugins.plugin_fly_data.local_variables.bar.BarData'>

3.1 BarData 包含的字段

字段名

类型

说明

示例值

dt

datetime

当前bar的时间戳

2026-04-14 13:46:00

is_open

int

是否开盘(1=是,0=否)

1

money

float

成交额(单位:元)

nan 或具体数值

pre_close

float

前收盘价

26.69

price

float

当前价格

26.57

returns

float

收益率(本期/上期-1)

-0.0045

sid

str

证券代码

600570.SS

3.2 调试输出示例

=== 600570.SS ===
  类型: <class 'IQEngine.plugins.plugin_fly_data.local_variables.bar.BarData'>
  dt: 2026-04-14 13:46:00
  is_open: 1
  money: nan
  pre_close: 26.69
  price: 26.57
  returns: -0.0044960659423005245
  sid: 600570.SS

4. 常用访问方法

4.1 获取所有证券代码

def handle_data(context, data):
    # 方法1: 使用 keys()
    securities = data.keys()
    print(list(securities))  # ['600570.SS']

    # 方法2: 使用 len()
    print(len(data))  # 证券数量

    # 方法3: 使用 in 检查是否存在
    if '600570.SS' in data:
        print("600570.SS 存在")

4.2 获取单个证券数据

def handle_data(context, data):
    # 方法1: 直接使用证券代码访问
    bar = data['600570.SS']

    # 方法2: 先检查存在性再访问
    if '600570.SS' in data:
        bar = data['600570.SS']

    # 方法3: 遍历所有证券
    for security in data.keys():
        bar = data[security]
        print(f"{security}: {bar.price}")

4.3 遍历所有证券数据

def handle_data(context, data):
    # 方法1: 遍历 items()
    for security, bar in data.items():
        print(f"证券: {security}")
        print(f"价格: {bar.price}")
        print(f"时间: {bar.dt}")

    # 方法2: 遍历 keys() 再访问
    for security in data.keys():
        bar = data[security]
        print(f"{security}: {bar.price}")

5. 实际使用示例

5.1 基础价格获取

def initialize(context):
    g.security = "600570.SS"
    set_universe(g.security)

def handle_data(context, data):
    bar = data[g.security]

    # 获取当前价格
    current_price = bar.price
    # 获取前收盘价
    prev_close = bar.pre_close
    # 获取收益率
    returns = bar.returns

    # 计算涨跌幅
    if prev_close > 0:
        change_pct = (current_price - prev_close) / prev_close
        print(f"涨跌幅: {change_pct:.2%}")

    # 获取时间
    current_time = bar.dt
    print(f"当前时间: {current_time}")

5.2 多证券组合

def initialize(context):
    g.securities = ["600570.SS", "510300.SS"]
    set_universe(g.securities)

def handle_data(context, data):
    for security in g.securities:
        if security in data:
            bar = data[security]
            print(f"{security}: 价格={bar.price}, 收益率={bar.returns:.2%}")

5.3 价格异常检测

def handle_data(context, data):
    bar = data[g.security]

    # 检测价格是否有效
    if bar.price > 0 and bar.pre_close > 0:
        change_pct = abs(bar.price - bar.pre_close) / bar.pre_close

        # 涨幅超过5%报警
        if change_pct > 0.05:
            print(f"价格异常波动: {change_pct:.2%}")

6. 常见问题

Q1: money 字段是 nan?

# 答:部分bar数据可能没有成交额,特别是:
# 1. 分钟级数据可能不提供money字段
# 2. 特定证券在某些时段没有成交

# 建议添加判断
if bar.money and not math.isnan(bar.money):
    print(f"成交额: {bar.money}")
else:
    print("成交额数据不可用")

Q2: 如何判断是否开盘?

# 使用 is_open 字段
if bar.is_open == 1:
    print("当前处于交易时段")
else:
    print("当前非交易时段(如停牌、涨跌停等)")


7. 完整调试代码

如果想查看 data 对象的所有可用信息,可以使用以下调试代码:

def handle_data(context, data):
    print("=" * 60)
    print(f"data 类型: {type(data)}")
    print(f"data keys: {list(data.keys())}")

    for security, bar in data.items():
        print(f"\n--- {security} ---")
        print(f"  dt: {bar.dt}")
        print(f"  price: {bar.price}")
        print(f"  pre_close: {bar.pre_close}")
        print(f"  returns: {bar.returns}")
        print(f"  is_open: {bar.is_open}")
        print(f"  money: {bar.money}")
        print(f"  sid: {bar.sid}")

        # 计算涨跌幅
        if bar.pre_close > 0:
            change = (bar.price - bar.pre_close) / bar.pre_close
            print(f"  涨跌幅: {change:.2%}")
    print("=" * 60)

8. 总结

概念

说明

BarDict

data 参数的类型,类似于字典

BarData

单个证券的数据对象

访问方式

data[security]data.items()

核心字段

price, pre_close, returns, dt, is_open

提示: 在使用前养成检查字段是否为 nanNone 的习惯,避免计算错误。

发布于 1 天前

免责声明:

本文由 阿凡 原创发布于 百果量化交流平台 ,著作权归作者所有。

登录一下,更多精彩内容等你发现,贡献精彩回答,参与评论互动

登录! 还没有账号?去注册

暂无评论