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

JoinQuant 聚宽 get_bars 函数如何同时获取多标的数据?(附性能对比)

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

问题描述

get_bars同时取多标的的情况

get_bars(security, count, unit='1d',
fields=['date','open','high','low','close'],
include_now=False, end_dt=None, fq_ref_date=None,df=True)

security: 股票代码,支持单个及多个标的

请问:这里面可以使用多个标的,但是返回的df中,并没有告诉如何区分标的,另外这个与轮询相比,哪个性能更高??感谢!

解决方案

一、 返回的 DataFrame 中如何区分标的?

在 JoinQuant 中,当您使用 get_bars 函数且传入的 security 是一个列表(多个标的),并且设置 df=True 时,返回的 pandas.DataFrame 会使用 MultiIndex(多重索引) 来区分不同的标的。

1. 当 df=True 时(返回 DataFrame)

返回的 DataFrame 的 index 是一个 MultiIndex,通常包含两个层级:一个是时间(date),另一个是标的代码(security)。您可以通过 pandas 的多重索引切片方法(如 .loc.xs)来提取特定标的的数据。

示例代码:

# 获取多标的数据
df = get_bars(['000001.XSHE', '000002.XSHE'], count=5, unit='1d', fields=['date', 'close'], df=True)

# 查看返回的 MultiIndex 结构
print(df)

# 提取特定标的(例如平安银行 000001.XSHE)的数据
# 方法1:使用 xs
df_000001 = df.xs('000001.XSHE', level=0) # 假设 level 0 是标的代码

# 方法2:使用 loc
df_000001 = df.loc['000001.XSHE']

2. 强烈建议:当 df=False 时(返回 Dict)

如果您觉得 MultiIndex 处理起来比较麻烦,建议将 df 参数设置为 False(这也是官方的默认值)。此时,函数会返回一个 字典 (Dict),键 (key) 是标的代码,值 (value) 是对应的 numpy.ndarray 数据。这种方式区分标的非常直观,且运行速度更快。

示例代码:

# df=False 返回字典
data_dict = get_bars(['000001.XSHE', '000002.XSHE'], count=5, unit='1d', fields=['date', 'close'], df=False)

# 直接通过字典键获取对应标的的数据
array_000001 = data_dict['000001.XSHE']
print(array_000001['close'])

二、 批量获取 vs 轮询(for循环),哪个性能更高?

结论:批量获取(将多个标的放入一个 list 传给 get_bars)的性能远高于 for 循环轮询。

性能差异原因:

  1. 网络与 I/O 开销:每次调用 API(如 get_bars)都会产生底层的网络请求、数据库查询和数据封装开销。如果使用 for 循环轮询 100 只股票,就会产生 100 次 I/O 开销;而将 100 只股票打包成一个 list 传入,只需 1 次 I/O 开销。
  2. 底层优化:JoinQuant 的底层数据库对批量查询进行了专门的优化,能够并行或更高效地从数据库中提取多只股票的数据。
  3. 数据结构开销:如果设置 df=Truepandas.DataFrame 的创建本身就比较耗时。循环创建 100 个 DataFrame 的耗时远大于一次性创建一个 MultiIndex DataFrame。

优化建议:

  • 尽量使用批量查询:在策略中,尽量将需要查询的股票代码收集到一个列表中,一次性调用 get_bars
  • 关闭 DataFrame 转换:在对性能要求极高的场景(如 Tick 级或分钟级高频策略),建议设置 df=False,直接处理 numpy.ndarray,这会比生成 pandas.DataFrame 快得多。