正版视频 | 公众号内【技术视频】
或点击左下角
公众号:乐学Fintech
网站:lexueoude.com
这是乐学偶得的第 140篇原创技术文章0.文章内容
在这篇文章中,我们将使用未来现金流折现的方法,运用我们熟悉的Python语言来实现对公司的自动化估值。
我们将构建一个动态的DCF模型——也就是说,我们通过Python编写好这个模型后进行打包,在未来可以将这个模型重复利用, 应用到任何公司的估值过程中。
1.DCF(现金流量折现法)是什么?
我们如果看一家公司的报表——现金流量表将公司的活动分为三个部分:1.投资活动
2.融资活动
3.经营活动。
对于现金流量折现法,我们将主要关注经营现金流。
因为营业性现金流量反映了与公司商品和服务的生产和销售有关的所有现金流入和流出,而与一家公司长期估值相关的,就是这家公司老老实实做业务赚来的钱,而不是光靠融资或者投资获得的钱。
2.注意!!!净收入中的猫腻
我们需要注意到,净收入中其实是可以暗含很多猫腻的——比如非现金项目、折旧假设、赊销等等很可能会污染我们的净收入——道理很简单,这些商业行为很多是并未发生现金上的转移的。
举一个简单的例子:你卖了老王一台宝马车,但是老王不付钱给你,说给你打个白条。我们会计上会把这种“赊销行为”算作收入,但是其实我们并未收到任何现金。
3.估值中的数据与会计报表中数据的调整
在我们拿到一张报表的时候,往往是从净收入开始对数据进行调整,算出真正跟“经营”有关的经营性现金流,然后再扣除必要设备与资本支持,算出自由现金流(也就是完全能自由支配的现金流)——FCF(Free Cash Flow),然后再放入DCF模型进行折现。
会计数据与估值数据变换如下:
净收入 |
+折旧 |
应收帐款增加(-) |
库存增加(-) |
其他资产增加(-) |
应付帐款增加(+) |
增加其他负债(+) |
经营性现金流 |
–购买设备或资本支出 |
自由现金流 |
这里初学者或者金融、财会背景较弱的小伙本很容易将符号的加减弄晕。不过没问题,大家有兴趣可以阅读原文查看更多乐学偶得lexueoude.com出品的更多金融科技FinTech与Python建模、量化等内容,其中有大量金融原理的补充。
这里我们并不展开讲解会计科目与变换,不过分享一种快速弄清加减的方法——你就思考这项商业活动是使得你获得了现金还是失去了现金?然后我们将现金流还原即可——
比如折旧是否真正从你口袋里掏出钱了?没有吧~ 于是咱们加回折旧。
比如应收帐款是不是真正收到现金了?没有吧~于是咱们减去应收帐款增加。。。。。。
另外,购买设备或资本支出这一项也很好理解——你需要维持公司正常经营与持续扩张,需要投入的“维持资金”。
这样所有的必要调整与维持资金的考量完毕后,我们就可以通过一下步骤估值公司价值了——
4.从自由现金流到DCF模型
利用自由现金流(Free Cash Flow of company)对公司估值的原理如下:
其中FCFF为每期的自由现金流,TV为终值,g为增长率,WACC为公司的综合融资成本。关于WACC的计算,我们在乐学偶得lexueoude.com的公众号:乐学FinTech中的《如何用Python计算公司加权平均资本成本(WACC股权+债权)》这一期推送中有介绍,也是通过Python自动获取并计算的,这里就不再赘述。
5.多期自由现金流的预测方法
这里我们自然而然遇到一个问题——我们如果需要用到DCF模型,必须要预测未来几年的自由现金流。那么未来的现金流量该如何建模呢?
我们在《实用Excel操作与VBA财务金融建模》课中的财务建模板块与大家逐行分析介绍了如何预测现金流,然后也介绍了如何通过VBA进行常见财务与金融模型的估值建模编程。 这个步骤稍微有一点繁琐,如果大家有兴趣可以点击阅读原文观看相关视频。在这里我们简要说明一下主要思路:
1.估计收入增长(我们可以假设每年公司收入增长相同,然后通过找到同行公司的销售额增长,与对全行业的成熟程度进行分析,最终估计该公司的收入增长)
2.将公司报表中的销售额百分比算出
3.根据资产负债表预测未来5年的损益表、资产负债表、现金流量表
4.使用WACC作为折现率对未来的FCFF自由现金流进行折现,计算净现值
5.计算公司最终价值TV
6.计算权益价值与公司总债务,最终按照股份数计算每股价值
好了,理清思路,我们就可以使用Python这个工具进行估值了。
6.利用Python计算公司未来收入增长
我们假设公司收入将保持与去年相同的百分比增长。我们以GOOGLE为例进行计算,数据来源我们还是选取免费的API:
import requestsimport numpy as npimport pandas as pdcompany = 'GOOG'demo = 'your api keyIS = requests.get(f'https://financialmodelingprep.com/api/v3/income-statement/{company}?apikey={demo}').json()count = 0#get revenue growth to estimate future salesrevenue_g = []for item in IS: if count < 4: #print(item) revenue_g.append(item['revenue']) count = count + 1revenue_g = (revenue_g[0] - revenue_g[1]) /revenue_g[1] print(revenue_g)#ouctome0.15469210475913925
我们可以看到,去年Google的收入增长了15.46%。我们可以以这个增长率进行下面的建模。
7.损益表和资产负债表处理
我们接下来处理损益表和资产负债表,注意这里我们对数据进行了一个百分比的处理,这样有对比:
#Get net incomenet_income = IS[0]['netIncome']BS = requests.get(f'https://financialmodelingprep.com/api/v3/balance-sheet-statement/{company}?apikey={demo}').json()#get income statement as % of revenue for future predictions and forecast 5 next IS yearsincome_statement = pd.DataFrame.from_dict(IS[0],orient='index')#The [5:26] below get rids of not needed items coming from the APIincome_statement = income_statement[5:26]income_statement.columns = ['current_year']income_statement['as_%_of_revenue'] = income_statement / income_statement.iloc[0]#forecasting 5 next years income statementincome_statement['next_year'] = (income_statement['current_year']['revenue'] * (1+revenue_g)) * income_statement['as_%_of_revenue'] income_statement['next_2_year'] = (income_statement['next_year']['revenue'] * (1+revenue_g)) * income_statement['as_%_of_revenue'] income_statement['next_3_year'] = (income_statement['next_2_year']['revenue'] * (1+revenue_g)) * income_statement['as_%_of_revenue'] income_statement['next_4_year'] = (income_statement['next_3_year']['revenue'] * (1+revenue_g)) * income_statement['as_%_of_revenue'] income_statement['next_5_year'] = (income_statement['next_4_year']['revenue'] * (1+revenue_g)) * income_statement['as_%_of_revenue'] #Get Balance sheet as a percentage of revenuebalance_sheet = pd.DataFrame.from_dict(BS[0],orient='index')balance_sheet = balance_sheet[5:-2]balance_sheet.columns = ['current_year']balance_sheet['as_%_of_revenue'] = balance_sheet / income_statement['current_year'].iloc[0]#forecasting the next 5 years Balance Sheet.balance_sheet['next_year'] = income_statement['next_year'] ['revenue'] * balance_sheet['as_%_of_revenue']balance_sheet['next_2_year'] = income_statement['next_2_year'] ['revenue'] * balance_sheet['as_%_of_revenue']balance_sheet['next_3_year'] = income_statement['next_3_year']['revenue'] * balance_sheet['as_%_of_revenue'] balance_sheet['next_4_year'] = income_statement['next_4_year']['revenue'] * balance_sheet['as_%_of_revenue'] balance_sheet['next_5_year'] = income_statement['next_5_year']['revenue'] * balance_sheet['as_%_of_revenue']
8.预测经营活动的未来现金流量
这里的代码不要看很多,但是思路非常清晰,我们回顾一下刚刚跟大家讲解的会计数据与估值数据的变换公式:
净收入 |
+折旧 |
应收帐款增加(-) |
库存增加(-) |
其他资产增加(-) |
应付帐款增加(+) |
增加其他负债(+) |
经营性现金流 |
–购买设备或资本支出 |
自由现金流 |
变换成代码为:
CF_forecast = {}CF_forecast['next_year'] = {}CF_forecast['next_year']['netIncome'] = income_statement['next_year']['netIncome']CF_forecast['next_year']['inc_depreciation'] = income_statement['next_year']['depreciationAndAmortization'] - income_statement['current_year']['depreciationAndAmortization']CF_forecast['next_year']['inc_receivables'] = balance_sheet['next_year']['netReceivables'] - balance_sheet['current_year']['netReceivables']CF_forecast['next_year']['inc_inventory'] = balance_sheet['next_year']['inventory'] - balance_sheet['current_year']['inventory']CF_forecast['next_year']['inc_payables'] = balance_sheet['next_year']['accountPayables'] - balance_sheet['current_year']['accountPayables']CF_forecast['next_year']['CF_operations'] = CF_forecast['next_year']['netIncome'] + CF_forecast['next_year']['inc_depreciation'] + (CF_forecast['next_year']['inc_receivables'] * -1) + (CF_forecast['next_year']['inc_inventory'] *-1) + CF_forecast['next_year']['inc_payables']CF_forecast['next_year']['CAPEX'] = balance_sheet['next_year']['propertyPlantEquipmentNet'] - balance_sheet['current_year']['propertyPlantEquipmentNet'] + income_statement['next_year']['depreciationAndAmortization']CF_forecast['next_year']['FCF'] = CF_forecast['next_year']['CAPEX'] + CF_forecast['next_year']['CF_operations']CF_forecast['next_2_year'] = {}CF_forecast['next_2_year']['netIncome'] = income_statement['next_2_year']['netIncome']CF_forecast['next_2_year']['inc_depreciation'] = income_statement['next_2_year']['depreciationAndAmortization'] - income_statement['next_year']['depreciationAndAmortization']CF_forecast['next_2_year']['inc_receivables'] = balance_sheet['next_2_year']['netReceivables'] - balance_sheet['next_year']['netReceivables']CF_forecast['next_2_year']['inc_inventory'] = balance_sheet['next_2_year']['inventory'] - balance_sheet['next_year']['inventory']CF_forecast['next_2_year']['inc_payables'] = balance_sheet['next_2_year']['accountPayables'] - balance_sheet['next_year']['accountPayables']CF_forecast['next_2_year']['CF_operations'] = CF_forecast['next_2_year']['netIncome'] + CF_forecast['next_2_year']['inc_depreciation'] + (CF_forecast['next_2_year']['inc_receivables'] * -1) + (CF_forecast['next_2_year']['inc_inventory'] *-1) + CF_forecast['next_2_year']['inc_payables']CF_forecast['next_2_year']['CAPEX'] = balance_sheet['next_2_year']['propertyPlantEquipmentNet'] - balance_sheet['next_year']['propertyPlantEquipmentNet'] + income_statement['next_2_year']['depreciationAndAmortization']CF_forecast['next_2_year']['FCF'] = CF_forecast['next_2_year']['CAPEX'] + CF_forecast['next_2_year']['CF_operations']CF_forecast['next_3_year'] = {}CF_forecast['next_3_year']['netIncome'] = income_statement['next_3_year']['netIncome']CF_forecast['next_3_year']['inc_depreciation'] = income_statement['next_3_year']['depreciationAndAmortization'] - income_statement['next_2_year']['depreciationAndAmortization']CF_forecast['next_3_year']['inc_receivables'] = balance_sheet['next_3_year']['netReceivables'] - balance_sheet['next_2_year']['netReceivables']CF_forecast['next_3_year']['inc_inventory'] = balance_sheet['next_3_year']['inventory'] - balance_sheet['next_2_year']['inventory']CF_forecast['next_3_year']['inc_payables'] = balance_sheet['next_3_year']['accountPayables'] - balance_sheet['next_2_year']['accountPayables']CF_forecast['next_3_year']['CF_operations'] = CF_forecast['next_3_year']['netIncome'] + CF_forecast['next_3_year']['inc_depreciation'] + (CF_forecast['next_3_year']['inc_receivables'] * -1) + (CF_forecast['next_3_year']['inc_inventory'] *-1) + CF_forecast['next_3_year']['inc_payables']CF_forecast['next_3_year']['CAPEX'] = balance_sheet['next_3_year']['propertyPlantEquipmentNet'] - balance_sheet['next_2_year']['propertyPlantEquipmentNet'] + income_statement['next_3_year']['depreciationAndAmortization']CF_forecast['next_3_year']['FCF'] = CF_forecast['next_3_year']['CAPEX'] + CF_forecast['next_3_year']['CF_operations']CF_forecast['next_4_year'] = {}CF_forecast['next_4_year']['netIncome'] = income_statement['next_4_year']['netIncome']CF_forecast['next_4_year']['inc_depreciation'] = income_statement['next_4_year']['depreciationAndAmortization'] - income_statement['next_3_year']['depreciationAndAmortization']CF_forecast['next_4_year']['inc_receivables'] = balance_sheet['next_4_year']['netReceivables'] - balance_sheet['next_3_year']['netReceivables']CF_forecast['next_4_year']['inc_inventory'] = balance_sheet['next_4_year']['inventory'] - balance_sheet['next_3_year']['inventory']CF_forecast['next_4_year']['inc_payables'] = balance_sheet['next_4_year']['accountPayables'] - balance_sheet['next_3_year']['accountPayables']CF_forecast['next_4_year']['CF_operations'] = CF_forecast['next_4_year']['netIncome'] + CF_forecast['next_4_year']['inc_depreciation'] + (CF_forecast['next_4_year']['inc_receivables'] * -1) + (CF_forecast['next_4_year']['inc_inventory'] *-1) + CF_forecast['next_4_year']['inc_payables']CF_forecast['next_4_year']['CAPEX'] = balance_sheet['next_4_year']['propertyPlantEquipmentNet'] - balance_sheet['next_3_year']['propertyPlantEquipmentNet'] + income_statement['next_4_year']['depreciationAndAmortization']CF_forecast['next_4_year']['FCF'] = CF_forecast['next_4_year']['CAPEX'] + CF_forecast['next_4_year']['CF_operations']CF_forecast['next_5_year'] = {}CF_forecast['next_5_year']['netIncome'] = income_statement['next_5_year']['netIncome']CF_forecast['next_5_year']['inc_depreciation'] = income_statement['next_5_year']['depreciationAndAmortization'] - income_statement['next_4_year']['depreciationAndAmortization']CF_forecast['next_5_year']['inc_receivables'] = balance_sheet['next_5_year']['netReceivables'] - balance_sheet['next_4_year']['netReceivables']CF_forecast['next_5_year']['inc_inventory'] = balance_sheet['next_5_year']['inventory'] - balance_sheet['next_4_year']['inventory']CF_forecast['next_5_year']['inc_payables'] = balance_sheet['next_5_year']['accountPayables'] - balance_sheet['next_4_year']['accountPayables']CF_forecast['next_5_year']['CF_operations'] = CF_forecast['next_5_year']['netIncome'] + CF_forecast['next_5_year']['inc_depreciation'] + (CF_forecast['next_5_year']['inc_receivables'] * -1) + (CF_forecast['next_5_year']['inc_inventory'] *-1) + CF_forecast['next_5_year']['inc_payables']CF_forecast['next_5_year']['CAPEX'] = balance_sheet['next_5_year']['propertyPlantEquipmentNet'] - balance_sheet['next_4_year']['propertyPlantEquipmentNet'] + income_statement['next_5_year']['depreciationAndAmortization']CF_forecast['next_5_year']['FCF'] = CF_forecast['next_5_year']['CAPEX'] + CF_forecast['next_5_year']['CF_operations']
注意我们不要看代码多,我们预测了5年。
9.将数据导入Python的Pandas方便批量处理
终于到了末尾了,我们之前的数据处理完毕后就可以很干净的导入到Python的Pandas里的dataframe,这样可以做进一步的批量处理:
#add the forecasted cash flows into a PandasCF_forec = pd.DataFrame.from_dict(CF_forecast,orient='columns')#add below option to format the dataframe with thousand separatorspd.options.display.float_format = '{:,.0f}'.formatprint(CF_forec)
有
10.将自由现金流FCF通过WACC折现
为了折现预测的自由现金流量(FCF),我们将使用WACC进行折现。因此,我们需要估算公司的平均加权资本成本(WACC)。我们在乐学偶得lexueoude.com公众号:乐学FinTech的上一篇推送中《如何用Python计算公司加权平均资本成本(WACC股权+债权)》有详细介绍过,这里就不再赘述,直接上代码:
import pandas_datareader.data as webimport datetimeimport requestsdemo = 'your api key'#Interest coverage ratio = EBIT / interest expensesdef interest_coveraga_and_RF(company): IS= requests.get(f'https://financialmodelingprep.com/api/v3/income-statement/{company}?apikey={demo}').json() EBIT= IS[0]['ebitda'] - IS[0]['depreciationAndAmortization'] interest_expense = IS[0]['interestExpense'] interest_coverage_ratio = EBIT / interest_expense #RF start = datetime.datetime(2019, 7, 10) end= datetime.datetime.today().strftime('%Y-%m-%d') #end = datetime.datetime(2020, 7, 10) Treasury = web.DataReader(['TB1YR'], 'fred', start, end) RF = float(Treasury.iloc[-1]) RF = RF/100 return [RF,interest_coverage_ratio] #Cost of debtdef cost_of_debt(company, RF,interest_coverage_ratio): if interest_coverage_ratio > 8.5: #Rating is AAA credit_spread = 0.0063 if (interest_coverage_ratio > 6.5) & (interest_coverage_ratio <= 8.5): #Rating is AA credit_spread = 0.0078 if (interest_coverage_ratio > 5.5) & (interest_coverage_ratio <= 6.5): #Rating is A+ credit_spread = 0.0098 if (interest_coverage_ratio > 4.25) & (interest_coverage_ratio <= 5.49): #Rating is A credit_spread = 0.0108 if (interest_coverage_ratio > 3) & (interest_coverage_ratio <= 4.25): #Rating is A- credit_spread = 0.0122 if (interest_coverage_ratio > 2.5) & (interest_coverage_ratio <= 3): #Rating is BBB credit_spread = 0.0156 if (interest_coverage_ratio > 2.25) & (interest_coverage_ratio <= 2.5): #Rating is BB+ credit_spread = 0.02 if (interest_coverage_ratio > 2) & (interest_coverage_ratio <= 2.25): #Rating is BB credit_spread = 0.0240 if (interest_coverage_ratio > 1.75) & (interest_coverage_ratio <= 2): #Rating is B+ credit_spread = 0.0351 if (interest_coverage_ratio > 1.5) & (interest_coverage_ratio <= 1.75): #Rating is B credit_spread = 0.0421 if (interest_coverage_ratio > 1.25) & (interest_coverage_ratio <= 1.5): #Rating is B- credit_spread = 0.0515 if (interest_coverage_ratio > 0.8) & (interest_coverage_ratio <= 1.25): #Rating is CCC credit_spread = 0.0820 if (interest_coverage_ratio > 0.65) & (interest_coverage_ratio <= 0.8): #Rating is CC credit_spread = 0.0864 if (interest_coverage_ratio > 0.2) & (interest_coverage_ratio <= 0.65): #Rating is C credit_spread = 0.1134 if interest_coverage_ratio <= 0.2: #Rating is D credit_spread = 0.1512 cost_of_debt = RF + credit_spread return cost_of_debtdef costofequity(company): #RF start = datetime.datetime(2019, 7, 10) end= datetime.datetime.today().strftime('%Y-%m-%d') #end = datetime.datetime(2020, 7, 10) Treasury = web.DataReader(['TB1YR'], 'fred', start, end) RF = float(Treasury.iloc[-1]) RF = RF/100#Beta beta = requests.get(f'https://financialmodelingprep.com/api/v3/company/profile/{company}?apikey={demo}') beta = beta.json() beta = float(beta['profile']['beta']) #Market Return start = datetime.datetime(2019, 7, 10) end= datetime.datetime.today().strftime('%Y-%m-%d') SP500 = web.DataReader(['sp500'], 'fred', start, end) #Drop all Not a number values using drop method. SP500.dropna(inplace = True) SP500yearlyreturn = (SP500['sp500'].iloc[-1]/ SP500['sp500'].iloc[-252])-1 cost_of_equity = RF+(beta*(SP500yearlyreturn - RF)) return cost_of_equity#effective tax rate and capital structuredef wacc(company): FR = requests.get(f'https://financialmodelingprep.com/api/v3/ratios/{company}?apikey={demo}').json() ETR = FR[0]['effectiveTaxRate']# BS = requests.get(f'https://financialmodelingprep.com/api/v3/balance-sheet-statement/{company}?period=quarter&apikey={demo}').json() Debt_to = BS[0]['totalDebt'] / (BS[0]['totalDebt'] + BS[0]['totalStockholdersEquity']) equity_to = BS[0]['totalStockholdersEquity'] / (BS[0]['totalDebt'] + BS[0]['totalStockholdersEquity']) WACC = (kd*(1-ETR)*Debt_to) + (ke*equity_to) return WACCRF_and_IntCov = interest_coveraga_and_RF(company)RF = RF_and_IntCov[0]interest_coverage_ratio = RF_and_IntCov[1]ke = costofequity(company)kd = cost_of_debt(company,RF,interest_coverage_ratio)wacc_company = wacc(company)print('wacc of ' + company + ' is ' + str((wacc_company*100))+'%')
11.计算自由现金流量的净现值
这一步非常简单,只需要套公式折现就可以了:
#FCF List of CFs for each yearFCF_List = CF_forec.iloc[-1].values.tolist()npv = np.npv(wacc_company,FCF_List)
12.计算终值
我们可以通过反推的方式计算种植TV:
这里我们有一个未知的g。
注意,一般来说我们假设永久性利率为2%,因为通常的做法是与长期通货膨胀率(通常为2%左右)保持一致。然后,我们使用WACC对价值进行折现。
#Terminal valueLTGrowth = 0.02Terminal_value = (CF_forecast['next_5_year']['FCF'] * (1+ LTGrowth)) /(wacc_company - LTGrowth)Terminal_value_Discounted = Terminal_value/(1+wacc_company)**4Terminal_value_Discounted
13.计算标的公司价格
OK,一切数据我们都计算出来了,我们直接可以算出公司的股价了:
target_equity_value = Terminal_value_Discounted + npvdebt = balance_sheet['current_year']['totalDebt']target_value = target_equity_value - debtnumbre_of_shares = requests.get(f'https://financialmodelingprep.com/api/v3/enterprise-values/{company}?apikey={demo}').json()numbre_of_shares = numbre_of_shares[0]['numberOfShares']target_price_per_share = target_value/numbre_of_sharestarget_price_per_shareprint(company + ' forecasted price per stock is ' + str(target_price_per_share) )print('the forecast is based on the following assumptions: '+ 'revenue growth: ' + str(revenue_g) + ' Cost of Capital: ' + str(wacc_company) )print('perpetuity growth: ' + str(LTGrowth) )#outcomeGOOG forecasted price per stock is 4828.474984873333the forecast is based on the following assumptions: revenue growth: 0.15469210475913925 Cost of Capital: 0.07348998226517206perpetuity growth: 0.02
文中所计算的是GOOGLE的股价,如果按照这个模型,估值为4828美元,可是google目前股价为1400多美金,这个差距有点大。问题出在哪里呢?
14.从华尔街认同的股价与我们模型反推得到的信息
我们是使用DCF模型进行估值的,DCF模型一般有一个局限就是增长率,也就是如果按照我们模型15%的增长率肯定不靠谱。所以我们必须要调低对google增长的预期(也可以看作市场已经进行了调整,所以股价并没有那么高)。
比如我们调整成5%,估值结果为2638美金。
15.那么问题来了
估值还不对,增长率看来还要低咯......