3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant (聚宽) 平台上使用本地离线训练好的 XGBoost 模型进行回测是完全可行的。整个流程主要包括:上传模型文件、在策略中读取并加载模型、构造特征并进行预测。以下是详细的步骤和性能优化建议:
joblib 或 pickle 将模型保存为文件(例如 xgb_model.pkl)。xgb_model.pkl 文件上传到研究环境的根目录(或指定文件夹)。在回测代码中,不能直接使用本地路径读取文件,必须使用聚宽提供的 read_file API。为了避免每次调仓都重新加载模型导致回测极慢,强烈建议将模型加载逻辑放在 process_initialize 或 initialize 函数中。
import jqdata
import pandas as pd
import numpy as np
import xgboost as xgb
import joblib
from six import BytesIO
def initialize(context):
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
g.security = '000001.XSHE'
# 加载模型
load_model(context)
# 每天开盘前运行
run_daily(market_open, time='09:30')
def load_model(context):
# 使用 read_file 读取研究环境中的模型文件
# 注意:如果是 Python3 环境,使用 BytesIO
model_bytes = read_file('xgb_model.pkl')
g.model = joblib.load(BytesIO(model_bytes))
log.info("XGBoost 模型加载成功!")
在定时运行函数(如 market_open)或 handle_data 中,获取最新的行情数据,构造与训练时完全一致的特征,然后输入模型进行预测。
def market_open(context):
# 1. 获取数据构造特征 (假设模型需要过去5天的收盘价和成交量)
df = attribute_history(g.security, 5, '1d', ['close', 'volume'])
# 2. 构造特征向量 (需与离线训练时的特征工程保持绝对一致)
# 这里仅为示例,实际特征可能更复杂
feature_vector = np.array([[df['close'].mean(), df['volume'].mean()]])
# 3. 模型预测
prediction = g.model.predict(feature_vector)[0]
# 4. 根据信号下单
cash = context.portfolio.available_cash
if prediction == 1 and cash > 0:
order_value(g.security, cash)
log.info("预测信号为1,买入")
elif prediction == 0 and context.portfolio.positions[g.security].closeable_amount > 0:
order_target(g.security, 0)
log.info("预测信号为0,卖出")
会不会很慢取决于你的代码实现方式。 如果处理不当,确实会非常慢甚至触发超时(聚宽限制每个函数运行不能超过 1800 秒)。请注意以下几点优化技巧:
initialize 或 process_initialize 中只加载一次模型,将其存入全局变量 g 中。千万不要在 handle_data 中每次都 read_file。for 循环中对每只股票单独调用 model.predict()。应该先将所有股票的特征拼接成一个大的 pandas.DataFrame 或 numpy.ndarray,然后一次性调用 g.model.predict(features_df)。XGBoost 的批量预测速度极快,而循环单条预测会带来巨大的函数调用开销。xgboost 原生的 .model 格式保存和加载,通常比 pickle 更省内存。总结来说,只要模型加载一次,并且采用批量特征构造 + 批量预测的方式,在聚宽平台上进行 K 线级别(无论是日线还是分钟线)的 XGBoost 信号预测是完全可以做到高效且流畅的。