3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在聚宽(JoinQuant)平台中,当我们需要为多因子策略处理大量股票时,频繁在循环中单只调用数据接口(如 attribute_history 或旧版接口)极易导致策略运行缓慢、超时甚至被系统判定为恶意调用而终止。
为了实现高效取数,聚宽官方推荐使用 get_bars 接口。该接口原生支持传入股票代码列表(List),能够一次性批量获取多只股票的历史 K 线数据,从而大幅降低 API 调用次数,提升回测和模拟交易的运行效率。
get_bars 批量取数?security 参数支持传入 list 或 tuple 格式的标的代码,一次性返回所有标的数据。fq_ref_date 进行定点复权,并可通过 df=True 直接返回便于多因子计算的 pandas.DataFrame(带 MultiIndex 索引)。get_bars 核心参数解析security: 标的代码或包含交易代码的列表。例如:['000001.XSHE', '600000.XSHG']。count: 大于0的整数,表示获取 bar 的个数。unit: bar 的时间单位,如 '1d'(天)、'1m'(分钟)。fields: 获取数据的字段,如 ['date', 'open', 'high', 'low', 'close', 'volume', 'money']。df: 是否返回 pandas.DataFrame 对象。批量取数时,强烈建议设置 df=True,此时返回的 DataFrame 索引为 MultiIndex(第一层为标的代码,第二层为行号/时间),非常适合多因子矩阵运算。以下是在聚宽回测/模拟环境或研究环境中,批量获取沪深300成分股最近5天日 K 线数据的完整示例:
import pandas as pd
import datetime
from jqdata import *
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 每天开盘时运行
run_daily(market_open, time='09:30')
def market_open(context):
# 1. 获取沪深300成分股列表(约300只股票)
stock_list = get_index_stocks('000300.XSHG')
# 2. 设定获取的K线数量和字段
count_num = 5
fields_list = ['date', 'open', 'high', 'low', 'close', 'volume']
log.info("开始批量获取 %d 只股票的行情数据..." % len(stock_list))
# 3. 使用 get_bars 批量获取数据(设置 df=True 返回 MultiIndex DataFrame)
# fq_ref_date=context.current_dt.date() 表示以当前回测日期为基准进行前复权
df_bars = get_bars(
security=stock_list,
count=count_num,
unit='1d',
fields=fields_list,
include_now=False,
end_dt=context.current_dt,
fq_ref_date=context.current_dt.date(),
df=True
)
# 4. 数据处理示例
if not df_bars.empty:
log.info("数据获取成功!")
# 打印前5行数据查看结构
print(df_bars.head())
# 提取所有股票的收盘价矩阵 (行索引为日期,列索引为股票代码)
# 这种矩阵格式非常适合直接进行多因子计算
close_matrix = df_bars['close'].unstack(level=0)
print("收盘价矩阵前5行:")
print(close_matrix.head())
get_bars 支持批量获取,但单次请求的“股票数量 × count”不宜过大(建议单次总数据量控制在 20 万条以内)。如果股票池有数千只且需要获取较长历史,建议在代码中将股票列表分批(如每 500 只一组)进行获取,然后使用 pd.concat 合并。get_bars 默认不包含停牌的数据。如果某只股票在查询区间内有停牌,返回的 bar 数量可能会少于 count。在多因子计算时,需注意处理非对齐的数据(如使用 unstack 展开后进行 ffill 填充)。fq_ref_date 务必设置为 context.current_dt.date()(动态复权),以避免引入未来函数。