【财报分析】读取和处理财报数据

说明:本节使用的财报数据下载方式参见 https://www.jianshu.com/p/fdb673ed8c9b

在财报分析系列文章中,小鱼分别介绍了如何读取和分析资产负债表、利润表以及现金流量表,并且将分析成果保存成 Word 文档输出。

不过,之前的系列文章中代码的部分小鱼未做太多整合,所以整体篇幅比较长,这样做的目的呢,也是为了通过大量输入的代码,来熟悉 Pandas 的 API。接下来的系列文章中,小鱼将对代码部分进行整合,向上抽取出公共的函数,提高代码的可扩展性。

定义配置文件 ini.json

在之前进行分析时,无论是分析的主题,图片保存的名称,还是列名都是直接定义为变量,或者使用字面量。这样的方式很不友好,当我们想要分析其他公司的时候,就必须要复制到新的 Jupyter NoteBook 中。

为此,小鱼定义了一个 ini.json 的配置文件,感兴趣的读者朋友只需要保存该配置文件,打开新的 Jupyter NoteBook 笔记时只需要从配置文件中加载变量即可。

{
  "debt": {
    "auto": [
      "资产合计(元)",
      "负债合计(元)",
      "货币资金(元)",
      "交易性金融资产(元)",
      "一年内到期的非流动负债(元)",
      "短期借款(元)",
      "一年内到期的非流动负债(元)",
      "长期借款(元)",
      "应付债券(元)",
      "其中:应付票据(元)",
      "应付账款(元)",
      "预收款项(元)",
      "合同负债(元)",
      "其中:应收票据(元)",
      "合同资产(元)",
      "应收账款(元)",
      "预付款项(元)",
      "固定资产合计(元)",
      "在建工程合计(元)",
      "以公允价值计量且其变动计入当期损益的金融资产(元)",
      "债权投资(元)",
      "可供出售金融资产(元)",
      "其他权益工具投资(元)",
      "持有至到期投资(元)",
      "其他非流动金融资产(元)",
      "长期股权投资(元)",
      "投资性房地产(元)",
      "资产合计(元)",
      "存货(元)",
      "商誉(元)",
      "归属于母公司所有者权益合计(元)"
    ],
    "hands": [
      "其他流动资产里的理财产品",
      "其他流动资产里的结构性存款",
      "长期应付款",
      "应收款项融资",
      "工程物资"
    ]
  },
  "benefit": {
    "auto": [
      "其中:营业收入(元)",
      "其中:营业成本(元)",
      "销售费用(元)",
      "管理费用(元)",
      "研发费用(元)",
      "财务费用(元)",
      "营业税金及附加(元)",
      "三、营业利润(元)",
      "五、净利润(元)",
      "归属于母公司所有者的净利润(元)"
    ]
  },
  "cash": {
    "auto": [
      "经营活动产生的现金流量净额(元)",
      "购建固定资产、无形资产和其他长期资产支付的现金(元)",
      "经营活动产生的现金流量净额(元)",
      "投资活动产生的现金流量净额(元)",
      "筹资活动产生的现金流量净额(元)"
    ]
  },
  "images": [
    ["总资产","总资产增长率"],
    "资产负债率",
    ["准货币资金与有息负债", "准货币资金与有息负债的差额"],
    ["应付预收与应收预付","应收预付明细","应付预收减应收预付的差额"],
    "应收账款和合同资产占总资产的比率",
    "固定资产工程占总资产的比率",
    "投资类资产占总资产的比率",
    "存货和应收账款情况",
    "商誉占总资产的比率",
    ["营业收入","营业收入增长率"],
    ["毛利率","毛利率波动幅度"],
    ["期间费用率","期间费用率占毛利率的比例"],
    "销售费用率",
    ["主营利润率","主营利润占营业利润的比率"],
    "",
    ["净资产收益率ROE","归属于母公司所有者的净利润增长率"],
    "购建支付的现金与经营活动产生的现金流量净额的比率",
    "分配股利、利润或偿付利息支付的现金与经营活动产生的现金流量净额的比率",
    "三大活动的现金流量净额情况"
  ],
  "titles": [
    "一.看总资产,判断公司实力及扩张能力",
    "二.看资产负债率,了解公司的偿债风险",
    "三.看有息负债和准货币资金,排除偿债风险",
    "四.看“应付预收”减“应收预付”的差额,了解公司的竞争优势",
    "五.看应收账款、合同资产,了解公司的产品竞争力",
    "六.看固定资产,了解公司维持竞争力的成本",
    "七.看投资类资产,判断公司的专注程度",
    "八.看存货,了解公司未来业绩爆雷的风险",
    "九.看商誉,了解公司未来爆雷的风险",
    "十.看营业收入,了解公司的行业地位及成长性",
    "十一.看毛利率,了解公司的产品竞争力及风险",
    "十二.看期间费用率,了解公司的成本管控能力",
    "十三.看销售费用率,了解公司产品的销售难易度",
    "十四.看主营利润,了解公司主业的盈利能力及利润质量",
    "十五.看净利润,了解公司的经营成果及含金量,净利润主要看净利润含金量",
    "十六.看归母净利润,了解公司的整体盈利能力及持续性",
    "十七.看购买固定资产、无形资产和其他长期资产支付的现金,了解公司的增长潜力",
    "十八.看分配股利、利润或偿付利息支付的现金,了解公司的现金分红情况",
    "附:三大活动产生的现金流量净额"
  ],
  "tables_fields": {
    "t1": {
      "columns": ["资产合计(元)", "总资产增长率"],
      "auto": ["资产合计(元)"]
    },
    "t2": {
      "columns": ["负债合计(元)", "资产合计(元)", "资产负债率"],
      "auto": ["负债合计(元)", "资产合计(元)"]
    },
    "t3": {
      "columns": ["货币资金(元)", "交易性金融资产(元)", "其他流动资产里的理财产品", "其他流动资产里的结构性存款", "准货币资金",
        "短期借款(元)", "一年内到期的非流动负债(元)", "长期借款(元)", "应付债券(元)", "长期应付款", "有息负债总额",
        "总货币资金与有息负债之差"],
      "auto": ["货币资金(元)", "交易性金融资产(元)", "其他流动资产里的理财产品", "其他流动资产里的结构性存款", "短期借款(元)",
        "一年内到期的非流动负债(元)", "长期借款(元)", "应付债券(元)", "长期应付款"]
    },
    "t4": {
      "columns": ["其中:应付票据(元)", "应付账款(元)", "预收款项(元)", "合同负债(元)", "应付与预收合计", "其中:应收票据(元)",
        "合同资产(元)", "应收款项融资", "应收账款(元)", "预付款项(元)", "应收与预付合计", "应付预收减应收预付的差额"],
      "auto": ["其中:应付票据(元)", "应付账款(元)", "预收款项(元)", "合同负债(元)", "其中:应收票据(元)", "合同资产(元)",
        "应收款项融资","应收账款(元)", "预付款项(元)"]
    },
    "t5": {
      "columns": ["合同资产(元)", "应收账款(元)", "应收账款+合同资产", "资产合计(元)", "(应收账款+合同资产)占总资产的比率"],
      "auto": ["合同资产(元)", "应收账款(元)", "资产合计(元)"]
    },
    "t6": {
      "columns": ["固定资产合计(元)", "在建工程合计(元)", "工程物资", "固定资产+在建工程+工程物资", "资产合计(元)",
        "固定资产工程占总资产的比率"],
      "auto": ["固定资产合计(元)", "在建工程合计(元)", "工程物资", "资产合计(元)"]
    },
    "t7": {
      "columns": ["以公允价值计量且其变动计入当期损益的金融资产(元)", "债权投资(元)", "可供出售金融资产(元)",
        "其他权益工具投资(元)", "持有至到期投资(元)", "其他非流动金融资产(元)", "长期股权投资(元)","投资性房地产(元)",
        "投资类资产合计", "资产合计(元)", "投资类资产占总资产的比率"],
      "auto": ["以公允价值计量且其变动计入当期损益的金融资产(元)", "债权投资(元)", "可供出售金融资产(元)",
        "其他权益工具投资(元)", "持有至到期投资(元)", "其他非流动金融资产(元)", "长期股权投资(元)","投资性房地产(元)",
        "资产合计(元)"]
    },
    "t8": {
      "columns": ["存货(元)", "资产合计(元)", "存货占总资产的比率"],
      "auto": ["存货(元)", "资产合计(元)"]
    },
    "t9": {
      "columns": ["商誉(元)", "资产合计(元)", "商誉占总资产的比率"],
      "auto": ["商誉(元)", "资产合计(元)"]
    },
    "t10": {
      "columns": ["其中:营业收入(元)", "营业收入增长率"],
      "auto": ["其中:营业收入(元)"]
    },
    "t11": {
      "columns": ["其中:营业收入(元)", "其中:营业成本(元)", "毛利率", "毛利率波动率"],
      "auto": ["其中:营业收入(元)", "其中:营业成本(元)"]
    },
    "t12": {
      "columns": ["销售费用(元)","管理费用(元)", "研发费用(元)", "财务费用(元)", "四费合计", "其中:营业收入(元)",
        "期间费用率", "毛利率", "期间费用率占毛利率的比率"],
      "auto": ["销售费用(元)","管理费用(元)", "研发费用(元)", "财务费用(元)", "其中:营业收入(元)"]
    },
    "t13": {
      "columns": ["销售费用(元)","其中:营业收入(元)", "销售费用率"],
      "auto": ["销售费用(元)","其中:营业收入(元)"]
    },
    "t14": {
      "columns": ["其中:营业收入(元)","其中:营业成本(元)", "营业税金及附加(元)", "四费合计", "主营利润", "主营利润率",
        "三、营业利润(元)", "主营利润占营业利润的比率"],
      "auto": ["其中:营业收入(元)","其中:营业成本(元)", "营业税金及附加(元)", "三、营业利润(元)"]
    },
    "t15": {
      "columns": ["经营活动产生的现金流量净额(元)", "五、净利润(元)", "净利润现金比率"],
      "auto": ["经营活动产生的现金流量净额(元)", "五、净利润(元)"]
    },
    "t16": {
      "columns": ["归属于母公司所有者的净利润(元)", "归属于母公司所有者权益合计(元)", "ROE 净资产收益率",
        "归属于母公司所有者的净利润增长率"],
      "auto": ["归属于母公司所有者的净利润(元)", "归属于母公司所有者权益合计(元)"]
    },
    "t17": {
      "columns": ["购建固定资产、无形资产和其他长期资产支付的现金(元)", "经营活动产生的现金流量净额(元)",
        "购建支付的现金与经营活动产生的现金流量净额的比率"],
      "auto": ["购建固定资产、无形资产和其他长期资产支付的现金(元)", "经营活动产生的现金流量净额(元)"]
    },
    "t18": {
      "columns": ["分配股利、利润或偿付利息支付的现金(元)","经营活动产生的现金流量净额(元)",
        "分配股利、利润或偿付利息支付的现金占经营活动产生的现金流量净额的比率"],
      "auto": ["分配股利、利润或偿付利息支付的现金(元)","经营活动产生的现金流量净额(元)"]
    },
    "t19": {
      "columns": ["经营活动产生的现金流量净额(元)", "投资活动产生的现金流量净额(元)", "筹资活动产生的现金流量净额(元)",
        "三大活动现金流量净额类型"],
      "auto": ["经营活动产生的现金流量净额(元)", "投资活动产生的现金流量净额(元)", "筹资活动产生的现金流量净额(元)"]
    }
  }
}

