🚀 AI 一键生成 joinquant 策略代码

JoinQuant handle_data 中的 data 对象详解:mavg, vwap, stddev 等方法应用

joinquant | 发布时间: 2025/12/9
以下内容由 EasyQuant 生成。

问题描述

handle_data 函数里的 data 参数具体是什么?怎么用它来计算移动平均线?

解决方案

在 JoinQuant(聚宽)的策略回测框架中,handle_data(context, data) 是核心的策略执行函数。以下是关于 data 参数的详细解释以及如何使用它计算移动平均线的说明。

1. data 参数具体是什么?

data 是一个字典形式的对象(Dictionary-like Object),它包含了当前单位时间(按天回测是前一天,按分钟回测是前一分钟)的行情数据快照。

  • 键 (Key):标的代码(例如 '000001.XSHE')。
  • 值 (Value)SecurityUnitData 对象。

当你使用 data['000001.XSHE'] 时,你获取的是该标的在当前时间点的 SecurityUnitData 对象。这个对象包含以下常用属性和方法:

  • 基本属性open, close, high, low, volume, money, high_limit, low_limit, paused 等。
  • 内置计算方法mavg() (移动平均), vwap() (加权平均), stddev() (标准差)。

注意:为了提高回测速度,data 中的数据是按需获取(Lazy Loading)的。只有当你代码中明确调用 data[security] 时,系统才会去获取该标的的数据。

2. 如何使用 data 计算移动平均线?

SecurityUnitData 对象内置了一个便捷方法 mavg,可以直接用来计算移动平均线。

语法

data[security].mavg(days, field='close')
  • days:计算平均线的时间窗口长度(例如 5 表示 5日均线)。
  • field:基于哪个字段计算,默认为 'close'(收盘价),也可以是 'volume'(成交量)等。

3. 代码示例

下面是一个完整的策略代码示例,展示了如何在 handle_data 中使用 data 参数来获取 5日均线 和 10日均线,并打印出来。

# -*- coding: utf-8 -*-
def initialize(context):
    # 定义一个全局变量, 保存要操作的股票
    g.security = '000001.XSHE'
    # 设置股票池
    set_universe([g.security])
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)

def handle_data(context, data):
    security = g.security
    
    # 1. 获取 SecurityUnitData 对象
    # 注意:如果股票停牌或未上市,data[security] 可能无法获取有效数据,建议先检查
    if security in data:
        stock_data = data[security]
        
        # 2. 使用 .mavg() 方法计算移动平均线
        # 计算过去5天的收盘价平均值
        ma5 = stock_data.mavg(5, field='close')
        
        # 计算过去10天的收盘价平均值
        ma10 = stock_data.mavg(10, field='close')
        
        # 3. 获取当前结束时的收盘价
        current_close = stock_data.close
        
        # 打印结果
        log.info("股票: %s, 当前价: %.2f, MA5: %.2f, MA10: %.2f" % (security, current_close, ma5, ma10))
        
        # 简单的策略逻辑示例:金叉买入
        if ma5 > ma10 and context.portfolio.positions[security].total_amount == 0:
            order_value(security, context.portfolio.available_cash)
            log.info("金叉买入")
            
        # 死叉卖出
        elif ma5 < ma10 and context.portfolio.positions[security].total_amount > 0:
            order_target(security, 0)
            log.info("死叉卖出")

4. 补充说明:另一种计算方式(推荐)

虽然 data[security].mavg() 很方便,但在复杂的策略中,通常建议使用 attribute_history 函数配合 pandasnumpy 来计算指标。这种方式更灵活,且能处理更复杂的逻辑(如计算 MACD、KDJ 等)。

使用 attribute_history 计算均线的示例:

# 获取过去5天的收盘价数据(DataFrame格式)
history_data = attribute_history(g.security, 5, '1d', ['close'])
# 计算均值
ma5 = history_data['close'].mean()

Q&A

Q: data 参数里包含当天的数据吗?
A: 不包含。在回测中,为了避免“未来函数”,handle_data 中的 data 获取的是前一个单位时间的数据。如果是按天回测,data 是昨天的收盘数据;如果是按分钟回测,data 是上一分钟的数据。如果需要当天的开盘价或实时涨跌停价,请使用 get_current_data()

Q: data[security].mavg(5) 会包含停牌的日期吗?
A: mavg 方法会自动跳过停牌日期。如果历史交易天数不足(例如刚上市),可能会返回 nan

Q: 为什么有时候调用 data[security] 会报错?
A: 如果该股票在当前时间点已退市、未上市,或者不在你的 set_universe(股票池)设置范围内(虽然现在 set_universe 已主要用于 history 默认参数,但保持良好的股票池设置习惯很重要),可能会导致获取不到数据。建议在使用前判断 if security in data: