问题描述
新人,求教为什么使用def 定义的函数名不可随意设置,比如initialize(context)就不可以自定义为init(context),学习python自定义函数的时候函数名不应该是任意设置的嘛?另外为什么定义initialize程序就只会执行一次,这些函数是有什么内在的规则嘛?
解决方案
你好!这是一个非常好的问题,很多刚从纯 Python 学习过渡到量化框架的新手都会有这个疑惑。简单来说,这是因为 JoinQuant 平台底层引擎的“回调机制(Callback)” 决定的。
1. 为什么函数名不能随意更改?
在纯 Python 编程中,你确实可以随意命名自己定义的函数,只要符合命名规范即可。因为在纯 Python 脚本中,是你自己写代码去调用这些函数(比如你定义了 init(),然后你在代码最后写一行 init() 去执行它)。
但在 JoinQuant 这样的量化交易框架中,情况发生了**“控制反转”**:
不是你去调用这些函数,而是平台的底层回测引擎在特定的时间点自动来调用你的函数。
为了让底层引擎知道“在回测刚开始时该执行哪段代码”、“在每天开盘时该执行哪段代码”,平台**硬性规定(约定)**了几个特定的函数名。引擎在运行时,会去你的代码里寻找这些特定名字的函数:
- 引擎启动时,它会寻找名为
initialize的函数并执行。 - 如果找不到
initialize,它可能就会报错或者跳过初始化步骤。 - 如果你把它改成了
init,引擎并不认识init,它依然只会去寻找initialize,所以你的初始化代码就不会被执行。
2. 为什么 initialize 只执行一次?
这也是由底层引擎的规则决定的。JoinQuant 的策略程序架构中,不同的保留函数有不同的触发时机和执行频率:
-
initialize(context)(初始化函数):- 规则:在整个回测或模拟交易最开始时,且仅执行一次。
- 用途:用于设置基准、设置滑点手续费、定义全局变量(如
g.security)、注册定时运行函数(run_daily)等。
-
handle_data(context, data)(盘中运行函数):- 规则:根据你设置的回测频率,每个单位时间调用一次(按天回测则每天调用一次,按分钟回测则每分钟调用一次)。
- 用途:编写主要的交易逻辑、买卖下单等。
-
before_trading_start(context)(开盘前运行函数):- 规则:每天开始交易前(09:00)被调用一次。
- 用途:获取昨日收盘数据、更新当天的股票池等。
-
after_trading_end(context)(收盘后运行函数):- 规则:每天结束交易后(15:30)被调用一次。
- 用途:盘后计算、打印当天的收益日志等。
3. 我还能自定义函数吗?
当然可以! 除了上述平台保留的特定函数名之外,你完全可以按照学习 Python 时的习惯,随意定义自己的函数。比如:
# 这是你自定义的函数,名字随便起
def my_custom_stock_filter(context):
# 写一些选股逻辑
return ['000001.XSHE', '000002.XSHE']
# 这是平台规定的函数,名字不能改
def initialize(context):
# 在平台规定的函数中,调用你自定义的函数
g.my_stocks = my_custom_stock_filter(context)
总结:
initialize、handle_data 等是 JoinQuant 框架的**“接口”或“钩子(Hook)”**,你必须按照框架的命名规则来写,框架才能正确地在对应的时间点驱动你的策略运行。而在这之外,你依然可以自由地编写自定义函数来辅助你的策略逻辑。