下面,我们读配置文件中的信息做一个简单介绍。

json 最外层的 debt benefit cash 分别表示资产负债表字段、利润表字段以及现金流量表字段。

其中,benefitcash 不包含需要手动赋值的字段 hands ,这是因为我们下载的利润表和现金流量表可以成功导出所有我们分析需要的字段。

资产负债表 debt 中包含了 autohands 两部分,hands 部分定义的项目在读取时需要手动查找年报数据,进行录入。

说明:其他流动资产里的理财产品和结构性存款如果有,会在财务报表附注中说明;长期应付款我们在分析准货币资金和有息负债时须要用到,要通过年报查找长期应付款是否为有息;应收款项融资有的公司导不出来;2018年之后工程物资并入在建工程,在分析2017年及之前的财务数据时,需要手动查找工程物资。

接下来的字段是 imagestitles ,保存的是图片的名称以及标题信息。最后是 tables_fields ,保存了每个分析子表的信息,其中 columns 为子表的列名称,在初始化 DataFrame 时使用,auto 中的列可以直接从总表中读取并复制,未出现在 auto 中的列则需要计算得出。

读取配置文件 ini.json

读取 json 格式的配置文件:

import json

with open('./ini.json', encoding='utf-8') as f:
    config = json.load(f)

images = config['images']
titles = config['titles']
tables_fields = config['tables_fields']

