In [1]:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from fredpy import series, window_equalize, toFredSeries
%matplotlib inline
In [2]:
# Download nominal GDP, nominal personal consumption expenditures, nominal
# gross private domestic investment, the GDP deflator, and an index of hours
# worked in the nonfarm business sector produced by the BLS. All data are
# from FRED and are quarterly.
gdp = series('GDP')
cons = series('PCEC')
invest = series('GPDI')
hours = series('HOANBS')
defl = series('GDPDEF')
# Make sure that all of the downloaded series have the same data ranges
gdp,cons,invest,hours,defl = window_equalize([gdp,cons,invest,hours,defl])
# Compute real GDP, real consumption, real investment
gdp.data = gdp.data/defl.data*100
cons.data = cons.data/defl.data*100
invest.data = invest.data/defl.data*100
Next, compute the quarterly capital stock series for the US using the perpetual inventory method. The discrete-time Solow growth model is given by:
\begin{align} Y_t & = A_tK_t^{\alpha}L_t^{1-\alpha} \tag{1}\\ C_t & = (1-s)Y_t \tag{2}\\ Y_t & = C_t + I_t \tag{3}\\ K_{t+1} & = I_t + (1-\delta)K_t \tag{4}\\ A_{t+1} & = (1+g)A_t \tag{5}\\ L_{t+1} & = (1+n)L_t \tag{6}. \end{align}Here the model is assumed to be quarterly so $n$ is the quarterly growth rate of labor hours, $g$ is the quarterly growth rate of TFP, and $\delta$ is the quarterly rate of depreciation of the capital stock. Given a value of the quarterly depreciation rate $\delta$, an investment series $I_t$, and an initial capital stock $K_0$, the law of motion for the capital stock, Equation (4), can be used to compute an implied capital series. But we don't know $K_0$ or $\delta$ so we'll have to calibrate these values using statistics computed from the data that we've already obtained.
Let lowercase letters denote a variable that's been divided by $A_t^{1/(1-\alpha)}L_t$. E.g.,
\begin{align} y_t = \frac{Y_t}{A_t^{1/(1-\alpha)}L_t}\tag{7} \end{align}Then (after eliminating consumption from the model), the scaled version of the model can be written as:
\begin{align} y_t & = k_t^{\alpha} \tag{8}\\ i_t & = sy_t \tag{9}\\ k_{t+1} & = i_t + (1-\delta-n-g')k_t,\tag{10} \end{align}where $g' = g/(1-\alpha)$ is the growth rate of $A_t^{1/(1-\alpha)}$. In the steady state:
\begin{align} k & = \left(\frac{s}{\delta+n+g'}\right)^{\frac{1}{1-\alpha}} \tag{11} \end{align}which means that the ratio of capital to output is constant:
\begin{align} \frac{k}{y} & = \frac{s}{\delta+n+g'} \tag{12} \end{align}Furthermore, in the steady state, the growth rate of output is constant:
\begin{align} \frac{\Delta Y}{Y} & = n + g' \tag{13} \end{align}Then, armed with calibrated values for $K_0$ and $\delta$, compute $K_1, K_2, \ldots$ recursively. See Timothy Kehoe's notes for more information on the perpetual inventory method:
http://users.econ.umn.edu/~tkehoe/classes/GrowthAccountingNotes.pdf
In [3]:
# Set the capital share of income
alpha = 0.35
# Average saving rate
s = np.mean(invest.data/gdp.data)
# Average quarterly labor hours growth rate
n = (hours.data[-1]/hours.data[0])**(1/(len(hours.data)-1)) - 1
# Average quarterly real GDP growth rate
g = ((gdp.data[-1]/gdp.data[0])**(1/(len(gdp.data)-1)) - 1) - n
# Compute annual depreciation rate
depA = series('M1TTOTL1ES000')
gdpA = series('gdpa')
gdpA = gdpA.window([gdp.dates[0],gdp.dates[-1]])
gdpA,depA = window_equalize([gdpA,depA])
deltaKY = np.mean(depA.data/gdpA.data)
delta = (n+g)*deltaKY/(s-deltaKY)
# print calibrated values:
print('Avg saving rate: ',round(s,5))
print('Avg annual labor growth:',round(4*n,5))
print('Avg annual gdp growth: ',round(4*g,5))
print('Avg annual dep rate: ',round(4*delta,5))
# Construct the capital series. Note that the GPD and investment data are reported on an annualized basis
# so divide by 4 to get quarterly data.
capital = np.zeros(len(gdp.data))
capital[0] = gdp.data[0]/4*s/(n+g+delta)
for t in range(len(gdp.data)-1):
capital[t+1] = invest.data[t]/4 + (1-delta)*capital[t]
# Save in a fredpy series
capital = toFredSeries(data = capital,dates =gdp.dates,units = gdp.units,title='Capital stock of the US',freq='Quarterly')
# plot the computed capital series
plt.plot_date(capital.dates,capital.data,'-',lw=3,alpha = 0.7)
plt.grid()
plt.ylabel(capital.units)
plt.title(capital.title)
Out[3]:
In [4]:
# Compute TFP
tfp = gdp.data/capital.data**alpha/hours.data**(1-alpha)
tfp = toFredSeries(data = tfp,dates =gdp.dates,units = gdp.units,title='TFP of the US',freq='Quarterly')
# Plot the computed capital series
plt.plot_date(tfp.dates,tfp.data,'-',lw=3,alpha = 0.7)
plt.grid()
plt.ylabel(tfp.units)
plt.title(tfp.title)
Out[4]:
In [5]:
# Convert each series into per capita using civilian pop 16 and over
gdp = gdp.percapita(civ_pop=True)
cons = cons.percapita(civ_pop=True)
invest = invest.percapita(civ_pop=True)
hours = hours.percapita(civ_pop=True)
capital = capital.percapita(civ_pop=True)
# Put GDP, consumption, and investment in units of thousands of dollars per person
gdp.data = gdp.data*1000
cons.data = cons.data*1000
invest.data = invest.data*1000
capital.data = capital.data*1000
# Scale hours per person to equal 100 on October (Quarter III) of 2009
hours.data = hours.data/hours.data[hours.dates.index('2009-10-01')]*100
# Make sure TFP series has same length as the rest (since the .percapita() function may affect the date range.
tfp,gdp = window_equalize([tfp,gdp])
# Compute and plot log real GDP, log consumption, log investment, log hours
gdp_log = gdp.log()
cons_log = cons.log()
invest_log = invest.log()
hours_log = hours.log()
capital_log = capital.log()
tfp_log = tfp.log()
# HP filter to isolate trend and cyclical components
gdp_log_cycle,gdp_log_trend = gdp_log.hpfilter()
cons_log_cycle,cons_log_trend = cons_log.hpfilter()
invest_log_cycle,invest_log_trend = invest_log.hpfilter()
hours_log_cycle,hours_log_trend = hours_log.hpfilter()
capital_log_cycle,capital_log_trend = capital_log.hpfilter()
tfp_log_cycle,tfp_log_trend = tfp_log.hpfilter()
In [6]:
# Create a DataFrame with actual and trend data
data = pd.DataFrame({
'gdp':gdp.data,
'gdp_trend':np.exp(gdp_log_trend.data),
'consumption':cons.data,
'consumption_trend':np.exp(cons_log_trend.data),
'investment':invest.data,
'investment_trend':np.exp(invest_log_trend.data),
'hours':hours.data,
'hours_trend':np.exp(hours_log_trend.data),
'capital':capital.data,
'capital_trend':np.exp(capital_log_trend.data),
'tfp':tfp.data,
'tfp_trend':np.exp(tfp_log_trend.data),
},index = pd.DatetimeIndex(gdp.dates))
columns_ordered =[]
names = ['gdp','consumption','investment','hours','capital','tfp']
for name in names:
columns_ordered.append(name)
columns_ordered.append(name+'_trend')
data[columns_ordered].to_csv('Econ129_Rbc_Data.csv')