I think I found a bug in the toolkit function EvalFnOnAgentDist_AllStats_FHorz_Case1_PType, when the user wants conditional moments with permanent types and conditional restrictions.
I cooked up a simple example in IntroToLifeCycleModels/ALE/AleModel24.m at main · aledinola/IntroToLifeCycleModels · GitHub
First, let me describe very briefly the model.
- The state variables are \left( a,z_{1},z_{2},e,\theta ,j\right) , where z_{1} and z_{2} are two exogenous states (Markov), e is iid exogenous state, \theta is permanent type, j is age.
- The shock z_{2}\in \left\{ 0,1\right\} (sick vs healthy) is age-dependent and type-dependent (see lines 100-131 in my github example)
As a test, I compute average assets conditional on being sick (i.e. z2=0, 1st grid point). The function to evaluate assets and to communicate the conditional restriction are very simple:
FnsToEvaluate.assets=@(h,aprime,a,z1,z2,e) a;
condres.sick = @(h,aprime,a,z1,z2,e) (z2==0);
condres.healthy = @(h,aprime,a,z1,z2,e) (z2==1);
Then I compute the model statistics using
AllStats=EvalFnOnAgentDist_AllStats_FHorz_Case1_PType(StatDist, Policy, FnsToEvaluate, Params,n_d,n_a,n_z,N_j,N_i,d_grid, a_grid, z_grid, simoptions);
The mathematical definition of average assets conditional on being sick is:
E\left[ a|z_{2}=0\right] =\frac{\sum_{a,z_{1},e,\theta ,j}a\times \mu \left(
a,z_{1},0,e,\theta ,j\right) }{\sum_{a,z_{1},e,\theta ,j}\mu \left(
a,z_{1},0,e,\theta ,j\right) }
where \mu is the distribution. Note that the denominator in the expression above denotes the share of sick people in the population.
- In the toolkit, E\left[ a|z_{2}=1\right] is given by
age_sick_assets1=AllStats.sick.assets.Mean - Another way to compute E\left[ a|z_{2}=1\right] with the toolkit is the following (please, correct me if you don’t agree)
age_sick_assets2=sum(AgeStats.sick.assets.Mean.*AgeStats.share_sick.Mean.*Params.mewj)/...
sum(AgeStats.share_sick.Mean.*Params.mewj)
- Yet another (and last, I promise!) way to get E\left[ a|z_{2}=1\right] is to compute it “manually” by following the mathematical definition above,
age_sick_assets3 = sum(Values_assets(:,:,1,:,:,:).*mu_cpu(:,:,1,:,:,:),"all")/...
sum(mu_cpu(:,:,1,:,:,:),"all");
where Values_assets is the asset grid repeated to make it comformable with the distribution.
Now, all these three numbers should be identical
disp([age_sick_assets1,age_sick_assets2,age_sick_assets3])
and in the simple case where (the transition probability of) z2 does not depend on Ptype, they are:
2.6526 2.6526 2.6526
But if I let pi_z2 depend on Ptype (so that the low-educated have a higher probability of being sick, comment line 131 in the code), then all three numbers differ from each other!
2.5282 2.4156 2.2048
So, to sum up, if z2 does not depend on Ptype (only on age), you set pi_z2_J.low = pi_z2_J.high in line 131 and all is good. If however you comment line 131, so that pi_z2_J is different for low and high type, then there is a bug.