from datetime import datetime as dt
from datetime import timedelta
import numpy as np
import pandas as pd
import tushare as ts
# 对于tushare的一些初始化设置
token = "[你的tushare密钥]"
ts.set_token(token)
pro = ts.pro_api(token)
# 对于warnings的一个过滤,除非你知道你在干嘛,如果不了解建议别乱过滤
from warnings import simplefilter
from pandas.errors import PerformanceWarning, SettingWithCopyWarning
def ignore_warnings():
simplefilter(action="ignore", category=FutureWarning)
simplefilter(action="ignore", category=DeprecationWarning)
simplefilter(action="ignore", category=UserWarning)
simplefilter(action="ignore", category=SyntaxWarning)
simplefilter(action="ignore", category=PerformanceWarning)
simplefilter(action="ignore", category=SettingWithCopyWarning)
前几天在进行日常的代码学习和检查,忽然发现一个问题:就是我的股票池有一个返回值连续两天是空值,我就开始了我的核查。后来发现是tushare之前的张婷的股票查询进行了升级和改动。现在返回值和过去的返回值都变了,所以呢我就需要对代码进行一些微调。即使是微调,我还是发现了一个我的知识盲区。
d00 = dt.now()
d01 = d00 - timedelta(days=22)
today = d00.strftime("%Y%m%d")
month = d01.strftime("%Y%m%d")
我们需要返回的列有:日期,交易代码,行业,企业名称,收盘价,涨幅,流动市值,换手率,炸板次数,封板频率,连续封板次数
fields = ['trade_date', 'ts_code', 'industry',
'name', 'close', 'pct_chg', 'float_mv',
'turnover_ratio', 'open_times',
'up_stat', 'limit_times']
data = pro.limit_list_d(start_date=month, end_date=today, limit_type="U", fields=fields)
>>> #,trade_date,ts_code,industry,name,close,pct_chg,float_mv,turnover_ratio,open_times,up_stat,limit_times
>>> 0,20230922,688498.SH,半导体,源杰科技,183.92,20.00,3.725956e+09,21.62,0,1/1,1
>>> 1,20230922,605277.SH,消费电子,新亚电子,14.82,10.02,1.629821e+09,16.94,0,1/1,1
>>> 2,20230922,603496.SH,互联网服,恒为科技,21.47,9.99,6.874892e+09,11.57,8,1/1,1
>>> 3,20230922,603220.SH,通信服务,中贝通信,26.65,9.99,8.896354e+09,21.88,3,1/1,1
>>> 4,20230922,603206.SH,通信服务,嘉环科技,18.00,10.02,1.569600e+09,14.88,0,1/1,1
data = data[~data.name.str.contains('\*')] # 去除带星名称的
data = data[~data.name.str.contains('ST')] # 去除带ST名称的
data = data[~data.name.str.contains('N')] # 去除带N名称的
data = data[data.open_times <= 5] # 当天炸板不能多余5次
data = data[data.limit_times <= 3] # 连续涨停不能超过3天
data = data[data.turnover_ratio <= 20] # 换手率20以内
data = data[data.float_mv >= 4*10**9] # 只看40+亿市值的公司
>>> #,trade_date,ts_code,industry,name,close,pct_chg,float_mv,turnover_ratio,open_times,up_stat,limit_times
>>> 5,20230922,603123.SH,商业百货,翠微股份,11.24,9.98,7.331582e+09,8.30,1,1/1,1
>>> 6,20230922,603118.SH,通信设备,共进股份,11.62,10.04,9.144775e+09,6.60,0,1/1,1
>>> 7,20230922,603083.SH,通信设备,剑桥科技,48.10,9.99,1.253020e+10,11.24,0,1/1,1
>>> 9,20230922,601858.SH,文化传媒,中国科传,30.92,10.00,2.444226e+10,5.75,4,1/1,1
>>> 14,20230922,300570.SZ,通信设备,太辰光,39.20,19.99,7.598915e+09,16.16,0,1/1,1
我是故意将行业放入在数据列中的,我的目的是想看哪些行业的股票再这过去的22天内,那些个行业出现的频率次数最多,然后过滤掉那些频率低的。我更看好大概率事件,而非偶然的个例。然后我就开始头大了,因为我还真没这么过滤过数据。
data = data[data.industry.value_counts() > 5]
>>> IndexingError: Unalignable boolean Series provided as indexer
(index of the boolean Series and of the indexed object do not match).
这行代码看着好像与之前的过滤方式有异曲同工之妙之处。但是,我们引用value_count()
这个函数, 导致我们的过滤并非是一个简简单单的对于某列进行简易的筛选,所以我们不能这样做,而且也不会成功,因为它报错了: IndexError。说明我们的索引出现了问题,我们的判定是True 和 False 的返回,并不是数值返回,所以我们需要对代码进行修改。报错的提示很明了,我们看到的是IndexError,那我们应该从Index上入手。我们要过滤的是industry行业列,那我们就把行业列设为Index。然后我们只是需要在上面的代码加上.loc
函数即可,这样我们的目的就达到了,我们来看看输出如何。
data.index = data.industry
data = data.loc[data.industry.value_counts() > 5]
>>> #,industry,trade_date,ts_code,industry,name,close,pct_chg,float_mv,turnover_ratio,open_times,up_stat,limit_times
>>> 1,商业百货,20230922,603123.SH,商业百货,翠微股份,11.24,9.98,7.331582e+09,8.30,1,1/1,1
>>> 2,通信设备,20230922,603118.SH,通信设备,共进股份,11.62,10.04,9.144775e+09,6.60,0,1/1,1
>>> 3,通信设备,20230922,603083.SH,通信设备,剑桥科技,48.10,9.99,1.253020e+10,11.24,0,1/1,1
>>> 4,文化传媒,20230922,601858.SH,文化传媒,中国科传,30.92,10.00,2.444226e+10,5.75,4,1/1,1
>>> 5,通信设备,20230922,300570.SZ,通信设备,太辰光,39.20,19.99,7.598915e+09,16.16,0,1/1,1
当我们运用到通过一些函数来对于数据Dataframe进行过滤筛选的时候,我们最好是把需要过滤筛选的列作为索引先,然后用df.loc
来进行过滤筛选数据。这个方法你学废了么?