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

聚宽策略年化收益异常高?教你系统排查未来函数、幸存者偏差与回测陷阱

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

问题描述

JoinQuant 回测异常高收益如何排查未来函数与过拟合?
聚宽策略出现年化收益极高但实盘表现显著变差时,应该如何系统检查未来函数、幸存者偏差、回测参数和交易摩擦?

解决方案

在量化交易中,“回测是上帝,实盘是地狱”。当您的策略在聚宽(JoinQuant)上跑出异常高的收益时,绝大多数情况下并非发现了“圣杯”,而是触发了某种回测陷阱。以下是系统排查和修正策略的四大步骤:

一、 开启避免未来数据模式(Avoid Future Data)

未来函数是指在回测历史的某一时刻,使用了该时刻之后(未来)才发生的数据。这是导致回测收益虚高的最常见原因。

排查与解决方法:

  1. 开启聚宽内置检测:
    initialize 中加入以下代码。开启后,若策略在运行中尝试获取当前逻辑时间(context.current_dt)之后的数据,系统会直接抛出 FutureDataError 异常。
    def initialize(context):
        # 开启避免未来数据模式
        set_option("avoid_future_data", True)
    
  2. 检查高频未来函数 API:
    • get_price / get_bars:检查 end_dateend_dt 是否传入了大于 context.current_dt 的值。如果不设限制,默认可能会取到当天的收盘价,而在开盘时使用收盘价交易即引入了未来函数。
    • get_fundamentals:查询财务数据时,若传入 statDate(如指定季度 2023q1),由于上市公司财报披露存在滞后性,直接在季度结束日获取该数据会引入未来函数。建议使用 date 参数,系统会自动查找该日期前已发布的最新财报。
    • get_call_auction:集合竞价数据在当日 9:28 之前无法获取,若在 9:00 运行的函数中调用并据此交易,即为未来函数。

二、 启用动态复权(真实价格)模式,规避复权陷阱

传统的“前复权”回测模式会使用未来的复权因子对历史价格进行调整,这在回测中会引入隐蔽的未来函数,导致买入数量和价格不真实。

排查与解决方法:

  1. 开启真实价格回测:
    initialize 中调用 set_option('use_real_price', True)。开启后:
    • 交易时使用历史当天的真实价格撮合,买入数量严格遵守 100 股的整数倍限制。
    • 历史持仓若发生分红送股,对应的股数和现金会自动在账户中动态调整,完全模拟实盘。
    def initialize(context):
        # 强烈建议开启真实价格(动态复权)模式
        set_option('use_real_price', True)
    
  2. 注意数据缓存:
    开启真实价格后,通过 history 等 API 拿到的仍是基于当天日期的前复权价格,但不同日期看到的前复权价格不同。切勿跨日期缓存 API 返回的价格数据

三、 检查幸存者偏差与退市股票

如果您的策略只在当前存活的股票池(如当前的沪深300成分股)中进行历史回测,就会漏掉历史上已经退市或被 ST 的股票,从而产生严重的“幸存者偏差”。

排查与解决方法:

  1. 动态获取成分股:
    不要使用固定的静态股票列表。在回测中,应使用带日期参数的 API 动态获取历史当时的成分股:
    # 获取历史特定日期的指数成分股,避免幸存者偏差
    stocks = get_index_stocks('000300.XSHG', date=context.current_dt)
    
  2. 过滤停牌与 ST 股:
    在下单前,必须使用 get_current_data() 检查标的是否停牌或被 ST,实盘中停牌股是无法交易的:
    current_data = get_current_data()
    if current_data[security].paused or current_data[security].is_st:
        # 停牌或ST股不操作
        return
    

四、 还原真实的交易摩擦(滑点与税费)

回测中默认的成交极其理想,而实盘中由于冲击成本、盘口深度不足,会产生明显的滑点和手续费,高频调仓策略若不设置合理的摩擦,回测收益会严重失真。

排查与解决方法:

  1. 设置合理的滑点(Slippage):
    聚宽默认滑点为 PriceRelatedSlippage(0.00246)。对于小市值或流动性差的股票,应调高滑点:
    # 设置股票固定滑点,买入加0.01元,卖出减0.01元
    set_slippage(FixedSlippage(0.02), type='stock')
    
  2. 严格限制成交量占比(Order Volume Ratio):
    实盘中您的订单不可能瞬间吞下全市场的成交量。必须限制单笔订单占当日真实成交量的比例:
    # 设定成交量比例,单笔成交量不超过本日真实成交量的 25%
    set_option('order_volume_ratio', 0.25)
    
  3. 设置真实的交易税费:
    确保印花税(卖方单边千分之一)和券商佣金(双边万分之三,最低5元)符合实际:
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    

通过以上四个步骤的系统排查,您可以挤掉回测中的“虚胖”水分,获得一个真正具备实盘指导意义的量化策略净值曲线。