-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathOLGModel2.m
More file actions
160 lines (128 loc) · 8.28 KB
/
OLGModel2.m
File metadata and controls
160 lines (128 loc) · 8.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
%% OLG Model 2: use tax to fund pensions
% In the first model households received pensions which simply 'fall from the sky' in the sense
% that there was no government/tax to fund the pensions.
% In the second model we will add a tax to fund pensions.
%
% The model already included a tax rate "tau" which was set equal to zero.
% We will now consider tau as something to be determined in general
% equilibrium based on the tax revenue of tau being enough to pay for the
% pensions (that the pension system runs a balanced budget).
%% Begin setting up to use VFI Toolkit to solve
% Lets model agents from age 20 to age 100, so 81 periods
Params.agejshifter=19; % Age 20 minus one. Makes keeping track of actual age easy in terms of model age
Params.J=100-Params.agejshifter; % =81, Number of period in life-cycle
% Grid sizes to use
n_d=101; % Endogenous labour choice (fraction of time worked)
n_a=1;
n_z=0; % This is how the VFI Toolkit thinks about deterministic models
N_j=Params.J; % Number of periods in finite horizon
figure_c=0; % I like to use a counter for the figures. Makes it easier to keep track of them when editing.
%% Parameters
% Discount rate
Params.beta = 0.99;
% Preferences
Params.sigma = 2; % Coeff of relative risk aversion (curvature of consumption)
Params.eta = 1.5; % Curvature of leisure (This will end up being 1/Frisch elasty)
Params.psi = 10; % Weight on leisure
Params.A=1; % Aggregate TFP. Not actually used anywhere.
% Production function
Params.alpha = 0.3; % Share of capital
Params.delta = 0.1; % Depreciation rate of capital
% Demographics
Params.Jr=67-Params.agejshifter; % Retirement age is 67 (remember j=1 is age 20) (You work when younger, not working from Jr on)
Params.agej=(1:1:Params.J)'; % Current 'j' age, so can check when you retire.
% The amount of pension that retirees receive
Params.pension=0.3;
%% Some initial values/guesses for variables that will be determined in general eqm
Params.tau=0.1; % Initial guess (this will be determined in general eqm)
Params.w=1;
%% Grids
% While there are no 'a' for 'z' in this model, VFI Toolkit requires them
% to figure out what is going on. By making them just a single grid point,
% and then not using them anywhere, we are essentially solving a model without them.
a_grid=1;
z_grid=1; % Note: n_z=0 means that z_grid and pi_z will be ignored, but we still need them as inputs to various commands
pi_z=1;
% Grid for labour choice
h_grid=linspace(0,1,n_d)';
% Switch into toolkit notation
d_grid=h_grid;
%% Now, create the return function
DiscountFactorParamNames={'beta'};
% Note: the following return function actually includes 'assets', but since
% this very basic model has only one possible value for assets this ends up
% irrelevant (VFI Toolkit is not really designed for models this simple with no endogenous state so it looks like it is just overkill when used to solve them).
ReturnFn=@(h,aprime,a,agej,w,sigma,psi,eta,Jr,pension,tau)...
OLGModel1_ReturnFn(h,aprime,a,agej,w,sigma,psi,eta,Jr,pension,tau);
%% Now solve the value function iteration problem, just to check that things are working before we go to General Equilbrium
disp('Test ValueFnIter')
vfoptions=struct(); % Just using the defaults.
tic;
[V, Policy]=ValueFnIter_Case1_FHorz(n_d,n_a,n_z,N_j, d_grid, a_grid, z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions);
toc
%% Initial distribution of agents at birth (j=1)
jequaloneDist=1; % n_a by n_z, but in current setup this is just 1-by-1 in anycase so 'everyone' is going to have to be born here.
%% Agents age distribution
% Many OLG models include some kind of population growth, and perhaps
% some other things that create a weighting of different ages that needs to
% be used to calculate the stationary distribution and aggregate variable.
% This toy model does not have population growth, but there will be
% different fractions of households of each age due to the probability of dying.
% This toy model does not.
Params.mewj=ones(1,Params.J)/Params.J; % This is the Marginal distribution of households over age
% Agents are evenly spread across all ages.
AgeWeightsParamNames={'mewj'}; % Many finite horizon models apply different weights to different 'ages'; eg., due to survival rates or population growth rates.
%% Test
disp('Test StationaryDist')
simoptions=struct(); % Just use the defaults
tic;
StationaryDist=StationaryDist_FHorz_Case1(jequaloneDist,AgeWeightsParamNames,Policy,n_d,n_a,n_z,N_j,pi_z,Params,simoptions);
toc
%% Everything until this point is just the same as for Life-Cycle Models
% For OLG models we need to add a few things
% 1) GEPriceParamNames: the names of the parameters/prices to be determined in general equilibrium
% 2) FnsToEvaluate: these are same as in Life-Cycle models
% 3) GeneralEqmEqns: the general equilibrium equations, these will be equal to zero in general equilibrium
% they take any price/parameter as inputs, and also any FnsToEvaluate as inputs
% 4) That is it for set up, now just use HeteroAgentStationaryEqm_Case1_FHorz() command to solve for the general equilibrium
% 5) p_eqm contains the general equilibrium values of parameters/prices determined in general
% equilibrium, we can put these in Params and then just calculate anything like value
% function, agent stationary distribution, life-cycle profiles, etc., as normal.
%% General eqm variables
GEPriceParamNames={'w','tau'};
%% Set up the General Equilibrium conditions (on assets/interest rate, assuming a representative firm with Cobb-Douglas production function)
% Stationary Distribution Aggregates (important that ordering of Names and Functions is the same)
FnsToEvaluate.L = @(h,aprime,a) h; % Aggregate labour supply
% This version of the model is simple enough that tax revenues and pension expenditures can all just be calculated 'directly'.
% General Equilibrium conditions (these should evaluate to zero in general equilbrium)
GeneralEqmEqns.labormarket = @(w,alpha,L,A) w-(1-alpha)*A*L^(-alpha); % wage equals marginal product of labour
GeneralEqmEqns.pensionbalance = @(pension,L,J,Jr,tau,w) pension*((J-Jr)/J)-tau*w*L; % Retirement benefits equal Payroll tax revenue: pension*fractionretired-tau*w*H
% Note: Inputs to general equilibrium conditions must be either aggregate variables or parameters
%% Test
disp('Test AggVars')
AggVars=EvalFnOnAgentDist_AggVars_FHorz_Case1(StationaryDist, Policy, FnsToEvaluate, Params, [], n_d, n_a, n_z,N_j, d_grid, a_grid, z_grid);
% Advanced: If you did want to test the GeneralEqmEqns to makes sure they are doing what you expect the following commented out lines show how
% % % To be able to test the general equilibrium conditions you need to add the aggregate variables into Params
% % AggVarNames=fieldnames(AggVars);
% % for ii=1:length(AggVarNames)
% % Params.(AggVarNames{ii})=AggVars.(AggVarNames{ii}).Mean;
% % end
% % GeneralEqmConditionsVec=real(GeneralEqmConditions_Case1_v2(GeneralEqmEqns,Params, 2));
%% Solve for the General Equilibrium
% Use the toolkit to find the equilibrium price index.
% In what follows I use the (default) 'search' approach to calculate the General equilibrium.
heteroagentoptions.verbose=1;
p_eqm=HeteroAgentStationaryEqm_Case1_FHorz(jequaloneDist,AgeWeightsParamNames,n_d, n_a, n_z, N_j, 0, pi_z, d_grid, a_grid, z_grid, ReturnFn, FnsToEvaluate, GeneralEqmEqns, Params, DiscountFactorParamNames, [], [], [], GEPriceParamNames, heteroagentoptions, simoptions, vfoptions);
%% p_eqm contains the general equilibrium 'prices', to calculate things about the model
% economy in general equilibrium we must put these in Params, and then use them as standard.
% p_eqm contains the general equilibrium parameter values
% Put this into Params so we can calculate things about the general equilibrium
Params.w=p_eqm.w;
Params.tau=p_eqm.tau;
% Calculate a few things related to the general equilibrium.
[V, Policy]=ValueFnIter_Case1_FHorz(n_d,n_a,n_z,N_j, d_grid, a_grid, z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, [], vfoptions);
StationaryDist=StationaryDist_FHorz_Case1(jequaloneDist,AgeWeightsParamNames,Policy,n_d,n_a,n_z,N_j,pi_z,Params,simoptions);
% We could of course also look at things like life-cycle profiles or
% simulate panel data, but we will wait until later OLG Models to do so.
% E.g., OLG Model 3 plots some life-cycle profiles, OLG Model 4 plots some
% 'aggregates', like GDP and the capital-output ratio.