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

为什么同样的双因子策略,不同起期到最后产生的股票组合不一样?

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

问题描述

为什么同样的双因子策略,不同起期到最后产生的股票组合不一样

请问,用get_fundamentals(query(valuation,indicator).filter(valuation.code.in_stoke_list))获取当前财务数据会产生未来函数么。为什么我用财务双因子策略从不同时间起回测,后面的股票组合不一致呢?
比如说,用同样条件,从2017-2022年选5只股,以及从2019-2022年选5只股,但是在2019-2022年期间选的股票都不一样。

解决方案

针对您在 JoinQuant (聚宽) 平台上遇到的双因子策略回测结果不一致的问题,主要可以从是否引入未来函数以及回测路径依赖两个方面来解答。

一、 使用 get_fundamentals 会产生未来函数吗?

在 JoinQuant 中,使用 get_fundamentals 获取财务数据是否会产生未来函数,取决于您传入的参数

  1. 默认情况(不传 datestatDate
    在回测环境中,如果不传入 datestatDatedate 的默认值会随着回测日期变化而变化,等于 context.current_dt前一天。因为在实际交易中,我们只能看到前一天的财报和市值数据,所以这种默认设置不会产生未来函数
  2. 传入 date 参数
    查询指定日期 date 收盘后所能看到的最近的数据。系统会查找上市公司在这个日期之前(包括此日期)发布的最新数据,不会有未来函数
  3. 传入 statDate 参数(需警惕)
    如果您传入了 statDate(如 '2019q1''2019'),系统会返回该季度或年份的财务数据。由于公司发布财报通常有滞后性(例如一季报可能在4月底才发布),如果您在1月份就通过 statDate 获取了一季报的数据,这就引入了未来函数。因此,回测中应尽量避免使用 statDate,或者严格控制调用时间。

结论:您使用的 get_fundamentals(query(valuation, indicator).filter(valuation.code.in_(stock_list))) 没有指定 statDate,默认使用的是回测当前逻辑时间的前一天的数据,因此不会产生未来函数

二、 为什么不同起期回测,后面的股票组合不一致?

即使策略逻辑完全相同,且没有未来函数,从 2017 年开始回测和从 2019 年开始回测,在 2019-2022 年期间的持仓组合大概率是不一样的。这主要是由**回测的路径依赖(Path Dependency)**引起的:

1. 账户资金与持仓状态的差异

  • 资金规模不同:从 2017 年开始运行的策略,到了 2019 年初,账户的可用资金(available_cash)和总资产(total_value)已经经历了两年的盈亏变化,与 2019 年初直接以初始资金启动的账户完全不同。
  • 买入能力不同:在 2019 年的某个调仓日,2017 年起期的账户可能因为资金充裕买入了排名第 1 到第 5 的股票;而 2019 年起期的账户可能资金较少,或者受限于 A 股“买入必须是 100 的整数倍”的规则,导致某些高价股买不够数量,甚至只能买入排名第 1 到第 4 的股票,资金残余留到了下一次调仓。

2. 历史持仓对调仓逻辑的影响

  • 卖出逻辑的触发:2017 年起期的账户在 2019 年初可能已经持有某些股票。在调仓时,策略通常会判断“如果持仓股不在新的目标股票池中,则卖出”。这种卖出动作会释放资金,进而影响当天的买入动作。而 2019 年起期的账户在第一天是空仓的,只有买入动作。
  • 持仓数量限制:如果您设定了“最多持有 5 只股票”,2017 年起期的账户可能因为某些老股票依然符合条件而继续持有,只替换了 2 只;而 2019 年起期的账户则是全新买入 5 只。如果遇到涨跌停无法买卖的情况,两者的持仓差异会进一步拉大。

3. 动态复权(真实价格模式)的微小影响

  • 如果您开启了 set_option('use_real_price', True),回测使用的是真实价格撮合,但通过 API(如 history)获取的是基于当天的前复权价格。不同时间点看到的前复权价格是不同的。虽然这主要影响技术指标(如均线),但如果您的双因子策略中结合了价格过滤条件,微小的价格差异也可能导致选股结果的边缘变化。

4. 订单撮合与滑点

  • 资金量不同导致下单量不同。如果下单量较大,可能会触发 order_volume_ratio(成交量比例限制),导致部分订单未成交。未成交的资金会留在账户中,影响下一次的选股和买入。

总结

量化回测是一个连续的动态过程,前一天的状态决定了今天的决策基础。不同起期导致到达同一时间点时,账户的“初始状态”(资金、持仓、成本)截然不同,因此后续的交易行为和股票组合自然会产生分化。这是正常的量化回测现象,并非策略代码存在错误或未来函数。