问题描述
如果希望获取每分钟bar数据,在handle_date中使用get_bars获取,但由于handle_date并不包括11:30和15:00这两分钟,所以导致这两分钟无法获取bar数据。
问题一:请问为什么handle_date不包含11:30和15:00这两分钟呢?
问题二:该如何获取这两分钟的bar数据呢?
解决方案
您好!关于您在 JoinQuant 聚宽平台使用 handle_data 和 get_bars 时遇到的时间点触发问题,以下是详细的解答:
问题一:为什么 handle_data 不包含 11:30 和 15:00 这两分钟?
这与 JoinQuant 引擎的底层设计以及 A 股的交易时间划分有关。
根据 JoinQuant 的 API 文档说明:
按分钟回测/模拟,在每分钟的第一秒运行,每天执行 240 次,不包括 11:30 和 15:00 这两分钟,data 是上一分钟的分钟数据。
具体原因如下:
- K 线的定义(后对齐):聚宽的 K 线数据是后对齐的。例如,09:31 的 K 线,代表的是 09:30:00 到 09:30:59 这一分钟的交易数据。因此,每天的第一根分钟 K 线是 09:31,最后一根是 15:00。
- 触发机制:
handle_data是在每分钟的开始触发的。每天的 240 次触发时间点分别是09:30到11:29(共 120 次),以及13:00到14:59(共 120 次)。 - 收盘时刻没有盘中触发:11:30 和 15:00 是中午和下午的收盘时刻。在 11:30:00 产生的是 11:29:00-11:29:59 的 K 线(标记为 11:30),此时盘面已经休息,引擎不会在 11:30 触发盘中回调。同理,15:00 是全天收盘,引擎会在收盘后执行
after_trading_end,而不会再触发handle_data。
简单来说,handle_data 是用来在交易时段内做决策的,而 11:30 和 15:00 已经是休市状态,因此不会触发。
问题二:该如何获取这两分钟的 bar 数据呢?
虽然 handle_data 不在这两分钟触发,但这两分钟的 K 线数据是真实存在的。您可以通过以下几种方式获取:
方法 1:在下一个交易时段的开始获取(推荐)
11:30 的 K 线可以在 13:00 触发时获取;15:00 的 K 线可以在收盘后的函数中获取。
def handle_data(context, data):
# 当时间是 13:00 时,获取到的最新一根 1m K线就是 11:30 的
if context.current_dt.strftime('%H:%M') == '13:00':
bars = get_bars('000001.XSHE', count=1, unit='1m', fields=['date', 'close'])
log.info("获取到 11:30 的数据: %s" % bars)
def after_trading_end(context):
# 15:00 的数据在收盘后获取
bars = get_bars('000001.XSHE', count=1, unit='1m', fields=['date', 'close'])
log.info("获取到 15:00 的数据: %s" % bars)
方法 2:使用 run_daily 定时任务
如果您希望在特定的时间点准时处理,可以放弃 handle_data,改用 run_daily 来精确控制运行时间。
def initialize(context):
# 盘中每分钟运行(等同于 handle_data)
run_daily(my_handle, time='every_bar')
# 专门针对 11:30 和 15:00 之后的时间点设置定时任务
# 注意:11:30 和 15:00 刚收盘,建议稍微延后一点点获取,或者在收盘后函数中获取
run_daily(get_1130_data, time='13:00') # 13:00 开盘时获取上午最后一分钟
run_daily(get_1500_data, time='15:30') # 收盘后获取全天最后一分钟
def my_handle(context):
# 正常的盘中逻辑
pass
def get_1130_data(context):
bars = get_bars('000001.XSHE', count=1, unit='1m', include_now=False)
log.info("11:30 的 Bar: %s" % bars)
def get_1500_data(context):
bars = get_bars('000001.XSHE', count=1, unit='1m', include_now=False)
log.info("15:00 的 Bar: %s" % bars)
方法 3:直接拉取更长周期的 get_bars
如果您在盘中某个时刻需要过去一段时间的连续数据(包含 11:30),只要 count 足够大,get_bars 返回的数组中自然会包含 11:30 的数据。例如在 13:05 调用 get_bars(..., count=10, unit='1m'),返回的数据中就会包含 11:26 到 11:30,以及 13:01 到 13:05 的连续 K 线。
总结:
11:30 和 15:00 的数据并没有丢失,只是 handle_data 的触发机制避开了休市时刻。利用 after_trading_end 或在下一个开盘时刻(13:00 和次日 09:30)调用 get_bars 即可完美获取。