问题描述
解决方案
在聚宽(JoinQuant)平台中,要在每天开盘前运行准备代码,最标准和推荐的方法是使用系统内置的 before_trading_start(context) 函数。
以下是详细的实现方法和代码示例。
方法一:使用内置函数 before_trading_start(推荐)
这是聚宽框架提供的标准回调函数。
- 运行时间:默认在每个交易日的 09:00 运行。
- 用途:通常用于获取当天的财务数据、筛选股票池、重置每日的全局变量、处理停牌或ST股票过滤等。
代码示例
# -*- coding: utf-8 -*-
import jqdata
def initialize(context):
# 初始化策略,设置基准等
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
log.info("策略初始化完成")
def before_trading_start(context):
"""
每天开盘前运行一次 (默认 09:00)
"""
log.info("---盘前准备开始---")
# 1. 获取当前时间
current_date = context.current_dt.date()
log.info("当前日期: %s" % current_date)
# 2. 重置或定义每日需要使用的全局变量
g.daily_buy_list = []
# 3. 示例:获取沪深300成分股作为今日备选股票池
stocks = get_index_stocks('000300.XSHG')
# 4. 示例:过滤掉今日停牌的股票
current_data = get_current_data()
g.buyable_stocks = [stock for stock in stocks if not current_data[stock].paused]
log.info("今日可选股票数量: %d" % len(g.buyable_stocks))
log.info("---盘前准备结束---")
def handle_data(context, data):
# 盘中运行逻辑
pass
方法二:使用 run_daily 定时运行(自定义时间)
如果你需要在 09:00 以外的特定时间(例如 09:15 或 09:25)运行准备代码,可以在 initialize 中使用 run_daily 函数进行注册。
代码示例
# -*- coding: utf-8 -*-
import jqdata
def initialize(context):
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
# 注册一个自定义函数,在每天 09:10 运行
run_daily(my_preparation, time='09:10')
def my_preparation(context):
"""
自定义的盘前准备函数
"""
log.info("执行自定义盘前准备,时间:%s" % context.current_dt)
# 在这里编写你的准备逻辑
# 注意:run_daily 注册的函数只能接收 context 一个参数
g.my_signal = True
def handle_data(context, data):
pass
常见用途
在盘前阶段(before_trading_start),通常进行以下操作:
- 选股与过滤:调用
get_fundamentals查询财务数据,或使用get_industry_stocks获取行业成分股,并过滤掉 ST、退市或停牌的股票。 - 数据预处理:获取历史数据(
history或attribute_history)计算技术指标(如均线),为盘中交易做准备。 - 变量重置:清空用于记录当日交易状态的全局变量(例如
g.today_bought_count = 0)。 - 更新参数:根据市场情况动态调整策略参数(如止损阈值)。
Q&A
Q: before_trading_start 函数中可以下单交易吗?
A: 虽然代码上可以调用 order 系列函数,但由于该函数默认在 09:00 运行,此时交易所尚未开盘(A股竞价在 09:15 开始),因此下的单通常会暂存,直到正式交易时段才会被撮合。建议将下单逻辑放在 handle_data 或通过 run_daily 设置在交易时间运行的函数中。
Q: 如果我在 before_trading_start 中获取 get_current_data(),能拿到当天的开盘价吗?
A: 不能。before_trading_start 默认在 09:00 运行,此时当天的集合竞价尚未开始,因此无法获取当天的开盘价(day_open)。如果需要获取当日开盘价,建议使用 run_daily 将函数设置在 09:25 或 09:30 之后运行。
Q: before_trading_start 和 initialize 有什么区别?
A: initialize 仅在回测开始的第一天执行一次,用于初始化整个策略的生命周期配置;而 before_trading_start 会在回测期间的每一个交易日开盘前都执行一次。