常用估值方法的编程实现(1):自由现金流折现
目录
- 自由现金流模型介绍
- 简介及计算
- 估值
- 其他数据计算方法
- 折现率
- 编程实现
- 编程求取折现率
- NI、NCC、WC_Inv、FC_Inv以及NB的编程计算
- FCFE的编程计算
- 主函数(估值)
- 总结
本文主要介绍自由现金流折现的意义、计算方法,以及基于python与Tushare数据接口的编程实现。参考资料主要为CFA二级Equity Evaluation的Free Cash Flow Evaluation部分。
自由现金流模型介绍
简介及计算
自由现金流(Free Cash Flow,FCF)衡量公司/股东在不影响公司持续发展的前提下可供分配的最大金额,话句话说,其衡量的是一种提供股息的能力。FCF分两种,即FCFF和FCFE,F和E分别代表firm和equity。二者的计算公式分别为:
公式中,各符号代表如下:
NI:net income,当期净利润;
Int:interest,当期利息;
t:tax rate,税率;
NCC:non cash charge,非货币支出,一般有depreciation折旧、amortization摊销等等;
WC Inv:working capital investment,对于营运资本的投资,working capital=流动资产-流动负债。但对于流动资产不考虑账上的现金,而对于流动负债不考虑应付票据和长期票据的短期部分;
FC Inv:fixed capital investment,固定资产支出;
NB:net borrowing,净借贷。
估值
利用自由现金流进行估值的大体思路实际就是对未来每一期预测的自由现金流进行折现,这样假定每年都有一个固定的永续增长率g的话,就可以用戈登增长模型(实际上就是从等比数列求和推出来的)进行计算,公式如下:
或
需要说明的是,由于变量设置的原因,可能导致利用FCFF和FCFE进行的估值并不一致。
其他数据计算方法
折现率
对于股票估值,折现率R有两种取法:1.取要求回报率、2.利用CAPM(资本资产定价模型)进行计算。对于前者直接赋值即可,对于后者计算方法如下。
CAPM模型:
此处Rf为无风险回报率,可取Shibor(上海银行间同业拆借利率)的值;
Rm为市场平均回报率,可以取指数在一定期间内的平均回报,注意由于复利的原因,这里的平均应该取几何平均而非算术平均;
Beta值的定义式如下:
可见,只要找到市场(还是用指数替代)和个股之间的关系,即可求得相应的Beta系数。
编程实现
编程求取折现率
具体计算公式见Section 2.1。
无风险收益率计算:
ShiBOR = pro.shibor(start_date= TODAY, end_date= TODAY)
Rf = ShiBOR["1y"].values[0]
Rf = Rf / 100
print("-- Rf : ", Rf)
市场平均收益率计算:
year = int(TODAY[0 : 4]) - TERM
startDate = str(year) + TODAY[4 : ]
StockIndex = pro.index_daily(ts_code= stockIndex, start_date= startDate, end_date= TODAY)
startPrice = StockIndex.loc[StockIndex.shape[0] -1, "close"]
endPrice = StockIndex.loc[0, "close"]
Rm = (endPrice / startPrice) ** (1 / TERM) - 1
print("-- Rm :", Rm)
beta计算:
indexTrend = StockIndex.loc[:, ["trade_date", "close"]]
indexTrend.columns = ["date", "index"]
stockDF = pro.daily(ts_code= stockCode, start_date= startDate, end_date= TODAY)
# stockDF = pro.index_daily(ts_code='399300.SZ', start_date= startDate, end_date= TODAY)
stockTrend = stockDF.loc[:, ["trade_date", "close"]]
stockTrend.columns = ["date", "stock"]
mergedDF = pd.merge(indexTrend, stockTrend, how= "inner", on= ["date"]) # Only keep those days both are traded
x = np.array(mergedDF.loc[:, "index"].values)
y = np.array(mergedDF.loc[:, "stock"].values)
Var = np.var(x)
Cov = np.cov(x, y)[0,1]
beta = Cov / Var
print("-- beta : ", beta)
折现率计算:
Ri = Rf + beta * (Rm - Rf)
print("-- Ri : ", Ri)
NI、NCC、WC_Inv、FC_Inv以及NB的编程计算
具体计算公式见Section 1.1。另外有几点需要注意:
1、NCC的计算利用了EBITDA与EBIT的差值,前者为earning before interest, tax, depreciation and amortization,后者为earning before interest and tax,差值正好是NCC;
2、这里用到了tushare的财务数据接口,资产负债表pro.balancesheet和损益表pro.income,可能会涉及到一些积分不够无法调取的问题。
def GetFinancialData(pro, eachStockCode, STOCK_LIST, TODAY):line = STOCK_LIST.loc[STOCK_LIST["ts_code"] == eachStockCode].values[0]IPO_date = line[-1]IPO_year = int(IPO_date[0 : 4])if int(TODAY[4 : 6]) < 4 :Last_year = int(TODAY[0: 4]) - 2else:Last_year = int(TODAY[0 : 4]) - 1if Last_year - IPO_year <= 2 :return "new", "new", "new", "new", "new"total_cur_assets = []money_cap = []total_cur_liab = []notes_payable = []non_cur_liab_due_1y = []lt_borr = []st_borr = []n_income = []ebitda = []ebit = []fix_assets = []for i in range(Last_year - IPO_year):thisYear = IPO_year + ithisDate = str(thisYear) + "1231"BalanceSheet = pro.balancesheet(ts_code= eachStockCode, period= thisDate)BalanceSheet = BalanceSheet.fillna(0)total_cur_assets.append(BalanceSheet["total_cur_assets"].values[0])money_cap.append(BalanceSheet["money_cap"].values[0])total_cur_liab.append(BalanceSheet["total_cur_liab"].values[0])notes_payable.append(BalanceSheet["notes_payable"].values[0])non_cur_liab_due_1y.append(BalanceSheet["non_cur_liab_due_1y"].values[0])lt_borr.append(BalanceSheet["lt_borr"].values[0])st_borr.append(BalanceSheet["st_borr"].values[0])fix_assets.append(BalanceSheet["fix_assets"].values[0])IncomeSheet = pro.income(ts_code= eachStockCode, period= thisDate)IncomeSheet = IncomeSheet.fillna(0)n_income.append(IncomeSheet["n_income"].values[0])ebitda.append(IncomeSheet["ebitda"].values[0])ebit.append(IncomeSheet["ebit"].values[0])WC_Inv = []FC_Inv = []NB = []NCC = []NI = n_income[1 : len(n_income)]for eachYear in range(1, len(total_cur_assets)):CA = total_cur_assets[eachYear] - money_cap[eachYear]CA_0 = total_cur_assets[eachYear - 1] - money_cap[eachYear - 1]CL = total_cur_liab[eachYear] - notes_payable[eachYear] - non_cur_liab_due_1y[eachYear]CL_0 = total_cur_liab[eachYear - 1] - notes_payable[eachYear - 1] - non_cur_liab_due_1y[eachYear - 1]WC = CA - CLWC_0 = CA_0 - CL_0WC_Inv.append(WC - WC_0)borrowing = lt_borr[eachYear] + st_borr[eachYear] + notes_payable[eachYear]borrowing_0 = lt_borr[eachYear - 1] + st_borr[eachYear - 1] + notes_payable[eachYear - 1]NB.append(borrowing - borrowing_0)NCC.append(ebitda[eachYear] - ebit[eachYear])FC = fix_assets[eachYear]FC_0 = fix_assets[eachYear - 1]FC_Inv.append(FC - FC_0)return NI, NCC, WC_Inv, FC_Inv, NB
FCFE的编程计算
具体计算公式见Section 1.1。
def CalculateFCFE(NI, NCC, WC_Inv, FC_Inv, NB, term):FCFE = []for i in range(len(NI)):fcfe = NI[i] + NCC[i] - WC_Inv[i] - FC_Inv[i] + NB[i]if fcfe < 0 :fcfe = 0FCFE.append(fcfe)start = FCFE[-term]last = FCFE[-1]g = (last / start) ** (1 / term) - 1return FCFE, g
主函数(估值)
具体计算公式见Section 2.1。
TODAY = "20200213"
STOCK_CODE = "002410.SZ"
STOCK_INDEX = "000001.SH"
TERM = 7
alphaReturn = 5pro = ts.pro_api("############################")
STOCK_LIST = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')NI, NCC, WC_Inv, FC_Inv, NB = GetFinancialData(pro, STOCK_CODE, STOCK_LIST, TODAY)
FCFE, g = CalculateFCFE(NI, NCC, WC_Inv, FC_Inv, NB, TERM)r = CalculateDiscountRate(pro, STOCK_CODE, STOCK_INDEX, TODAY, TERM)
r = r / 100
ShiBOR = pro.shibor(start_date=TODAY, end_date=TODAY)
Rf = ShiBOR["1y"].values[0]
if (Rf + alphaReturn) / 100 > r :r = (Rf + alphaReturn) / 100V_0 = FCFE[-1] * (1 + g) / (r - g)
daily = pro.daily_basic(ts_code= STOCK_CODE, trade_date= TODAY)
shares = daily["total_share"].values[0] * 10000
price = pro.daily(ts_code= STOCK_CODE, start_date= TODAY, end_date= TODAY)["close"].values[0]
value = V_0 / sharesprint("NI : ", NI[-1])
print("NCC : ", NCC[-1])
print("WC_Inv : ", WC_Inv[-1])
print("FC_Inv : ", FC_Inv[-1])
print("NB : ", NB[-1])
print("FCFE : ", FCFE[-1])
print("g : ", g)
print("r : ", r)
print("V_0 : ", V_0 )
print("price : ", price)
print("value : ", value)
总结
自由现金流折现是一种常用的估值方法,是我在学习CFA二级的时候学到的,之后就想着能否把整套估值方法代码话,进行自动化分析估值。CFA这个东西说实话学起来很杂,我希望可以尽量把我的学习成果总结后呈现给大家,以求达到知识共享的目的。
对于代码、公式推导甚至经济金融原理,有没写清楚或者没有理解透的地方都可以与我交流(VX:Erich-Duan)。之后这个系列还会继续更新残余收益模型等等的基于python与tushare的实现。
人生路漫漫,与诸君共勉。
常用估值方法的编程实现(1):自由现金流折现相关推荐
- 基于 Python 的 8 种常用抽样方法
抽样是统计学.机器学习中非常重要,也是经常用到的方法,因为大多时候使用全量数据是不现实的,或者根本无法取到.所以我们需要抽样,比如在推断性统计中,我们会经常通过采样的样本数据来推断估计总体的样本. 上 ...
- java 中常用方法_java_中常用的方法总结
8月1日 练习: 合理覆盖Cat数据类型的,equals()方法 Cat.java 1 覆盖hashCode() 返回的整型值是唯一的 int hashCode() 用法: 一般使用String ...
- Hibernate框架--学习笔记(上):hibernate项目的搭建和常用接口方法、对象的使用
一.什么是Hibernate框架: 1.Hibernate是一个操作数据库的框架,实现了对JDBC的封装: 2.Hibernate是一个ORM(对象关系映射)框架,我们在写程序时 ,用的是面向对象的方 ...
- PCB板常用检测方法
本文来介绍PCB板常用检测方法 1.PCB板人工目测 使用放大镜或校准的显微镜,利用操作人员视觉检查来确定电路板合不合格,并确定什么时候需进行校正操作,它是最传统的检测方法.它的主 要优点是低的预先成 ...
- Day07:常用模块,面向对象编程(对象类)及内置函数
今日内容: 1.常用模块 2.面向对象编程(*****) 介绍面向对象编程 类 对象 3.内置函数 ------------------------------ 1.面向过程编 ...
- 2022 全球网络黑客常用攻击方法 Top10
近几年,借助互联网产业发展的东风,网络黑产也迎来更加巅峰的状态,不论是从攻击效率,组织规模,亦或是收益变现能力,都在一天天变的成熟完善.根据艾瑞咨询 2020 年发布的<现代网络诈骗分析报告&g ...
- android常用控件实验报告,常用控件的编程实验报告
实验二 常用控件的编程 一.实验目的和要求 (1)掌握窗口下拉列表框.选择钮.组合框.多行编辑框等常用控件的基本使用方法和编程方法: (2)掌握窗口控件的齐整性操纵方法以及Tab顺序的设置: (3)掌 ...
- 100天精通Python(数据分析篇)——第62天:pandas常用统计方法大全(含案例)
文章目录 一.常用统计方法与案例 1. 求和(sum) 2. 求平均值(mean) 3. 求最小值(min) 4. 求最大值(max) 5. 求中位数(median) 6. 求众数(mode) 7. ...
- 计算机编程常用英语6,计算机编程常用英语.(DOC)
计算机编程常用英语.(DOC),计算机编程常用英语,计算机编程英语,计算机编程用英语怎么说,计算机编程中常用的术语,计算机编程英语词汇,计算机编程常用单词,市场上常用的计算机编程软件,计算机编程英语简 ...
最新文章
- Creating Apps With Material Design —— Defining Custom Animations
- Linux下root密码忘记的解决办法
- linux中没有semanagea安装包,如何使用semanage管理SELinux安全策略
- Linux 设备树 : 节点与属性的删除
- 如何监视ps/查询的性能和使用
- c语言的一段程序,C语言第一个程序(入门)
- hdu 2612 FindAWay 两点BFS
- 英语词汇辨异 —— 形近字、近义词
- 【mybatis】mybatis基础知识总结
- nod32 update and id
- 万稞pw80线切割编程软件_Sodick 沙迪克慢走丝线切割机床,工件摆斜不校边加工步骤...
- MC2D v0.0.6 Source Code
- 10款主流的软件测试工具,你用过吗
- 前端 js 深浅拷贝
- 关于csdn里面如何设置字体和背景的问题
- 如何快速提升教育直播间人气
- RGB的光的三原色、品红黄青颜料的三原色
- cherry 键盘WIN键不生效问题
- 继承的表现形式与特点
- This probably means that Tcl wasn‘t installed properly报错