问题描述
解决方案
在 JoinQuant(聚宽)量化平台中,data 是一个非常经典的概念,主要出现在 handle_data(context, data) 函数中。下面为您详细解答 data 的含义、使用场景,以及不使用 data 的区别。
1. data 是什么意思?
在聚宽的 API 中,data 是一个字典(dict)类型的对象,它的 key 是标的代码(如 '000001.XSHE'),value 是当时的 SecurityUnitData 对象。
它存放的是前一个单位时间(按天回测就是前一天,按分钟回测就是前一分钟)的数据快照。通过 data[security],你可以获取该标的在当时的开盘价、收盘价、最高价、最低价、成交量、是否停牌等信息,甚至可以直接调用内置方法计算均价。
常用的属性和方法包括:
data[security].close: 结束时价格(收盘价)data[security].open: 开始时价格(开盘价)data[security].volume: 成交量data[security].paused: 是否停牌(True/False)data[security].mavg(days): 过去 days 天的每天收盘价的平均值
2. 什么场景用 data?(举个例子)
通常在早期的策略编写中,我们会在 handle_data 中使用 data 来快速获取当前价格或计算均线,从而生成交易信号。
示例:使用 data 编写一个简单的双均线策略
def initialize(context):
g.security = '000001.XSHE'
# handle_data 每天/每分钟自动运行一次
def handle_data(context, data):
security = g.security
# 场景1:判断股票今天是否停牌,停牌则不操作
if data[security].paused:
return
# 场景2:获取当前价格(上一单位时间结束时的价格)
current_price = data[security].close
# 场景3:利用 data 自带的方法快速计算 5日 和 10日 均线
ma5 = data[security].mavg(5)
ma10 = data[security].mavg(10)
# 产生交易信号
if ma5 > ma10 and context.portfolio.positions[security].closeable_amount == 0:
order_value(security, context.portfolio.available_cash)
elif ma5 < ma10 and context.portfolio.positions[security].closeable_amount > 0:
order_target(security, 0)
3. 不写 data 会有什么不同?(官方推荐做法)
非常重要的一点: 聚宽官方文档明确指出,为了向前兼容保留了 data 对象,但由于效率问题,现在已经不推荐使用了!
现在的标准写法是使用 run_daily 等定时运行函数,这些自定义函数只接收 context 一个参数,没有 data 参数。如果不使用 data,你需要使用聚宽提供的专门的数据获取 API(如 attribute_history、get_price、get_current_data 等)来替代。
不写 data 的不同之处:
- 代码结构不同:不再使用
handle_data,而是用run_daily绑定自定义函数。 - 获取数据方式不同:不能再用
data[security].close,而是用attribute_history或get_current_data。 - 运行效率更高:
data对象在底层是按需动态生成的,频繁调用会拖慢回测速度;而直接使用attribute_history批量获取数据(如 Pandas DataFrame)效率高得多。
示例:不使用 data 的现代写法(推荐)
def initialize(context):
g.security = '000001.XSHE'
# 使用定时函数,每天开盘时运行 market_open
run_daily(market_open, time='09:30')
# 自定义函数只有 context 参数,没有 data
def market_open(context):
security = g.security
# 替代场景1:使用 get_current_data 判断是否停牌
current_data = get_current_data()
if current_data[security].paused:
return
# 替代场景2 & 3:使用 attribute_history 获取历史收盘价来计算均线和当前价
# 获取过去10天的收盘价数据
hist = attribute_history(security, 10, '1d', ['close'])
# 当前价格(取最后一天)
current_price = hist['close'][-1]
# 计算均线(利用 Pandas 的 mean 方法)
ma5 = hist['close'][-5:].mean()
ma10 = hist['close'].mean()
# 产生交易信号
if ma5 > ma10 and context.portfolio.positions[security].closeable_amount == 0:
order_value(security, context.portfolio.available_cash)
elif ma5 < ma10 and context.portfolio.positions[security].closeable_amount > 0:
order_target(security, 0)
总结
data是什么:历史遗留的标的数据快照对象,包含价格、成交量和简单的均线计算方法。- 使用场景:在
handle_data中快速获取单只股票的当前状态和简单指标。 - 不写
data的区别:你需要改用run_daily配合attribute_history/get_current_data等 API。这是目前官方强烈推荐的做法,因为它的执行效率更高,且更适合进行多只股票的向量化(Pandas)计算。