问题描述
解决方案
在 JoinQuant 聚宽平台中,如果您希望在回测或模拟交易结束时进行数据总结、统计分析或日志输出,可以使用 on_strategy_end(context) 函数。
该函数是策略框架的可选回调函数,仅在回测或模拟交易正常结束时被调用一次。
核心实现方法
您需要在策略代码中定义 on_strategy_end(context) 函数。在该函数内部,您可以访问 context 对象来获取最终的账户状态、持仓信息或回测期间记录的全局变量。
以下是一个完整的代码示例,展示了如何在策略结束时打印最终的总资产和收益率:
# -*- coding: utf-8 -*-
# 导入函数库
from jqdata import *
def initialize(context):
# 初始化设置
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
log.info('策略开始运行')
# 每天运行一次
run_daily(market_open, time='every_bar')
def market_open(context):
# 简单的买入示例:如果空仓则买入平安银行
if len(context.portfolio.positions) == 0:
order_value('000001.XSHE', context.portfolio.available_cash)
# ------------------------------------------------------------------
# 策略结束回调函数
# ------------------------------------------------------------------
def on_strategy_end(context):
"""
策略运行结束时调用
"""
print('=' * 50)
print('策略运行结束,开始进行数据总结:')
# 1. 获取最终账户信息
final_value = context.portfolio.total_value
starting_cash = context.portfolio.starting_cash
returns = context.portfolio.returns
# 2. 打印总结信息
log.info('初始资金: %.2f' % starting_cash)
log.info('最终资产: %.2f' % final_value)
log.info('累计收益率: %.2f%%' % (returns * 100))
# 3. 打印最终持仓
positions = context.portfolio.positions
if len(positions) > 0:
log.info('最终持仓详情:')
for security, position in positions.items():
log.info('标的: %s, 持仓数量: %d, 市值: %.2f' %
(security, position.total_amount, position.value))
else:
log.info('最终无持仓')
print('数据总结完成。')
print('=' * 50)
on_strategy_end 的主要用途
- 统计分析:计算策略特有的指标(如特定因子的平均暴露度、交易胜率等,前提是您在
g全局变量中记录了过程数据)。 - 日志输出:输出最终的资金曲线摘要或持仓快照。
- 文件持久化:结合
write_file函数,将回测过程中的自定义数据(如每日的信号值)保存为 CSV 或 JSON 文件,以便在“研究”模块中进一步分析。
注意事项
- 触发条件:该函数仅在回测时间结束(到达
end_date)或模拟交易到期结束时调用。如果策略因报错而终止,或用户手动停止策略,该函数不会被调用。 - Context 对象:此时的
context对象包含了策略结束那一刻的所有状态信息。 - API 限制:在该函数中不能调用下单函数(如
order),因为交易已经结束。
Q&A
Q: on_strategy_end 函数中可以使用 write_file 保存数据吗?
A: 可以。这是非常常见的用法。您可以在回测过程中将数据保存在全局变量(如 g.my_data_list)中,然后在 on_strategy_end 中将其转换为 DataFrame 并使用 write_file 保存到研究目录,方便后续分析。
Q: 如果我在回测中途手动点击“停止”,on_strategy_end 会运行吗?
A: 不会。根据 API 文档,手动在到期前关闭策略或回测发生异常错误时,该函数不会被调用。它仅在流程正常走完时间轴后触发。
Q: 这个函数能用来平掉所有仓位吗?
A: 不能。on_strategy_end 运行时回测/交易已经结束,此时调用 order 等交易函数是无效的。如果您需要在最后一天平仓,需要在 handle_data 或定时函数中判断当前日期是否为回测结束日期来实现。