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

JoinQuant 聚宽平台过滤当日涨停股票的最佳性能实践

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

问题描述

请问排除掉当日涨停股票的性能最佳的方式是什么呢?

我目前用的是

def filter_limitup_stock_pd(context, stock_list):
last_prices = history(1, unit='1m', field='close', security_list=stock_list, df=True)
high_limit = history(1, unit='1m', field='high_limit', security_list=stock_list, df=True)
data = high_limit - last_prices
data = data[data>0]
return data
这种写法,但是性能不佳,看 profile 两次 history 开销很大

解决方案

在 JoinQuant 聚宽平台中,使用 history 函数来获取当前价格和涨停价确实会导致较大的性能开销。原因在于 history 主要用于获取历史时间序列数据,并且默认返回 pandas.DataFrame 格式,底层的数据拼接和 DataFrame 对象的创建非常耗时。

性能最佳的替代方案:使用 get_current_data()

聚宽专门提供了 get_current_data() API 来获取当前时刻的快照数据(包括最新价、涨跌停价、停牌状态等)。这个函数返回的是一个按需加载的字典,底层经过了高度优化,开销极小。

你可以将你的过滤函数优化为如下形式:

def filter_limitup_stock(context, stock_list):
    # 获取当前时刻的数据快照
    current_data = get_current_data()
    
    # 使用列表推导式进行高效过滤
    # 如果最新价严格小于涨停价,则说明未涨停
    filtered_stocks = [
        stock for stock in stock_list 
        if current_data[stock].last_price < current_data[stock].high_limit
    ]
    
    return filtered_stocks

为什么这种方式性能更好?

  1. 按需获取 (Lazy Loading)get_current_data() 返回的字典初始是空的,只有当你通过 current_data[stock] 访问特定股票时,引擎才会去内存中提取该股票的数据,避免了全市场数据的无谓加载。
  2. 避免 DataFrame 开销:原方法中 history(..., df=True) 会在底层构建 Pandas DataFrame,这在 Python 中是一个相对沉重的操作。新方法直接操作对象属性,速度快了几个数量级。
  3. 单次调用:原方法调用了两次 history,而新方法只需调用一次 get_current_data() 即可同时拿到 last_pricehigh_limit

进阶提示

如果你还需要同时过滤掉停牌跌停的股票,可以顺便在这个推导式中一并完成,效率极高:

def filter_untradable_stocks(context, stock_list):
    current_data = get_current_data()
    return [
        stock for stock in stock_list 
        if not current_data[stock].paused  # 未停牌
        and current_data[stock].last_price < current_data[stock].high_limit  # 未涨停
        and current_data[stock].last_price > current_data[stock].low_limit   # 未跌停
    ]

建议在策略中全面使用 get_current_data() 来替代 history 获取当天的截面状态数据,你的策略运行速度(尤其是分钟级或 Tick 级回测)将会有显著提升。