I overhauled the codes for riskyasset which is typically used for portfolio choice, but is any endogenous state in which next period value aprime cannot be chosen directly but instead is a function of decision variables d and a between-period i.i.d. shock u, that is, aprime(d,u).
The overhaul was about ‘refining’ out the d1 and d3 decisions, before putting the expectations term together with the return function and then solving for the d2 decision (you don’t need to understand this sentence). The effect is anything from a 2x to a 10x improvement in runtimes.
The overhaul is about setting up (following is copy-paste from Life-Cycle Model 31):
To make things run faster we will also use vfoptions.refine\_{}d, which is always a 1-by-3 vector. The three elements are respectively the number of d1, d2 and d3 decision variables, where d1 are decision variables that appear in the return function but not the aprime function, d2 are decision variables that appear in the aprime function but not the return function, and d3 are decision variables that appear in both the aprime function and the return function. As a result the first inputs to the return function are (d1,d3,a,z,...), while the first inputs to the aprime function are (d2,d3,u,...). Our current model has two decisions, riskyshare and savings: riskyshare is only needed in the aprime function so it is a d2 variable, and savings is needed for both the return function and the aprime function so it is a d3 variable, and this model has no d1 variables. Hence we set vfoptions.refine\_{}d=[0,1,1], and we have to make sure that the ordering used for the decision variables in n\_{}d and d\_{}grid fit with the same ordering (we don’t have a d1 in this model, so first is our d2 which is riskyshare, and then comes our d3 which is savings). Note, the codes allow for more than one of each of d1, d2 and d3 variables; you can also have no d1 variables, but you cannot have no d2 nor no d3 variables. Note, functions to evaluate still take all decision variables. You also need to set simoptions.refine\_{}d=vfoptions.refine\_{}d.
What this means in the codes is you need one line of code where you set, e.g., vfoptions.refine_d=[0,1,1] and then other than this is just about being careful with the order in which you put your decision variables in n_d and d_grid, and how you send them as inputs to return fn and aprime fn (and fns to evaluate which will use all decision variables).
So for example in Life-Cycle Model 31 codes:
%% To speed up the use of riskyasset we use 'refine_d', which requires us to set the decision variables in a specific order
vfoptions.refine_d=[0,1,1]; % 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];
% It is possible to solve models without any d1, as is the case here.
simoptions.refine_d=vfoptions.refine_d;
I have updated all the Life-Cycle Models 31-35 to use vfoptions.refine_d. Other than the line setting the option itself, it was a trivial matter of rearranging the decision variables to have the right order, and then minor changes to the inputs for return fn and aprime fn. I also updated the example based on Cocco, Gomes & Maenhout (2005). An example of a d1 decision (which is in return fn but not aprime fn) is the endogenous labor supply decision in Life-Cycle Model 34.
This refine is intended as the standard setup for riskyasset from now on. You can still use the old approach which is no longer documented anywhere, it works fine just now prints a warning that you should switch over to using refine.