3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant(聚宽)平台上,获取历史行情数据是最基础也是最频繁的操作。你观察到的现象非常准确:广场上的开源策略确实绝大多数都在使用 get_price 或 attribute_history,而较少使用 get_bars。这并非单纯因为速度问题,而是由历史习惯、停牌处理机制、返回值格式以及适用场景等多方面因素决定的。
下面我们来深度剖析这三个函数的区别和注意点:
attribute_history(回测/模拟专用)handle_data 等周期运行函数中获取单个标的的过去 N 个周期的历史数据。skip_paused=True(跳过停牌日)。get_price(全局通用)skip_paused=False,即不跳过停牌日,停牌期间的数据会用停牌前最后一个交易日的数据进行填充。这在处理多只股票的截面数据时非常关键,能保证所有股票的时间轴(Index)是对齐的。panel=False 返回等效的 DataFrame)。get_bars(偏底层、高性能)include_now=True)。numpy.ndarray(也可以设置 df=True 返回 DataFrame)。get_bars?主要有以下几个原因:
在量化选股(多标的)策略中,我们通常需要获取一个股票池在同一时间段的数据。如果使用 get_price,停牌的股票会被前值填充,返回的 DataFrame 形状是规整的(例如 100只股票 * 5天)。
但如果使用 get_bars,由于它不填充停牌数据,导致不同股票返回的数据时间轴可能完全不一致。比如 A 股票返回的是过去 5 天的数据,B 股票因为停牌,返回的可能是过去 7 天中交易的 5 天的数据。这给后续的矩阵运算(如 Pandas 的截面计算)带来了极大的麻烦。
get_price 和 attribute_history 是聚宽平台最早提供的一批 API,官方的早期教程、示例代码以及社区里积累的经典策略(如双均线、小市值等)几乎全部基于这两个函数。后来的用户在学习和复制策略时,自然就沿用了下来。
get_bars 默认返回 numpy.ndarray。虽然 Numpy 数组在计算速度上远超 Pandas DataFrame,但对于大部分非高频的日频/分钟频策略来说,Pandas 提供的 mean(), shift(), rolling() 等内置方法太方便了。为了开发效率,大家更愿意牺牲一点点性能去使用返回 DataFrame 的 get_price。
如果是追求极致速度,get_bars(返回 numpy 数组)是最快的。
get_price 和 attribute_history 在底层需要将数据组装成 Pandas DataFrame,这个过程在频繁调用时(例如在分钟级回测的 handle_data 中每次都调用)会产生较大的性能开销。get_bars 并直接处理 numpy 数组。| 函数 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
attribute_history |
回测中获取单只股票的历史指标(如计算均线)。 | 防未来函数,调用简单。 | 只能查单只股票,速度一般。 |
get_price |
研究环境数据分析、回测中获取多只股票的截面数据。 | 支持停牌填充,数据对齐完美,返回 DataFrame 易处理。 | 频繁调用时 DataFrame 组装耗时较长。 |
get_bars |
高频策略、需要获取当前 Bar 快照、对运行速度要求极高的场景。 | 速度极快,支持 include_now。 |
停牌不对齐,处理 numpy 数组门槛稍高。 |
最终建议:
get_price(多标的)或 attribute_history(单标的),开发效率最高,坑最少。get_bars,享受 Numpy 带来的性能飞跃,但要自己写代码处理好停牌和数据对齐的问题。