读取和处理财务数据

导入和配置 Pandas ,将三大财务报表的文件名定义为常量:

import pandas as pd

pd.set_option('display.float_format', lambda x: '%.2f' % x)
pd.set_option('mode.chained_assignment', None)

DEBT = 'xxxxxx_debt_year.xls'
BENEFIT = 'xxxxxx_benefit_year.xls'
CASH = 'xxxxxx_cash_year.xls'

读取同花顺个股下载的资产负债表:

debt_df = pd.read_excel(DEBT, sheet_name='Worksheet', header=1, index_col=0)
# 删除空行
debt_df.dropna(inplace=True)
# 将省略符号 '--' 替换为 0
debt_df.replace({'--': 0}, inplace=True)
# 取最近 6 年的数据,正序排列
debt_df = debt_df.T[:6][::-1]
debt_df.columns.name = ''

读取的资产负债表(长度关系只展示部分列):

同花顺个股在导出资产负债表、利润表、现金流量表时,如果某个科目历年的数据全部为空,该字段将不会被导出。

下面,我们遍历 auto 中的字段,如果该字段在 debt_df 的列字段中不存在,则赋值为 0 。

for field in config['debt']['auto']:
    if field not in debt_df:
        print(field)
        debt_df[field] = [0,0,0,0,0,0]

