Life-cycle model estimation: Parametrize kappaj

I had a look at model 47, where we want to estimate the parameters of the determistic age profile of earnings.

Labor earnings in the model are defined as

w \kappa_j \exp(z) h

where h is hours worked, z is an exogenous shock to labor productivity, \kappa_j is an age-dependent parameter and w is wage per efficiency units.

We can parametrize \kappa_j as a low degree polynomial and estimate the coefficients of the polynomial to match some appropriate data targets.

The code in model 47 uses a special function to do this, reported below:

function Params=LifeCycleModel47_ParametrizeKappajFn(Params)

agevec=(Params.agejshifter+Params.agej)/100; % real world ages (this just seems a nicer thing to put the polynomial on, rather than model period; easier to relate to data work)

% log(kappa_j) is a fifth-order polynomial in age (actually, age divided by 100, as otherwise the polynomial just gives 
% numbers so large that when we take the exponential they blow up)
Params.kappa_j=exp(Params.kappa_j_c0+Params.kappa_j_c1*agevec+Params.kappa_j_c2*agevec.^2+Params.kappa_j_c3*agevec.^3+Params.kappa_j_c4*agevec.^4+Params.kappa_j_c5*agevec.^5);
% Note: in the estimation we require that kappa_j is positive, and by
% making log(kappa_j) a polynomial, rather than making kappa_j a
% polynomial, we ensure that kappa_j is alway positive.

end

Why bother doing this and not simply estimating the coefficients of the polynomial together with the other parameters? I can easily add the code of LifeCycleModel47_ParametrizeKappajFn to f_ReturnFn and define kappa_j_c0, kappa_j_c1, etc as additional parameters in the return function, as follows:

function F=LifeCycleModel45_ReturnFn(h,aprime,a,z,w,sigma,psi,eta,agej,Jr,pension,r,kappa_j_c0,kappa_j_c1,kappa_j_c2,kappa_j_c3,kappa_j_c4,kappa_j_c5,agejshifter)

age=(agejshifter+agej)/100; 

kappa_j=exp(kappa_j_c0+kappa_j_c1*age+kappa_j_c2*age^2+kappa_j_c3*age^3+kappa_j_c4*age^4+kappa_j_c5*age^5);

F=-Inf;
if agej<Jr % If working age
    c=w*kappa_j*z*h+(1+r)*a-aprime; % Add z here
else % Retirement
    c=pension+(1+r)*a-aprime;
end

if c>0
    F=(c^(1-sigma))/(1-sigma) -psi*(h^(1+eta))/(1+eta); % The utility function
end

end %end function

This would be an equivalent way to do so.

The nice thing about the way the toolkit does it is that it is just a bit more general. E.g., I could parameterize the conditional survival probabilities which works with the ‘parameterize params’ approach of the toolkit but cannot be done via the return fn. Or I could parameterize the std dev of the innovations to an age-dependent markov process (and then use ‘ExogShockFn’). Or when I want to parameterize the distribution of a parameter across permanent types (useful, e.g., for modelling unobserved heterogeneity; although this could in principle be done by the kind of ‘evaluate the parametrization inside the return fn’ approach you take here).

The main advantage though is about convenience, which is that having kappa_j as a vector means it can easily be used in things like FnsToEvaluate. When kappa_j is a vector dependence on age is handled automatically, but if you parameterize it you have to handle that manually. So if I set it up in the style you do, where kappa_j is parameterized and I only evaluate the kappa_j inside the return fn, then I would have to add this kind of evaluation of the kappa_j in the FnsToEvaluate or anywhere else I want to use it. [Of course you could add a line of code in which you evaluate kappa_j as a vector from the parameterized one, but this opens up a lot of opportunities to forget to update something and means you are mixing using one in the return fn and the other in the FnsToEvaluate.]

Since you only want to use this parameterization of kappa_j as being a polynomial during the calibration/estimation step, and prefer it as a vector (so that dependence on age is handled automatically) the rest of the time, it is nice to only have to set the parameterization up while doing the calibration/estimation and ignore it the rest of the time.

1 Like

Nice explanation, thanks!
I have a technical question: is ParametrizeKappajFn ever passed to arrayfun? If not, I could parametrize \kappa_j as a spline, right? I estimate the spline coefficients and then I evaluate the spline inside ParametrizeKappajFn. In this case my approach based on evaluating the parametrization inside the return function would not work, since you can’t invoke spline in the return function.

Internally it will just run Params=ParametrizeKappajFn(Params). So depending on what you write inside ParametrizeKappajFn() it will use the gpu or cpu following what you tell it to do.

1 Like