A bug in CaliberateLifeCycleModel_PType

I think there is a bug in the calibrate function for the life-cycle model. There are error messages when running the example of HuggettVenturaYaron2006 with the most updated toolkit.

Error using cell/ismember (line 34)
Input A of class double and input B of class cell must be cell arrays of
character vectors, unless one is a character vector.

Error in ParameterConstraints_PType_TransformParamsToUnconstrained (line 69)
if any(~ismember(caliboptions.constrainpositivenames, CalibParamNames))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in CalibrateLifeCycleModel_PType (line 196)
[calibparamsvec0,caliboptions]=ParameterConstraints_PType_TransformParamsToUnconstrained(calibparamsvec0,calibparamsvecindex,CalibParamNames,nCalibParamsFinder,caliboptions,1);
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in HuggettVenturaYaron2006 (line 330)
[CalibParams1,calibsummary1]=CalibrateLifeCycleModel_PType(CalibParamNames,TargetMoments,n_d,n_a,n_z,N_j,N_i,d_grid, a_grid, z_grid, pi_z, ReturnFn, Params, DiscountFactorParamNames, jequaloneDistFn,AgeWeightParamNames, PTypeDistParamNames, PTypeParamFn, FnsToEvaluate, caliboptions, vfoptions,simoptions);
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

PS: I ran the same code with the older version of the toolkit, it worked fine.

2 Likes

Interesting. I think I had found something similar in an older post: Constrain General Eqm Parameters - #8 by aledinola

1 Like

I ran a toy calibration example to test “CalibrateLifeCycleModel_PType” and I got a different error message.

To give an idea of my test:

TargetMoments.AgeConditionalStats.assets.Mean = ave.assets;
hours_target = ave.hours;
hours_target(~Params.working) = NaN;
TargetMoments.AgeConditionalStats.hours.Mean = hours_target;

CalibParamNames = {'beta', 'nu'};
ParametrizeParamsFn = [];
caliboptions = struct();
caliboptions.fminalgo = 8;
caliboptions.constrain0to1 = {'beta', 'nu'};
caliboptions.verbose = 1;
caliboptions.weights = 1;

[CalibParams, calibsummary] = CalibrateLifeCycleModel_PType( ...
    CalibParamNames, TargetMoments, n_d, n_a, n_z, N_j, Names_i, ...
    d_grid, a_grid, z_grid, pi_z, ReturnFn, Params, ...
    DiscountFactorParamNames, jequaloneDist, AgeWeightParamNames, ...
    PTypeDistParamNames, ParametrizeParamsFn, FnsToEvaluate, ...
    caliboptions, vfoptions, simoptions);

Here n_d = 0 and d_grid = [], since labor is implicit. The earlier direct
calls to ValueFnIter_Case1_FHorz_PType,
StationaryDist_Case1_FHorz_PType, and
LifeCycleProfiles_FHorz_Case1_PType all run successfully with the same
vfoptions structure.

Error

The calibration call errors before reaching the optimizer:

Unrecognized field name "n_semiz".

Error in CalibrateLifeCycleModel_PType (line 260)
if prod(vfoptions.n_semiz)>0
        ^^^^^^^^^^^^^^^^^
