🚀 AI 一键生成 joinquant 策略代码

为什么在JoinQuant平台9:30前后获取的数据不一样?

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

问题描述

这个9:30前后获取的数据真不一样,我也遇到过,不知道缘由,期待大神解答。

解决方案

很多量化开发者在JoinQuant(聚宽)平台上编写策略时,会发现在9:30开盘前后获取的数据存在差异。这并非系统Bug,而是由A股市场的交易机制(集合竞价)以及平台的底层数据处理逻辑共同决定的。以下是详细的原因解析及正确的处理方法。

一、 为什么9:30前后数据不一样?

1. K线时间标识与对齐机制

在JoinQuant中,所有的行情K线数据为后对齐,标识K线的时间为数据的结束时间。

  • 一分钟K线没有09:30:每天的第一根1分钟K线标识为 09:31。这根K线包含了 09:25:00 ~ 09:30:59 的所有数据。
  • 开盘价的归属:09:31这根K线的开盘价,实际上就是09:25集合竞价产生的开盘价。
    如果在9:30整去获取分钟K线,此时09:31的K线尚未走完,你获取到的最新完整K线其实是前一交易日15:00的K线。

2. 集合竞价数据的生成延迟

A股的开盘集合竞价在09:25结束并产生当天的开盘价。但在实际的模拟盘或实盘中,交易所的数据分发和平台的数据处理需要时间。

  • 根据官方文档,当天的开盘价(day_open至少在09:27分之后才可获取。
  • 集合竞价的详细Tick数据(通过 get_call_auction 获取),最晚于 09:28分 返回。
    如果在09:25到09:27之间去请求当天的开盘价,可能会获取不到或者获取到异常值。

3. 模拟盘的“提前运行”机制

为了减少并发运行模拟盘数量的压力,对于使用当日开盘价撮合的日级模拟盘,JoinQuant会在9:25集合竞价完成时获取开盘价,并将策略提前到 9:27~9:30 之间运行

  • 虽然策略实际运行的物理时间可能是9:28,但策略内获取到的逻辑时间(context.current_dt)仍然是 9:30
  • 这种物理时间与逻辑时间的错位,会导致你在“以为是9:30”的时候,底层数据切片可能还停留在9:28的状态。

二、 如何正确获取开盘相关数据?

为了避免9:30前后的数据混乱,建议根据具体需求使用专门的API:

1. 获取当天的开盘价、涨跌停价(推荐)

如果你在 handle_datarun_daily(..., time='09:30') 中需要知道今天的开盘价,请使用 get_current_data()。这个API专门用于获取当前单位时间已知的数据。

def market_open(context):
    # 此时逻辑时间为9:30,实际物理时间可能在9:27-9:30之间
    current_data = get_current_data()
    security = '000001.XSHE'
    
    # 获取当天开盘价(09:27之后可用)
    today_open = current_data[security].day_open
    
    # 获取最新价(09:30之前调用通常返回昨日收盘价或集合竞价价格)
    last_price = current_data[security].last_price
    
    # 获取涨跌停价
    high_limit = current_data[security].high_limit
    
    log.info(f"今日开盘价: {today_open}, 最新价: {last_price}")

2. 获取集合竞价的详细盘口数据

如果你需要分析集合竞价的买卖盘力量,可以使用 get_call_auction。建议在09:30的函数中调用,以确保数据已经完全就绪。

from jqdata import *

def market_open(context):
    # 获取当天的集合竞价数据
    today = context.current_dt.strftime('%Y-%m-%d')
    df_auction = get_call_auction('000001.XSHE', start_date=today, end_date=today)
    
    if not df_auction.empty:
        log.info(f"集合竞价成交价: {df_auction['current'].iloc[-1]}")
        log.info(f"集合竞价成交量: {df_auction['volume'].iloc[-1]}")

3. 获取历史K线数据

如果你使用 historyattribute_history 获取日线数据,请注意:

  • 日线数据不包含当天:即使在15:00收盘后调用,获取的日线数据也不包含当天。要获取当天数据,必须取分钟线(如 frequency='1m')。
  • 避免未来函数:如果在9:30获取当天的日线收盘价,属于未来数据。平台开启 avoid_future_data 时会报错。

总结

9:30前后数据不一致的核心在于集合竞价的特殊性K线生成规则。在编写早盘策略时,切忌用常规的分钟K线逻辑去套用9:30这个时间点。明确区分“昨日收盘价”、“今日集合竞价/开盘价”和“9:31第一根分钟线”,并使用 get_current_data()get_call_auction(),就能完美避开这个坑。