CustomModelStats

Have just rolled out CustomModelStats to all the stationary general equilibrium and calibration commands. Works for InfHorz and FHorz, and with/without PTypes.

Basic idea is that you can write a command:
myStats()
that outputs a structure, call it CustomStats, with the values of your ‘custom’ statistics, call them myStat1 and myStat2. So inside the command myStats() you set CustomStats.myStat1 and CustomStats.myStat2.

If you want to use them in stationary general eqm, you set
heteroagentoptions.CustomModelStats=@() myStats()
and you can then use myStat1 and myStat2 in (intermediateEqns and) GeneralEqmEqns.

If you want to use them in calibration, you set
caliboptions.CustomModelStats=@() myStats()
and you can then use myStat1 and myStat2 as targets, putting their ‘data version’ in TargetMoments.CustomModelStats.myStat1 and TargetMoments.CustomModelStats.myStat2

The inputs to CustomModelStats are hardcoded, and depend InfHorz/FHorz, and on PTypes. If you are using
InfHorz: the inputs to CustomModelStats are
myStats(V,Policy,StationaryDist,Parameters,FnsToEvaluate,n_d,n_a,n_z,N_j,d_grid,a_grid,z_grid,pi_z,caliboptions,vfoptions,simoptions)
FHorz: the inputs to CustomModelStats are (just add N_j)
myStats(V,Policy,StationaryDist,Parameters,FnsToEvaluate,n_d,n_a,n_z,N_j,d_grid,a_grid,z_grid,pi_z,caliboptions,vfoptions,simoptions)
InfHorz with PType: the inputs to CustomModelStats are (just add Names_i)
myStats(V,Policy,StationaryDist,Parameters,FnsToEvaluate,n_d,n_a,n_z,Names_i,d_grid,a_grid,z_grid,pi_z,caliboptions,vfoptions,simoptions)
FHorz with PType: the inputs to CustomModelStats are (just add N_j, Names_i)
myStats(V,Policy,StationaryDist,Parameters,FnsToEvaluate,n_d,n_a,n_z,N_j,Names_i,d_grid,a_grid,z_grid,pi_z,caliboptions,vfoptions,simoptions)
[The input caliboptions is when you use caliboptions.CustomModelStats and should be replaced with heteroagentoptions when you set heteroagentoptions.CustomModelStats]

Hopefully this is enough to let you calculate any kind of model statistics you can think of, that can then be used as part of stationary general eqm or for calibration. Note, if you need any other input you can always ‘hide’ it in caliboptions (or heteroagentoptions, as appropriate).

This allows for all sorts of things. Two examples, you could use the statistic ‘expected value fn of firm w.r.t. distribution of unemployed households’ as part of a free-entry condition set up as a GeneralEqmEqn. Or you can simulate panel data and run regressions inside myStats(), and thus calibrate model parameters so you get the same regression results you did in real-world panel data [if this was estimation instead of calibration it would be “Indirect Inference”].

By default z_grid and pi_z are the internal toolkit versions (joint-grid, age-dependent). If you want the versions you passed as user, set heteroagentoptions/caliboptions.CustomModelStats_origgrids=1

3 Likes

This is nice!
As far as I understand, I could even calculate here statistics that the toolkit already calculate elsewhere. This may turn out handy if the standard toolkit command is a bit slow and I prefer to use a faster, more specialized code.
Question: are the outputs of this function supposed to be on the gpu? Or it doesn’t matter?

You certainly can do. Codes make a decent effort at speed when calculating the model statistics.
(i) AllStats, AutoCorrTransProbs, and CrossSectionCovarCorr (in InfHorz) are each only run if you are using them in TargetMoments.
(ii) FnsToEvaluate is split into three version for each of the three stats to only do the ones needed for TargetMoments
(iii) simoptions.whichstats is set to only calculate the stats needed for TargetMoments

In FHorz, (i) is done for AllStats and AgeConditionalStats, it also does (ii) and (iii).

Shouldn’t matter (pretty sure it doesn’t matter, but I might not quite have done it in a way that is fully robust, if it does cause an issue just tell me and I will clean it up).

1 Like

I haven’t played with Intermediate Equations yet, but my sense is that it’s more logical for CustomModelStats to use Intermediate Equations than vice-versa. I guess we’ll see…

1 Like

The order of evaluation means it is possible to use (the output of) CustomModelStats in intermediateEqns, but not vice-versa.

(anything intermediateEqns can do for you, you can anyway just manually do while writing CustomModelStats, so you are not losing ‘functionality’ from this ordering, just convenience)

1 Like

BTW, I’ve made the adjustments in my code to use the new CustomModelStats. They work well. I may have found a few typos, but I’m going to dive into merging the latest PType changes first.

If you want a sneak peak, here it is: 4f12a647e62849ef19aba114f5aef424400b76ab

I’ll draw your attention to a missing “end” (merge failure on my part?) at my new line 108 of HeteroAgentStationaryEqm_Case1_FHorz_PType_subfn and also a missing transpose of ptweights at my new line 116.

Please ignore the cprint-related changes. They are in my code and not easily removed for the purpose of this sneak peak.

2 Likes

I might have found an issue when doing the combo of these:

  • CalibrateBIHAModel
  • vfoptions.ExogShockFn
  • caliboptions.CustomModelStats

I want to calibrate a model where some parameter of the exogenous shocks have to be calibrated. So the calibration routine must recompute z_grid and pi_z at each iteration

inside the objective function, the current shock grid is recomputed via something like:

[z_gridvals, pi_z, vfoptions] = ExogShockSetup_InfHorz( ...
    n_z, z_gridvals, pi_z, Parameters, vfoptions, 3);

So far so good. But are we sure that z_grid (or z_gridvals) and pi_z passed to CustomModelStats = @fun_custom_stats are the updated ones and not the initial ones?

The CustomModelStats callback is called with:

caliboptions.CustomModelStatsInputs.z_grid
caliboptions.CustomModelStatsInputs.pi_z

These fields seem to be stored once near the beginning of CalibrateBIHAModel, before the calibration loop, from the original input z_grid and pi_z.

A minimal workaround is to recompute the shock grid inside the user’s CustomModelStats function from the current Parameters, e.g. call the same Tauchen/Rouwenhorst helper there. But it seems more natural if the toolkit passed the current z_gridvals and pi_z from the objective function to CustomModelStats when caliboptions.calibrateshocks == 1

This is the exact complaint Michael made recently.

I had thought “CustomStats gives you exactly the same z_grid you input” would be the easiest behaviour for the user to follow. But clearly not as this is now two people saying that is not what they wanted, and no-one who says this is what they wanted.

I will go change the defaults so that the “internal z_grid” is what you get in CustomStats, and it is an option you can set to get the “same z_grid you input” instead.

2 Likes

Thanks! I had missed Michael’s comment… glad that we all agree :slight_smile:

1 Like

I changed the defaults. CustomModelStats receives z_gridvals (_J) and pi_z (_J) that are used internally. If you want to instead get the ones the user passed, set heteroagentoptions/caliboptions/estimoptions.CustomModelStats_origgrids=1

2 Likes