当前位置: 首页 > news >正文

别再一只只查了!用Tushare Pro批量筛选全市场ST股票,效率提升百倍

金融数据高效处理:Tushare Pro批量筛选ST股票实战指南

在量化投资和风险管理领域,快速准确地识别ST/*ST股票是每个专业分析师的基本功。传统单只查询的方法不仅耗时费力,更可能错过关键交易时机。本文将彻底改变你的工作流程,展示如何利用Tushare Pro的批量查询能力,在秒级完成全市场ST状态筛查。

1. 传统方法的效率瓶颈与突破思路

大多数金融数据工程师第一次接触ST股票筛选时,都会从单只股票查询开始。这种方法看似简单直接,却隐藏着巨大的效率陷阱。以A股市场约5000只股票计算,单只查询0.1秒的速度看似很快,但全市场扫描需要近8小时——这在实际交易环境中完全不可行。

关键效率对比

方法类型单次查询时间全市场耗时适用场景
单只循环查询0.1秒~500分钟极少量股票检查
批量全量查询0.8秒0.8秒全市场扫描
时间范围优化0.4秒0.4秒近期数据筛查

突破点在于发现namechange接口的隐藏特性——它可以不指定股票代码直接获取全市场数据。这个看似简单的认知转变,将工作效率提升了三个数量级。

2. Tushare Pro批量查询核心技术解析

2.1 接口参数深度理解

pro.namechange()接口的设计初衷是查询股票名称变更历史,但巧妙运用其参数可以实现ST状态批量识别。核心参数包括:

pro.namechange( ts_code=None, # 不指定则返回全市场数据 start_date='20200101', # 查询起始日 end_date='20231231', # 查询结束日 fields='ts_code,name,start_date,end_date,ann_date,change_reason' )

参数使用技巧

  • 留空ts_code实现全市场扫描
  • 合理设置start_date缩小查询范围(ST股票通常3年内会退市)
  • 精确选择fields减少不必要的数据传输

2.2 数据清洗关键步骤

原始数据中存在需要特别注意的"坑",主要是重复记录问题。典型数据异常表现为:

ts_code name start_date end_date change_reason 002122.SZ ST天马 20230110 None 撤销*ST 002122.SZ ST天马 20230110 20230227 撤销*ST

处理方案:

# 按end_date排序后去重 clean_df = (raw_df.sort_values('end_date', ascending=True) .drop_duplicates(['ts_code', 'start_date'], keep='first'))

3. 完整解决方案与性能优化

3.1 基础实现代码框架

import datetime import tushare as ts def get_st_stocks(target_date): """获取指定日期的全市场ST股票清单 Args: target_date (str): 格式为'YYYYMMDD'的目标日期 Returns: DataFrame: 包含ts_code, name, start_date, end_date的ST股票清单 """ pro = ts.pro_api('your_token_here') # 计算3年前日期作为查询起点 start_date = (datetime.datetime.strptime(target_date, '%Y%m%d') - datetime.timedelta(days=365*3)).strftime('%Y%m%d') # 批量获取全市场名称变更记录 raw_data = pro.namechange( start_date=start_date, end_date=target_date, fields='ts_code,name,start_date,end_date,change_reason' ) # 数据清洗与筛选 st_stocks = ( raw_data[ (raw_data['change_reason'].isin(['ST', '*ST'])) & (raw_data['start_date'] <= target_date) & ((raw_data['end_date'] >= target_date) | (raw_data['end_date'].isna())) ] .sort_values('end_date') .drop_duplicates(['ts_code', 'start_date']) ) return st_stocks[['ts_code', 'name', 'start_date', 'end_date']]

3.2 进阶性能优化技巧

内存优化方案

  • 分批次查询:对于超大时间范围,可分年度查询后合并
  • 字段精简:只请求必要字段减少数据传输量
  • 本地缓存:将常用时间段数据保存为本地文件

查询速度对比测试

数据范围记录数原始耗时优化后耗时
1个月1,2000.9s0.6s
1年8,5001.2s0.8s
3年24,0001.8s1.1s

4. 生产环境中的实战应用

4.1 量化研究集成方案

将ST筛选功能嵌入因子研究流程:

def clean_factor_data(factor_df, trade_date): """在因子数据中剔除ST股票""" st_stocks = get_st_stocks(trade_date) clean_df = factor_df[~factor_df['ts_code'].isin(st_stocks['ts_code'])] return clean_df

4.2 实时风控系统对接

对于实时交易系统,建议采用以下架构:

  1. 盘前批量更新ST名单
  2. 内存中维护当前ST股票集合
  3. 订单执行前快速校验
  4. 异常交易实时预警

风控检查代码示例

def pre_trade_check(order): if order['ts_code'] in current_st_set: raise ValueError(f"拒绝ST股票交易: {order['ts_code']}") # 其他风控检查...

4.3 历史回测注意事项

处理历史ST状态时需要特别小心:

  • 使用复权价格避免停牌期价格失真
  • 考虑ST公告日与实际生效日的时间差
  • 处理特殊情形如暂停上市后又恢复交易
# 回测中正确处理ST状态的示例 def adjust_for_st(status_df, price_df): """根据ST状态调整价格序列""" merged = pd.merge_asof( price_df.sort_values('trade_date'), status_df.sort_values('start_date'), on='trade_date', by='ts_code' ) merged['adj_close'] = np.where( merged['is_st'], merged['close'] * 0.95, # 模拟ST股票流动性折扣 merged['close'] ) return merged

5. 异常处理与边界情况

实际应用中会遇到各种特殊情况,需要完善处理逻辑:

典型边界案例

  • 新上市股票尚无历史数据
  • 长时间停牌后恢复交易的股票
  • 多次在ST和正常状态间切换的股票
  • 退市整理期的特殊处理

健壮性增强代码

try: st_data = get_st_stocks(target_date) except ts.DataError as e: logger.error(f"Tushare接口异常: {str(e)}") st_data = load_local_cache(target_date) # 降级方案 except Exception as e: logger.exception("未知错误") raise

处理特殊日期逻辑:

# 判断是否为交易日 if not is_trading_day(target_date): raise ValueError("非交易日无ST状态数据") # 处理节假日顺延 while not is_trading_day(target_date): target_date = (datetime.strptime(target_date, '%Y%m%d') + timedelta(days=1)).strftime('%Y%m%d')
http://www.jsqmd.com/news/879293/

相关文章:

  • Gemini ESG报告生成全流程拆解,从数据接入、指标映射到审计就绪PDF一键输出
  • 2026年温州瓯海黄金金条/饰品回收公司哪家好?——企业级选型指南与行业标杆深度解析 - 2026年企业推荐榜
  • IoT设备协议逆向实战:从加密HTTP流量还原标准API
  • ChatGPT记忆功能怎么用:仅剩48小时!OpenAI即将关闭Beta记忆入口——立即掌握这5个不可逆存档技巧
  • 文档下载自动化:从技术视角解析开源工具的高效解决方案
  • 5分钟让你拥有微信自动化能力
  • VEESA框架:函数型数据机器学习可解释性实战指南
  • 告别重复造轮子:用ArcGIS脚本工具封装你的Python代码,效率提升不止一点点
  • SketchUp STL插件:从3D建模到实体打印的完整指南
  • 【MySQL全面教学】MySQL聚合函数与分组Day5(2026年)
  • C# Unity人形机器人数字孪生:从物理建模到ZMP平衡控制
  • 2026 年 5 月温州瓯海黄金金条饰品回收公司哪家好?企业级选型深度报告 - 2026年企业推荐榜
  • 避坑指南:在Ubuntu 20.04搭配CUDA 11.3/11.4环境下,成功安装并验证TensorRT 8.2.5的关键几步
  • 机器学习公平性新视角:用自一致性度量与拒绝机制应对决策任意性
  • 手把手教你:通过iLO5远程为HPE Gen10服务器安装Windows Server 2012 R2(含P816i-a SR阵列卡驱动加载避坑指南)
  • ChatGPT自动生成项目计划书:7步标准化流程,从需求输入到可交付文档一键输出
  • 开源热物理计算库CoolProp:工程计算与科研分析的强大引擎
  • 【MySQL全面教学】MySQL多表查询与JOIN Day6(2026年)
  • 融合物理与数据:基于切削力学的机器学习建模革新加工动力学
  • 从KL散度到比率散度:对称度量如何优化概率模型训练与采样
  • ssm网上订餐系统(10089)
  • AppImageLauncher:3步破解Linux应用安装难题的终极解决方案
  • 如何用1分钟语音数据训练高质量AI语音克隆?GPT-SoVITS完整指南揭秘
  • 留存完整活动轨迹,助力事故溯源与险情复盘 ——以山西通洲集团留神峪煤矿“5·22”瓦斯爆炸为例
  • Windows 10/11 上从零部署DETR:手把手教你搞定COCOAPI安装与自定义数据集训练
  • 电脑里突然冒出的FNPLicensingService.exe是啥?手把手教你关闭它(附Adobe/CAD/Xshell等软件排查指南)
  • 别再只用OTSU了!OpenCV实战:用Triangle算法搞定单峰图像的二值化(附Python代码)
  • 告别黑屏!手把手教你为OpenEuler 22.03 LTS配置漂亮的XFCE桌面(附LightDM背景修复)
  • 凯莱德门业怎么样?3万平方生产基地、200名员工,专注铸铝门与高端大门定制 - Amonic
  • ssm仓库管理信息系统(10091)