使用tushare筛选某一天的ST股票

Tushare数据平台提供了丰富的金融数据,对于量化分析来说是必不可少的利器。但是相比其他在线平台,它提供的数据都是比较基础的,需要自己加工。
比如量化分析时经常需要剔除当时的ST、*ST股票,tushare没有提供现成的工具。

现成方法

网上现成的方法都是筛选某一只股票在特定时间是否ST,比如这样的:Tushare判断指定日期股票是否ST,基本思路是使用tushare的“股票曾用名”函数,先提取单只股票所有的更名记录,然后判断要筛选的时间是否在ST的时间范围内。

我试了一下,运行这位大佬的函数需要0.1秒,对单只股票来说不错,但是如果要筛选一个时间点所有ST股票难道要调用5000多次,那就是500多分钟,8个多小时?显然是不可接受的。

函数解析

tushare的“股票曾用名”函数定义如下:

pro = ts.pro_api()

df = pro.namechange(ts_code,start_date,end_date,fields)

返回结果:
名称	类型	默认输出	描述
ts_code	str	Y	TS代码
name	str	Y	证券名称
start_date	str	Y	开始日期
end_date	str	Y	结束日期
ann_date	str	Y	公告日期
change_reason	str	Y	变更原因

注意这里有个小坑:参数中的start_date,end_date是公告日期,返回结果中的start_date,end_date是st的开始时间和结束时间,不过对接下来的程序影响不大,知道就行了。

这个函数可以不用指定股票代码,甚至不用任何参数,也就是说可以一次调取历史上所有股票所有更名记录。经测试,调用所有数据只需要0.8秒,在可接受范围。
当然还可以优化,由于ST最多3年就要退市,可以只取3年内被ST的记录。这样时间可以缩短到大约0.4秒。

注意有坑

说到这里思路就出来了:提取3年内所有股票更名记录,然后筛选目标时间在返回结果的start_date和end_date之间的数据,就是目标时间处于ST状态的股票了。但是注意有个坑:

运行如下代码:

pro.namechange(ts_code='002122.SZ')

输出结果:

ts_code	name	start_date	end_date	ann_date	change_reason
0	002122.SZ	天马股份	20230228	None	20230227	撤销ST
1	002122.SZ	ST天马	20230110	None	20230107	撤销*ST
2	002122.SZ	ST天马	20230110	20230227	20230107	撤销*ST
3	002122.SZ	*ST天马	20221102	None	20221101	*ST
4	002122.SZ	*ST天马	20221102	20230109	20221101	*ST
5	002122.SZ	ST天马	20210616	None	20210615	摘星
6	002122.SZ	ST天马	20210616	20221101	20210615	摘星
7	002122.SZ	*ST天马	20180503	None	20180502	*ST
8	002122.SZ	*ST天马	20180503	20210615	20180502	*ST
9	002122.SZ	天马股份	20070328	20180502	None	其他|

注意看,每次更名ST的记录都出现了两次,其中一次end_date为None,另一次为正常时间。如果直接判断会出错,必须把多余的一次去掉。使用如下代码:

pro.namechange(ts_code='002122.SZ').sort_values(by='end_date',ascending=True).drop_duplicates(['ts_code','start_date'],keep='first')

输出为:


ts_code	name	start_date	end_date	ann_date	change_reason
9	002122.SZ	天马股份	20070328	20180502	None	其他
8	002122.SZ	*ST天马	20180503	20210615	20180502	*ST
6	002122.SZ	ST天马	20210616	20221101	20210615	摘星
4	002122.SZ	*ST天马	20221102	20230109	20221101	*ST
2	002122.SZ	ST天马	20230110	20230227	20230107	撤销*ST
0	002122.SZ	天马股份	20230228	None	20230227	撤销ST

输出正确!

完整代码

import datetime as datetime
import tushare as ts

ts.set_token('******')
#此处为注册后才有的token,请用文章开头的链接注册
pro = ts.pro_api()
def get_st(trade_date):
    '''
    功能:筛选指定时间ST、*ST股票
    输入:要筛选的目标日期,格式YYYYMMDD
    输出:该时间内处于ST、*ST状态的股票代码、名称、ST开始结束日期、公告日期
    '''
    # 获取三年前日期,因为ST最多3年
    start_date = (datetime.datetime.strptime(trade_date,'%Y%m%d') - datetime.timedelta(days=365*3)).strftime('%Y%m%d')
    # 获取三年内所有更名记录
    df = pro.namechange(start_date=start_date,end_date=trade_date, fields='ts_code,name,start_date,end_date,ann_date,change_reason')
    # 筛选更名原因为ST或*ST的记录,去掉结束日期重复为None的
    df = df[(df['change_reason']=='ST') | (df['change_reason']=='*ST')] \
.sort_values(by='end_date',ascending=True).drop_duplicates(subset=['ts_code','start_date'],keep='first')
    # 筛选目标日期在ST时间段的记录
    result = df[(df.start_date<=trade_date) & ((df.end_date>=trade_date) | (df.end_date.isna()))]
    return result
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值