问题描述
解决方案
在 PTrade 策略中,handle_data(context, data) 是策略的核心驱动函数,其中 data 参数是一个非常关键的数据容器。
以下是关于 data 参数的详细解释以及获取开盘价和收盘价的代码示例。
1. data 参数具体是什么?
- 数据类型:
data是一个字典 (dict)。 - 键 (Key):字典的键是标的代码(字符串,例如
'600570.SS')。 - 值 (Value):字典的值是一个
SecurityUnitData对象。这个对象包含了该标的在当前运行周期(如当前这一分钟或当前这一天)的行情数据。 - 数据范围:为了提高运行效率,
data中只包含你在initialize函数中通过set_universe()设置的股票池中的标的数据。
2. 如何获取开盘价和收盘价?
你可以通过 data['股票代码'] 获取该股票的数据对象,然后通过访问该对象的属性来获取具体价格。
SecurityUnitData 对象包含以下常用属性:
.open:时间段开始时的价格(开盘价).close:时间段结束时的价格(收盘价).high:最高价.low:最低价.volume:成交量.money:成交金额.price:最新价(通常等于 close).dt:时间戳
3. 代码示例
以下是一个完整的策略示例,展示了如何在 handle_data 中解析 data 并打印开盘价和收盘价。
def initialize(context):
# 1. 初始化股票池,必须设置 set_universe,否则 data 中不会有数据
g.security = '600570.SS' # 恒生电子
set_universe(g.security)
def handle_data(context, data):
# 2. 检查股票是否在 data 字典中(防止停牌或未上市导致报错)
if g.security in data:
# 3. 获取该股票的 SecurityUnitData 对象
stock_data = data[g.security]
# 4. 获取开盘价和收盘价
# 注意:如果是日线回测,close 为当日收盘价;如果是分钟回测,close 为该分钟收盘价
open_price = stock_data.open
close_price = stock_data.close
# 5. 获取其他数据(可选)
high_price = stock_data.high
low_price = stock_data.low
volume = stock_data.volume
# 打印结果
log.info("代码: %s, 时间: %s" % (g.security, context.blotter.current_dt))
log.info("开盘价: %.2f, 收盘价: %.2f" % (open_price, close_price))
log.info("最高价: %.2f, 最低价: %.2f, 成交量: %.0f" % (high_price, low_price, volume))
else:
log.info("%s 当前无数据(可能停牌或不在股票池中)" % g.security)
4. 注意事项
- 依赖
set_universe:data只会推送你订阅的股票。如果你没有在initialize中调用set_universe(['股票A', '股票B']),那么data字典里将找不到这些股票的数据。 - 当前周期数据:
data提供的是当前切片的数据。- 如果你跑的是日线回测,
data里就是当天的日线数据(开高低收)。 - 如果你跑的是分钟回测,
data里就是当前这一分钟的 K 线数据。
- 如果你跑的是日线回测,
- 历史数据:如果你需要获取过去 N 天的数据(例如计算 5 日均线),不能只用
data,而应该使用get_history()或get_price()函数。
Q&A 常见问题解答
Q: data 中的 .price 和 .close 有什么区别?
A: 在大多数情况下,它们是相同的,都代表当前周期的结束价格。但在某些特定语境下(如盘中实时撮合),price 更强调“最新成交价”,而 close 指的是该 K 线周期的收盘价。在 PTrade 的 handle_data 中,通常可以互换使用。
Q: 如果股票停牌了,data 中还会有数据吗?
A: 如果股票停牌,通常 data 中可能不会包含该股票的 key,或者其数据状态会标识为停牌。因此,代码中建议使用 if security in data: 进行判断,以增强策略的健壮性。
Q: 我可以直接打印 data 来看里面的内容吗?
A: 可以,使用 log.info(data) 即可。但由于 data 包含的是对象引用,直接打印可能只会显示对象的内存地址或简略信息,建议打印具体的字段(如 data[security].close)。