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

JoinQuant 平台 get_price 函数前复权数据在 initialize 和 market_open 阶段不一致的原因解析

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

问题描述

get_price没复权,这是bug吗?

新建空模板,然后分别在init和open阶段调用这个函数,发现没复权

print(get_price('300600.XSHE', fq='pre', count=2, end_date='2019-2-1'))
这是bug吗还是个feature?

console输出如下

2019-02-03 00:00:00 - INFO - open close high low volume money
2019-01-31 11.31 11.36 11.46 11.11 4320218.0 48569830.37
2019-02-01 11.40 12.12 12.12 11.22 7174664.0 83992505.24

2019-02-11 09:30:00 - INFO - open close high low volume money
2019-01-31 20.53 20.63 20.81 20.17 2379710.0 48569830.37
2019-02-01 20.70 22.00 22.00 20.37 3952027.0 83992505.24

2019-02-12 09:30:00 - INFO - open close high low volume money
2019-01-31 20.53 20.63 20.81 20.17 2379710.0 48569830.37
2019-02-01 20.70 22.00 22.00 20.37 3952027.0 83992505.24
完整代码如下

# 导入函数库
from jqdata import *

# 初始化函数,设定基准等等
def initialize(context):
print(get_price('300600.XSHE', fq='pre', count=2, end_date='2019-2-1'))
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)

# 过滤掉order系列API产生的比error级别低的log
# log.set_level('order', 'error')

### 股票相关设定 ###
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')

## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
# 开盘前运行
run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')
# 开盘时或每分钟开始时运行
run_daily(market_open, time='every_bar', reference_security='000300.XSHG')
# 收盘后运行
run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')

## 开盘前运行函数
def before_market_open(context):
pass

## 开盘时运行函数
def market_open(context):
print(get_price('300600.XSHE', fq='pre', count=2, end_date='2019-2-1'))

## 收盘后运行函数
def after_market_close(context):
pass

解决方案

这不是 Bug,而是 JoinQuant 平台动态复权机制(use_real_price)设计的一个 Feature(特性)

导致你在 initializemarket_open 阶段打印出的前复权价格不一致的根本原因,在于 set_option('use_real_price', True) 的调用时机以及复权基准日(fq_ref_date)的变化

深入原因解析

  1. initialize 阶段(未开启真实价格模式)
    在你的代码中,print(get_price(...)) 写在了 set_option('use_real_price', True) 之前。此时,回测引擎处于默认的传统前复权模式
    根据 JoinQuant API 文档说明,在未开启 use_real_price 时,前复权的基准日期是建立回测的现实日期(即你坐在电脑前点击“运行回测”的今天)。因此,你看到的 11.xx 是基于现实今天的复权因子计算出的前复权价格。

  2. market_open 阶段(已开启真实价格模式)
    当代码执行到 market_open 时,use_real_price 已经被设置为 True。此时引擎进入了动态复权(真实价格)模式
    文档中明确指出:开启真实价格回测后,通过 get_price 拿到的前复权价格,是**基于回测当天的逻辑日期(context.current_dt)**作为基准日的前复权价格。在你的日志中,逻辑时间是 2019-02-11,所以你看到的 20.xx 是基于 2019-02-11 这一天的复权因子计算出的前复权价格。

  3. 为什么价格会变?
    因为 300600.XSHE2019-02-11 到你运行回测的现实日期之间,发生了分红送转(除权除息)。基准日不同,计算出来的前复权历史价格自然就不同了。

解决方案与建议

如果你希望在 initialize 阶段获取的数据与盘中一致,请set_option('use_real_price', True) 放在 initialize 函数的第一行

def initialize(context):
    # 1. 必须先开启动态复权模式
    set_option('use_real_price', True)
    
    # 2. 然后再获取数据
    print(get_price('300600.XSHE', fq='pre', count=2, end_date='2019-2-1'))
    
    # 其他初始化设置...
    set_benchmark('000300.XSHG')

官方文档特别提醒:
开启真实价格回测之后,你在不同日期调用 get_price 返回的前复权价格可能是不一样的(因为随着时间推移,如果遇到除权除息,前复权价格会发生变化)。因此,千万不要跨日期缓存这些 API 返回的前复权结果,每次需要历史数据时,请在当前逻辑时间点重新调用 API 获取。