问题描述
handle_data和按分钟策略run_daily+every_bar哪个先执行?
另外,这二者是不是达到的效果一样?
最主要的是,我能设定哪个先运行哪个后运行吗?
解决方案
在 JoinQuant (聚宽) 量化平台中,关于 handle_data 和 run_daily(..., time='every_bar') 的执行机制,官方文档有明确的规定。以下是针对您三个问题的详细解答:
1. 哪个先执行?
run_daily 先执行。
根据 JoinQuant API 文档的说明:“同一个时间点, 总是先运行 run_xxx 指定的函数, 然后是 before_trading_start , handle_data 和 after_trading_end”。
因此,在每一分钟(或每一天)的同一个 Bar 触发时,通过 run_daily(func, time='every_bar') 注册的函数会优先于 handle_data 执行。
2. 这二者达到的效果一样吗?
触发频率和基本效果是一样的,但官方推荐使用 run_daily。
- 触发频率相同:在按分钟回测/模拟时,两者都会在每分钟的 Bar 结束时(即每分钟的第一秒)被调用一次。
- 官方建议:文档中明确指出:“一个策略中尽量不要同时使用 run_daily 和 handle_data,建议使用 run_daily”。
run_daily提供了更高的灵活性,不仅可以设置为every_bar,还可以精确到具体的时分秒(如time='14:50'),而handle_data只能被动跟随全局频率触发。
3. 能否设定哪个先运行哪个后运行?
不能直接修改系统底层的触发顺序,且不建议依赖注册顺序。
- 系统底层已经写死了
run_xxx优先于handle_data的执行顺序,您无法将其反转。 - 即使您使用多个
run_daily注册了多个函数,文档也强调:“用户策略不应该依赖于这些计划任务执行的顺序。”
最佳实践(如何严格控制执行顺序):
如果您有严格的先后执行逻辑需求,请放弃使用 handle_data,并将所有逻辑封装在普通的 Python 函数中,然后通过一个 run_daily 调用的主函数来按顺序执行它们。例如:
def initialize(context):
# 只注册一个 every_bar 的定时任务
run_daily(main_logic, time='every_bar')
def main_logic(context):
# 在这里严格控制执行顺序
step_one_logic(context) # 先执行逻辑1
step_two_logic(context) # 后执行逻辑2
def step_one_logic(context):
# 您的第一步逻辑
pass
def step_two_logic(context):
# 您的第二步逻辑
pass
通过这种方式,您可以 100% 掌控代码的执行顺序,避免因平台底层调度机制带来的不确定性。