🚀 AI 一键生成 joinquant 策略代码
立即体验
👉 AI 生成代码 👈

为什么在JoinQuant回测时 context.portfolio.total_value 总是不变?

joinquant | 发布时间: 2026/6/24
以下内容由 EasyQuant 生成。

问题描述

总权益回测时不变

回测时context.portfolio.total_value这个数值不会改变是为什么?

解决方案

在 JoinQuant(聚宽)平台上进行回测时,如果发现 context.portfolio.total_value(账户总权益)始终保持初始资金不变,通常是因为策略在回测期间没有产生任何实际的成交。总权益等于可用资金加上持仓价值,如果没有买入任何标的,总权益自然不会随市场波动而改变。

以下是导致该问题的常见原因及排查方法:

1. 交易条件从未被触发

这是最常见的原因。您的策略代码中可能包含了某些买入条件(例如:均线金叉、MACD突破等),但在您设定的回测时间段内,这些条件从未被满足。

  • 排查方法:在触发下单的代码块前加上 log.info("准备下单"),查看日志中是否有该输出。如果没有,说明逻辑判断条件过严或有误。

2. 下单失败或订单未成交

即使代码执行到了 order 系列函数,订单也可能因为各种原因未能成交:

  • 资金不足:尝试买入的数量超过了 context.portfolio.available_cash
  • 标的停牌或退市:下单的股票在当天处于停牌状态,无法撮合成交。
  • 涨跌停限制:在未开启盘口撮合时,如果以市价单买入涨停股,或卖出跌停股,订单会被系统自动撤销。
  • 限价单未达触发价:设置的限价单价格偏离市场价过大,导致一直挂单直到收盘被撤销。
  • 排查方法:在 after_trading_endhandle_data 中打印订单状态:
    orders = get_orders()
    for order_id, order in orders.items():
        log.info("订单状态: %s, 未成交原因: %s" % (order.status, order.filled))
    

3. 标的代码错误或不存在

如果您硬编码了股票代码(如 g.security = '000001'),但忘记加后缀(正确的应为 '000001.XSHE'),系统会找不到该标的,导致下单失败(通常日志会有 Warning 提示)。

4. 打印时机不对

如果您只在 initialize 函数中打印了 context.portfolio.total_value,那么它只会输出一次初始资金。initialize 在整个回测中只运行一次。

  • 排查方法:确保您是在 handle_datarun_daily 调用的定时函数中打印总权益:
    def handle_data(context, data):
        log.info("当前总权益: %f" % context.portfolio.total_value)
    

5. 未开启动态复权(真实价格)模式

虽然这通常不会导致总权益完全不变,但可能会导致买入数量计算异常,进而影响成交。建议在 initialize 中始终开启真实价格模式:

set_option('use_real_price', True)

总结建议:请重点检查回测日志(Log)中的 Warning 信息,聚宽系统通常会在下单失败(如资金不足、停牌、涨跌停)时输出黄色的警告日志。通过分析日志,您可以快速定位是逻辑未触发还是订单被拒。