├── README.md ├── TS_getStock.py ├── TS分析单只股票_单周期.py ├── TS分析单只股票_多周期平均达标.py ├── TS获取股票行情.py ├── TS获取股票财务指标.py ├── TS获取资产负债表.py ├── TS计算大股东质押率.py ├── TS财务和质押指标选股_单周期.py ├── TS财务指标选股_多周期平均达标.py └── TS财务指标选股_多周期每期达标.py /README.md: -------------------------------------------------------------------------------- 1 | ## TS_Stock_Analyse 2 | 利用Tushare接口的原始数据,经过数据清理和加工,搭建股票分析模型。 3 | 4 | ## 一、获取数据 5 | 1.获取全量股票列表,模块为“TS_getStock.py” 6 | 2.获取指定单只/多只股票的财务、行情数据: 7 | 2.1 获取基本财务指标,模块为“TS获取股票财务指标.py” 8 | 2.2 获取资产负债表指标,模块为"TS获取资产负债表“ 9 | 2.3 获取价格行情指标,模块为”TS获取股票行情.py" 10 | 3.获取每个股东的质押数据,计算前十大股东的质押率,质押率特别说明: 11 | 1)存在质押的前十大股东累计质押股数/存在质押的前十大股东累计持股数 12 | 2)存在质押的前十大股东每人的质押率 13 | 模块为“TS计算大股东质押率.py” 14 | 15 | ## 二、分析单只股票 16 | 根据基础的财务指标、行情指标、质押数据,计算组合指标的数据,并对关键指标的值设置预警标准。输入股票后,系统自动分析该股票的财务、行情、质押数据,打印指标值及预警信息。分为: 17 | 1.根据单一财务报告期、某个时点的股价和质押数据,分析单只股票,模块为“TS分析单只股票_单周期.py” 18 | 2.根据多个财务报告期、某个时点的股价和质押数据,分析单只股票,模块为“TS分析单只股票_多周期平均达标.py” 19 | 20 | ## 三、筛选符合选股条件的股票池 21 | 根据基础的财务指标、行情指标、质押数据,计算组合指标的数据,并对关键指标的值设置预警标准。输入股票后,系统自动分析该股票的财务、行情、质押数据,打印指标值及预警信息。分为: 22 | 1.根据单一财务报告期、某个时点的股价和质押数据,筛选达标的股票池,模块为“TS财务和质押指标选股_单周期.py”, 23 | 2.根据多个财务报告期的数据,根据平均值达标筛选股票池,模块为“TS财务指标选股_多周期平均达标.py” 24 | 3.根据多个财务报告期的数据,根据每期值都达标筛选股票池,模块为“TS财务指标选股_多周期每期达标” 25 | 26 | -------------------------------------------------------------------------------- /TS_getStock.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | 5 | # 从本地读取token 6 | f = open('D:\\股票分析\\token.txt') 7 | token = f.read() 8 | 9 | ts.set_token(token) 10 | pro = ts.pro_api() 11 | 12 | def get_stock(): 13 | '''获取股票列表''' 14 | stock_pd = pro.stock_basic(list_status='L', fields='ts_code,symbol,name,area,industry,market,list_date,is_hs') 15 | stock_pd.columns = ['ts_code', '股票代码', '股票名称', '所在地域', '所属行业', '市场类型', '上市日期', '是否沪深港通标的'] 16 | stock_pd = stock_pd.sort_values(by='所属行业', ascending=True) 17 | # count = stock_pd['所属行业'].value_counts(normalize=False, dropna=False) # 按行业统计各行业股票的家数 18 | # kind = set(stock_pd['所属行业'].values) # 获取行业的种类,集合去重 19 | stock_pd.to_csv('D:\\股票分析\\沪深股票列表.csv') 20 | return stock_pd 21 | 22 | if __name__ == '__main__': 23 | get_stock() 24 | -------------------------------------------------------------------------------- /TS分析单只股票_单周期.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | import TS_getStock, TS计算大股东质押率 5 | import time 6 | 7 | # 从本地读取token 8 | f = open('D:\\股票分析\\token.txt') 9 | token = f.read() 10 | 11 | ts.set_token(token) 12 | pro = ts.pro_api() 13 | pd_stock = TS_getStock.get_stock() 14 | 15 | # 1.输入股票 16 | while True: 17 | stock = input('请输入股票名称/代码:') 18 | ts_code = '' 19 | if stock in pd_stock['股票代码'].values: 20 | if stock.startswith('6'): 21 | ts_code = stock + '.SH' 22 | elif stock.startswith('3'): 23 | ts_code = stock + '.SZ' 24 | else: # 最后一种可能性,即是以0开头 25 | ts_code = stock + '.SZ' 26 | break 27 | 28 | elif stock in pd_stock['股票名称'].values: 29 | ts_code = list(pd_stock[pd_stock['股票名称'].isin([stock])]['ts_code'])[0] # 将series转化成列表,取出列表中的值 30 | break 31 | 32 | else: 33 | print('输入的股票不存在,请重新输入:') 34 | 35 | 36 | # 2.调用接口,查询财务指标、资产负债表、最新日行情, 并去重。同时查找股票基本信息 37 | pd_fin = pro.fina_indicator(ts_code=ts_code, period='20191231', fields= 38 | 'ts_code, ann_date, end_date, eps, dt_eps, total_revenue_ps, profit_dedt, current_ratio, quick_ratio,' 39 | 'inv_turn, ar_turn, assets_turn, bps, profit_to_gr, op_of_gr, roe, roe_waa, roe_dt, roa,' 40 | 'salescash_to_or, ocf_to_opincome, debt_to_assets, basic_eps_yoy, dt_eps_yoy, op_yoy, netprofit_yoy, dt_netprofit_yoy,' 41 | 'roe_yoy, tr_yoy, or_yoy, rd_exp, update_flag', timeout=5) 42 | pd_fin = pd_fin.drop_duplicates(subset=['ts_code'], keep='last') 43 | 44 | pd_fin.columns = ['ts_code', '公告日期', '报告期', '基本每股收益', '稀释每股收益', '每股营业总收入', '扣除非经常性损益后的净利润', '流动比率', '速动比率', '存货周转率', '应收账款周转率', '总资产周转率', 45 | '每股净资产', '净利率(%)', '营业利润率(%)', '净资产收益率(%)', '加权平均净资产收益率(%)', '净资产收益率(扣除非经常性损益)(%)', '总资产报酬率(%)', '销售商品提供劳务收到的现金/营业收入', 46 | '经营活动产生的现金流量净额/经营活动净收益', '资产负债率(%)', '基本每股收益同比增长率(%)', '稀释每股收益同比增长率(%)', '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', 47 | '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', '净资产收益率(摊薄)同比增长率(%)', '营业总收入同比增长率(%)', '营业收入同比增长率(%)', '研发费用', '更新标识'] 48 | 49 | 50 | pd_balance = pro.balancesheet(ts_code=ts_code, period='20191231', fields='ts_code, end_date, report_type, comp_type, total_share,' 51 | 'money_cap, trad_asset, notes_receiv, accounts_receiv, oth_receiv, prepayment, inventories,' 52 | 'fa_avail_for_sale, htm_invest, lt_eqt_invest, time_deposits,' 53 | 'intan_assets, r_and_d, goodwill, total_assets, total_liab, minority_int, total_hldr_eqy_exc_min_int,' 54 | 'total_hldr_eqy_inc_min_int, update_flag', timeout=5) 55 | pd_balance = pd_balance.drop_duplicates(subset=['ts_code'], keep='last') 56 | 57 | pd_balance.columns = ['ts_code', '报告期', '报表类型', '公司类型', '期末总股本', 58 | '货币资金', '交易性金融资产', '应收票据', '应收账款', '其他应收款', '预付款项', '存货', 59 | '可供出售金融资产', '持有至到期投资', '长期股权投资', '定期存款', 60 | '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '少数股东权益', '股东权益合计(不含少数股东权益)', '股东权益合计(含少数股东权益)', 61 | '更新标识'] 62 | 63 | 64 | pd_price = ts.pro_bar(ts_code=ts_code, start_date='20200706', end_date='20200706', adj='qfq', 65 | factors=['tor', 'vr']) # 本接口不需要用pro.pro_bar 66 | 67 | pd_price.columns = ['交易日期', 'ts_code', '开盘价', '最高价', '最低价', '收盘价', '昨收价', '涨跌额', '涨跌幅 ', '成交量(手)', '成交额(千元)', 68 | '换手率', '量比'] 69 | 70 | pd_basic = pd_stock[pd_stock['ts_code'] == ts_code] 71 | 72 | 73 | # 3.合并以上查到的表字段 74 | plus1 = pd_fin.merge(pd_balance, how='left', on='ts_code') # 将财务指标表与资产负债表合并 75 | plus2 = plus1.merge(pd_price, how='left', on='ts_code') # 将合并的表与股票行情表合并 76 | plus3 = plus2.merge(pd_basic, how='left', on='ts_code') # 将合并的表与股票基本信息表合并 77 | 78 | 79 | # 4.增加相关字段 80 | plus3['市盈率'] = plus3['收盘价']/plus3['基本每股收益'] 81 | plus3['市净率'] = plus3['收盘价']/plus3['每股净资产'] 82 | plus3['商誉净资产比'] = plus3['商誉']/plus3['股东权益合计(含少数股东权益)'] 83 | plus3['存货净资产比'] = plus3['存货']/plus3['股东权益合计(含少数股东权益)'] 84 | plus3['应收账款净资产比'] = plus3['应收账款']/plus3['股东权益合计(含少数股东权益)'] 85 | plus3['应收票据净资产比'] = plus3['应收票据']/plus3['股东权益合计(含少数股东权益)'] 86 | 87 | # 数字与NaN(空值)相加为0的处理方法1——对于列中值为NaN的数据,在新创建的副本中替换为0,再赋给原对象,以便相加 88 | # plus3.loc[:, ['应收账款净资产比', '应收票据净资产比']] = plus3.loc[:, ['应收账款净资产比', '应收票据净资产比']].fillna(0) 89 | # # 数字与NaN(空值)相加为0的处理方法2——对于列中值为NaN的数据,在原对象(非新创建的副本)中先替换为0,以便相加。注意:方法1中用loc选择多行后,不能用 90 | # # inplace=True,可能是因为loc选择多行后,已经脱离了原对象,创建了新对象 91 | # plus3['应收账款净资产比'].fillna(0, inplace=True) 92 | # plus3['应收票据净资产比'].fillna(0, inplace=True) 93 | # plus3['应收账款和应收票据合计占净资产比'] = plus3['应收账款净资产比'] + plus3['应收票据净资产比'] 94 | # # 数字与NaN(空值)相加为0的处理方法3——不更改原始列,只更改相加汇总的列,在汇总列中的计算中,将值NaN替换为0 95 | plus3['应收账款和应收票据合计占净资产比'] = plus3['应收账款净资产比'].add(plus3['应收票据净资产比'], fill_value=0) 96 | 97 | plus3['扣非净利率(%)'] = plus3['扣除非经常性损益后的净利润']/(plus3['每股营业总收入']*plus3['期末总股本'])*100 98 | plus3['扣非净利润增长率/市盈率'] = plus3['归属母公司股东的净利润-扣除非经常损益同比增长率(%)']/plus3['市盈率'] 99 | 100 | 101 | # 5.打印主要指标,如指标不符合设定标准,打印预警信息 102 | # print(plus3) 103 | print('公司基本信息:') 104 | print('股票名称:', plus3.loc[0, '股票名称']) 105 | print('所属行业:', plus3.loc[0, '所属行业']) 106 | print('所在地域:', plus3.loc[0, '所在地域']) 107 | print('上市日期:', plus3.loc[0, '上市日期']) 108 | print() 109 | 110 | print('公司静态估值数据:') 111 | print('市盈率为:', plus3.loc[0, '市盈率']) 112 | print('市净率为:', plus3.loc[0, '市净率']) 113 | print('扣非净利润增长率/市盈率:', plus3.loc[0, '扣非净利润增长率/市盈率']) 114 | print() 115 | 116 | plus3.fillna(0, inplace=True) 117 | 118 | print('公司2019年的财务数据:') 119 | print('加权平均净资产收益率(%):', plus3.loc[0, '加权平均净资产收益率(%)'], end=' ') 120 | if plus3.loc[0, '加权平均净资产收益率(%)'] < 15: 121 | print('-->预警:加权平均净资产收益率(%)小于15!', end='') 122 | print('\n销售商品提供劳务收到的现金/营业收入:', plus3.loc[0, '销售商品提供劳务收到的现金/营业收入'], end=' ') 123 | if plus3.loc[0, '销售商品提供劳务收到的现金/营业收入'] < 1: 124 | print('-->预警:销售商品提供劳务收到的现金/营业收入小于1!', end='') 125 | print('\n经营活动产生的现金流量净额/经营活动净收益:', plus3.loc[0, '经营活动产生的现金流量净额/经营活动净收益'], end=' ') 126 | if plus3.loc[0, '经营活动产生的现金流量净额/经营活动净收益'] < 1: 127 | print('-->预警:经营活动产生的现金流量净额/经营活动净收益小于1!', end='') 128 | print('\n扣非净利率(%):', plus3.loc[0, '扣非净利率(%)'], end=' ') 129 | if plus3.loc[0, '扣非净利率(%)'] < 15: 130 | print('-->预警:扣非净利率(%)小于15!', end='') 131 | print('\n商誉净资产比:', plus3.loc[0, '商誉净资产比'], end=' ') 132 | if plus3.loc[0, '商誉净资产比'] > 0.5: 133 | print('-->预警:商誉净资产比大于0.5!', end='') 134 | print('\n存货净资产比:', plus3.loc[0, '存货净资产比'], end=' ') 135 | if plus3.loc[0, '存货净资产比'] > 0.5: 136 | print('-->预警:存货净资产比大于0.5!', end='') 137 | print('\n应收账款净资产比:', plus3.loc[0, '应收账款净资产比'], end=' ') 138 | if plus3.loc[0, '应收账款净资产比'] > 0.5: 139 | print('-->预警:应收账款净资产比大于0.5!', end='') 140 | print('\n应收票据净资产比:', plus3.loc[0, '应收票据净资产比'], end=' ') 141 | if plus3.loc[0, '应收票据净资产比'] > 0.5: 142 | print('-->预警:应收票据净资产比大于0.5!', end='') 143 | print('\n应收账款和应收票据合计占净资产比:', plus3.loc[0, '应收账款和应收票据合计占净资产比'], end=' ') 144 | if plus3.loc[0, '应收账款和应收票据合计占净资产比'] > 0.5: 145 | print('-->预警:应收账款和应收票据合计占净资产比大于0.5!', end='') 146 | print('\n资产负债率(%):', plus3.loc[0, '资产负债率(%)'], end=' ') 147 | if plus3.loc[0, '资产负债率(%)'] > 60: 148 | print('-->预警:资产负债率(%)大于60!', end='') 149 | print('\n流动比率:', plus3.loc[0, '流动比率'], end=' ') 150 | if plus3.loc[0, '流动比率'] < 2: 151 | print('-->预警:流动比率小于2!', end='') 152 | print('\n速动比率:', plus3.loc[0, '速动比率'], end=' ') 153 | if plus3.loc[0, '速动比率'] < 1: 154 | print('-->预警:速动比率小于1!', end='') 155 | print('\n营业总收入同比增长率(%):', plus3.loc[0, '营业总收入同比增长率(%)'], end=' ') 156 | if plus3.loc[0, '营业总收入同比增长率(%)'] < 20: 157 | print('-->预警:营业总收入同比增长率(%)小于20!', end='') 158 | print('\n归属母公司股东的净利润同比增长率(%):', plus3.loc[0, '归属母公司股东的净利润同比增长率(%)'], end=' ') 159 | if plus3.loc[0, '归属母公司股东的净利润同比增长率(%)'] < 20: 160 | print('-->预警:归属母公司股东的净利润同比增长率(%)小于20!', end='') 161 | print('\n归属母公司股东的净利润-扣除非经常损益同比增长率(%):', plus3.loc[0, '归属母公司股东的净利润-扣除非经常损益同比增长率(%)'], end=' ') 162 | if plus3.loc[0, '归属母公司股东的净利润-扣除非经常损益同比增长率(%)'] < 20: 163 | print('-->预警:归属母公司股东的净利润-扣除非经常损益同比增长率(%)小于20!', end='') 164 | print() 165 | 166 | # 6.获取前十大股东质押数据 167 | print('\n前十大股东质押数据:') 168 | TS计算大股东质押率.get_pledgeHolders10(ts_code, '20200331') -------------------------------------------------------------------------------- /TS分析单只股票_多周期平均达标.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | import TS_getStock, TS计算大股东质押率 5 | import time 6 | 7 | # 从本地读取token 8 | f = open('D:\\股票分析\\token.txt') 9 | token = f.read() 10 | 11 | ts.set_token(token) 12 | pro = ts.pro_api() 13 | pd_stock = TS_getStock.get_stock() 14 | 15 | # 1.输入股票 16 | while True: 17 | stock = input('请输入股票名称/代码:') 18 | ts_code = '' 19 | if stock in pd_stock['股票代码'].values: 20 | if stock.startswith('6'): 21 | ts_code = stock + '.SH' 22 | elif stock.startswith('3'): 23 | ts_code = stock + '.SZ' 24 | else: # 最后一种可能性,即是以0开头 25 | ts_code = stock + '.SZ' 26 | break 27 | 28 | elif stock in pd_stock['股票名称'].values: 29 | ts_code = list(pd_stock[pd_stock['股票名称'].isin([stock])]['ts_code'])[0] # 将series转化成列表,取出列表中的值 30 | break 31 | 32 | else: 33 | print('输入的股票不存在,请重新输入:') 34 | 35 | 36 | # 2.调用函数,获取股票在指定报告期的财务指标、资产负债表, 并去重,并匹配股票基本信息 37 | def evaluateStock(period): 38 | '''获取某一年度的财务指标''' 39 | pd_fin = pro.fina_indicator(ts_code=ts_code, period=period, fields= 40 | 'ts_code, ann_date, end_date, eps, dt_eps, total_revenue_ps, profit_dedt, current_ratio, quick_ratio,' 41 | 'inv_turn, ar_turn, assets_turn, bps, profit_to_gr, op_of_gr, roe, roe_waa, roe_dt, roa,' 42 | 'salescash_to_or, ocf_to_opincome, debt_to_assets, basic_eps_yoy, dt_eps_yoy, op_yoy, netprofit_yoy, dt_netprofit_yoy,' 43 | 'roe_yoy, tr_yoy, or_yoy, rd_exp, update_flag', timeout=5) 44 | pd_fin = pd_fin.drop_duplicates(subset=['ts_code'], keep='last') 45 | 46 | pd_fin.columns = ['ts_code', '公告日期', '报告期', '基本每股收益', '稀释每股收益', '每股营业总收入', '扣除非经常性损益后的净利润', '流动比率', '速动比率', '存货周转率', '应收账款周转率', '总资产周转率', 47 | '每股净资产', '净利率(%)', '营业利润率(%)', '净资产收益率(%)', '加权平均净资产收益率(%)', '净资产收益率(扣除非经常性损益)(%)', '总资产报酬率(%)', '销售商品提供劳务收到的现金/营业收入', 48 | '经营活动产生的现金流量净额/经营活动净收益', '资产负债率(%)', '基本每股收益同比增长率(%)', '稀释每股收益同比增长率(%)', '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', 49 | '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', '净资产收益率(摊薄)同比增长率(%)', '营业总收入同比增长率(%)', '营业收入同比增长率(%)', '研发费用', '更新标识'] 50 | 51 | 52 | pd_balance = pro.balancesheet(ts_code=ts_code, period=period, fields='ts_code, end_date, report_type, comp_type, total_share,' 53 | 'money_cap, trad_asset, notes_receiv, accounts_receiv, oth_receiv, prepayment, inventories,' 54 | 'fa_avail_for_sale, htm_invest, lt_eqt_invest, time_deposits,' 55 | 'intan_assets, r_and_d, goodwill, total_assets, total_liab, minority_int, total_hldr_eqy_exc_min_int,' 56 | 'total_hldr_eqy_inc_min_int, update_flag', timeout=5) 57 | pd_balance = pd_balance.drop_duplicates(subset=['ts_code'], keep='last') 58 | 59 | pd_balance.columns = ['ts_code', '报告期', '报表类型', '公司类型', '期末总股本', 60 | '货币资金', '交易性金融资产', '应收票据', '应收账款', '其他应收款', '预付款项', '存货', 61 | '可供出售金融资产', '持有至到期投资', '长期股权投资', '定期存款', 62 | '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '少数股东权益', '股东权益合计(不含少数股东权益)', '股东权益合计(含少数股东权益)', 63 | '更新标识'] 64 | 65 | # 合并以上查到的表字段 66 | plus1 = pd_fin.merge(pd_balance, how='left', on='ts_code') # 将财务指标表与资产负债表合并 67 | plus2 = plus1.merge(pd_stock, how='left', on='ts_code') # 将合并的表与股票基本信息表合并 68 | 69 | 70 | # 增加相关字段 71 | plus2['商誉净资产比'] = plus2['商誉']/plus2['股东权益合计(含少数股东权益)'] 72 | plus2['存货净资产比'] = plus2['存货']/plus2['股东权益合计(含少数股东权益)'] 73 | plus2['应收账款净资产比'] = plus2['应收账款']/plus2['股东权益合计(含少数股东权益)'] 74 | plus2['应收票据净资产比'] = plus2['应收票据']/plus2['股东权益合计(含少数股东权益)'] 75 | 76 | # 数字与NaN(空值)相加为0的处理方法1——对于列中值为NaN的数据,在新创建的副本中替换为0,再赋给原对象,以便相加 77 | # plus2.loc[:, ['应收账款净资产比', '应收票据净资产比']] = plus2.loc[:, ['应收账款净资产比', '应收票据净资产比']].fillna(0) 78 | # # 数字与NaN(空值)相加为0的处理方法2——对于列中值为NaN的数据,在原对象(非新创建的副本)中先替换为0,以便相加。注意:方法1中用loc选择多行后,不能用 79 | # # inplace=True,可能是因为loc选择多行后,已经脱离了原对象,创建了新对象 80 | # plus2['应收账款净资产比'].fillna(0, inplace=True) 81 | # plus2['应收票据净资产比'].fillna(0, inplace=True) 82 | # plus2['应收账款和应收票据合计占净资产比'] = plus2['应收账款净资产比'] + plus2['应收票据净资产比'] 83 | # # 数字与NaN(空值)相加为0的处理方法3——不更改原始列,只更改相加汇总的列,在汇总列中的计算中,将值NaN替换为0 84 | plus2['应收账款和应收票据合计占净资产比'] = plus2['应收账款净资产比'].add(plus2['应收票据净资产比'], fill_value=0) 85 | plus2['扣非净利率(%)'] = plus2['扣除非经常性损益后的净利润']/(plus2['每股营业总收入']*plus2['期末总股本'])*100 86 | 87 | return plus2 88 | 89 | list_date = ['20191231', '20181231', '20171231'] 90 | pd_plusDate = pd.DataFrame() 91 | 92 | 93 | for date in list_date: 94 | pd = evaluateStock(date) 95 | pd_plusDate = pd_plusDate.append(pd) 96 | pd_plusDate.index = list(range(3)) # 修改索引,以便后续查找 97 | 98 | 99 | # 3.求最新的股价、市盈率等 100 | pd_price = ts.pro_bar(ts_code=ts_code, start_date='20200706', end_date='20200706', adj='qfq', 101 | factors=['tor', 'vr']) # 本接口不需要用pro.pro_bar 102 | pd_price.columns = ['交易日期', 'ts_code', '开盘价', '最高价', '最低价', '收盘价', '昨收价', '涨跌额', '涨跌幅 ', '成交量(手)', '成交额(千元)', 103 | '换手率', '量比'] 104 | pd_basic = pd_stock[pd_stock['ts_code'] == ts_code] 105 | pd_priceStock = pd_price.merge(pd_basic, how='left', on='ts_code') # 将股票行情表与股票基本表合并 106 | 107 | pd_priceStock['市盈率'] = pd_priceStock['收盘价']/pd_plusDate.loc[0, '基本每股收益'] 108 | pd_priceStock['市净率'] = pd_priceStock['收盘价']/pd_plusDate.loc[0, '每股净资产'] 109 | pd_priceStock['扣非净利润增长率/市盈率'] = pd_plusDate.loc[0, '归属母公司股东的净利润-扣除非经常损益同比增长率(%)'] / pd_priceStock['市盈率'] 110 | 111 | pd_plusDate.fillna(0, inplace=True) 112 | 113 | 114 | # 4.打印公司基本信息、市盈率等 115 | print('1.公司基本信息:') 116 | print('股票名称:', pd_plusDate.loc[0, '股票名称']) 117 | print('所属行业:', pd_plusDate.loc[0, '所属行业']) 118 | print('所在地域:', pd_plusDate.loc[0, '所在地域']) 119 | print('上市日期:', pd_plusDate.loc[0, '上市日期']) 120 | print() 121 | 122 | print('2.公司最新静态估值数据:') 123 | print('市盈率为:', pd_priceStock.loc[0, '市盈率']) 124 | print('市净率为:', pd_priceStock.loc[0, '市净率']) 125 | print('扣非净利润增长率/市盈率:', pd_priceStock.loc[0, '扣非净利润增长率/市盈率']) 126 | print() 127 | 128 | # 5.打印多年财务平均指标 129 | print('3.公司最近%s年的平均财务数据:' % len(list_date)) 130 | print('加权平均净资产收益率(%):', pd_plusDate['加权平均净资产收益率(%)'].mean(), end=' ') 131 | if pd_plusDate['加权平均净资产收益率(%)'].mean() < 15: 132 | print('-->预警:加权平均净资产收益率(%)小于15!', end='') 133 | print('\n销售商品提供劳务收到的现金/营业收入:', pd_plusDate['销售商品提供劳务收到的现金/营业收入'].mean(), end=' ') 134 | if pd_plusDate['销售商品提供劳务收到的现金/营业收入'].mean() < 1: 135 | print('-->预警:销售商品提供劳务收到的现金/营业收入小于1!', end='') 136 | print('\n经营活动产生的现金流量净额/经营活动净收益:', pd_plusDate['经营活动产生的现金流量净额/经营活动净收益'].mean(), end=' ') 137 | if pd_plusDate['经营活动产生的现金流量净额/经营活动净收益'].mean() < 1: 138 | print('-->预警:经营活动产生的现金流量净额/经营活动净收益小于1!', end='') 139 | print('\n扣非净利率(%):', pd_plusDate['扣非净利率(%)'].mean(), end=' ') 140 | if pd_plusDate['扣非净利率(%)'].mean() < 15: 141 | print('-->预警:扣非净利率(%)小于15!', end='') 142 | print('\n商誉净资产比:', pd_plusDate['商誉净资产比'].mean(), end=' ') 143 | if pd_plusDate['商誉净资产比'].mean() > 0.5: 144 | print('-->预警:商誉净资产比大于0.5!', end='') 145 | print('\n存货净资产比:', pd_plusDate['存货净资产比'].mean(), end=' ') 146 | if pd_plusDate['存货净资产比'].mean() > 0.5: 147 | print('-->预警:存货净资产比大于0.5!', end='') 148 | print('\n应收账款净资产比:', pd_plusDate['应收账款净资产比'].mean(), end=' ') 149 | if pd_plusDate['应收账款净资产比'].mean() > 0.5: 150 | print('-->预警:应收账款净资产比大于0.5!', end='') 151 | print('\n应收票据净资产比:', pd_plusDate['应收票据净资产比'].mean(), end=' ') 152 | if pd_plusDate['应收票据净资产比'].mean() > 0.5: 153 | print('-->预警:应收票据净资产比大于0.5!', end='') 154 | print('\n应收账款和应收票据合计占净资产比:', pd_plusDate['应收账款和应收票据合计占净资产比'].mean(), end=' ') 155 | if pd_plusDate['应收账款和应收票据合计占净资产比'].mean() > 0.5: 156 | print('-->预警:应收账款和应收票据合计占净资产比大于0.5!', end='') 157 | print('\n资产负债率(%):', pd_plusDate['资产负债率(%)'].mean(), end=' ') 158 | if pd_plusDate['资产负债率(%)'].mean() > 60: 159 | print('-->预警:资产负债率(%)大于60!', end='') 160 | print('\n流动比率:', pd_plusDate['流动比率'].mean(), end=' ') 161 | if pd_plusDate['流动比率'].mean() < 2: 162 | print('-->预警:流动比率小于2!', end='') 163 | print('\n速动比率:', pd_plusDate['速动比率'].mean(), end=' ') 164 | if pd_plusDate['速动比率'].mean() < 1: 165 | print('-->预警:速动比率小于1!', end='') 166 | print('\n营业总收入同比增长率(%):', pd_plusDate['营业总收入同比增长率(%)'].mean(), end=' ') 167 | if pd_plusDate['营业总收入同比增长率(%)'].mean() < 20: 168 | print('-->预警:营业总收入同比增长率(%)小于20!', end='') 169 | print('\n归属母公司股东的净利润同比增长率(%):', pd_plusDate['归属母公司股东的净利润同比增长率(%)'].mean(), end=' ') 170 | if pd_plusDate['归属母公司股东的净利润同比增长率(%)'].mean() < 20: 171 | print('-->预警:归属母公司股东的净利润同比增长率(%)小于20!', end='') 172 | print('\n归属母公司股东的净利润-扣除非经常损益同比增长率(%):', pd_plusDate['归属母公司股东的净利润-扣除非经常损益同比增长率(%)'].mean(), end=' ') 173 | if pd_plusDate['归属母公司股东的净利润-扣除非经常损益同比增长率(%)'].mean() < 20: 174 | print('-->预警:归属母公司股东的净利润-扣除非经常损益同比增长率(%)小于20!', end='') 175 | print() 176 | 177 | # 6.获取前十大股东质押数据 178 | print('\n4.前十大股东质押数据:') 179 | TS计算大股东质押率.get_pledgeHolders10(ts_code, '20200331') 180 | 181 | 182 | # # 5.打印主要指标,如指标不符合设定标准,打印预警信息 183 | # print('公司2019年的财务数据:') 184 | # print('加权平均净资产收益率(%):', plus3.loc[0, '加权平均净资产收益率(%)'], end=' ') 185 | # if plus3.loc[0, '加权平均净资产收益率(%)'] < 15: 186 | # print('-->预警:加权平均净资产收益率(%)小于15!', end='') 187 | # print('\n销售商品提供劳务收到的现金/营业收入:', plus3.loc[0, '销售商品提供劳务收到的现金/营业收入'], end=' ') 188 | # if plus3.loc[0, '销售商品提供劳务收到的现金/营业收入'] < 1: 189 | # print('-->预警:销售商品提供劳务收到的现金/营业收入小于1!', end='') 190 | # print('\n经营活动产生的现金流量净额/经营活动净收益:', plus3.loc[0, '经营活动产生的现金流量净额/经营活动净收益'], end=' ') 191 | # if plus3.loc[0, '经营活动产生的现金流量净额/经营活动净收益'] < 1: 192 | # print('-->预警:经营活动产生的现金流量净额/经营活动净收益小于1!', end='') 193 | # print('\n扣非净利率(%):', plus3.loc[0, '扣非净利率(%)'], end=' ') 194 | # if plus3.loc[0, '扣非净利率(%)'] < 15: 195 | # print('-->预警:扣非净利率(%)小于15!', end='') 196 | # print('\n商誉净资产比:', plus3.loc[0, '商誉净资产比'], end=' ') 197 | # if plus3.loc[0, '商誉净资产比'] > 0.5: 198 | # print('-->预警:商誉净资产比大于0.5!', end='') 199 | # print('\n存货净资产比:', plus3.loc[0, '存货净资产比'], end=' ') 200 | # if plus3.loc[0, '存货净资产比'] > 0.5: 201 | # print('-->预警:存货净资产比大于0.5!', end='') 202 | # print('\n应收账款净资产比:', plus3.loc[0, '应收账款净资产比'], end=' ') 203 | # if plus3.loc[0, '应收账款净资产比'] > 0.5: 204 | # print('-->预警:应收账款净资产比大于0.5!', end='') 205 | # print('\n应收票据净资产比:', plus3.loc[0, '应收票据净资产比'], end=' ') 206 | # if plus3.loc[0, '应收票据净资产比'] > 0.5: 207 | # print('-->预警:应收票据净资产比大于0.5!', end='') 208 | # print('\n应收账款和应收票据合计占净资产比:', plus3.loc[0, '应收账款和应收票据合计占净资产比'], end=' ') 209 | # if plus3.loc[0, '应收账款和应收票据合计占净资产比'] > 0.5: 210 | # print('-->预警:应收账款和应收票据合计占净资产比大于0.5!', end='') 211 | # print('\n资产负债率(%):', plus3.loc[0, '资产负债率(%)'], end=' ') 212 | # if plus3.loc[0, '资产负债率(%)'] > 60: 213 | # print('-->预警:资产负债率(%)大于60!', end='') 214 | # print('\n流动比率:', plus3.loc[0, '流动比率'], end=' ') 215 | # if plus3.loc[0, '流动比率'] < 2: 216 | # print('-->预警:流动比率小于2!', end='') 217 | # print('\n速动比率:', plus3.loc[0, '速动比率'], end=' ') 218 | # if plus3.loc[0, '速动比率'] < 1: 219 | # print('-->预警:速动比率小于1!', end='') 220 | # print('\n营业总收入同比增长率(%):', plus3.loc[0, '营业总收入同比增长率(%)'], end=' ') 221 | # if plus3.loc[0, '营业总收入同比增长率(%)'] < 20: 222 | # print('-->预警:营业总收入同比增长率(%)小于20!', end='') 223 | # print('\n归属母公司股东的净利润同比增长率(%):', plus3.loc[0, '归属母公司股东的净利润同比增长率(%)'], end=' ') 224 | # if plus3.loc[0, '归属母公司股东的净利润同比增长率(%)'] < 20: 225 | # print('-->预警:归属母公司股东的净利润同比增长率(%)小于20!', end='') 226 | # print('\n归属母公司股东的净利润-扣除非经常损益同比增长率(%):', plus3.loc[0, '归属母公司股东的净利润-扣除非经常损益同比增长率(%)'], end=' ') 227 | # if plus3.loc[0, '归属母公司股东的净利润-扣除非经常损益同比增长率(%)'] < 20: 228 | # print('-->预警:归属母公司股东的净利润-扣除非经常损益同比增长率(%)小于20!', end='') 229 | # print() -------------------------------------------------------------------------------- /TS获取股票行情.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | import TS_getStock 5 | import time 6 | 7 | # 从本地读取token 8 | f = open('D:\\股票分析\\token.txt') 9 | token = f.read() 10 | 11 | ts.set_token(token) 12 | pro = ts.pro_api() 13 | 14 | 15 | # 方法1:循环获取单只股票行情 16 | def get_price(tscode, retry_count=3, pause=2): 17 | ''' 18 | 获取每只股票的价格 19 | --------- 20 | retry_count:重试次数 21 | pause:暂停秒数 22 | ''' 23 | 24 | number = 0 25 | while number <= retry_count: 26 | try: 27 | pd_temp = ts.pro_bar(ts_code=tscode, start_date='20200529', end_date='20200529', adj='qfq', 28 | factors=['tor', 'vr']) # 本接口不需要用pro.pro_bar 29 | except: 30 | number += 1 31 | if number <= retry_count: 32 | time.sleep(pause) 33 | else: 34 | print('自动重试次数超限,未能获取到ts_code代码为%s的股票的价格' % tscode) 35 | else: 36 | return pd_temp 37 | 38 | 39 | # 方法2:循环获取单只股票行情 40 | # def get_price(tscode, retry_count=3, pause=2): 41 | # ''' 42 | # 获取每只股票的价格 43 | # --------- 44 | # retry_count:重试次数 45 | # pause:暂停秒数 46 | # ''' 47 | # 48 | # for number in range(retry_count): 49 | # try: 50 | # pd_temp = ts.pro_bar(ts_code=tscode, start_date='20200522', end_date='20200522', adj='qfq', 51 | # factors=['tor', 'vr']) # 本接口不需要用pro.pro_bar 52 | # except: 53 | # time.sleep(pause) 54 | # else: 55 | # return pd_temp 56 | # print('自动重试次数超限,未能获取到ts_code代码为%s的股票的价格' % tscode) 57 | 58 | 59 | stock_pd = TS_getStock.get_stock() # 获取股票列表 60 | stock_price = pd.DataFrame() # 创建空dataframe,用于存放所有股票的价格 61 | 62 | for i in stock_pd['ts_code'].values: # 遍历每只股票的ts_code 63 | stock_singlePri = get_price(i) # 获取该只股票的价格 64 | stock_price = stock_price.append(stock_singlePri) # 将该只股票的价格放到汇总dataframe中 65 | # time.sleep(0.75) 66 | 67 | stock_price.columns = ['交易日期', 'ts_code', '开盘价', '最高价', '最低价', '收盘价', '昨收价', '涨跌额', '涨跌幅 ', '成交量(手)', '成交额(千元)', 68 | '换手率', '量比'] 69 | stock_price.to_csv('D:\\股票分析\\沪深股票价格20200529.csv') 70 | 71 | 72 | -------------------------------------------------------------------------------- /TS获取股票财务指标.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | import TS_getStock 5 | import time 6 | 7 | # 从本地读取token 8 | f = open('D:\\股票分析\\token.txt') 9 | token = f.read() 10 | 11 | ts.set_token(token) 12 | pro = ts.pro_api() 13 | 14 | def get_finIndic(tscode, retry_count=3, pause=2): 15 | ''' 16 | 获取每只股票的财务指标 17 | --------- 18 | retry_count:重试次数 19 | pause:暂停秒数 20 | ''' 21 | 22 | number = 0 23 | while number <= retry_count: 24 | try: 25 | # pd_temp = pro.fina_indicator(ts_code=tscode, period='20191231', fields= 26 | # 'ts_code, ann_date, end_date, eps, dt_eps, total_revenue_ps, revenue_ps, extra_item, profit_dedt, gross_margin, current_ratio, quick_ratio,' 27 | # 'arturn_days, inv_turn, ar_turn, assets_turn, ebit, ebitda, fcff, interestdebt, diluted2_eps, bps, ocfps, cfps, ebit_ps, netprofit_margin, grossprofit_margin,' 28 | # 'profit_to_gr, saleexp_to_gr, adminexp_of_gr, finaexp_of_gr, impai_ttm, op_of_gr, ebit_of_gr, roe, roe_waa, roe_dt, roa, roe_avg, salescash_to_or,' 29 | # 'ocf_to_opincome, debt_to_assets, assets_to_eqt, nca_to_assets, currentdebt_to_debt, ebit_to_interest, profit_prefin_exp, non_op_profit, profit_to_op, basic_eps_yoy,' 30 | # 'dt_eps_yoy, op_yoy, ebt_yoy, netprofit_yoy, dt_netprofit_yoy, roe_yoy, eqt_yoy, tr_yoy, or_yoy, equity_yoy, rd_exp, update_flag', 31 | # timeout=5) 32 | pd_temp = pro.fina_indicator(ts_code=tscode, start_date='20170101', end_date='20191231', fields= 33 | 'ts_code, ann_date, end_date, eps, dt_eps, total_revenue_ps, profit_dedt, current_ratio, quick_ratio,' 34 | 'inv_turn, ar_turn, assets_turn, bps, profit_to_gr, op_of_gr, roe, roe_waa, roe_dt, roa,' 35 | 'salescash_to_or, ocf_to_opincome, debt_to_assets, basic_eps_yoy, dt_eps_yoy, op_yoy, netprofit_yoy, dt_netprofit_yoy,' 36 | 'roe_yoy, tr_yoy, or_yoy, rd_exp, update_flag', timeout=5) 37 | 38 | except: 39 | number += 1 40 | if number != retry_count: 41 | time.sleep(pause) 42 | else: 43 | print('自动重试次数超限,未能获取到ts_code代码为%s的股票的财务指标' % tscode) 44 | else: 45 | return pd_temp 46 | 47 | 48 | stock_pd = TS_getStock.get_stock() # 获取股票列表 49 | stock_finIndic = pd.DataFrame() # 创建空dataframe,用于存放所有股票的财务指标 50 | 51 | for i in stock_pd['ts_code'].values: # 遍历每只股票的ts_code 52 | stock_singleFin = get_finIndic(i) # 获取该只股票的财务指标 53 | stock_finIndic = stock_finIndic.append(stock_singleFin) # 将该只股票的财务指标放到汇总dataframe中 54 | time.sleep(0.75) 55 | 56 | # 对财务指标股票表进行去重,保留最新记录 (由于上市公司更新财报,会导致同一公司存在多条记录) 57 | stock_finIndic = stock_finIndic.drop_duplicates(subset=['ts_code', 'end_date'], keep='last') 58 | 59 | stock_finIndic.columns = ['ts_code', '公告日期', '报告期', '基本每股收益', '稀释每股收益', '每股营业总收入', '扣除非经常性损益后的净利润', '流动比率', '速动比率', '存货周转率', '应收账款周转率', '总资产周转率', 60 | '每股净资产', '净利率(%)', '营业利润率(%)', '净资产收益率(%)', '加权平均净资产收益率(%)', '净资产收益率(扣除非经常性损益)(%)', '总资产报酬率(%)', '销售商品提供劳务收到的现金/营业收入', 61 | '经营活动产生的现金流量净额/经营活动净收益', '资产负债率(%)', '基本每股收益同比增长率(%)', '稀释每股收益同比增长率(%)', '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', 62 | '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', '净资产收益率(摊薄)同比增长率(%)', '营业总收入同比增长率(%)', '营业收入同比增长率(%)', '研发费用', '更新标识'] 63 | 64 | stock_finIndic.to_csv('D:\\股票分析\\沪深股票财务指标_2017至2019年.csv') 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /TS获取资产负债表.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | import TS_getStock 5 | import time 6 | 7 | # 从本地读取token 8 | f = open('D:\\股票分析\\token.txt') 9 | token = f.read() 10 | 11 | ts.set_token(token) 12 | pro = ts.pro_api() 13 | 14 | def get_balance(tscode, retry_count=3, pause=2): 15 | ''' 16 | 获取每只股票的资产负债表信息 17 | --------- 18 | retry_count:重试次数 19 | pause:暂停秒数 20 | ''' 21 | 22 | number = 0 23 | while number <= retry_count: 24 | try: 25 | # pd_temp = pro.balancesheet(ts_code=tscode, period='20191231', fields='ts_code, ann_date, f_ann_date, end_date, report_type, comp_type, total_share,' 26 | # 'money_cap, trad_asset, notes_receiv, accounts_receiv, oth_receiv, prepayment, div_receiv, int_receiv, inventories, amor_exp,' 27 | # 'fa_avail_for_sale, htm_invest, lt_eqt_invest, invest_real_estate, time_deposits, oth_assets, fix_assets, cip, const_materials,' 28 | # 'intan_assets, r_and_d, goodwill, defer_tax_assets, total_assets, total_liab, minority_int, total_hldr_eqy_exc_min_int,' 29 | # 'total_hldr_eqy_inc_min_int, update_flag', timeout=5) 30 | # 不能改变顺序,因为返回的字段是按照接口顺序返回的,不是按照这里,如果改变了顺序,后面更改列名称时,也是按照接口返回的字段顺序改的,会导致与期望的不一致 31 | pd_temp = pro.balancesheet(ts_code=tscode, start_date='20170331', end_date='20200630', fields= 32 | 'ts_code, end_date, report_type, comp_type, total_share,' 33 | 'money_cap, trad_asset, notes_receiv, accounts_receiv, oth_receiv, prepayment, inventories,' 34 | 'fa_avail_for_sale, htm_invest, lt_eqt_invest, time_deposits,' 35 | 'intan_assets, r_and_d, goodwill, total_assets, total_liab, minority_int, total_hldr_eqy_exc_min_int,' 36 | 'total_hldr_eqy_inc_min_int, update_flag', timeout=5) 37 | 38 | except: 39 | number += 1 40 | if number != retry_count: 41 | time.sleep(pause) 42 | else: 43 | print('自动重试次数超限,未能获取到ts_code代码为%s的股票的资产负债表信息' % tscode) 44 | else: 45 | return pd_temp 46 | 47 | 48 | stock_pd = TS_getStock.get_stock() # 获取股票列表 49 | stock_balance = pd.DataFrame() # 创建空dataframe,用于存放所有股票的资产负债表信息 50 | 51 | for i in stock_pd['ts_code'].values: # 遍历每只股票的ts_code 52 | stock_singleBal = get_balance(i) # 获取该只股票的资产负债表信息 53 | stock_balance = stock_balance.append(stock_singleBal) # 将该只股票的资产负债表信息放到汇总dataframe中 54 | time.sleep(1) 55 | 56 | # 对财务指标股票表进行去重,保留最新记录 (由于上市公司更新财报,会导致同一公司存在多条记录) 57 | stock_balance = stock_balance.drop_duplicates(subset=['ts_code', 'end_date'], keep='last') 58 | 59 | stock_balance.columns = ['ts_code', '报告期', '报表类型', '公司类型', '期末总股本', 60 | '货币资金', '交易性金融资产', '应收票据', '应收账款', '其他应收款', '预付款项', '存货', 61 | '可供出售金融资产', '持有至到期投资', '长期股权投资', '定期存款', 62 | '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '少数股东权益', '股东权益合计(不含少数股东权益)', '股东权益合计(含少数股东权益)', 63 | '更新标识'] 64 | 65 | stock_balance.to_csv('D:\\股票分析\\沪深股票资产负债表_2017至2019年.csv') 66 | 67 | # 如果获取失败,将失败的股票,单独重新获取,导出为Excel,将新旧Excel相加! -------------------------------------------------------------------------------- /TS计算大股东质押率.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import tushare as ts 3 | import pandas as pd 4 | 5 | # 从本地读取token 6 | f = open('D:\\股票分析\\token.txt') 7 | token = f.read() 8 | 9 | ts.set_token(token) 10 | pro = ts.pro_api() 11 | 12 | def get_pledgeHolders10(ts_code, day): 13 | '''计算前十大股东的质押数据''' 14 | # 1.获取最近一期的10大股东,并排序 15 | pd_holdersTop10 = pro.top10_holders(ts_code=ts_code, period=day, timeout=5) 16 | pd_holdersTop10.columns = ['ts_code', '公告日期', '报告期', '股东名称', '持有数量(股)', '持有比例'] 17 | pd_holdersTop10 = pd_holdersTop10.sort_values(by='持有比例', ascending=False) 18 | pd_holdersTop10['股东持股量名次'] = list(range(1, (len(pd_holdersTop10) + 1))) 19 | 20 | # 2.获取质押明细 21 | pd_pledgeDetail = pro.pledge_detail(ts_code=ts_code) 22 | pd_pledgeDetail.columns = ['ts_code', '公告日期', '股东名称', '质押数量(万股)', '质押开始日期', '质押结束日期', '是否已解押', '解押日期', 23 | '质押方', '持股总数(万股)', '质押总数(万股)', '本次质押占总股本比例', '持股总数占总股本比例', '是否回购'] 24 | # print(pd_pledgeDetail) 25 | 26 | # 3.从质押明细中,找出前十个股东的最新一条质押明细(最新一条包含了持股总数、质押总数) 27 | pd_pledgeHolders10 = pd.DataFrame() 28 | for holder in pd_holdersTop10['股东名称'].values: 29 | pd_temp = pd_pledgeDetail[pd_pledgeDetail['股东名称'] == holder] 30 | if len(pd_temp) > 0: 31 | pd_temp = pd_temp.iloc[0, :] # 提示:从dataframe中截取一列或一行的数据时,会自动转化成series,但不影响在dataframe中相加 32 | # pd_temp = pd.DataFrame([pd_temp.values], columns=pd_temp.index) # 如series转化成只有一行的dataframe,则index变为0 33 | pd_pledgeHolders10 = pd_pledgeHolders10.append(pd_temp) 34 | 35 | if len(pd_pledgeHolders10) > 0: 36 | # 清除最新一条质押明细中最新质押总数为0的数据 37 | pd_pledgeHolders10 = pd_pledgeHolders10[pd_pledgeHolders10['质押总数(万股)'] > 0] 38 | 39 | if len(pd_pledgeHolders10) > 0: 40 | # 4.将股东持股量名次并入 41 | pd_holdersTop10_simple = pd_holdersTop10.loc[:, ['股东名称', '股东持股量名次']] 42 | pd_pledgeHolders10 = pd_pledgeHolders10.merge(pd_holdersTop10_simple, how='left', on='股东名称') 43 | 44 | # 5.计算前十大股东的合计质押比率、每人质押比率 45 | pd_pledgeHolders10['质押比率(%)'] = pd_pledgeHolders10['质押总数(万股)']/pd_pledgeHolders10['持股总数(万股)']*100 46 | # print(pd_pledgeHolders10) 47 | 48 | # 打印合计质押比率 49 | sum_pledge = pd_pledgeHolders10['质押总数(万股)'].sum() 50 | sum_holding = pd_pledgeHolders10['持股总数(万股)'].sum() 51 | sum_pledgeHolders10 = sum_pledge/sum_holding*100 52 | print('存在质押股份的前十大股东中,整体质押率(%)为:', sum_pledgeHolders10, end=' ') 53 | if sum_pledgeHolders10 > 25: 54 | print('-->预警:整体质押率(%)大于25!', end='') 55 | 56 | # 打印每个股东的质押比率 57 | for number in range(len(pd_pledgeHolders10)): 58 | print('\n第%s大股东%s的质押率为:%s' % (pd_pledgeHolders10.loc[number, '股东持股量名次'], pd_pledgeHolders10.loc[number, '股东名称'], 59 | pd_pledgeHolders10.loc[number, '质押比率(%)']), end=' ') 60 | if pd_pledgeHolders10.loc[number, '质押比率(%)'] > 25: 61 | print('-->预警:该股东累计质押率(%)大于25!', end='') 62 | 63 | return sum_pledgeHolders10 -------------------------------------------------------------------------------- /TS财务和质押指标选股_单周期.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import pandas as pd 3 | import TS计算大股东质押率 4 | import time 5 | 6 | pd_stock = pd.read_csv('D:\\股票分析\\沪深股票列表.csv') 7 | pd_fin = pd.read_csv('D:\\股票分析\\沪深股票财务指标20191231.csv') 8 | pd_price = pd.read_csv('D:\\股票分析\\沪深股票价格20200529.csv') 9 | pd_balance = pd.read_csv('D:\\股票分析\\沪深股票资产负债表20191231.csv') 10 | 11 | 12 | # 1.对财务指标中的同一只股票去重,保留最新记录 (由于上市公司更新财报,会导致同一公司存在多条记录) 13 | result_fin = pd_fin.drop_duplicates(subset=['ts_code'], keep='last') 14 | result_balance = pd_balance.drop_duplicates(subset=['ts_code'], keep='last') 15 | 16 | 17 | # 2.从财务指标股票表、资产负债表中精选指标 18 | result_fin = pd_fin.loc[:, ['ts_code', 'ann_date', 'end_date', 'eps', 'dt_eps', 'total_revenue_ps', 'profit_dedt', 'current_ratio', 'quick_ratio', 'inv_turn', 'ar_turn', 19 | 'assets_turn', 'bps', 'profit_to_gr', 'op_of_gr', 'roe', 'roe_waa', 'roe_dt', 'roa', 'salescash_to_or', 20 | 'ocf_to_opincome', 'debt_to_assets', 'basic_eps_yoy', 'dt_eps_yoy', 'op_yoy', 'netprofit_yoy', 'dt_netprofit_yoy', 21 | 'roe_yoy', 'tr_yoy', 'or_yoy', 'rd_exp', 'update_flag']] 22 | 23 | result_fin.columns = ['ts_code', '公告日期', '报告期', '基本每股收益', '稀释每股收益', '每股营业总收入', '扣除非经常性损益后的净利润', '流动比率', '速动比率', '存货周转率', '应收账款周转率', '总资产周转率', 24 | '每股净资产', '净利率(%)', '营业利润率(%)', '净资产收益率(%)', '加权平均净资产收益率(%)', '净资产收益率(扣除非经常性损益)(%)', '总资产报酬率(%)', '销售商品提供劳务收到的现金/营业收入', 25 | '经营活动产生的现金流量净额/经营活动净收益', '资产负债率(%)', '基本每股收益同比增长率(%)', '稀释每股收益同比增长率(%)', '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', 26 | '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', '净资产收益率(摊薄)同比增长率(%)', '营业总收入同比增长率(%)', '营业收入同比增长率(%)', '研发费用', '更新标识'] 27 | 28 | 29 | result_balance = result_balance.loc[:, ['ts_code', 'end_date', 'report_type', 'comp_type', 'total_share', 30 | 'money_cap', 'trad_asset', 'notes_receiv', 'accounts_receiv', 'oth_receiv', 'prepayment', 'inventories', 31 | 'fa_avail_for_sale', 'htm_invest', 'lt_eqt_invest', 'time_deposits', 32 | 'intan_assets', 'r_and_d', 'goodwill', 'total_assets', 'total_liab', 'minority_int', 'total_hldr_eqy_exc_min_int', 33 | 'total_hldr_eqy_inc_min_int', 'update_flag']] 34 | 35 | result_balance.columns = ['ts_code', '报告期', '报表类型', '公司类型', '期末总股本', 36 | '货币资金', '交易性金融资产', '应收票据', '应收账款', '其他应收款', '预付款项', '存货', 37 | '可供出售金融资产', '持有至到期投资', '长期股权投资', '定期存款', 38 | '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '少数股东权益', '股东权益合计(不含少数股东权益)', 39 | '股东权益合计(含少数股东权益)', '更新标识'] 40 | 41 | result_price = pd_price.loc[:, ['ts_code', '交易日期', '收盘价', '涨跌幅 ', '换手率', '量比']] 42 | 43 | 44 | # 3.合并各类表 45 | plus1 = result_fin.merge(pd_stock, how='left', on='ts_code') # 将精简财务指标表与股票全量列表合并 46 | plus2 = plus1.merge(result_price, how='left', on='ts_code') # 将合并的表与股票行情表合并 47 | plus3 = plus2.merge(result_balance, how='left', on='ts_code') # 将合并的表与资产负债表合并 48 | 49 | 50 | # 4. 根据原始指标,计算相关指标,增加到表格中 51 | plus3['市盈率'] = plus3['收盘价']/plus3['基本每股收益'] 52 | plus3['市净率'] = plus3['收盘价']/plus3['每股净资产'] 53 | plus3['商誉净资产比'] = plus3['商誉']/plus3['股东权益合计(含少数股东权益)'] 54 | plus3['存货净资产比'] = plus3['存货']/plus3['股东权益合计(含少数股东权益)'] 55 | plus3['应收账款净资产比'] = plus3['应收账款']/plus3['股东权益合计(含少数股东权益)'] 56 | plus3['应收票据净资产比'] = plus3['应收票据']/plus3['股东权益合计(含少数股东权益)'] 57 | plus3['扣非净利率(%)'] = plus3['扣除非经常性损益后的净利润']/(plus3['每股营业总收入']*plus3['期末总股本'])*100 58 | plus3['扣非净利润增长率/市盈率'] = plus3['归属母公司股东的净利润-扣除非经常损益同比增长率(%)']/plus3['市盈率'] 59 | 60 | 61 | # 5.调整列的顺序 62 | order = ['ts_code', '股票代码', '股票名称', '所属行业', '所在地域', '加权平均净资产收益率(%)', '净资产收益率(扣除非经常性损益)(%)', '扣非净利率(%)', '销售商品提供劳务收到的现金/营业收入', 63 | '市盈率', '扣非净利润增长率/市盈率', '市净率', '营业总收入同比增长率(%)', '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', '基本每股收益同比增长率(%)', 64 | '稀释每股收益同比增长率(%)','资产负债率(%)', '流动比率', '速动比率', '商誉净资产比', '存货净资产比', '应收账款净资产比', '应收票据净资产比', '营业收入同比增长率(%)', 65 | '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', '净资产收益率(摊薄)同比增长率(%)', 66 | '公告日期', '报告期_x', '基本每股收益', '稀释每股收益', '存货周转率', '应收账款周转率', '总资产周转率', '每股净资产', '净利率(%)', '营业利润率(%)', 67 | '净资产收益率(%)', '总资产报酬率(%)', '经营活动产生的现金流量净额/经营活动净收益', '研发费用', '更新标识_x', 68 | '市场类型', '上市日期', '是否沪深港通标的', '交易日期', '收盘价', '涨跌幅 ', '换手率', '量比', '报告期_y', '报表类型', 69 | '公司类型', '期末总股本', '货币资金', '交易性金融资产', '应收票据', '应收账款', '其他应收款', '预付款项', '存货', '可供出售金融资产', '持有至到期投资', 70 | '长期股权投资', '定期存款', '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '股东权益合计(含少数股东权益)', '股东权益合计(不含少数股东权益)', 71 | '少数股东权益', '更新标识_y'] 72 | 73 | plus3 = plus3[order] 74 | 75 | 76 | # 6.从合并后的表中,筛选出满足指标的股票 77 | plus3['上市日期'] = pd.to_datetime(plus3['上市日期'], format='%Y%m%d') # 将数据类型转换为日期类型,以便下面按日期进行筛选 78 | 79 | # 使用日期截断函数truncate()之前,需要先将上市日期设为index,并排序(此处按升序排) 80 | # 方法1: 81 | # plus3 = plus3.sort_values('上市日期') 82 | # plus3 = plus3.set_index('上市日期') 83 | # 方法2: 84 | plus3 = plus3.set_index('上市日期').sort_index() 85 | 86 | select = plus3[(plus3['加权平均净资产收益率(%)']>=15) & (plus3['销售商品提供劳务收到的现金/营业收入']>=1) & (plus3['经营活动产生的现金流量净额/经营活动净收益']>=1) & 87 | (plus3['扣非净利率(%)']>=15) & (plus3['商誉净资产比']<=0.5) & (plus3['存货净资产比']<=0.5) & (plus3['应收账款净资产比']<=0.5) & 88 | (plus3['流动比率']>=2) & (plus3['速动比率']>=1) & (plus3['营业总收入同比增长率(%)']>=20) & (plus3['归属母公司股东的净利润-扣除非经常损益同比增长率(%)']>=20)] 89 | 90 | select = select.truncate(after='2019-05-01') # 截取指定日期以后的数据,只保留日期之前的数据。注意:该筛选条件不能与上面财务指标筛选写在一起,上面 91 | # 针对columns筛选,这里针对index筛选,函数的格式不同,放到一起会报错! 92 | 93 | select = select.sort_values(by='市盈率', ascending=True) 94 | 95 | 96 | # 7.在筛选出的股票基础上,评估大股东质押率 97 | list_pledge = [] 98 | for code in select['ts_code'].values: 99 | a = TS计算大股东质押率.get_pledgeHolders10(code, '20200331') 100 | list_pledge.append(a) 101 | select['前十大股东质押率'] = list_pledge 102 | select['前十大股东质押率'].fillna(0, inplace=True) # 将质押率为NaN(即空)的数据,转化成0,以便筛选 103 | select = select[select['前十大股东质押率']<=25] 104 | select.to_csv('D:\\股票分析\\基本面选股_基于19年年报和0529股价(市盈率升序).csv') 105 | 106 | 107 | # 后续迭代 108 | # 1.衡量业绩的稳定性:评估至少两年的财报指标 109 | -------------------------------------------------------------------------------- /TS财务指标选股_多周期平均达标.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import pandas as pd 3 | 4 | 5 | pd_fin = pd.read_csv('D:\\股票分析\\沪深股票财务指标_2017至2019年.csv') 6 | pd_balance = pd.read_csv('D:\\股票分析\\沪深股票资产负债表_2017至2019年.csv') 7 | pd_stock = pd.read_csv('D:\\股票分析\\沪深股票列表.csv') 8 | 9 | # 1.将基本财务指标、资产负债表、股票基本信息表合并,筛选出近三年的年报 10 | plus_financial = pd_fin.merge(pd_balance, how='left', on=['ts_code', '报告期']) # 将基本财务指标与资产负债表指标合并 11 | plus_financial = plus_financial[plus_financial['报告期'].isin(['20171231', '20181231', '20191231'])] # 筛选出年报数据 12 | plus_candidate = plus_financial.merge(pd_stock, how='left', on='ts_code') # 将年报数据与股票基本信息合并 13 | 14 | 15 | # 2.在原始指标上,加工生成新的指标 16 | plus_candidate['商誉净资产比'] = plus_candidate['商誉']/plus_candidate['股东权益合计(含少数股东权益)'] 17 | plus_candidate['存货净资产比'] = plus_candidate['存货']/plus_candidate['股东权益合计(含少数股东权益)'] 18 | plus_candidate['应收账款净资产比'] = plus_candidate['应收账款']/plus_candidate['股东权益合计(含少数股东权益)'] 19 | plus_candidate['应收票据净资产比'] = plus_candidate['应收票据']/plus_candidate['股东权益合计(含少数股东权益)'] 20 | plus_candidate['扣非净利率(%)'] = plus_candidate['扣除非经常性损益后的净利润']/(plus_candidate['每股营业总收入']*plus_candidate['期末总股本'])*100 21 | 22 | # 调整列的顺序 23 | order = ['ts_code', '公告日期', '报告期', '股票代码', '股票名称', '所在地域', '所属行业', '上市日期', '基本每股收益', '稀释每股收益', '每股营业总收入', 24 | '扣除非经常性损益后的净利润', '流动比率', '速动比率', '存货周转率', '应收账款周转率', '总资产周转率', '每股净资产', 25 | '净利率(%)', '营业利润率(%)', '净资产收益率(%)', '加权平均净资产收益率(%)', 26 | '净资产收益率(扣除非经常性损益)(%)', '总资产报酬率(%)', '销售商品提供劳务收到的现金/营业收入', 27 | '经营活动产生的现金流量净额/经营活动净收益', '资产负债率(%)', '基本每股收益同比增长率(%)', '稀释每股收益同比增长率(%)', 28 | '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', 29 | '净资产收益率(摊薄)同比增长率(%)', '营业总收入同比增长率(%)', '营业收入同比增长率(%)', '研发费用', '更新标识_x', 30 | 'Unnamed: 0_y', '报表类型', '公司类型', '期末总股本', '货币资金', '交易性金融资产', '应收票据', 31 | '应收账款', '其他应收款', '预付款项', '存货', '可供出售金融资产', '持有至到期投资', '长期股权投资', '定期存款', 32 | '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '少数股东权益', '股东权益合计(不含少数股东权益)', 33 | '股东权益合计(含少数股东权益)', '更新标识_y', '市场类型', '是否沪深港通标的', '商誉净资产比', '存货净资产比', '应收账款净资产比', 34 | '应收票据净资产比', '扣非净利率(%)'] 35 | plus_candidate = plus_candidate[order] 36 | 37 | 38 | # 3.过滤点次新股(成立时间早于2019.3.31) 39 | plus_candidate['上市日期'] = pd.to_datetime(plus_candidate['上市日期'], format='%Y%m%d') # 将数据类型转换为日期类型,以便下面按日期进行筛选 40 | plus_candidate = plus_candidate.set_index('上市日期').sort_index() # 使用日期截断函数truncate()之前,需要先将上市日期设为index,并排序(此处按升序排) 41 | plus_candidate = plus_candidate.truncate(after='2019-03-01') # 截取指定日期以后的数据,只保留日期之前的数据。注意:该筛选条件不能与上面财务指标筛选写在一起,上面 42 | 43 | 44 | # 4.计算每只股票,最近三年的指标是否都满足条件(须考虑有些股票成立时间不足三年) 45 | select = pd.DataFrame() # 用于后续记录符合条件的股票 46 | set_tscode = set(plus_candidate['ts_code'].values) 47 | for stock in set_tscode: 48 | pd_temp = plus_candidate[plus_candidate['ts_code'] == stock] 49 | 50 | # pd_judge筛选出相反条件的数据,pd_judge存在数据,则说明该只股票不符合筛选条件 51 | if pd_temp['加权平均净资产收益率(%)'].mean() < 15 or\ 52 | pd_temp['销售商品提供劳务收到的现金/营业收入'].mean() < 1 or\ 53 | pd_temp['经营活动产生的现金流量净额/经营活动净收益'].mean() < 1 or\ 54 | pd_temp['扣非净利率(%)'].mean() < 15 or\ 55 | pd_temp['商誉净资产比'].mean() > 0.5 or\ 56 | pd_temp['存货净资产比'].mean() > 0.5 or\ 57 | pd_temp['应收账款净资产比'].mean() > 0.5 or\ 58 | pd_temp['流动比率'].mean() < 2 or\ 59 | pd_temp['速动比率'].mean() < 1 or\ 60 | pd_temp['营业总收入同比增长率(%)'].mean() < 15 or\ 61 | pd_temp['归属母公司股东的净利润-扣除非经常损益同比增长率(%)'].mean() < 15: 62 | continue 63 | else: 64 | select = select.append(pd_temp) 65 | 66 | select.to_csv('D:\\股票分析\\财务指标选股(多期平均值满足)_2017至2019年.csv') 67 | -------------------------------------------------------------------------------- /TS财务指标选股_多周期每期达标.py: -------------------------------------------------------------------------------- 1 | #! usr/bin/env python 2 | import pandas as pd 3 | 4 | 5 | pd_fin = pd.read_csv('D:\\股票分析\\沪深股票财务指标_2017至2019年.csv') 6 | pd_balance = pd.read_csv('D:\\股票分析\\沪深股票资产负债表_2017至2019年.csv') 7 | pd_stock = pd.read_csv('D:\\股票分析\\沪深股票列表.csv') 8 | 9 | # 1.将基本财务指标、资产负债表、股票基本信息表合并,筛选出近三年的年报 10 | plus_financial = pd_fin.merge(pd_balance, how='left', on=['ts_code', '报告期']) # 将基本财务指标与资产负债表指标合并 11 | plus_financial = plus_financial[plus_financial['报告期'].isin(['20171231', '20181231', '20191231'])] # 筛选出年报数据 12 | plus_candidate = plus_financial.merge(pd_stock, how='left', on='ts_code') # 将年报数据与股票基本信息合并 13 | 14 | 15 | # 2.在原始指标上,加工生成新的指标 16 | plus_candidate['商誉净资产比'] = plus_candidate['商誉']/plus_candidate['股东权益合计(含少数股东权益)'] 17 | plus_candidate['存货净资产比'] = plus_candidate['存货']/plus_candidate['股东权益合计(含少数股东权益)'] 18 | plus_candidate['应收账款净资产比'] = plus_candidate['应收账款']/plus_candidate['股东权益合计(含少数股东权益)'] 19 | plus_candidate['应收票据净资产比'] = plus_candidate['应收票据']/plus_candidate['股东权益合计(含少数股东权益)'] 20 | plus_candidate['扣非净利率(%)'] = plus_candidate['扣除非经常性损益后的净利润']/(plus_candidate['每股营业总收入']*plus_candidate['期末总股本'])*100 21 | 22 | # 调整列的顺序 23 | order = ['ts_code', '公告日期', '报告期', '股票代码', '股票名称', '所在地域', '所属行业', '上市日期', '基本每股收益', '稀释每股收益', '每股营业总收入', 24 | '扣除非经常性损益后的净利润', '流动比率', '速动比率', '存货周转率', '应收账款周转率', '总资产周转率', '每股净资产', 25 | '净利率(%)', '营业利润率(%)', '净资产收益率(%)', '加权平均净资产收益率(%)', 26 | '净资产收益率(扣除非经常性损益)(%)', '总资产报酬率(%)', '销售商品提供劳务收到的现金/营业收入', 27 | '经营活动产生的现金流量净额/经营活动净收益', '资产负债率(%)', '基本每股收益同比增长率(%)', '稀释每股收益同比增长率(%)', 28 | '营业利润同比增长率(%)', '归属母公司股东的净利润同比增长率(%)', '归属母公司股东的净利润-扣除非经常损益同比增长率(%)', 29 | '净资产收益率(摊薄)同比增长率(%)', '营业总收入同比增长率(%)', '营业收入同比增长率(%)', '研发费用', '更新标识_x', 30 | 'Unnamed: 0_y', '报表类型', '公司类型', '期末总股本', '货币资金', '交易性金融资产', '应收票据', 31 | '应收账款', '其他应收款', '预付款项', '存货', '可供出售金融资产', '持有至到期投资', '长期股权投资', '定期存款', 32 | '无形资产', '研发支出', '商誉', '资产总计', '负债合计', '少数股东权益', '股东权益合计(不含少数股东权益)', 33 | '股东权益合计(含少数股东权益)', '更新标识_y', '市场类型', '是否沪深港通标的', '商誉净资产比', '存货净资产比', '应收账款净资产比', 34 | '应收票据净资产比', '扣非净利率(%)'] 35 | plus_candidate = plus_candidate[order] 36 | 37 | 38 | # 3.过滤点次新股(成立时间早于2019.3.31) 39 | plus_candidate['上市日期'] = pd.to_datetime(plus_candidate['上市日期'], format='%Y%m%d') # 将数据类型转换为日期类型,以便下面按日期进行筛选 40 | plus_candidate = plus_candidate.set_index('上市日期').sort_index() # 使用日期截断函数truncate()之前,需要先将上市日期设为index,并排序(此处按升序排) 41 | plus_candidate = plus_candidate.truncate(after='2019-03-01') # 截取指定日期以后的数据,只保留日期之前的数据。注意:该筛选条件不能与上面财务指标筛选写在一起,上面 42 | 43 | 44 | # 4.计算每只股票,最近三年的指标是否都满足条件(须考虑有些股票成立时间不足三年) 45 | select = pd.DataFrame() # 用于后续记录符合条件的股票 46 | set_tscode = set(plus_candidate['ts_code'].values) 47 | for stock in set_tscode: 48 | pd_temp = plus_candidate[plus_candidate['ts_code'] == stock] 49 | 50 | # pd_judge筛选出相反条件的数据,pd_judge存在数据,则说明该只股票不符合筛选条件 51 | pd_judge = pd_temp[(pd_temp['加权平均净资产收益率(%)'] < 15) | (pd_temp['销售商品提供劳务收到的现金/营业收入'] < 1) | (pd_temp['经营活动产生的现金流量净额/经营活动净收益'] < 1) | 52 | (pd_temp['扣非净利率(%)'] < 15) | (pd_temp['商誉净资产比'] > 0.5) | (pd_temp['存货净资产比'] > 0.5) | (pd_temp['应收账款净资产比'] > 0.5) | 53 | (pd_temp['流动比率'] < 2) | (pd_temp['速动比率'] < 1) | (pd_temp['营业总收入同比增长率(%)'] < 15) | (pd_temp['归属母公司股东的净利润-扣除非经常损益同比增长率(%)'] < 15)] 54 | if len(pd_judge): 55 | continue 56 | else: 57 | select = select.append(pd_temp) 58 | 59 | select.to_csv('D:\\股票分析\\财务指标选股(每期都满足)_2017至2019年.csv') 60 | --------------------------------------------------------------------------------