Section 4.5 of my notes provides proofs that WACC is the appropriate discount rate for unlevered FCFF in the world of Miller and Modigliani, with and without taxes. This notebook replicates the numerical illustrations of this fact we provided in class.
First we import the modules we will need.
import pandas as pd # pandas is excellent for creating and manipulating dataframes, R-style
import numpy as np # great for array manipulations and simulations
import matplotlib.pyplot as plt #graphing module with matlab-like properties
%matplotlib inline
Now we set parameters and perform a couple of preliminary computations.
Ebitlow=50 # Ebit in bad times
Ebithigh=150 # Ebit in good times
phigh=0.5 # frequency of good times
rD=0.08 # interest rate on debt
ErU=0.12 # unlevered equity return
tau=0.3 # tax rate on EBIT
n=20 # number of grid points for debt levels
# first we compute the value of the unlevered corporation and the max debt level
Ebit=phigh*Ebithigh+(1-phigh)*Ebitlow # expected EBIT each period
Vunotax=Ebit/ErU
Vutax=(1-tau)*Vunotax
Dmax=Ebitlow/rD
# debt grid
Dgrid=np.array([i*Dmax/(n-1) for i in range(n)])
Now we make tables of values with and without taxes.
pd.options.display.float_format = '{:,.2f}'.format # this is the financial format we like
Vnotax=pd.DataFrame({'D':Dgrid}) # no tax
Vtax=pd.DataFrame({'D':Dgrid}) # with tax
Vnotax['V(D)']=Vunotax # value of corporation if no tax
Vtax['V(D)']=np.array([Vutax+Dgrid[i]*tau for i in range(n)]) # value of corporation if tax
Vnotax['E']=Vnotax['V(D)']-Vnotax['D'] # equity value with no tax
Vtax['E']=Vtax['V(D)']-Vtax['D'] # equity value with tax
Vnotax['E(rE)']=100*(Ebit-Vnotax['D']*rD)/Vnotax['E'] # return on equity if no tax
Vtax['E(rE)']=100*(1-tau)*(Ebit-Vtax['D']*rD)/Vtax['E'] # return on equity with tax
Vnotax['WACC']=(Vnotax['E']*Vnotax['E(rE)']+Vnotax['D']*100*rD)/Vnotax['V(D)'] # wacc if no tax
Vtax['WACC']=(Vtax['E']*Vtax['E(rE)']+Vtax['D']*100*rD*(1-tau))/Vtax['V(D)'] # wacc with tax
# the following is a check on our basic leverage formula
Vnotax['E(rE) check']=100*ErU + Vnotax['D']/Vnotax['E']*100*(ErU-rD)# another way to check E(rE) with no tax
Vtax['E(rE) check']=100*ErU + (1-tau)*Vtax['D']/Vtax['E']*100*(ErU-rD) # another way to check E(rE) with tax
# the following is a check that discounting unlevered FCFF at WACC gives the right answer in both cases
Vnotax['V(D) check']=Ebit/(Vnotax['WACC']/100)# another way to check V(D) without tax
Vtax['V(D) check']=(1-tau)*Ebit/(Vtax['WACC']/100) # another way to check V(D) with tax
print('Value calculations with no tax')
print(Vnotax)
print('\n')
print('Value calculations with taxes')
print(Vtax)
A couple plots we did in class.
fig, axs = plt.subplots(1,3,figsize=(12, 8))
axs[0].plot(Vnotax['D'],Vnotax['V(D)'],label='Firm value, no tax')
axs[0].plot(Vnotax['D'],Vtax['V(D)'],label='Firm value, with tax')
#axs[0].set_ylabel('Firm value')
axs[0].set_xlabel('Leverage(D)')
axs[0].legend()
axs[1].plot(Vnotax['D'],Vnotax['WACC'],label='WACC, No tax')
axs[1].plot(Vnotax['D'],Vtax['WACC'],label='WACC with tax')
#axs[1].set_ylabel('WACC')
axs[1].set_xlabel('Leverage(D)')
axs[1].legend()
axs[2].plot(Vnotax['D'],Vnotax['E'],label='Equity value, no tax')
axs[2].plot(Vnotax['D'],Vtax['E'],label='Equity value, with tax')
#axs[2].set_ylabel('Firm value')
axs[2].set_xlabel('Leverage(D)')
axs[2].legend()
Now assume that expected bankrupcty costs are $0.0005 * D^2$. What is the optimal capital structure? Let's look at it graphically first.
def objective(d):
return -(Vutax+tau*d -0.0005*d**2)
# let's find the optimal capital structure so we can plot it our upcoming chart
from scipy.optimize import minimize
from scipy.optimize import Bounds
bounds=[(0,Dmax)]
res = minimize(objective, 0, method='trust-constr',
options={'verbose': 1}, bounds=bounds)
#let's plot the problem we just solved
dplot=np.arange(start=0,stop=Dmax,step=0.1)
plt.plot(dplot,-objective(dplot))
ax = plt.gca()
ax.set_ylabel('Value of the corporation')
ax.set_xlabel('Leverage (D)')
plt.title('Value vs. leverage')
plt.vlines(res.x, 570, -res.fun, linestyle="dashed")
plt.hlines(-res.fun, 0, res.x, linestyle="dashed")
plt.ylim(570,640)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['left'].set_position(('data',0))
Obvioulsy we are looking for the top of that hill. We could use a fine grid in the tables above but, instead, we just cut through the chase and used Python's optimization routine, so we can just print out the bottom line.
print('The optimal level of debt is %.2f.' %res.x)
print('The value of the corporation as the optimal capital structure is %.2f.' %-res.fun)