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

joinquant 平台 get_bars 多标的获取与 MultiIndex DataFrame 解析指南

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

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: joinquant 数据处理:get_bars 多标的获取与 MultiIndex DataFrame 解析

Question: 当 get_bars 设置 df=True 且传入多标的时,如何高效解析返回的 MultiIndex 数据?

解决方案

在 JoinQuant(聚宽)量化平台中,使用 get_bars 获取多个标的的行情数据并设置 df=True 时,系统会返回一个带有 MultiIndex(双层复合索引)pandas.DataFrame。理解并高效处理这种数据结构是编写多股票/期货策略的核心技能。


一、MultiIndex DataFrame 数据结构解析

当传入标的列表(如 ['000001.XSHE', '600000.XSHG'])并设置 df=True 时,返回的 DataFrame 的行索引(Index)包含两层:

  1. level 0 (code): 标的代码(如 000001.XSHE
  2. level 1 (date/time): 时间(如 2023-01-03

列字段(Columns)通常包括:date, open, high, low, close, volume, money 等。


二、高效解析 MultiIndex 数据的四大方法

1. 按标的代码提取单个 DataFrame (xs 方法)

使用 .xs() 可以按指定层级快速提取某一标的的数据:

# 获取 000001.XSHE 的所有历史 Bar 数据
df_pingan = df.xs('000001.XSHE', level=0)
print(df_pingan.head())

2. 将 MultiIndex 转换为收盘价透视表 (unstack 方法)

在多因子策略或配对交易中,常常需要构建“行是时间,列是股票代码”的价格矩阵,使用 unstack 最为高效:

# 提取 close 列并重构索引,生成以时间为行、标的为列的 DataFrame
close_matrix = df['close'].unstack(level=0)
print(close_matrix)

3. 重置索引转为标准平铺 DataFrame (reset_index 方法)

如果希望以常规的列形式处理 codedate,可以使用 reset_index

# 将复合索引转换为普通列
flat_df = df.reset_index()
# 提取特定条件的数据
pingan_bars = flat_df[flat_df['level_0'] == '000001.XSHE']

4. 使用 IndexSlice 进行多维高效切片

利用 pd.IndexSlice 可以精准筛选特定标的和时间段:

idx = pd.IndexSlice
# 筛选 000001.XSHE 在指定时间段的数据
sub_df = df.loc[idx['000001.XSHE', '2023-01-01':'2023-01-10'], :]

三、策略实战代码示例(获取多标的并计算均线)

以下代码展示了如何在 JoinQuant 策略中通过 get_bars 获取多标的数据并进行 MultiIndex 解析与信号计算:

from jqdata import *
import pandas as pd

def initialize(context):
    g.securities = ['000001.XSHE', '600000.XSHG', '000002.XSHE']
    run_daily(market_open, time='9:30')

def market_open(context):
    # 1. 获取多标的最近 20 个交易日日 K 线数据
    bars = get_bars(
        security=g.securities, 
        count=20, 
        unit='1d', 
        fields=['date', 'close'], 
        include_now=False, 
        df=True
    )
    
    # 2. 转换成以时间为行、股票为列的收盘价矩阵
    close_df = bars['close'].unstack(level=0)
    
    # 3. 批量计算各标的的 5 日与 20 日均线
    ma5 = close_df.tail(5).mean()
    ma20 = close_df.mean()
    
    # 4. 遍历提取判断计算结果
    for code in g.securities:
        current_ma5 = ma5[code]
        current_ma20 = ma20[code]
        log.info(f"{code} MA5: {current_ma5:.2f}, MA20: {current_ma20:.2f}")

四、性能与最佳实践建议

  1. 推荐使用 unstack(level=0):将多标的的长表(Long format)转为宽表(Wide format),方便直接进行矩阵运算与向量化操作(如计算收益率、计算相关系数等),比循环遍历快数十倍。
  2. 指定 fields 参数:仅获取策略所需的字段(如 ['date', 'close']),可显著减少内存开销与数据解析耗时。
  3. 避免在循环中使用 get_bars:一次性传入标的列表获取 MultiIndex DataFrame,比在 for 循环中逐个标的调用 get_bars 效率更高。