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

在JoinQuant中使用 context.current_dt 获取技术指标会引入未来数据吗?

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

问题描述

用current_dt获取的技术分析指标是未来数据吗?

回测或实时模拟交易时,run_daily('time =every_bar')的情况下,用check_date = context.current_dt获取到的技术分析指标是当日开盘时的数据还是未来数据?

解决方案

结论:会引入未来数据

在 JoinQuant(聚宽)平台中,如果在盘中(如 run_daily(time='every_bar'),即每天 9:30 或每分钟运行)使用 check_date = context.current_dt 去获取日线级别的技术分析指标(如 MACD、BOLL、RSI 等),获取到的是包含当天最终收盘价计算出的未来数据,而不是当日开盘时的数据。


为什么会产生未来数据?

  1. 技术指标的计算基础:绝大多数日线级别的技术分析指标(如 jqlib.technical_analysis 库中的函数)是基于日 K 线(包含当天的开盘价、最高价、最低价、收盘价)计算的。
  2. 时间错位:当策略在盘中(例如 9:30 或 10:00)运行时,当天的交易尚未结束,真实的“今日收盘价”还不存在。但如果你强行传入 check_date = context.current_dt(包含今天的日期),底层数据接口为了计算指标,会直接提取当天的最终日线数据(即下午 15:00 的收盘价)。
  3. 后果:你的策略在早上 9:30 就提前“偷看”了下午 15:00 的收盘结果,这会导致回测收益曲线极其完美,但在实盘或模拟盘中完全失效。

正确的解决方案

为了避免未来函数,你应该使用前一个交易日的日期来获取技术指标,或者开启平台的防未来数据机制。

方法一:使用 context.previous_date(推荐)

在盘中做决策时,只能基于昨天及昨天之前的指标数据。将 check_date 设置为 context.previous_date

from jqlib.technical_analysis import *

def handle_data(context, data):
    # 错误写法:会引入未来数据!
    # macd = MACD('000001.XSHE', check_date=context.current_dt)
    
    # 正确写法:使用前一个交易日
    macd_jax, macd_ylx, macd_zcx = MACD('000001.XSHE', check_date=context.previous_date)
    
    # 基于昨天的指标进行今天的交易决策
    if macd_jax['000001.XSHE'] > 0:
        order('000001.XSHE', 100)

方法二:开启避免未来数据模式

强烈建议在 initialize 函数中开启聚宽提供的防未来数据选项。开启后,如果你的代码尝试获取未来数据,程序会直接报错(抛出 FutureDataError),从而帮你及时发现 Bug。

def initialize(context):
    # 开启避免未来数据模式
    set_option("avoid_future_data", True)
    
    # 建议同时开启动态复权(真实价格)模式
    set_option('use_real_price', True)

方法三:如果确实需要当天的盘中指标

如果你需要基于当天的盘中实时价格计算指标(例如 10:00 的实时 MACD),你不能直接调用日线级别的技术指标库。你需要:

  1. 使用 get_barshistory 获取分钟级别的数据(unit='1m')。
  2. 结合当天的分钟数据和历史的日线数据,自己编写逻辑计算实时的技术指标。