Oops, sorry, should be fixed now.
[I was doing some internal cleaning about two weeks ago so all the riskyasset codes did that bit of figuring out which decision variable is which using same few lines of code, clearly didn’t fully clean up.]
Oops, sorry, should be fixed now.
[I was doing some internal cleaning about two weeks ago so all the riskyasset codes did that bit of figuring out which decision variable is which using same few lines of code, clearly didn’t fully clean up.]
Thanks. But now the following error appears:
> Unrecognized function or variable 'l_a'.
>
> Error in StationaryDist_FHorz_Case1_RiskyAsset (line 111)
> if l_a==1 % just riskyasset
>
> Error in StationaryDist_FHorz_Case1 (line 147)
> StationaryDist=StationaryDist_FHorz_Case1_RiskyAsset(jequaloneDist,AgeWeightParamNames,Policy,n_d,n_a,n_z,N_j,pi_z_J,Parameters,simoptions);
>
> Error in LifeCycleModel35 (line 299)
> StationaryDist=StationaryDist_FHorz_Case1(jequaloneDist,AgeWeightsParamNames,Policy,n_d,n_a,n_z,N_j,pi_z,Params,simoptions);
Should be fixed.
I cannot test as I am away (so no gpu). Let me know if there is another issue.
Now it goes through without errors. Thank you!
I am trying to model a Mandatory Savings problem (loosely based on KiwiSaver). Agents earn money before they retire, and contribute a percentage of their employment income to the scheme. Employers match to some amount. Every year the balance increases by the rate of return applied to the balance. Agents cannot withdraw until they retire.
This is classic experienceasset behavior, so I wrote an aprimeFn to calculate the contributions made during employment, and to calculate the balance when pensioners decide they want to liquidate some (or all) of it. In the contribution phase, we need to know how much is being earned (a function of labor hours) so we can calculate the contribution. The two decision variables are thus h and ks_out.
In the retirement phase, pensioners can supplement their income by deciding to liquidate a fraction of their balance. The aprimeFn tells us the post-liquidation value of the experience asset, as it should. But the ReturnFn also needs to work with the liquidation decision variable (I think), so it can add the liquidated value to the consumption function. The return function also has h and ks_out as decision variables.
Because they both have the same two decision variables, then by this comment, d1 and d2 are 0 and all the action is in d3.
% tell the code how many d1, d2, and d3 there are
% Idea is to distinguish three categories of decision variable:
% d1: decision is in the ReturnFn but not in aprimeFn
% d2: decision is in the aprimeFn but not in ReturnFn
% d3: decision is in both ReturnFn and in aprimeFn
% Note: ReturnFn must use inputs (d1,d3,..)
% aprimeFn must use inputs (d2,d3,..)
% n_d must be set up as n_d=[n_d1, n_d2, n_d3]
% d_grid must be set up as d_grid=[d1_grid; d2_grid; d3_grid];
vfoptions.refine_d=[0,0,2];
But this creates a problem when calling into creating the ReturnFnParamNames. But that function doesn’t look through the two zero-valued decision variables to see that there are two decision variables in position 3.
Am I setting this up wrong, or do I need to fix ReturnFnParamNames?
…Partially answering my own question, I see that refine_d should not be used when everything is just d3. Fair enough. So I deleted that and now I’m stuck because the aprimeFnParamNames calculation proclaims that the first parameters will be (d2,a2), despite the fact that I need d1.
aprimeFnParamNames={temp{l_d2+l_a2+(l_a2>=2)+1:end}}; % the first inputs will always be (d2,a2)
Making changes to:
aprimeFnMatrix\CreateaprimePolicyExperienceAssetz.m
ValueFnIter\FHorz\ExperienceAsset\ValueFnIter_FHorz_ExpAsset.m
StationaryDist\FHorz\ExpAssetz\StationaryDist_FHorz_ExpAssetz.m
ValueFnIter\FHorz\ExperienceAssetz\ValueFnIter_FHorz_ExpAssetz.m
ValueFnIter\FHorz\ExperienceAssetz\ValueFnIter_FHorz_ExpAssetz_raw.m
I was able to run my program. Needless to say, having to accommodate n_d1 alongside n_d2 (and consequently d_grid instead of d2_grid) makes things get big fast. Happily, my experiments with single-precision value functions speed things up 4x in this case, which is the difference between one hour and four. It also required some special lowmemory handling to enable it to run with 26 of 32GB GPU RAM using the following:
% Grid sizes to use
n_d=[21,11]; % Endogenous labour choice (fraction of time worked); and kiwisaver redemption percentage
n_a=[51,21,11]; % Endogenous asset holdings: assets, pv, kiwisaver
n_z=[2,9]; % Exogenous labor productivity units shock; energy price shocks
But my agents can now choose to invest in solar capacity vs. retirement scheme to achieve optimal results in the case of a variety of shocks. A small up-front investment in energy cost reduction is a winner compared to an all-in approach to saving for retirement. Who knew?
I look forward to using the single-precision value function!
Do you currently use single precision only for value function iteration or also in other routines? In my experience the distribution is always very fast (so need there), but sometimes the calculation of model statistics (mean, variances, percentiles, etc) can be slow, especially if one has many “functions to evaluate” and/or "conditional restrictions.
Right now I’ve only focused on the value functions, but I’ll look at doing the statistics if there’s a win to be had there. The statistics code is all in one place, whereas I modified around 1300 files (!) across all the value-related functions.
Another update: I remembered that I can cleverly use the same d variable for two jobs: fraction of hours worked before retirement and fraction of retirement savings liquidated after retirement.
Thus, I don’t need special handling to pass an extra d-variable to the aprime function. I’m sure somebody will need that at some point, but not me, and not after today (for this model).
Yet another update: while refine_d may be relegated to only Risky Assets, a new variable cropped up that I had missed: vfoptions.l_dexperienceasset. That, truly, was what I was looking for. That, with other l_d... options, likely gives me everything I need for the toolkit to decide which decision variables need to be passed to what return, aprime, and other such functions.