[1]
import numpy as np

Estimating income processes

Consider NN households indexed by ii who are in the labor market for TT periods indexed by t{1,2,,T}t \in \{1,2,\dots,T\}.

Their wage income is stochastic and given by

Pi,t=ψi,tPi,t1,Y~i,t=ξi,tPi,t,Yi,t={0if μi,t<πY~i,telseψi,tLogNormal(0.5σψ2,σψ)ξi,tLogNormal(0.5σξ2,σξ)μi,tUniform(0,1)P0=1\begin{aligned} P_{i,t} &= \psi_{i,t} P_{i,t-1},\\ \tilde{Y}_{i,t} &= \xi_{i,t} P_{i,t},\\ Y_{i,t} &= \begin{cases} 0 & \text{if } \mu_{i,t} < \pi\\ \tilde{Y}_{i,t} & \text{else} \end{cases} \\ \psi_{i,t} &\sim \text{LogNormal}(-0.5\sigma_{\psi}^2,\sigma_{\psi})\\ \xi_{i,t} &\sim \text{LogNormal}(-0.5\sigma_{\xi}^2,\sigma_{\xi})\\ \mu_{i,t} &\sim \text{Uniform}(0,1)\\ P_{0} &= 1 \end{aligned}

where

  • σψ\sigma_{\psi} is the standard deviation of the permanent shocks, ψi,t\psi_{i,t}
  • σξ\sigma_{\xi} is the standard deviation of the transitory shocks, ξi,t\xi_{i,t}
  • π\pi is the risk of unemployment.

The data you have access to is:

[2]
dataY = np.load('dataY.npy')
T,N = dataY.shape

Question 1: Calculate income growth rates as log-changes

Δlog(Yi,t){log(Yi,t)log(Yi,t1)if Yi,t>0 and Yi,t1>0NaNelse\Delta \log(Y_{i,t}) \equiv \begin{cases} \log(Y_{i,t})-\log(Y_{i,t-1}) & \text{if } Y_{i,t}>0 \text{ and } Y_{i,t-1}>0\\ \text{NaN} & \text{else} \end{cases}

where NaN\text{NaN} is not-a-number (i.e. np.nan).

Question 2: Calculate the following 3 statistics from the data

  • s1datas_1^{data}: Share of observations with Yi,t=0Y_{i,t} = 0
  • s2datas_2^{data}: Variance of income growth rate, Var(ΔlogYi,t)\text{Var}(\Delta\log{Y_{i,t}})
  • s3datas_3^{data}: Co-variance of income growth rates one period apart, Cov(ΔlogYi,t,ΔlogYi,t1)\text{Cov}(\Delta\log{Y_{i,t}},\Delta\log{Y_{i,t-1}})

Question 3: Simulate the income process using your own choice of σψ\sigma_{\psi}, σξ\sigma_{\xi}, π\pi, TT and NN. Calculate the 3 same statistics. Compare with the data statistics.

  • s1sim(σψ,σξ,π)s_1^{sim}(\sigma_{\psi},\sigma_{\xi},\pi): Share of observations with Yi,t=0Y_{i,t} = 0
  • s2sim(σψ,σξ,π)s_2^{sim}(\sigma_{\psi},\sigma_{\xi},\pi): Variance of income growth Var(ΔlogYi,t)\text{Var}(\Delta\log{Y_{i,t}})
  • s3sim(σψ,σξ,π)s_3^{sim}(\sigma_{\psi},\sigma_{\xi},\pi): Co-variance of income growth one periods apart Cov(ΔlogYi,t,ΔlogYi,t1)\text{Cov}(\Delta\log{Y_{i,t}},\Delta\log{Y_{i,t-1}})

Question 4: Solve the following minimization problem to estimate σψ\sigma_{\psi}, σξ\sigma_{\xi} and π\pi

σψ,σξ,π=argminσψ0,σξ0,π[0,1](s1sims1data)2+(s2sims2data)2+(s3sims3data)2\sigma_{\psi}^{\ast},\sigma_{\xi}^{\ast},\pi^{\ast} = \arg \min_{\sigma_{\psi}\geq0,\sigma_{\xi}\geq0,\pi\in[0,1]} (s_1^{sim}-s_1^{data})^2 + (s_2^{sim}-s_2^{data})^2 + (s_3^{sim}-s_3^{data})^2

where for each new guess of σψ\sigma_{\psi}, σξ\sigma_{\xi}, and π\pi you should be re-simulating the data with the same seed and re-calculating the 3 statistics.

[3]
def objective():
    pass

# res = optimize.minimize(objective,x,method='L-BFGS-B',bounds=?,args=?,options={'eps':1e-4})
# hint: options={'eps':1e-4} uses a larger step-size when approximating the jacbian, which is useful in this case

Wealth in the utility function

In the final period, t=Tt=T, the household solves the following problem

vT(aT1)=maxcTcT1ρ1ρ+κ(aT+a)1σ1σs.t.aT=(1+r)aT1+ycT\begin{aligned} v_{T}(a_{T-1}) & = \max_{c_{T}} \frac{c_T^{1-\rho}}{1-\rho} + \kappa \frac{(a_T+\underline{a})^{1-\sigma}}{1-\sigma} \\ & \text{s.t.} & \\ a_{T}& = (1+r)a_{T-1} + y - c_T \end{aligned}

where

  • ata_t is end-of-period assets in period tt
  • ctc_t is consumption in period tt
  • ρ\rho is the CRRA-coefficient for consumption utility
  • σ\sigma is the CRRA-coefficient for wealth utility
  • a\underline{a} is an additive scaling factor for wealth utility
  • κ\kappa is a multiplicative scaling factor for wealth utility
  • rr is the rate of return
  • yy is income

The optimal consumption function is denoted ct(at1)c_t^{\ast}(a_{t-1}).

The optimal savings function is denoted at(at1)(1+r)at1+yct(at1)a_t^{\ast}(a_{t-1}) \equiv (1+r)a_{t-1} + y - c_t^{\ast}(a_{t-1}).

[4]
# a. parameters
rho = 2.0
sigma = 1.2
kappa = 0.6
a_ubar = 2.0
r = 0.04
y = 1.0

# b. grids
a_lag_vec = np.linspace(0,300,300)

Question 1: Find and plot the functions vT(aT1)v_{T}(a_{T-1}), cT(aT1)c_T^{\ast}(a_{T-1}), and aT(aT1)a_T^{\ast}(a_{T-1}).

In all periods before the last, t<Tt < T, the household solves:

vt(at1)=maxctct1ρ1ρ+κ(at+a)1σ1σ+βvt+1(at)s.t.at=(1+r)at1+yct\begin{aligned} v_{t}(a_{t-1}) & = \max_{c_{t}} \frac{c_t^{1-\rho}}{1-\rho} + \kappa \frac{(a_t+\underline{a})^{1-\sigma}}{1-\sigma} + \beta v_{t+1}(a_t)\\ & \text{s.t.} & \\ a_{t}& = (1+r)a_{t-1} + y - c_t \end{aligned}

where β\beta is the discount factor for future utility.

[5]
beta = 0.97
T = 20

Question 2: Find and plot vT1(aT2)v_{T-1}(a_{T-2}) and cT1(aT2)c_{T-1}^{\ast}(a_{T-2}).

Question 3: Find ct(at1)c_t^{\ast}(a_{t-1}) for t{0,1,,T}t \in \{0,1,\dots,T\} and plot them in a single figure.

Define the saving rate as:

st(at1)atat1y+rat1=((1+r)at1+yct(at1))aT1y+rat1s_t^{\ast}(a_{t-1}) \equiv \frac{a_t - a_{t-1}}{y+ra_{t-1}} = \frac{((1+r)a_{t-1} + y - c_t^{\ast}(a_{t-1})) - a_{T-1}}{y+ra_{t-1}}

Question 4: Plot s0(a1)s_0^{\ast}(a_{-1}). Do the rich or the poor save the most?

Question 5: Can you change the parameter choices such that s0(a1)s_0^{\ast}(a_{-1}) is monotonically decreasing in a1a_{-1}?

Refined grid search

Let x=[x1x2]\boldsymbol{x} = \left[\begin{array}{c} x_1 \\ x_2\\ \end{array}\right] be a two-dimensional vector.

Consider the following algorithm:

Algorithm: grid_search()

Goal: Minimize the function f(x)f(\boldsymbol{x}).

  1. Choose a grid size NN and minimum and maximum values of x1x_1 and x2x_2 denoted x1>x1\overline{x}_1 > \underline{x}_1 and x2>x2\overline{x}_2 > \underline{x}_2
  2. Calculate step-sizes

    Δ1=(x1x1)/(N1)Δ2=(x2x2)/(N1)\begin{aligned} \Delta_1 &= (\overline{x}_1 - \underline{x}_1)/(N-1)\\ \Delta_2 &= (\overline{x}_2 - \underline{x}_2)/(N-1) \end{aligned}
  3. Find the grid point with the lowest function value by solving

    j1,j2=argminj1{0,...N1},j2{0,...N1}f(x1+j1Δ1,x2+j2Δ2)j_1^{\ast},j_2^{\ast} = \arg \min_{j_1\in\{0,...N-1\},j_2\in\{0,...N-1\}} f(\underline{x}_1 + j_1\Delta_1, \underline{x}_2 + j_2\Delta_2)
  1. Return x1=x1+j1Δ1x_1^{\ast} = \underline{x}_1 + j_1^{\ast}\Delta_1, x2=x2+j2Δ2x_2^{\ast} = \underline{x}_2 + j_2^{\ast}\Delta_2 and f=f(x1,x2)f^{\ast} = f(x_1^{\ast},x_2^{\ast}).

Question 1: Implement the grid_search() algorithm to minimize the rosen function.

Hint: The global minimum of the rosen function is 00 at (1,1)(1,1).

[6]
def rosen(x):
    return (1.0-x[0])**2+2*(x[1]-x[0]**2)**2
[7]
def grid_search(f,x1_min,x1_max,x2_min,x2_max,N):
    return np.nan,np.nan,np.nan

# settings
x1_min = 0
x1_max = 5
x2_min = 0
x2_max = 4
N = 100

# apply grid search
x1,x2,f = grid_search(rosen,x1_min,x1_max,x2_min,x2_max,N)
print(f'minimum found at ({x1:.8f},{x2:.8f}) with the function value {f:.8f}')
minimum found at (nan,nan) with the function value nan

Also, consider the following algorithm:

Algorithm: refined_grid_search()

Goal: Minimize the function f(x)f(\boldsymbol{x}).

  1. Choose a grid size NN and minimum and maximum values of x1x_1 and x2x_2 denoted x1>x1\overline{x}_1 > \underline{x}_1 and x2>x2\overline{x}_2 > \underline{x}_2, and a refinement-level KK

  2. Set k=0k=0

  3. If k>0k > 0: Update the minimum and maximum values by

    Δ~1=3(x1x1)/(N1)Δ~2=3(x2x2)/(N1)x1=max(x1,x1Δ~1)x2=max(x2,x2Δ~2)x1=min(x1,x1+Δ~1)x2=min(x2,x2+Δ~2)\begin{aligned} \tilde{\Delta}_1 &= 3(\overline{x}_1 - \underline{x}_1)/(N-1)\\ \tilde{\Delta}_2 &= 3(\overline{x}_2 - \underline{x}_2)/(N-1)\\ \underline{x}_1 &= \max(\underline{x}_1,x_1^{\ast}-\tilde{\Delta}_1)\\ \underline{x}_2 &= \max(\underline{x}_2,x_2^{\ast}-\tilde{\Delta}_2)\\ \overline{x}_1 &= \min(\overline{x}_1,x_1^{\ast}+\tilde{\Delta}_1)\\ \overline{x}_2 &= \min(\overline{x}_2,x_2^{\ast}+\tilde{\Delta}_2) \end{aligned}
  4. Apply the grid_search() algorithm returning x1x_1^{\ast}, x2x_2^{\ast} and ff^\ast

  5. Increment kk by one

  6. If k<Kk < K return to step 3 else continue

  7. Return x1x_1^{\ast}, x2x_2^{\ast} and ff^{\ast}

Question 2: Implement the refined_grid_search() algorithm to minimize the rosen function.

[8]
def refined_grid_search(f,x1_min,x1_max,x2_min,x2_max,N,K):
    return np.nan,np.nan,np.nan

# more settings
K = 10

# apply refined grid search
x1,x2,f = refined_grid_search(rosen,x1_min,x1_max,x2_min,x2_max,N,K)
print(f'minimum found at ({x1:.8f},{x2:.8f}) with the function value {f:.8f}')
minimum found at (nan,nan) with the function value nan