🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

JoinQuant量化平台:回测必须实现handle_data函数吗?

joinquant | 发布时间: 2026/6/3
以下内容由 EasyQuant 生成。

问题描述

回测必须实现『handle_data』函数吗?

我发现不用『handle_data』函数,直接使用定时函数(类似如下代码),也可以进行回测,请问两者有何不同?

# 开盘前运行
run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')

# 开盘时运行
run_daily(market_open, time='open', reference_security='000300.XSHG')
# 收盘后运行
run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')

解决方案

在 JoinQuant(聚宽)平台上,回测并不是必须实现 handle_data 函数的。实际上,官方更推荐使用 run_daily 等定时函数来构建策略。

以下是 handle_datarun_daily 等定时函数的详细区别和使用建议:

1. 触发机制的不同

  • handle_data(context, data)

    • 这是一个被动触发的函数,它的执行频率完全依赖于你在回测页面设置的“回测频率”(按天或按分钟)。
    • 如果按天回测,它每天在交易时间(通常是 9:30)调用一次;如果按分钟回测,它在交易时间内每分钟调用一次。
    • 注意:Tick 频率的回测不支持 handle_data 函数。
  • run_daily / run_weekly / run_monthly

    • 这是主动设定的定时任务函数,具有极高的灵活性。
    • 你可以精确指定函数在每天的哪个具体时间点执行(例如 time='09:30'time='14:50'),甚至可以指定在开盘前(如 09:00)或收盘后(如 15:30)执行。
    • 它允许你在同一个策略中注册多个不同的函数在不同的时间点运行,非常适合复杂的业务逻辑(如早盘选股、盘中风控、尾盘调仓)。

2. 参数传递的不同

  • handle_data(context, data)

    • 接收两个参数:context(账户和上下文信息)和 data(当前单位时间的标的数据)。
    • 历史遗留问题data 参数是为了早期兼容性保留的,官方文档指出,为了加速,data 里面的数据是按需获取的。现在更推荐使用 get_pricehistoryget_current_data 等全局 API 来获取数据。
  • run_daily(func, time, ...) 指定的回调函数

    • 你自定义的回调函数(如你代码中的 market_open只能有一个参数 context
    • 获取数据时,直接在函数体内使用 history()get_current_data() 等 API 即可,代码更加清晰。

3. 官方最佳实践建议

根据 JoinQuant 官方 API 文档的建议:

  1. 推荐使用 run_daily:为了避免换算错误和逻辑混乱,建议设置 time 为具体的时间(例如:time='9:30'),并使用 run_daily 等定时函数。
  2. 不要混用:一个策略中尽量不要同时使用 run_dailyhandle_data,更不能写出 run_daily(handle_data, "xx:xx") 这样的代码。
  3. 可选实现initialize / before_trading_start / after_trading_end / handle_data 都是可选的。如果不是必须的,不要实现这些函数,一个空函数反而会降低运行速度。

总结

你发现的用法是非常正确且现代的。使用 run_daily 配合自定义函数(如 before_market_open, market_open, after_market_close)能够让你的策略时间轴更加清晰,逻辑解耦得更好,这也是目前量化策略编写的主流和推荐方式。完全可以抛弃 handle_data