问题描述
解决方案
在 JoinQuant(聚宽)平台中,过滤 ST 和 *ST 股票最常用且推荐的方法是使用 get_current_data() 函数。该函数返回的 SecurityUnitData 对象包含一个 is_st 属性,可以直接判断股票当前是否处于 ST 或 *ST 状态。
以下是具体的实现方法和代码示例。
方法一:在回测/模拟交易中使用 (推荐)
在策略的 before_trading_start 或 handle_data 函数中,通过 get_current_data() 获取当前时刻的股票属性进行过滤。
# -*- coding: utf-8 -*-
def filter_st_stocks(stock_list):
"""
过滤 ST 和 *ST 股票
输入:stock_list (list): 股票代码列表
输出:list: 剔除 ST 后的股票列表
"""
# 获取当前时刻的行情数据
current_data = get_current_data()
# 列表推导式过滤:保留 is_st 为 False 的股票
# current_data[stock].is_st 为 True 表示是 ST 或 *ST,False 表示正常
return [stock for stock in stock_list if not current_data[stock].is_st]
# 策略示例用法
def initialize(context):
set_benchmark('000300.XSHG')
run_daily(before_market_open, time='09:00')
def before_market_open(context):
# 1. 获取初始股票池(例如沪深300成分股)
initial_stocks = get_index_stocks('000300.XSHG')
# 2. 调用过滤函数剔除 ST
valid_stocks = filter_st_stocks(initial_stocks)
# 打印结果对比
log.info("初始数量: %d, 过滤ST后数量: %d" % (len(initial_stocks), len(valid_stocks)))
# 将过滤后的股票存入全局变量供后续使用
g.buy_list = valid_stocks
方法二:在研究环境中使用 (get_extras)
如果你是在“投资研究”模块(Notebook)中进行历史数据分析,可以使用 get_extras 函数来获取一段时间内的 ST 状态。
from jqdata import *
# 获取沪深300成分股
stocks = get_index_stocks('000300.XSHG')
date = '2023-01-01'
# 获取指定日期的 is_st 数据
# get_extras 返回一个 DataFrame,列是股票代码,值是布尔值
is_st_data = get_extras('is_st', stocks, start_date=date, end_date=date, df=True)
# 提取该日期不是 ST 的股票
# iloc[0] 取第一行(因为只查了一天),值为 False 代表不是 ST
non_st_stocks = is_st_data.columns[~is_st_data.iloc[0]].tolist()
print(f"过滤前数量: {len(stocks)}")
print(f"过滤后数量: {len(non_st_stocks)}")
核心逻辑说明
get_current_data(): 这是回测中最常用的 API。它返回一个字典,Key 是股票代码,Value 是对象。.is_st属性:- 该属性会自动判断股票在当前回测时间点是否被标记为 ST 或 *ST。
- 如果是 ST 或 *ST,返回
True。 - 如果是正常股票,返回
False。 - 它包含了 ST(特别处理)和 *ST(退市风险警示)两种情况,无需分别判断。
常见误区
- 不要通过股票名称过滤:不要尝试获取
display_name然后判断字符串中是否包含 "ST"。因为股票名称可能会发生变更,且字符串匹配效率较低,容易出错。直接使用官方提供的is_st字段是最准确和高效的。
Q&A
Q: is_st 属性是否包含退市整理期的股票?
A: is_st 主要针对被实施特别处理的股票。对于退市整理期的股票,建议结合 get_current_data()[security].name 判断是否包含“退”字,或者检查 paused 属性(如果已停牌)。但在大多数策略中,过滤掉 ST 和停牌股票(paused)通常就足够规避大部分风险。
Q: 过滤 ST 股票会引入未来函数吗?
A: 使用 get_current_data() 不会引入未来函数。该函数获取的是策略运行当时(例如 before_trading_start 运行时的 09:00)已知的状态。
Q: 除了 ST,通常还需要过滤什么?
A: 在选股策略中,通常建议同时过滤掉 停牌股票 (current_data[stock].paused) 和 涨跌停股票(无法买入或卖出),以保证策略的成交真实性。