#!/user/bin/env python
import time
import datetime
import pandas as pd
import numpy as np
import tushare as ts
import warnings
warnings.filterwarnings('ignore')
ts.set_token("1184ddddddddddddddddddddddddddddddddddf79f1") #请自行填入自己的token
pro = ts.pro_api()
# !!!这里需要自己填写:当天的日期
date_str = '20200120'
# 十年前的日期
start_date_str = '20100101'
# 获取所有A股股票当天的股票代码、交易日期、最新价格、股息率、PE、PB、总市值
df = pro.daily_basic(ts_code='', trade_date=date_str,
fields='ts_code,trade_date,close,dv_ratio,pe,pb,total_mv')
# 特殊处理:如果PE、PB、股息率是NAN值的话,删除该股票
# 筛选条件:
# 1、删除pb>1.5的股票
# 2、删除过去10年pb从来不高于1的股票
# 3、删除股息率为0的股票
# 4、排序:按照pe、pb、股息率越小得分越低去排序,总得分越低排序越靠前,负数的得分为非负数的个数+1
# 如果PE、PB、股息率是NAN值的话,删除该股票
afternan_df = df.dropna(axis=0, how='any',subset=['pe','pb','dv_ratio'])
afternan_df.reset_index(drop=True,inplace=True) # 重新写序号
# 删除pb>1.5的股票
afterpb_df = afternan_df[afternan_df.pb<=1.5]
afterpb_df.reset_index(drop=True,inplace=True) # 重新写序号
# 删除股息率为0的股票
afterpb_df[afterpb_df[['dv_ratio']]==0]=np.nan
afterdv_df = afterpb_df.dropna(axis=0, how='any',subset=['dv_ratio'])
afterdv_df.reset_index(drop=True,inplace=True) # 重新写序号
# 删除过去10年pb从来不高于1的股票(每个月的pb都取出来)
monthdate_df = pro.index_monthly(ts_code='000001.SH', start_date=start_date_str, end_date=date_str, fields='trade_date')
month_date_ls = monthdate_df.trade_date.tolist()
month_pb_10years_df = pd.DataFrame()
for month_date in month_date_ls:
# month_pb_df = pro.daily_basic(ts_code=afterdv_df.ts_code.tolist(), trade_date=month_date,
# fields='ts_code,trade_date,pb')
month_pb_df = pro.daily_basic(ts_code='', trade_date=month_date,
fields='ts_code,trade_date,pb')
month_pb_10years_df = pd.concat([month_pb_10years_df,month_pb_df],axis=0)
for stockcode in afterdv_df.ts_code.tolist():
stock_pb_df = month_pb_10years_df[month_pb_10years_df.ts_code==stockcode]
# 10年间最大的pb
max_pb = max(stock_pb_df.pb.tolist())
afterdv_df.loc[afterdv_df.ts_code==stockcode,'max_pb_10years'] = max_pb #记录过去10年间最大的pb
mystocks_df = afterdv_df[afterdv_df.max_pb_10years>=1] # 筛选出过去10年最大pb>=1的股票,至此,所有筛选条件已经完毕
mystocks_df.reset_index(drop=True,inplace=True) # 重新写序号
# 取股票股票名字、所属行业和审计机构数据
hy_df = pro.stock_basic(exchange='', list_status='L', fields='ts_code,name,industry')
mystocks_df = pd.merge(mystocks_df,hy_df,how='inner',on='ts_code')
for ind,stockcode in enumerate(mystocks_df.ts_code.tolist()):
# 股票最近一年的审计意见,取最新一次的审计机构为审计机构
# 因为接口限制,每分钟只能访问接口60次,所以每60次,休眠60s
if not (ind+1)%60: # 避免一开始浪费时间,+1
time.sleep(60)
audit_beg_date = datetime.datetime.strftime(
datetime.datetime.strptime(date_str,'%Y%m%d')-datetime.timedelta(365),'%Y%m%d')
stock_audit_df = pro.fina_audit(ts_code=stockcode, start_date=audit_beg_date, end_date=date_str)
mystocks_df.loc[mystocks_df.ts_code==stockcode,'audit_agency'] = stock_audit_df.loc[0,'audit_agency']
# 排序:按照pe、pb、股息率越小得分越低去排序,总得分越低排序越靠前,负数的得分为非负数的个数+1
# 先把为负数的记录为无穷大,即可解决
mystocks_df[mystocks_df['pe']<=0]=np.inf
mystocks_df[mystocks_df['pb']<=0]=np.inf
mystocks_df.loc[:,'pe_score'] = mystocks_df.pe.rank(ascending=True, method='min')
mystocks_df.loc[:,'pb_score'] = mystocks_df.pb.rank(ascending=True, method='min')
mystocks_df.loc[:,'dv_ratio_score'] = mystocks_df.dv_ratio.rank(ascending=False, method='min')
mystocks_df.loc[:,'score_sum'] = mystocks_df[['pe_score','pb_score','dv_ratio_score']].sum(axis=1)
# 按照总得分从低到高排序
mystocks_df.sort_values(['score_sum'],ascending=True,inplace=True)
mystocks_df.reset_index(drop=True,inplace=True) # 重新写序号
# 最后输出表stocks_score_df
# 表的列名为:股票代码、股票名字、目前股价、总市值、pe、pb、股息率、pe得分、pb得分、股息率得分、总得分、所属行业、审计机构
stocks_score_df = mystocks_df[['ts_code','name','close','total_mv','pe','pb','dv_ratio',
'pe_score','pb_score','dv_ratio_score','score_sum','industry','audit_agency']] #列稍微排个序
stocks_score_df.to_excel('stocks_score'+date_str+'.xlsx')
print("The End!")