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

为什么 JoinQuant 中 get_bars 比 get_price 慢?如何优化获取周期数据的性能?

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

问题描述

get_bars 性能比 get_price 慢了好几倍?

get_price 无法精确获取到类似股票软件提供的周期数据(因为周线从礼拜一开市到礼拜五,月线从月初到月末,如果一个礼拜只有不到 5 个交易日,简单调用 get_price 就会取到上个礼拜的数据)

但是 get_bars 性能还是过于慢了,虽然 get_bars 肯定做了大量的处理,聚宽有没有考虑下优化 get_bars 性能呢?

十倍之差,缩小到两倍都可以接受,也可以极大的降低你们的服务器消耗。

解决方案

get_bars 与 get_price 的性能差异解析

在 JoinQuant(聚宽)量化平台中,许多开发者会发现 get_bars 的执行速度明显慢于 get_price。这主要是由于两者在底层数据处理逻辑上的巨大差异造成的:

  1. 数据对齐逻辑不同get_price 获取多日数据时(如 frequency='5d'),采用的是简单的滑动窗口逻辑,即直接往前推5个交易日。而 get_bars(如 unit='1w''1M')为了对齐主流股票软件的显示,进行了复杂的日历时间对齐。它需要判断自然周、自然月的起始和结束,并处理节假日等不规则交易日,这带来了大量的额外计算开销。
  2. 实时快照处理get_bars 支持 include_now=True 参数,这意味着它在盘中调用时需要实时合成当前未结束的 Bar 数据,底层需要拼接历史 K 线和最新的 Tick/分钟数据。
  3. 停牌处理机制get_price 默认会用前收盘价填充停牌数据(skip_paused=False),而 get_bars 则是严格跳过停牌数据,不进行填充,这要求底层在切分 Bar 时进行更复杂的索引过滤。

如何优化获取周期数据的性能?

虽然官方在底层持续优化 API 性能,但在策略编写层面,我们可以通过以下几种替代方案和技巧,将性能提升数倍甚至十倍以上:

方案一:使用 Pandas 本地重采样(强烈推荐)

如果您觉得 get_bars 获取周线(1w)或月线(1M)太慢,最高效的替代方案是:使用 get_price 批量获取日线数据,然后在本地使用 Pandas 的 resample 方法合成为周线或月线。

get_price 获取日线速度极快,Pandas 的 C 语言底层重采样也非常高效。代码示例如下:

import pandas as pd
from jqdata import *

def get_custom_weekly_bars(security, start_date, end_date):
    # 1. 使用高速的 get_price 获取日线数据
    df = get_price(security, start_date=start_date, end_date=end_date, frequency='daily', panel=False)
    
    if df.empty:
        return df
        
    # 2. 将索引转换为 DatetimeIndex 以支持重采样
    df.index = pd.to_datetime(df.index)
    
    # 3. 使用 Pandas resample 按周('W')重采样
    # 聚合规则:开盘取第一个,收盘取最后一个,最高取最大,最低取最小,成交量/额求和
    weekly_df = df.resample('W').agg({
        'open': 'first',
        'close': 'last',
        'high': 'max',
        'low': 'min',
        'volume': 'sum',
        'money': 'sum'
    })
    
    # 4. 剔除没有交易的周(如长假)
    weekly_df = weekly_df.dropna()
    return weekly_df

方案二:保持 df=False 返回 Numpy 数组

如果您必须使用 get_bars,请务必保持默认参数 df=Falseget_bars 默认返回 numpy.ndarray,其构建速度远快于 pandas.DataFrame。只有在绝对必要时,才在本地将其转换为 DataFrame。

# 推荐:返回 numpy 数组,速度较快
bars_array = get_bars('000001.XSHE', count=100, unit='1w', df=False)

# 不推荐:直接返回 DataFrame,底层转换耗时
bars_df = get_bars('000001.XSHE', count=100, unit='1w', df=True)

方案三:批量获取多标的数据

无论是 get_price 还是 get_bars一次性传入一个股票列表获取数据,永远比在 for 循环中单只股票单只股票地获取要快得多。底层 API 对批量请求做了网络 I/O 和数据库查询的合并优化。

# 推荐做法:批量获取
stock_list = ['000001.XSHE', '000002.XSHE', '600000.XSHG']
bars_dict = get_bars(stock_list, count=10, unit='1w', df=False)

总结

get_bars 的“慢”是其提供精准日历对齐和实时快照功能的代价。在对性能要求极高的量化回测场景中,“获取细粒度数据 + 本地 Pandas 降采样合成” 是业界通用的提速法则。通过 get_price 获取日线并本地 resample,您可以完美兼顾“类似股票软件的精准周期”与“极速的执行性能”。