问题描述
方式1:bktest_id有creat_backtest创建
方式2:bktest_id从creat_backtest创建的回测完成后,从回测结果的网址取detail?backtestId=*
bktest = get_backtest(bktest_id)
bktest.get_risk()得到的数据
方式1 比方式2 少了
'avg_position_days',
'avg_trade_return',
'day_win_ratio',
'lose_count',
'profit_loss_ratio',
'turnover_rate',
'win_count',
'win_ratio'}
这个是怎么回事了?
解决方案
出现这种情况的核心原因在于回测任务的异步执行机制以及后端指标计算的延迟。
问题原因解析
-
方式1(代码直接获取):
当你使用create_backtest创建回测后,系统会在后台异步运行这个回测任务。如果你在创建后立即调用get_backtest(bktest_id).get_risk(),此时回测可能还没有完全结束,或者虽然基础的净值数据计算完了(状态刚变为done),但更复杂的交易统计指标(如胜率、盈亏比、平均持仓天数等)还在后端队列中进行二次计算。因此,你获取到的风险指标字典是不完整的。 -
方式2(网页手动获取):
当你从网页 URL 获取backtestId时,这个回测任务已经彻底完成,后端所有的二次统计指标(包括交易维度的胜率、盈亏比等)都已经计算完毕并落库。因此,此时调用get_risk()能够拿到最完整的数据。
解决方法
在使用 create_backtest 后,不能立即获取风险指标,必须通过轮询的方式检查回测状态,确保其完全结束。为了确保拿到完整的交易统计指标,建议在状态变为 done 后,再稍微等待一小段时间(或循环检查特定键是否存在)。
正确的代码示例:
import time
from jqdata import *
# 1. 创建回测
bktest_id = create_backtest(params)
print("回测创建成功,ID:", bktest_id)
# 2. 轮询等待回测完成
bktest = get_backtest(bktest_id)
while True:
status = bktest.get_status()
if status == 'done':
print("回测运行结束,等待指标计算...")
break
elif status in ['failed', 'canceled', 'deleted']:
raise Exception(f"回测异常结束,状态: {status}")
print("回测运行中,请稍候...")
time.sleep(5) # 每5秒检查一次
# 3. 确保高级风险指标已生成
max_retries = 10
for i in range(max_retries):
risk_data = bktest.get_risk()
# 检查缺失的指标是否已经计算完毕
if 'win_ratio' in risk_data:
print("所有风险指标计算完毕!")
break
else:
print("正在等待后端生成交易统计指标...")
time.sleep(3)
# 4. 打印完整的风险指标
print(risk_data)
总结
create_backtest 是非阻塞的,基础收益指标和高级交易统计指标的生成存在时间差。通过状态轮询 (get_status() == 'done') + 字段校验,即可在代码中获取与网页端完全一致的完整风险指标数据。