Error in main_calibration (line 107)
[CalibParams, calibsummary] = CalibrateLifeCycleModel_PType( ...
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The model does not use semi-exogenous shocks, and the non-calibration toolkit
calls appear to default this case internally. During the value-function solve,
the displayed vfoptions includes:

n_semiz: 0

However, the original vfoptions passed into CalibrateLifeCycleModel_PType
does not include n_semiz, because my setup only specifies:

vfoptions.verbose = 1;
vfoptions.gridinterplayer = 1;
vfoptions.ngridinterp = 20;

So CalibrateLifeCycleModel_PType seems to require a default option field that
other finite-horizon toolkit routines can infer.

Of course this can be easily fixed by writing

vfoptions.n_semiz = 0;

Tentative toolkit-side fix

A possible toolkit-side fix would be to default vfoptions.n_semiz before line
260, for example:

if ~isfield(vfoptions, 'n_semiz')
    vfoptions.n_semiz = 0;
end

or to guard the condition directly:

if isfield(vfoptions, 'n_semiz') && prod(vfoptions.n_semiz) > 0

@yechen Did you set vfoptions.n_semiz in your code?

If someone is interesting in replicating the error: lifecycle_endo_labor/codes_matlab/main_calibration.m at main ¡ aledinola/lifecycle_endo_labor ¡ GitHub

1 Like

I wanted to test another case, namely the possibility to tell the toolkit to “log” certain targets.
In my example one of the targets is average hours by age and suppose I want it logged, so that the distance is log(data_moment)-log(model_moment), which is the percentage deviation.

caliboptions.logmoments = struct();
caliboptions.logmoments.AgeConditionalStats.hours.Mean = 0;

I think this should work but it does not. I got the following error message:

Unrecognized field name "AllStats".

Error in [CalibrateLifeCycleModel_PType](matlab:matlab.lang.internal.introspective.errorDocCallback('CalibrateLifeCycleModel_PType', 'C:\Users\aledi\OneDrive\Documents\GitHub\VFIToolkit-matlab\Estimation\Calibration\CalibrateLifeCycleModel_PType.m', 293)) ([line 293](matlab: opentoline('C:\Users\aledi\OneDrive\Documents\GitHub\VFIToolkit-matlab\Estimation\Calibration\CalibrateLifeCycleModel_PType.m',293,0)))
caliboptions.logmoments(sofar+1:sofar+acscummomentsizes(1))=logmomentnames.AllStats.(acsmomentnames{1,1}).(acsmomentnames{1,2})*ones(acscummomentsizes(1),1); % Note: *ones() at end is so you can input 1 for a vector parameter and then this becomes a vector of ones
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in [main_calibration](matlab:matlab.lang.internal.introspective.errorDocCallback('main_calibration', 'C:\Users\aledi\OneDrive\Documents\GitHub\lifecycle_endo_labor\codes_matlab\main_calibration.m', 158)) ([line 158](matlab: opentoline('C:\Users\aledi\OneDrive\Documents\GitHub\lifecycle_endo_labor\codes_matlab\main_calibration.m',158,0)))
[CalibParams, calibsummary] = CalibrateLifeCycleModel_PType( ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1 Like

Now I tested whether I can estimate a parameter that depends on permanent type.
I have a simple example with a permanent income type \theta that takes two values. Think of it as a fixed effect in a wage equation:

w = \kappa_j \exp(z+\theta)

where z is an AR1 productivity shock and \theta \sim N(0,\sigma^2_\theta) is a permanent productivity. I set it up as

Params.theta = [exp(-sqrt(Params.sigma_theta)); exp(sqrt(Params.sigma_theta))];

This is a N_i times 1 vector, with N_i=2.

Then for calibration I set

CalibParamNames = {'theta'};
ParamsCalib0.theta = [0.80; 1.40];
caliboptions.constrainpositive = {'theta'};

This case failed after the optimizer, during final calibrated-parameter output
reconstruction. MATLAB reported:

Unrecognized function or variable 'CalibParams'.

Error in CalibrateLifeCycleModel_PType (line 430)
            if isfield(CalibParams,CalibParamNames{nCalibParamsFinder(pp,1)})
                       ^^^^^^^^^^^
Error in main_calibration (line 162)
[CalibParams, calibsummary] = CalibrateLifeCycleModel_PType( ...
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1 Like

@robertdkirkby In my repo I wrote a test script main_calibration where you can test these cases which generate errors

stress_case = "ptype_theta";

% Other possible values:

% "named_logmoments"

% "vector_logmoments"

% "ptype_theta"

% "custom_stats"

% "atoB_constraints"

Note: custom_stats actually works ok, I leave it there for completeness.
Note 2: I haven’t tested the semiz case, but my AI tells me that the branch will give an error, even without running any code, since there is an apparent mistake.

2 Likes

Thanks both. Looks to be an issue with the interaction of parameter constraints and permanent types. I am away (last week mountains, this week conference) and will fix this as soon as I am back.

2 Likes

Hi Aledinola, thank you very much for the testing work you’ve done. I didn’t set vfoptions for semiz because the model has no semi-exogenous state, and the error messages didn’t mention semiz at all.

By the way, is there any example of a model with a semi-endogenous state? What’s the difference between the expericenasset and the semi-endogenous state? @robertdkirkby

1 Like

Here’s a great example of semiz: GitHub - robertdkirkby/riskyassetsemiz: Life-cycle model of portfolio-choice with housing, demonstrate riskyasset+semiz · GitHub

1 Like

Currently just Life-Cycle model 28 covers semi-exogenous shocks. I need to create some more examples.

Semi-exogenous state: semiz’=Q(d,semiz)
Experienceasset: a’=F(d,a)

The difference is that F(d,a) is a function that gives a single value for a’. Whereas Q(d,semiz) is a transition probability matrix that gives the probabilities for each possible value of semiz’. So for situations where you have ‘control’ you use experienceasset, but if you can only ‘influence probabilities’ you use semi-exogenous state.

Intuitively, semi-exogenous state is a markov, but whose transition probabilities depend on the decision.

There are three main applications I know of for semi-exogenous states:

  1. Search-labor (semiz=employed/non-employed, and d=search effort, the more you search the higher the probability of finding a job)
  2. Endogenous fertility (semiz=number of children, d=decide to try have child, the probability you have a child is positive if you try to have a child and this probability depends on the woman’s age)
  3. Endogenous health (semiz=healthy/sick, d=healthy behaviour and health investment, if you choose to behave healthily your probability of getting sick is lower).
    Obviously though there are lots of other things you could use a semi-exogenous shock for. The riskyasset+semiz codes Michael linked to in the above post use the semi-exogenous state to track mortgages.

PS. Semi-exogenous can also be used when you need to track some history of decisions (as you can always make the transition probabilities deterministic). Although experienceasset can do the same. In this case the only advantage is that semi-exogenous state has been coded to work alongside almost all features of the toolkit, so, e.g., you can do riskyasset+semiz but there is not yet a code for riskyasset+experienceasset.

2 Likes

Thank you very much for your detailed explanation regarding the semi-exogenous state and experience asset. Now I can tell the subtle differences between them.

My other question is about the semi-endogenous state, which is an endogenous state whose transition probability depends on another endogenous state. I think the form is something like s′=π(a,s). I have never seen an example of it, but there is a footnote in the document introducing lifecycle models that explains the difference between a semi-exogenous state and a semi-endogenous state.

Sorry, I thought you typo-ed. You are quite right, there is also such a thing as a semi-endogenous shock, just that it is rare so I didn’t think that is what you were asking.

The idea of a semi-endogenous shock is that the (probability of the) shock will depend on your current endogenous state, so s'=\pi(a,s) exactly as you say. This only works in one place in VFI Toolkit currently, and that is solving a infinite horizon value fn problem with one endogenous state. It was implemented in response to a user request, the person had a model of a firm, and the size of the shocks depended on the capital of the firm (capital was an endogenous state). This was many years ago now.

No example exists (obviously there is one, just presumably not public, I guess there is one in my emails somewhere as I would have sent it to the user who requested the feature, ask me if you want a copy).

It has not been implemented anywhere else in the toolkit. But if someone out there does want to use semi-endogenous shocks just let me know and I am happy to roll them out in more places.

2 Likes

Sounds like a useful way to describe a household problem as climate change makes more properties self-insured. In physical risk modeling the shocks are characterized by hazard, vulnerability, and exposure. The vulnerability is typically related to the building stock/quality/maintenance and the exposure to the asset location.

I could see applications for both Life-Cycle analysis and transition analysis (disappearance of insurance over time).

1 Like