Macro simulations
NOTE: The present notebook is coded in R. It relies heavily on the tidyverse ecosystem of packages. We load the tidyverse below as a prerequisite for the rest of the notebook - along with a few other libraries.
\(\rightarrow\) Don’t forget that code flows sequentially. A random chunk may not work if the previous have have not been executed.
library(tidyverse) # Package for data wrangling
library(readxl) # Package to import MS Excel files
library(latex2exp) # Package for LaTeX expressions
library(quantmod) # Package for stock data extraction
library(highcharter) # Package for reactive plots
library(patchwork) # Package for plot layout
The content of the notebook is based on the Macro Simulation website and the neoclassical case in particular.
1 Context
Until now, we have seen a lot of theory, but limited simulations… This notebook is intended on providing some elements in this direction. And to show if the models achieve convergence - or not.
2 The model
2.1 Production & co.
We first start with a Cobb-Douglas production function: \[Y=AK^aN^{1-a}, \quad a \in(0,1), \tag{1}\] where \(N\) is labour/employment/active population. Next, the real wages \[w=(1-a)A(K/N)^a \tag{2}\] This comes from the labour demand of profit-maximizing firms. Indeed, the profit is \[\Pi(N)=AK^aN^{1-a}-wN-\text{other costs}, \tag{3}\] hence the FOC is \(\frac{\partial \Pi}{\partial N}=(1-a)A(K/N)^a-w=0\) QED.
Government expenditures are tied by: \(G=T+B\), i.e., taxes plus debt. But the future value is \(G^f=T^f-(1+r)B\) because the interest of the debt must be reimbursed (no default). Solving for \(B\) gives
\[G+\frac{G^f}{1+r}=T+\frac{T^f}{1+r}. \tag{4}\]
Labor supply is given by \[N = 1-b_1/w. \tag{5}\]
One way to come to this result is the following and stems from arbitrage with respect to leisure. We can assume that the agent in the economy has utility \[U(C,N)= C+b \log(1-N),\]
where \(1-N\) represents (properly normalized) the time dedicated to leisure. The parameter \(b\) tunes how much leisure matters for the agent. At the same time, the agent needs to work to consume: \(C=wN\). There are thus two competing effects: increase work to consume more or decrease work to spend more time on leisure. The logarithmic function is key to obtaining the desired form.
The FOC with respect to N (replacing \(C\) in the above expression) is thus \[\frac{\partial U}{\partial N}=w-\frac{b}{1-N}=0 \quad \Leftrightarrow \quad w(1-N)=b \quad \Leftrightarrow \quad N=1-b/w\]
2.2 Consumption
In fact the true utility is more complex: \[U(C)=\log(C+b_1\log(1-N))+b_2\log(C^f), \] where \(C^f\) is future consumption (expected and treated as exogenous), which is subject to a budget constraint involving future output. The current constraint is
\[C=Y-T-S,\] i.e., what is consumed is what is produced, minus taxes minus what is saved at rate \(r\). The future version is \[C^f=Y^f-T^f+(1+r)S\] Solving for \(S\),
\[C^f=Y^f-T^f+(1+r)(Y-T-C),\] where we can replace taxes by government spending thanks to Equation 4: \[C^f=Y^f-G^f+(1+r)(Y-G-C),\]
Hence the utility becomes
\[U(C,N)=\log(C+b_1\log(1-N))+b_2\log(Y^f-G^f+(1+r)(Y-G-C))\]
Then,
\[\frac{\partial U}{\partial C}=\frac{1}{C+b_1\log(1-N)}-\frac{b_2(1+r)}{Y^f-G^f+(1+r)(Y-G-C)},\] so the FOC with respect to \(C\) is
\[C^f=b_2(1+r)(C+b_1\log(1-N)) \quad \Leftrightarrow \quad C=\frac{C^f}{b_2(1+r)}-b_1\log(1-N) \tag{6}\]
Also, the derivative with respect to \(N\) requires to recall $Y= + wN $:
\[\frac{\partial U}{\partial N}=\frac{-b_1}{(1-N)(C+b_1\log(1-N))}+\frac{b_2(1+r)w}{C^f}\] where we recognize a similar term from Equation 6, which gives
\[C=w\frac{(1-N)(C+b_1\log(1-N))}{b_1}-b_1\log(1-N)\]
and rearranging \[C+b_1\log(1-N)=w\frac{(1-N)(C+b_1\log(1-N))}{b_1} \Leftrightarrow b_1/w = (1-N)\] QED (same form as before!).
3 The code
In fact, the original code has some unnecessary parts if we are only interested in production or consumption.
Below, we keep only the required rows.
3.1 Initializing variables
<- 5 # Number of scenarios (including baseline)
S <- 20 # Number of simulations
nb_sim
# Create and parameterise exogenous variables/parameters that will be shifted
<- vector(length=S) # government expenditures
G0 <- vector(length=S) # productivity
A <- vector(length=S) # expected future income
Yf <- vector(length=S) # household preference for leisure
b1 =1
G0[]=2
A[]=1
Yf[]=0.4 b1[]
# Set parameter values for different scenarios
2] <- 2 # scenario 3: fiscal expansion
G0[3] <- 3.5 # scenario 4: productivity boost
A[4] <- 0.2 # scenario 5: lower expected future income
Yf[5] <- 0.8 # scenario 6: increased preference for leisure
b1[
#Set constant parameter values
<- 0.3 # Capital elasticity of output
a <- 0.9 # discount rate
b2 <- 0.6 # household preference for money
b3 <- 5 # Exogenous capital stock
K <- 0.02 # Expected rate of inflation
pe <- 1 # Future government spending
Gf
# Initialise endogenous variables at arbitrary positive value
<- matrix(1, ncol = S, nrow = nb_sim)
w = I = Y = r = N = P = w C
3.2 Running the loop
#Solve this system numerically through 1000 iterations based on the initialization
for (i in 1:S){
for (t in 2:nb_sim){
#Model equations
<- A[i]*(K^a)*N[t-1, i]^(1-a) #(1) Cobb-Douglass production function
Y[t, i] <- A[i]*(1-a)*(K^a)*N[t-1, i]^(-a) #(2) Labor demand
w[t, i] <- 1 - (b1[i])/w[t-1, i] #(3) Labor supply
N[t, i] #(4) Consumption demand
<- (1/(1+b2+b3))*(Y[t-1, i] - G0[i] + (Yf[i]-Gf)/(1+r[t-1, i]) -b1[i]*(b2+b3)*log(b1[i]/w[t-1, i]))
C[t, i] <- (I[t-1, i]^(a-1))*a*A[i]*N[t,i]^(1-a) #(5) Investment demand, solved for r
r[t, i] <- Y[t, i] - C[t,i] - G0[i] #(6) Goods market equilibrium condition, solved for I
I[t, i]
} }
Let’s plot the result!
bind_cols(t = 1:nb_sim, as_tibble(Y)) |>
pivot_longer(-t, names_to = "scenario", values_to = "production") |>
ggplot(aes(x = t, y = production, color = scenario)) + geom_line() +
theme_classic() + theme(legend.position.inside = c(0.5,0.5))
Some scenarios are redundant (initial choices have no impact).
Let’s have a look at consumption…
bind_cols(t = 1:nb_sim, as_tibble(C)) |>
pivot_longer(-t, names_to = "scenario", values_to = "consumption") |>
ggplot(aes(x = t, y = consumption, color = scenario)) + geom_line() +
theme_classic() + theme(legend.position.inside = c(0.5,0.5))
Ok, some curves stop early… what happened? At time \(t=3\), the variable \(I\) became negative because \(G\) is too large!
What if we add a little noise on the production side? With small shocks to labor supply.
#Solve this system numerically through 1000 iterations based on the initialization
for (i in 1:S){
for (t in 2:nb_sim){
#Model equations
<- A[i]*(K^a)*N[t-1, i]^(1-a) # (1) Cobb-Douglass production function
Y[t, i] <- A[i]*(1-a)*(K^a)*N[t-1, i]^(-a) # (2) Labor demand
w[t, i] <- 1 - (b1[i])/w[t-1, i] + rnorm(1, sd = 0.02) # (3) Labor supply
N[t, i]
}
}bind_cols(t = 1:nb_sim, as_tibble(Y)) |>
pivot_longer(-t, names_to = "scenario", values_to = "production") |>
ggplot(aes(x = t, y = production, color = scenario)) + geom_line() +
theme_classic() + theme(legend.position.inside = c(0.5,0.5))
Ok so we still have convergence (mostly).
What if the shocks are ten times larger?
#Solve this system numerically through 1000 iterations based on the initialization
set.seed(42)
for (i in 1:S){
for (t in 2:nb_sim){
#Model equations
<- A[i]*(K^a)*N[t-1, i]^(1-a) # (1) Cobb-Douglass production function
Y[t, i] <- A[i]*(1-a)*(K^a)*N[t-1, i]^(-a) # (2) Labor demand
w[t, i] <- 1 - (b1[i])/w[t-1, i] + rnorm(1, sd = 0.2) # (3) Labor supply
N[t, i]
}
}bind_cols(t = 1:nb_sim, as_tibble(Y)) |>
pivot_longer(-t, names_to = "scenario", values_to = "production") |>
ggplot(aes(x = t, y = production, color = scenario)) + geom_line() +
theme_classic() + theme(legend.position.inside = c(0.5,0.5))
Rocky, but still relatively consistent.