🚀 AI 一键生成 joinquant 策略代码

聚宽量化回测中的“未来函数”排查:为何9:30计算止损收益远高于9:26?

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

问题描述

聚宽回测时做的交易是否存在自动的“未来函数”?

我最近做了一个趋势策略;使用相同的止损标准,例如都是亏损5%或者回撤5%卖出;我的卖出时机有两种,第一种是9:26分以当日开盘价计算亏损或者回撤,然后在开盘后卖出;另一种是9:30开盘获取实时股票价格,计算亏损或者回撤,然后确定是否卖出。其中其他的变量都是一致的;
最终我回测时前者年化收益很低,后者年化收益很高;各位大佬能帮我分析下原因吗?

解决方案

在聚宽(JoinQuant)平台上进行回测时,系统本身不会“自动”或“恶意”地加入未来函数,但由于日线级别回测的底层数据结构以及API调用方式的特殊性,开发者在编写代码时非常容易不小心引入未来数据

针对你描述的现象(9:26计算收益低,9:30计算收益极高),这几乎可以断定是在9:30的逻辑中引入了未来函数。以下是导致这种巨大差异的核心原因分析及排查建议:

1. 为什么9:30的逻辑极有可能引入了未来函数?

如果你使用的是按天回测(日频),在 handle_datarun_daily(..., time='09:30') 中获取当天的“实时价格”时,极易踩中以下几个“未来函数”陷阱:

  • 误用全天均价或收盘价: 在日频回测的 9:30,如果你通过 data[security].pricedata[security].avg 获取价格,根据聚宽API文档,日频下的 avg 代表的是该股票全天的成交均价(成交额/成交量)。在早上9:30使用全天均价来判断是否止损,等于提前知道了全天的走势。
  • 误取当天的最高/最低/收盘价: 如果你在9:30调用 get_priceattribute_history,且没有严格限制时间戳,可能会直接取到包含当天 closelowhigh 的整根日K线。用当天的最低价(low)或收盘价(close)来计算回撤,意味着你的策略在9:30就已经“预知”了今天盘中会跌到多少,从而精准逃顶或止损,这会导致年化收益率出现极其夸张的飙升。

2. 为什么9:26的逻辑收益较低(但更真实)?

在 9:26(通常在 before_trading_startrun_daily(..., time='09:26') 中运行),当天的日K线尚未生成。此时你只能通过 get_current_data().day_open 获取到集合竞价产生的开盘价,或者使用昨天的收盘价。

  • 数据真实: 此时你无法获取当天的 lowclose,因此计算出的亏损/回撤是基于真实的开盘价,没有任何未来数据。
  • 撮合机制: 在开盘前(9:26)下的市价单,会在9:30开盘时以开盘价(或加上滑点)进行撮合。这种交易逻辑完全符合真实市场的运作规律,因此测算出来的收益率虽然低,但往往是真实且可靠的

3. 如何排查和解决这个问题?

为了验证并修复你的策略,建议采取以下几个步骤:

第一步:开启“避免未来数据”模式

在策略的 initialize 函数中,强制开启聚宽提供的防未来函数选项。如果你的9:30逻辑确实用到了未来数据,系统会直接报错抛出 FutureDataError

def initialize(context):
    # 开启避免未来数据模式
    set_option("avoid_future_data", True)

第二步:检查9:30获取价格的代码

仔细检查你在9:30获取“实时价格”的代码:

  • 错误做法(日频下含未来函数): current_price = data[security].pricecurrent_price = data[security].close
  • 正确做法(获取真实最新价): 使用 get_current_data() 获取。
current_data = get_current_data()
current_price = current_data[security].last_price # 9:30时通常等于开盘价

第三步:使用“按分钟回测”进行日内止损

如果你希望在盘中(如跌破阈值的瞬间)实时止损,绝对不能使用按天回测。日频回测只能在每天的一个固定时间点(通常是开盘)做一次决策。

  • 解决方案: 将回测频率改为按分钟回测(Minute)。在分钟回测下,data[security].close 代表的是上一分钟的收盘价,这样你在 9:30 或盘中任何一分钟计算回撤时,使用的数据都是严格截止到上一分钟的,彻底杜绝了日内未来函数。

总结

你所观察到的“9:30收益极高”,99%是因为在日频回测的9:30调用了包含当天全天信息的字段(如日均价、日最低价、日收盘价)作为止损依据。请开启 avoid_future_data 选项,并确保日内止损逻辑在分钟级回测下运行,以获得具有实盘指导意义的真实收益率。