问题描述
我在运行量化策略时出现了奇怪的问题,我想问问这个怎么解决。
首先,我在研究里创建了一个mydata.py文件,想在这个文件里写一些需要重复使用的函数。于是我使用from jqdata import *语句导入了jqdata函数库,并在其中定义了一个函数func(),其中调用了jqdata函数库里的两个函数,分别是get_trade_days()与get_all_securities()。
然后,我在我的量化策略里导入了mydata模块并调用了func()函数。但量化策略编译运行时却出现了奇怪的现象,就是通过func()函数调用的get_trade_days()函数可以正常运行,但紧接着调用get_all_securities()函数时却出现了报错:
NameError: name 'get_all_securities' is not defined
也就是通过研究里面的文件导入的jqdata函数库找不到get_all_securities()函数,但是却可以找到get_trade_days()函数,我想问问这是怎么回事,是不是聚宽系统的bug?
解决方案
这不是聚宽系统的 bug,而是由于研究环境与回测环境的 API 命名空间差异导致的。
在 JoinQuant 平台中,get_trade_days() 属于纯数据获取接口,包含在 jqdata 模块中;而 get_all_securities() 等函数不仅是数据接口,还属于策略与回测环境的全局 API。当你在研究环境的根目录下创建自定义的 .py 文件(如 mydata.py)时,仅仅使用 from jqdata import * 是无法导入所有策略环境专用的 API 的。
解决方法
要在自定义的 Python 库文件中使用策略及数据相关的全局 API(如 get_all_securities、history、order 等),你需要显式地导入 kuanke.user_space_api 模块。
请在你的 mydata.py 文件的开头加上以下导入语句:
# -*- coding: utf-8 -*-
# 如果你的文件包含中文, 请在文件的第一行使用上面的语句指定文件编码
from jqdata import *
# 导入策略及数据相关全局 API
# 为了兼容研究环境和回测环境,建议使用 try...except 导入
try:
from kuanke.user_space_api import *
except ImportError:
pass
def func():
# 现在可以正常调用了
days = get_trade_days()
securities = get_all_securities()
return days, securities
为什么需要这样导入?
在回测环境的主代码编辑区,系统在底层已经自动为你注入了 kuanke.user_space_api 中的所有函数,所以你可以直接调用。但是,当你通过 import mydata 引入你自己写的外部模块时,Python 的模块隔离机制使得 mydata.py 无法自动获取这些注入的全局函数。因此,必须在 mydata.py 内部手动导入 kuanke.user_space_api,才能让该文件识别到 get_all_securities 等函数。
修改导入语句后,重新编译运行你的量化策略,报错就会消失了。