Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consistent t-index for time varying shock parameters. #1022

Closed
sbenthall opened this issue Jun 22, 2021 · 18 comments · Fixed by #1039 · May be fixed by #1042
Closed

Consistent t-index for time varying shock parameters. #1022

sbenthall opened this issue Jun 22, 2021 · 18 comments · Fixed by #1039 · May be fixed by #1042
Milestone

Comments

@sbenthall
Copy link
Contributor

Referring to #1021 and #326

Parameters for a time-varying income process are entered like this:

# Parameters that specify the income distribution over the lifecycle
    "PermShkStd" : [0.1,0.2,0.1,0.2,0.1,0.2,0.1,0,0,0],
    "PermShkCount" : 7,                    # Number of points in discrete approximation to permanent income shocks
    "TranShkStd" : [0.3,0.2,0.1,0.3,0.2,0.1,0.3,0,0,0],
    "TranShkCount" : 7,                    # Number of points in discrete approximation to transitory income shocks

But against what one might expect, the 0th element of the list is interpreted as the shock that occurs at the 0th as well as 1th periods. The 1th element of the list corresponds to the 2th shock, etc.

This not a natural way to define a model and is not very well documented; it is done this way because of some logic imported from earlier solution code. That code should be ammended.

@sbenthall sbenthall added this to the 1.0.0 milestone Jun 22, 2021
@sbenthall sbenthall mentioned this issue Jun 23, 2021
3 tasks
@sbenthall
Copy link
Contributor Author

This is the backwards induction code that iterates back through the time steps.

https://github.com/econ-ark/HARK/blob/master/HARK/core.py#L1006-L1034

What it's doing is:

  • Computing T as the length of the time-varying parameter lists
  • Iterating with t from 0 to (T-1). Let k = T - 1 - t, so k is ranging from (T-1) back down to 0. This is a backwards index for each time-varying value.
  • Get the one-period solver for k.
  • Get the properties of the agent at k needed for the solver, including the IncShkDstn, etc.
  • compute and store the solution.

The resulting list of solutions gets prepended to a list containing the terminal solution, which will be total of (T + 1) in length.

https://github.com/econ-ark/HARK/blob/master/HARK/core.py#L895-L902

The finite model is thus defined over (T + 1) periods, but with the first period omitted from list of T time-varying parameters.

To make the corrections recommended by this issue, we need to:

  • For every time-varying default parameter list, prepend a 0th element equal to its first, which will cover the 'newborn' case.
  • In the solve_one_cycle code, let k range from T to 1.

Everything should then work as before and the weird newborn handling questioned in #326 can then be removed.

@sbenthall
Copy link
Contributor Author

Ah, it is not quite so simple.

In the case of a cyclical model, with, say T = 4, then this buffering will not work.

@mnwhite I'm looking at this case:

# Make a dictionary to specify an infinite consumer with a four period cycle
init_cyclical = copy(init_idiosyncratic_shocks)
init_cyclical['PermGroFac'] = [1.082251, 2.8, 0.3, 1.1]
init_cyclical['PermShkStd'] = [0.1, 0.1, 0.1, 0.1]
init_cyclical['TranShkStd'] = [0.1, 0.1, 0.1, 0.1]
init_cyclical['LivPrb'] = 4*[0.98]
init_cyclical['T_cycle'] = 4

I guess what has been happening is that "newborns" born into this model experience a PermGroFac = 1.082251 their first period, then in the next period experience that value again. But in all subsequent iterations they experience PermGroFac in a 4-step cycle?

This is a very awkward default.

@sbenthall
Copy link
Contributor Author

One thing that perhaps simplifies this problem is that while time-vary one-period-solvers appear to be supported in the library, in practice this feature is never ever used, and so can be ignored and or removed until there's a good reason to put it back it. At such a point in the future, things may be redesigned so that it can be more easily accomodated. But there's no sense in maintaining backwards compatibility with a feature that is never used if it necessitates keeping an otherwise maddening design.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 23, 2021 via email

@mnwhite
Copy link
Contributor

