财报特征包含:资产、负债、营收、利润这几个方面,对同行业公司进来一个初步分析。
这类重复的工作利用python来简化,写好代码以后,后续的只需要输入股票代码,需要的报表日期,即可直接获得数据,数据接口用的tushare。
选取了三家公司:莱宝高科、劲拓股份、新亚电子的2023年半年报进行分析。近日华为产品带来了一波热点,这三家公司都是华为概念的企业,现在来看一下三家同行业公司的半年报,编辑出来的财报特征:
可以看出一下几点:
① 从资产结构上看,三家公司都是轻资产公司,其中莱宝高科有40%多的现金,说明公司的现金流很好。从财务费用率为 -3.79%也体现出,现金留给公司带来了利息收入。
② 新亚电子7.06%的无形资产和商誉,明显高于其他两家。
③ 从负债角度看,莱宝高科和劲拓股份债务非常健康,几乎没有长短借债。新亚电子的短期借债有点过高,达到资产的23.18%。因此莱宝高科的流动负债20.13%,劲拓股份是33.69%,新亚电子高达42.8%。因此从债务角度看,宝来高科的债务结构非常健康。
④ 从股东权益角度来看,莱宝高科的股东权益占比:75.91%,劲拓股份的股东权益占比:64.79% ,新亚电的股东权益占比:40.82% , 这个比例也可以看出,莱宝高科的资金来源主要是内部资金,而新亚电子主要是靠外债。
⑤ 股东权益和债务的比例也会影响净资产收益率,莱宝高科的股东权益占比过高,因此降低了净资产收益率,也就降低了股东的权益,所以股东权益和债务最好的结构为:1:1左右。
源代码如下:
# 获取第一个数据:资产、负债和所有者权益
def get_assets_data(code,date):
result_data1 = pro.balancesheet(ts_code=code, period=date,
fields='end_date,money_cap,trad_asset,fa_avail_for_sale,accounts_receiv,'
'notes_receiv,inventories,oth_cur_assets')\
.rename(columns={'end_date': '项目', 'money_cap': '货币资金', 'trad_asset': '金融',
'fa_avail_for_sale':'资产','accounts_receiv':'及账款','notes_receiv':'应收票据',
'inventories':'存货','oth_cur_assets': '其他流动资产'})
data2 = result_data1.drop_duplicates().set_index('项目') # 去掉完全重复行,并且将日期设置为索引行
data2 = data2.T.fillna(0).reset_index() # 将空值替换为0 为了方便计算,重置了索引
data2.loc[1] = data2.loc[1] + data2.loc[6]
data2.loc[2] = data2.loc[2] + data2.loc[3]
data2 = data2.drop(3)
data2 = data2.drop(6)
data2 = data2.set_index('index')
data2.loc['流动资产及长期金融资产合计'] = data2.sum(axis=0)
result_data2 = pro.balancesheet(ts_code=code, period=date,
fields='end_date,fix_assets,cip,intan_assets,goodwill,oth_nca,total_nca') \
.rename(columns={'end_date': '项目', 'fix_assets': '固定资产', 'cip': '在建工程','intan_assets': '无形资产',
'goodwill': '及商誉', 'oth_nca': '其他非流动资产','total_nca':'非流动资产合计'})
data3 = result_data2.drop_duplicates().set_index('项目') # 去掉完全重复行,并且将日期设置为索引行
data3 = data3.T.fillna(0).reset_index() # 将空值替换为0 为了方便计算,重置了索引
data3.loc[2] = data3.loc[2] + data3.loc[3]
data3 = data3.drop(3).set_index('index')
result = pd.concat([data2,data3])
result.loc['资产合计'] = result.loc['流动资产及长期金融资产合计'] + result.loc['非流动资产合计']
result['占比'] = result[date] / result.loc['资产合计', date]
return result
# 获取第二个数据:负债和股东权益
def get_liabilities_shareholders_data(code,date):
result_data = pro.balancesheet(ts_code=code, period=date,
fields='end_date,st_borr,acct_payable,notes_payable,oth_cur_liab,'
'total_cur_liab,lt_borr,oth_ncl,total_ncl,total_liab,'
'total_hldr_eqy_exc_min_int,minority_int,total_hldr_eqy_inc_min_int,'
'total_liab_hldr_eqy') \
.rename(columns={'end_date': '项目', 'st_borr': '短期借款', 'acct_payable': '及账款',
'notes_payable': '应付票据', 'oth_cur_liab': '其他流动负债',
'total_cur_liab': '流动负债合计','lt_borr': '长期借款',
'oth_ncl': '其他非流动负债', 'total_ncl': '非流动负债合计','total_liab':'负债合计',
'total_hldr_eqy_exc_min_int':'股东权益合计','minority_int':'少数股东权益',
'total_hldr_eqy_inc_min_int':'所有者权益合计','total_liab_hldr_eqy':'负债及股东权益总计'
})
data2 = result_data.drop_duplicates().set_index('项目') # 去掉完全重复行,并且将日期设置为索引行
data2 = data2.T.fillna(0).reset_index() # 将空值替换为0 为了方便计算,重置了索引
data2.loc[2] = data2.loc[2] + data2.loc[3]
result = data2.drop(3).set_index('index')
result['占比'] = result[date] / result.loc['负债及股东权益总计', date]
return result
# 获取第三个数据:营收、净利润
def get_revenue_profit_data(code,date):
result_data = pro.income(ts_code=code, period=date,
fields='end_date,total_revenue,total_cogs,oper_cost,'
'fin_exp,assets_impair_loss,operate_profit,int_exp,'
'non_oper_income,non_oper_exp,total_profit,income_tax,n_income') \
.rename(columns={'end_date': '项目', 'total_revenue': '营业总收入', 'total_cogs': '营业总成本',
'oper_cost': '营业成本','int_exp':'营业开支','fin_exp':'财务费用',
'assets_impair_loss': '资产减值损失',
'operate_profit': '营业利润', 'non_oper_income': '加:营业外收入',
'non_oper_exp':'减:营业外支出','total_profit':'利润总额','income_tax':'减:所得税费用',
'n_income':'净利润'})
data2 = result_data.drop_duplicates().set_index('项目') # 去掉完全重复行,并且将日期设置为索引行
data2 = data2.T.fillna(0) # 将空值替换为0 为了方便计算,重置了索引
data2.loc['营业开支'] = data2.loc['营业总成本'] - data2.loc['营业成本'] - data2.loc['财务费用'] - data2.loc['资产减值损失']
data2['占比'] = data2[date] / data2.loc['营业总收入', date]
return data2
def get_tatement_table(code,date):
data1 = get_assets_data(code, date)
data2 = get_liabilities_shareholders_data(code, date)
data3 = get_revenue_profit_data(code, date)
result = pd.concat([data1, data2, data3])
# 更改列名
result = result.rename(columns={date: code})
result.loc['净值产收益率', code] = result.loc['净利润', code] / result.loc['所有者权益合计', code]
result = result.fillna(0)
return result
# result = get_tatement_table('002415.sz','20151231')
# 如果有多只股票,一次性输出DateFrame
def get_lists_data(lists,date):
temp = pd.DataFrame() # 创建一个空dataframe用来拼接数据
for code in lists:
data = get_tatement_table(code, date)
temp = pd.concat([temp, data], axis=1) # 将多个DataFrame按列拼接在一起
return temp
# 获取多只股票的财报特征数据
lists = ['002106.sz','300400.sz','605277.sh']
result = get_lists_data(lists, '20230630')
# result.to_csv('../data/' + '财报特征.csv')