问题描述
在API文档中关于on_event事件回调函数有这段话:
“用户在策略中定义on_event,在账户中持仓的标的发生对应的事件时on_event会被调用。建议用户使用isinstance对事件类型进行判断。 目前已支持的事件有:
DividendsEvent:分红送股事件
ForcedLiquidationEvent:强行平仓事件
”
但是,用 if isinstance(event, DividendsEvent) 会报错,
NameError: name 'DividendsEvent' is not defined。
那应该如何用isinstance判断事件类型呢?
解决方案
在 JoinQuant (聚宽) 平台中,使用 on_event 函数处理事件回调时,如果直接使用 isinstance(event, DividendsEvent) 遇到 NameError: name 'DividendsEvent' is not defined 的报错,是因为在当前的代码作用域中没有导入这些事件类。
要解决这个问题,有以下两种常用的方法:
方法一:显式导入事件类(推荐)
在使用 isinstance 进行判断之前,你需要先从 jqdata 模块中导入对应的事件类。在策略的开头添加导入语句即可:
# 导入聚宽函数库及事件类
import jqdata
from jqdata import DividendsEvent, ForcedLiquidationEvent
def initialize(context):
# 策略初始化代码
g.security = '000001.XSHE'
order(g.security, 1000)
# 定义事件回调函数
def on_event(context, event):
# 使用 isinstance 进行判断
if isinstance(event, DividendsEvent):
log.info("发生分红送股事件!")
log.info("标的: %s, 分红信息: %s" % (event.security, event.dividends))
elif isinstance(event, ForcedLiquidationEvent):
log.info("发生强行平仓事件!")
log.info("标的: %s, 平仓数量: %s" % (event.security, event.amount))
方法二:通过类名字符串判断(无需导入)
如果你不想额外导入类,也可以通过 Python 内置的 type(event).__name__ 来获取事件对象的类名字符串,然后进行比对。这种方法同样有效且不会引发 NameError:
def on_event(context, event):
# 获取事件的类名字符串
event_type = type(event).__name__
if event_type == 'DividendsEvent':
log.info("发生分红送股事件!")
# 处理分红逻辑
elif event_type == 'ForcedLiquidationEvent':
log.info("发生强行平仓事件!")
# 处理强平逻辑
补充说明:事件对象的属性
为了更好地处理事件,了解事件对象包含哪些属性非常重要:
1. DividendsEvent (分红送股事件)
event.security: 发生分红的标的代码。event.dividends: 分红配送信息,是一个字典列表(通常只有一个元素)。例如:event.dividends[0]['bonus_pre_tax']: 税前分红event.dividends[0]['scale_factor']: 配送股比例
2. ForcedLiquidationEvent (强行平仓事件)
event.security: 被强平的标的代码。event.amount: 平仓数量。event.side: 仓位方向('long' 或 'short')。
建议使用方法一,因为使用 isinstance 是 Python 中判断对象类型的最标准和优雅的方式,同时也有利于代码的自动补全和类型检查。