mnwhite commented Jun 23, 2021 via email

@sbenthall
Copy link
Contributor Author

It's a straight up flawed design.

I'm fixing this now. How should it work?

For the cyclical case, I think for time-varying parameters p_0, p_1, ... p_c, you experience parameters p_0 whenever t mod (c + 1) = 0.

The solution for period 0 "looks forward" to p_1; and so on, until the solution for period c, which "looks forward" to p_0.

Does that sound right?

Separately, in the finite model with (p_0, p_1, ..., p_E), you start with a terminal solution s_E.

Then you work backwards starting with t = E - 1. s_t depends on the parameters p_{t+1}. p_0 is never used for a solution, but that's just fine.

Sound right?

They aren't used right now, but when we get to the "step by step" solvers that break a one period problem into sub-problems, this is the feature we'd want to use.

There are a lot of ideas about how to do this floating around.

I think these ideas are all far too preliminary for the library to be committed to a particular implementation at this point.

There are several areas where there are, as we know, flawed designs.

Let's fix those problems and then figure out how to build the next features we need on top of that better design.

@sbenthall
Copy link
Contributor Author

@Mv77 Could I double check something with you?

When you wrote the SCF dataset based parameters tools, which are now the default parameters for the ConsIndShock lifecycle model, did you drop the first row of the dataset in order to correct for the current handling of time-varying parameters? Or did you assume (as I would have) that the 0th element of the parameter list corresponded to the 0th represented age/period in the dataset?

I think I have figured out how to get the parameter indexing to work properly, so now it's just a matter of making the default parameters sensible.

@Mv77
Copy link
Contributor

Mv77 commented Jun 23, 2021

Hey Seb.

The SCF bit should not be a problem. It simply produces means and variances of log-normalized wealth at different ages so it does not interact with time indexing. It's used for initial conditions only.

The issue with forward looking indexing (X[t] containing things that pertain to shocks that happen next period) should manifest itself in the income tools and the survival probability tools. I believe I accounted for them, but let me present some evidence just for peace of mind:

@sbenthall
Copy link
Contributor Author

Thanks, @Mv77 I see that you have made adjustments throughout to accommodate the way parameters are indexed by 't+1'.

Now I'm wondering what changes would be needed to shift these values to the right.

@sbenthall
Copy link
Contributor Author

Huh.

So, a further complication. It appears that in the test cases, there is an example of a model with:

  • cycles = 1 -- so, finite horizon
  • 'time varying' parameters with lists of length 1

... not sure how that got in there...

@sbenthall
Copy link
Contributor Author

ahahaha... this is the default IndShockConsumer type.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 24, 2021 via email

@sbenthall
Copy link
Contributor Author

Ok. That makes sense.

So the solution is to make it more obviously a 2 period model by adding values for the first period.

One thing that made this a little hard to figure, which I mention here just because I noticed it just now -- the cycles=1 is a default argument to the constructor and so is being left out of the parameter dictionary.

I'm not sure if this is true across the board. I suppose I'd argue that we should encourage this cycles parameter which is among other things the flag determining if a problem is infinite horizon to be explicit in the model definition.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 24, 2021 via email

@sbenthall
Copy link
Contributor Author

OK. One more edge case... what about when cycles > 1 ?

Now I see a motivation for keeping it as is ... if you wanted the 2 period model to expand to an n + 1 period model by increasing the cycles number.

@mnwhite
Copy link
Contributor

mnwhite commented Jun 24, 2021 via email

@sbenthall
Copy link
Contributor Author

There is consensus around this redesign as of the meeting today. I'll follow through on the implementation.

I think the easy expansion of the tutorial case should follow on some other redesigns, such as working in the IndexDistribution more widely.

@Mv77 I'll make my best guess at how to update your empirical statistics for this change; I'll ask you to review those if you don't mind.

@sbenthall
Copy link
Contributor Author

For backwards compatibility reasons, I think the simplest way is to treat cycles > 1 cases like infinite horizon cyclic cases: assume that for the "final" solution of the cycle, the first or 0th parameters are used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants