问题描述
解决方案
在JoinQuant(聚宽)平台中,获取非标准周期(如3分钟)的K线数据以及获取当前正在形成的K线数据(包含最新Tick信息的Bar),主要推荐使用 get_bars 函数。该函数比旧版的 get_price 功能更强大,且支持 include_now 参数来满足你的需求。
以下是具体的实现方法和代码示例。
1. 获取3分钟周期的K线数据
JoinQuant 的 get_bars 函数支持自定义分钟周期。
- 函数:
get_bars(security, count, unit='1d', ...) - 方法:将
unit参数设置为'3m'即可获取3分钟频率的K线。 - 逻辑:系统会以每天的开盘时间为起始点,每3分钟合成一条Bar。
2. 获取当前正在形成的K线数据(包含当前时刻)
在回测或模拟交易中,默认获取的是“已完成”的时间片数据(即前一分钟的数据)。如果你需要在当前这一分钟结束前(例如 09:30:30)就拿到包含最新价格的K线数据:
- 函数:
get_bars(security, count, unit='1m', include_now=True, ...) - 关键参数:设置
include_now=True。 - 效果:
- 如果当前时间是 09:30:30,设置
include_now=True后,返回的最后一根K线会包含 09:30:00 到 09:30:30 之间的行情数据(开盘价是09:30的开盘价,收盘价是09:30:30的最新价)。 - 如果不设置或设为
False,则只能获取到 09:29:00 及之前的K线。
- 如果当前时间是 09:30:30,设置
完整策略代码示例
以下代码展示了如何在策略中同时实现这两个需求。
# -*- coding: utf-8 -*-
from jqdata import *
def initialize(context):
# 设置基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 设定要操作的股票
g.security = '000001.XSHE'
# 设置按分钟回测,每分钟运行一次
run_daily(market_open, time='every_bar')
def market_open(context):
# ----------------------------------------------------------------
# 需求1:获取3分钟周期的K线数据
# ----------------------------------------------------------------
# unit='3m' 表示3分钟周期
# count=5 表示获取过去5根3分钟K线
# include_now=False 表示只获取已完成的3分钟Bar(避免未来函数,通常用于计算指标)
bars_3m = get_bars(g.security, count=5, unit='3m',
fields=['date', 'open', 'high', 'low', 'close', 'volume'],
include_now=False, df=True)
# 打印3分钟K线数据
# 注意:在分钟回测中,context.current_dt 是当前分钟的开始,
# 比如现在是9:33,获取的是截止到9:33已完成的3分钟bar
print("=== 3分钟周期K线数据 (当前时间: %s) ===" % context.current_dt)
print(bars_3m)
# ----------------------------------------------------------------
# 需求2:获取当前正在形成的这根K线数据 (即时快照)
# ----------------------------------------------------------------
# unit='1m' 表示1分钟周期
# include_now=True 表示包含当前这一分钟尚未走完的数据
# 比如现在是 09:31:30,这根Bar的close就是 09:31:30 的最新价
current_bar = get_bars(g.security, count=1, unit='1m',
fields=['date', 'open', 'high', 'low', 'close', 'volume'],
include_now=True, df=True)
print("=== 当前正在形成的K线数据 (包含最新Tick信息) ===")
if len(current_bar) > 0:
# 获取最新的一行数据
latest_data = current_bar.iloc[-1]
print("时间: %s, 最新价: %.2f, 当前成交量: %.0f" %
(latest_data['date'], latest_data['close'], latest_data['volume']))
# ----------------------------------------------------------------
# 补充:如果只需要最新的一个价格点(Tick数据),也可以使用 get_current_tick
# ----------------------------------------------------------------
# tick = get_current_tick(g.security)
# print("Tick最新价:", tick.current)
常见问题 Q&A
Q: get_price 函数能否获取3分钟数据?
A: 可以。get_price 的 frequency 参数支持 '3m' 这样的格式。但是 get_price 不支持 include_now 参数,无法获取当前正在形成的K线。建议统一使用 get_bars,它的性能更好且功能更全。
Q: include_now=True 会导致未来函数吗?
A: 在回测中,如果你的策略逻辑是“在收盘前基于当天的收盘价做决策”,使用 include_now=True 并在盘中(如14:50)运行,这属于利用了当时的已知信息,不属于未来函数。但如果你在 09:30 利用了 09:30~09:31 整分钟的最终收盘价(而实际上当时还没收盘),那才是未来函数。include_now=True 获取的是截至到代码运行那一刻的快照数据,是符合实盘逻辑的。
Q: 3分钟K线的时间戳是如何标记的?
A: JoinQuant 的K线时间戳通常标记为该周期的结束时间。例如,09:31:00 到 09:34:00 的这根3分钟K线,其时间标签通常显示为 09:34:00。
Q: 为什么 get_bars 返回的数据有时候比 count 少?
A: get_bars 获取的是有效交易数据,不包含停牌期间的数据。如果股票在请求的时间段内停牌,或者上市时间不足,返回的数据行数可能会少于请求的 count 数量。