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

JoinQuant 聚宽提取多只股票历史最低价的正确姿势

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

问题描述

提取多种股票最低价??

import jqfactor
import pandas as pd
import jqdata
from jqlib.technical_analysis import *
def initialize(context):

#设定沪深300作为基准
set_benchmark('000300.XSHG')
#开启动态复权模式(真实价格)
set_option('use_real_price',True)
#输出内容到日志 log.info()
log.info('初始函数开始运行切全局只运行一次')


g.security =['300901.XSHE','000001.XSHE']


run_daily(period,time = 'every_bar')
def period(context):
security=g.security

q = get_bars(security, count=36, unit='1M',fields=('low'),include_now=True,end_dt=context.current_dt,fq_ref_date= context.current_dt.date(),df=True)

print(q)


for qq in q:
qq = q.min()


print(qq)
各位大神,怎么提取多种股票的最低价, 我只能打出所有的一起比较最低价,怎么不是那样一个股票一个最低价的,好烦躁!

解决方案

在 JoinQuant 聚宽平台上,当你使用 get_bars 函数并传入多个股票代码且设置 df=True 时,返回的是一个带有 MultiIndex(多重索引) 的 pandas DataFrame。直接对这个 DataFrame 调用 .min() 会计算整个列的最小值,而不是按股票分别计算。

要分别提取每只股票的最低价,有两种推荐的解决方法:

方法一:使用 df=False 返回字典格式(推荐,更简单高效)

当设置 df=False 时,get_bars 会返回一个字典,键(key)是股票代码,值(value)是包含数据的 numpy 数组。这样遍历起来非常直观:

import jqdata

def initialize(context):
    set_benchmark('000300.XSHG')
    set_option('use_real_price', True)
    log.info('初始函数开始运行且全局只运行一次')
    
    g.security = ['300901.XSHE', '000001.XSHE']
    # 建议按天运行,而不是 every_bar,避免分钟级别重复打印
    run_daily(period, time='09:30')

def period(context):
    security = g.security
    
    # 设置 df=False,返回字典
    q = get_bars(security, count=36, unit='1M', fields=['low'], 
                 include_now=True, end_dt=context.current_dt, 
                 fq_ref_date=context.current_dt.date(), df=False)
    
    # 遍历字典,分别获取每只股票的最低价
    for stock in security:
        # q[stock] 是一个 numpy 数组,包含 'low' 字段
        stock_low_data = q[stock]['low']
        min_low = stock_low_data.min()
        print(f"股票 {stock} 过去36个月的最低价是: {min_low}")

方法二:使用 df=True 并利用 pandas 的 groupby 分组计算

如果你坚持要使用 DataFrame 格式,可以通过 pandas 的 groupby 方法,按照索引中的股票代码层级(通常是 level 0)进行分组,然后再求最小值:

import jqdata
import pandas as pd

def initialize(context):
    set_benchmark('000300.XSHG')
    set_option('use_real_price', True)
    log.info('初始函数开始运行且全局只运行一次')
    
    g.security = ['300901.XSHE', '000001.XSHE']
    run_daily(period, time='09:30')

def period(context):
    security = g.security
    
    # 设置 df=True,返回 MultiIndex DataFrame
    q = get_bars(security, count=36, unit='1M', fields=['low'], 
                 include_now=True, end_dt=context.current_dt, 
                 fq_ref_date=context.current_dt.date(), df=True)
    
    # q 的 index 是 MultiIndex,第一层级 (level=0) 是股票代码
    # 使用 groupby 按股票代码分组,然后求最小值
    min_lows = q.groupby(level=0)['low'].min()
    
    print("各股票的最低价如下:")
    print(min_lows)
    
    # 如果你想遍历打印
    for stock, min_val in min_lows.items():
        print(f"股票 {stock} 的最低价是: {min_val}")

总结与建议

  1. 数据结构理解:处理多标的数据时,一定要清楚 API 返回的数据结构。get_bars 多标的 df=True 返回的是 MultiIndex DataFrame,不能像单标的那样直接操作。
  2. 性能优化:在量化回测中,尽量使用 df=False 获取 numpy 数组或字典,因为 pandas DataFrame 的构建和操作在大量循环中会显著拖慢回测速度。
  3. 运行频率:你的代码中使用了 time='every_bar',如果是分钟回测,每分钟都会去获取过去36个月的数据并计算,这非常耗时且没有必要。建议改为 time='09:30' 每天开盘计算一次即可。