3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在聚宽(JoinQuant)平台中,如果策略回测运行缓慢,最直接且官方推荐的方法是使用 性能分析函数 enable_profile()。
这个函数可以帮助你精确地定位每一行代码的执行时间、调用次数以及占用的时间比例。
enable_profile()initialize 之前)添加 enable_profile()。# -*- coding: utf-8 -*-
# 必须放在代码的最前面
enable_profile()
def initialize(context):
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
run_daily(market_open, time='every_bar')
def market_open(context):
# 假设这里有一段耗时的代码
for stock in get_index_stocks('000300.XSHG'):
close_data = attribute_history(stock, 5, '1d', ['close'])
开启后,你会在日志中看到类似下面的输出。重点关注 % Time(时间占比)和 Time(总耗时)这两列。
// 函数名及所在行号
Function: market_open at line 10
// Line #: 行号
// Hits: 该行代码被执行的次数
// Time: 该行代码总共消耗的时间(单位通常是微秒)
// Per Hit: 平均每次执行消耗的时间
// % Time: 该行代码占整个函数执行时间的百分比(最关键的指标)
// Line Contents: 代码内容
Line # Hits Time Per Hit % Time Line Contents
==============================================================
10 def market_open(context):
11 1 25000 25000.0 1.0 stocks = get_index_stocks('000300.XSHG')
12 300 2400000 8000.0 95.0 for stock in stocks:
13 300 2300000 7666.0 90.0 data = attribute_history(stock, 5, '1d', ['close'])
分析逻辑:
% Time 非常高(例如超过 50% 或 80%),说明这里就是性能瓶颈。Hits(执行次数)非常高,说明这行代码在循环中被频繁调用,考虑是否可以移出循环或向量化处理。根据聚宽的机制,导致回测慢的常见原因通常有以下几点:
循环调用数据 API:
for 循环中逐个调用 attribute_history 或 get_price。history(count, unit, field, security_list=股票列表) 可以一次性获取多只股票的数据,返回 DataFrame,效率远高于循环获取。频繁的 IO 操作:
handle_data 中频繁读写文件或进行复杂的日志输出(log.info 过于频繁)。重复计算:
initialize 或 run_daily 的开盘前函数中,并存储在 g 全局变量里。Pandas/Numpy 使用不当:
df.append),这非常耗时。要找出耗时代码,请立即在策略第一行加上 enable_profile() 并运行一个短周期的回测。定位到具体行数后,针对性地优化数据获取方式(从循环改为批量获取)通常能带来最大的性能提升。
Q: enable_profile() 可以在模拟交易(实盘模拟)中使用吗?
A: 不可以。enable_profile() 是回测环境专用的 API。在模拟交易中开启会报错或无效,且模拟交易本身对性能要求不同,通常不需要此类细粒度的代码行级分析。
Q: 为什么开启 enable_profile() 后,回测速度变得更慢了?
A: 这是正常的。性能分析工具需要监控每一行代码的执行并记录时间,这本身会带来巨大的系统开销。因此,该功能仅用于诊断阶段。找到问题并修改代码后,务必删除或注释掉 enable_profile() 再进行全量回测。
Q: 遇到 TimeoutError: function runs more than 1800 seconds 怎么办?
A: 这说明你的策略在某个时间单位(如一天或一分钟)内的计算量太大,超过了聚宽平台的单次运行限制。解决方法是:1. 使用 enable_profile() 找出耗时点并优化;2. 如果是初始化计算量大,尝试将计算分散到每天的 before_trading_start 中;3. 减少不必要的循环和数据查询。