执行过程中,会将不存在的列打印出来,并为该列赋值为 0 :

长期借款(元)
应付债券(元)
合同资产(元)
以公允价值计量且其变动计入当期损益的金融资产(元)
债权投资(元)
持有至到期投资(元)
其他非流动金融资产(元)

接下来是资产负债表需要手动查找的科目:

>> config['debt']['hands']
['其他流动资产里的理财产品', '其他流动资产里的结构性存款', '长期应付款', '应收款项融资', '工程物资']

查找历年年报,小鱼得到如下结果:

# 从15年开始依次录入
debt_df['其他流动资产里的理财产品'] = [0,0,1500000000,2570000000,0,0]
debt_df['其他流动资产里的结构性存款'] = [0,0,0,0,0,0]
debt_df['长期应付款'] = [0,0,0,0,0,0]
debt_df['应收款项融资'] = [0,0,0,0,408972104.07,0]
debt_df['工程物资'] = [0,0,0,0,0,0]

至此资产负债表的数据就处理完啦~

debt_df.apply(format_thousandth).T

为了方便查看,下面输出的是 benefit_df 的转置。

同样的方式,完成利润表的处理:

benefit_df = pd.read_excel(BENEFIT, sheet_name='Worksheet', header=1, index_col=0)
benefit_df.dropna(inplace=True)
benefit_df.replace({'--':0}, inplace=True)
benefit_df = benefit_df.T[:6][::-1]
benefit_df.columns.name = ''

for field in config['benefit']['auto']:
    if field not in benefit_df:
        print(field)
        benefit_df[field] = [0,0,0,0,0,0]

在执行以上代码时,一般情况下不会打印出任何缺失的科目,我们需要分析的科目都是包含的。

利润表的转置:

benefit_df.apply(format_thousandth).T

利润表部分科目:

最后是现金流量表的处理:

cash_df = pd.read_excel(CASH, sheet_name='Worksheet', header=1, index_col=0)
cash_df.dropna(inplace=True)
cash_df.replace({'--':0}, inplace=True)
cash_df = cash_df.T[:6][::-1]
cash_df.columns.name = ''

for field in config['cash']['auto']:
    if field not in cash_df:
        print(field)
        cash_df[field] = [0,0,0,0,0,0]

现金流量表部分科目:

合并三张报表

最后,我们将三份报表的数据合并到一起:

>> df = pd.concat([debt_df, benefit_df, cash_df], axis=1)
>> df

合并后的结果如下:

合并后的报表一共包含 161 个会计科目。将结果保存到 csv 文件,这样我们需要分析的时候,直接读取处理好的 CSV 就好了。

df.to_csv('data.csv')

以上就是今天的全部内容啦连载的下一篇文章,我们将继续优化财务报表分析步骤中的代码。下节见啦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341

推荐阅读更多精彩内容