Replication of: Imai, S. and Keane, M. P. (2004), "Intertemporal Labor Supply and Human Capital Accumulation," International Economic Review, 45(2), 601--641. DOI: 10.1111/j.1468-2354.2004.00138.x
Status: Reproducible REMARK (Tier 2)
- Overview
- The Model
- Installation
- Reproduction Instructions
- Code Organization
- Output Guide
- Parameter Modification Guide
- Data
- System Requirements
- Citation
- License
This repository replicates the lifecycle savings and labor supply model of Imai and Keane (2004) in Python. It is a contribution to the REMARK project at Econ-ARK.
Why do conventional microeconometric estimates of the intertemporal elasticity of substitution (IES) in labor supply yield values near zero, while macroeconomic models require values of 2 or higher to match business-cycle facts?
Imai and Keane solve a continuous-variable dynamic programming problem in which agents choose consumption and labor hours each period, accumulating human capital through learning by doing. They estimate the model by maximum likelihood on white male data from the NLSY79, using a backward-induction algorithm with Chebyshev polynomial interpolation and Gauss-Hermite quadrature.
This replication solves the same dynamic programming problem for three progressively richer parameter configurations and simulates 10,000 agents forward from age 20 to retirement.
The estimated IES is 3.82, far above conventional micro estimates (0.1--1.7). The bias in conventional estimates arises because human capital accumulation makes the shadow wage (marginal rate of substitution between labor and consumption) much higher than the observed wage for young workers. The shadow wage profile is relatively flat over the lifecycle even though observed wages rise steeply, which reconciles a high IES with the near-flat observed hours profile.
Agents maximize discounted expected lifetime utility over a working horizon from age 20 to 65:
where consumption utility is CRRA with age effects,
The budget constraint is
Human capital evolves via a production function that features complementarity between current hours and current human capital:
The age effects
This replication imposes a no-borrowing constraint (
git clone https://github.com/econ-ark/ImaiKeane_replication.git
cd ImaiKeane_replication
docker build -t imai_keane .
docker run --rm imai_keanegit clone https://github.com/econ-ark/ImaiKeane_replication.git
cd ImaiKeane_replication
conda env create -f binder/environment.yml
conda activate imaikeane-replication
./reproduce.shgit clone https://github.com/econ-ark/ImaiKeane_replication.git
cd ImaiKeane_replication
python -m venv .venv && source .venv/bin/activate
pip install -r binder/requirements.txt
./reproduce.sh./reproduce.shExpected runtime: ~22 minutes on a modern laptop.
The script installs dependencies (if not already present) and runs do_all.py, which solves the model under three parameter configurations, simulates agents, and generates figures.
pip install -r binder/requirements.txt
python do_all.pydo_all.py executes five stages:
- Setup: load data, build grids, import auxiliary functions
- Solve and simulate with no uncertainty and no wage growth (sigma=0, G=0)
- Solve and simulate with uncertainty and no wage growth (sigma=0.05, G=0)
- Solve and simulate with uncertainty and wage growth (sigma=0.05, G>0)
- Generate and save comparison figures
Launch the Jupyter notebook for an annotated walkthrough:
jupyter notebook Imai_and_Keane_2004.ipynb.
├── do_all.py # Main orchestration script
├── reproduce.sh # Entry point for full reproduction
├── Imai_and_Keane_2004.ipynb # Annotated Jupyter notebook
├── auxcode/
│ ├── solveproblem.py # Backward-induction solver (EGM, credit constraints, quadrature)
│ ├── simulate.py # Forward simulation of agents using policy functions
│ ├── getGrid.py # Grid construction (log, linear, power spacing)
│ ├── discretize_log_distribution.py # Log-normal quadrature nodes and weights
│ ├── getH.py # Optimal labor at the credit constraint boundary
│ └── getmeanpath.py # Mean path and moment-matching utilities
├── data/
│ ├── startingHCmean97.csv # Mean initial human capital (NLSY97)
│ ├── startingHCsd.csv # Std dev of initial human capital
│ ├── startingAmean97.csv # Mean initial assets
│ └── startingAsd.csv # Std dev of initial assets
├── results/
│ ├── output1/ # Scenario 1: sigma=0, G=0
│ ├── output2/ # Scenario 2: sigma>0, G=0
│ ├── output3/ # Scenario 3: sigma>0, G>0
│ └── figs/ # Generated figures
├── binder/
│ ├── environment.yml # Conda environment specification
│ └── requirements.txt # Pinned pip dependencies
├── Dockerfile # Docker configuration
├── REMARK.md # REMARK metadata
├── CITATION.cff # Citation metadata
├── ImaiKeaneLifeCycle.bib # BibTeX for the original paper
├── myst.yml # MyST documentation config
└── LICENSE # MIT License
Running reproduce.sh generates the following outputs:
Each results/outputN/ directory contains:
policyC.npy-- optimal consumption policy (grid: market resources x human capital x age)policyH.npy-- optimal hours policyendk.npy-- end-of-period human capitalpolicyM.npy-- market resources mappingsimdf.csv-- simulated panel of 10,000 agents (columns: age, assets, consumption, hours, human capital)
results/figs/assets_consumption_across_age.png-- mean assets and consumption by age across all three scenariosresults/figs/laborsupply_across_age.png-- mean labor supply by age across all three scenarios
Key model parameters are defined in do_all.py:
Preferences (line 88):
phi(=3): CRRA consumption parameterbeta(=0.98): discount factorgamma(=0.75): related to age effectssigma: std dev of human capital shock (0 or 0.05)alpha(=0.02): human capital production elasticityeta(=1.25): disutility of labor curvature
Grid resolution (line 33):
nM(=100): grid points for market resourcesnK(=100): grid points for human capitalnq(=6): quadrature points
To run a quick test, reduce nM and nK to 20 and nq to 3.
The data/ directory contains initial conditions drawn from the NLSY97:
startingHCmean97.csv/startingHCsd.csv: mean and standard deviation of initial human capital by education groupstartingAmean97.csv/startingAsd.csv: mean and standard deviation of initial asset holdings by education group
These calibration targets pin down the distribution of agents at age 20.
- Python: 3.10+
- Key packages: numpy 1.24, scipy 1.10, pandas 2.1, matplotlib 3.8, scikit-learn 1.3
- RAM: ~2 GB
- Disk: ~100 MB (results)
- Runtime: ~22 minutes (full), ~3 minutes (reduced grid)
- Docker: 20.0+ (if using containerized reproduction)
If you use this code, please cite both the replication and the original paper. See CITATION.cff for machine-readable metadata.
Original paper:
Imai, S. and Keane, M. P. (2004). "Intertemporal Labor Supply and Human Capital Accumulation." International Economic Review, 45(2), 601--641. DOI: 10.1111/j.1468-2354.2004.00138.x
This project is distributed under the MIT License. See LICENSE for details.