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

Set starting aNrm for Lucas population near equilibrium #205

Open
sbenthall opened this issue Mar 21, 2023 · 19 comments · May be fixed by econ-ark/HARK#1259 or #228
Open

Set starting aNrm for Lucas population near equilibrium #205

sbenthall opened this issue Mar 21, 2023 · 19 comments · May be fixed by econ-ark/HARK#1259 or #228
Assignees

Comments

@sbenthall
Copy link
Owner

Related to #204

solve_distributed_agents calls solve() on each AgentType

def solve_distributed_agents(self):
# see Market class for an example of how to solve distributed agents in parallel
for agent in self.agents:
agent.solve()

When we have multiple AgentTypes 'per type' (i.e. num_per_type), this introduces unnecessary computation, because the same solution can be used across different AgentTypes.

@alanlujan91
Copy link
Collaborator

def build_population(agent_type, parameters, rng=None, dphm=1500):
num_per_type = parameters.get("num_per_type", 1)
pop = AgentPopulation(
agent_type(), parameters, rng=rng, dollars_per_hark_money_unit=dphm
)
if "approx_params" in parameters:
pop.approx_distributions(parameters["approx_params"])
pop.parse_params()
pop.create_distributed_agents()
pop.create_database()
pop.solve_distributed_agents()
pop.solve(merge_by=parameters["ex_post"])
pop.explode_agents(num_per_type)
# initialize population model
pop.init_simulation()
return pop

This depends on the ordering of the methods. If you see the method above, solve happens before explode_agents, so this should only be solving the unique agents with ex_ante heterogeneity. In the Lucas case, this should be 1 agent.

However, I notice that there are more than 1 build_population methods on the codebase, we should probably get rid of those and just use the one above.

@sbenthall
Copy link
Owner Author

Hmm.

I think 'solve' got called 10 times when I ran:

$ python run_any_simulation.py --quarters 1 --dphm 500000 ../output/20230321_o

(I got 10 copies of the Thorn, etc., output)

I think that's using the build_population in parameters.py

I wonder if this is slowing down the tests as well.

@alanlujan91
Copy link
Collaborator

Are we solving anywhere else after creating the population?

@sbenthall sbenthall changed the title solve_distributed_agents solves every agent even when they are identical calling solve too many times Mar 21, 2023
@alanlujan91
Copy link
Collaborator

def init_simulation(self, T_sim=1000):
"""
Sets up the agents with their state for the state of the simulation
"""
for agent in self.agents:
agent.track_vars += ["pLvl", "mNrm", "cNrm", "Share", "Risky"]
agent.T_sim = T_sim
agent.initialize_sim()
if self.stored_class_stats is None:
## build an IndShockConsumerType "double" of this agent, with the same parameters
parameters = agent.parameters.copy()
if "Rfree" in parameters and isinstance(parameters["Rfree"], list):
# patch potential bug until HARK is updated
parameters["Rfree"] = parameters["Rfree"][0]
ind_shock_double = cism.IndShockConsumerType(**parameters)
## solve to get the mNrmStE value
## that is, the Steady-state Equilibrium value of mNrm, for the IndShockModel
ind_shock_double.solve()

Seems like we are solving the equivalent ind_shock agent for every agent, this probably shouldn't be happening

@sbenthall
Copy link
Owner Author

Aha. That could be it.

I think we're doing this because @llorracc was interested in the mNrmStE value for some reason.
But we haven't used it in any analysis and it adds a lot of overhead....

I guess it could be done once for each agent class/type, if needed.

@sbenthall
Copy link
Owner Author

I've tested commenting out that 'solve' use, and that's indeed it.
Thanks for catching that!

For G.G. Shark I'm going to hackily disable this code. We should figure out how to really fix this for FIRE SHARK.

@ccarrollATjhuecon
Copy link

Yes, I am interested in mNrmStE. But there's a unique answer to that which gets constructed automatically when the agent's problem is solved. I can't see any reason to recompute it. Why doesn't it just automatically transfer when the agent is duplicated?

@sbenthall sbenthall changed the title calling solve too many times Restore mNrmStE functionality efficiently Mar 21, 2023
@sbenthall
Copy link
Owner Author

Monday's discussion, and especially @alanlujan91 's point about starting wealth values, reminded me why we computed this:
#199 (comment)

I think the idea was that we would initialize agents with starting wealth calibrated to the normalized market asset holdings at steady state equilibrium (mNrmStE) so that we avoid the effects that @alanlujan91 was pointing to. See #30

I believe the reason why we were solving the agent twice is that mNrmStE is computed when an IndShockConsumerType is solved. But it is not computed when a RiskyPortfolioConsumerType (or whatever) is solved. (I believe the mNrmStE value of the IndShockConsumerType is only approximately correct for the equivalent RiskyPortfolioConsumer).

@llorracc
Copy link

llorracc commented Apr 4, 2023 via email

@alanlujan91
Copy link
Collaborator

I can add including the calculation of mNrmStE to PortfolioConsumerType to my to do list. I agree that it would be more efficient for Portfolio agent to do this calculation rather than having to create and solve a separate IndShock agent just for this calculation.

@sbenthall
Copy link
Owner Author

Thank you @alanlujan91 !

I wonder what the right general way to architect this sort of thing is.
Maybe something better to discuss on the HARK issue tracker.

@sbenthall
Copy link
Owner Author

@alanlujan91 Is the formula for mNrmStE written out anywhere?
I looked for it in the BufferStockTheory paper but couldn't find it.

I'm wondering because I'm wondering how this interacts with the near-zero income point. #208

@sbenthall
Copy link
Owner Author

mNrmStE is not analytically defined for the Portfolio or ConsInd shock models, but Tractable Buffer Stock has an analytic formula which is insightful for analysis:

http://www.econ2.jhu.edu/people/ccarroll/papers/ctdiscrete/

@sbenthall
Copy link
Owner Author

sbenthall commented Apr 20, 2023

What if rather than trying to do something too clever, we got the equilibrium/starting wealth value by:

  • solving the (homogeneous) agent type
  • Just once, simulate forward until aNrm converges with:
    • Arbitrary starting wealth (I think starting high would converge faster than starting low, because income is very low)
    • Setting the risky mean and standard deviation to match the USUAL expectations

Then take that aNrm value and use it as the initial aNrm for all the agents in the big simulation.

Do you think that would work, @alanlujan91 ?

@alanlujan91
Copy link
Collaborator

this could work, although I'm not sure if we have infrastructure for simulate until aNrmAvg converges

@alanlujan91 alanlujan91 linked a pull request Apr 20, 2023 that will close this issue
3 tasks
@llorracc
Copy link

llorracc commented Apr 20, 2023 via email

@sbenthall
Copy link
Owner Author

Cool thanks for pointing that out @llorracc

@sbenthall sbenthall changed the title Restore mNrmStE functionality efficiently Set starting aNrm for Lucas population near equilibrium Apr 21, 2023
@alanlujan91 alanlujan91 linked a pull request May 18, 2023 that will close this issue
@sbenthall
Copy link
Owner Author

Just as a short term fix....

This script simulates forward 3000 agents of our Lucas configuration for 3000 time periods, then plots the mean of their (natural) log mNrm over the course of the simulation.

https://github.com/sbenthall/SHARKFin/blob/master/macro/steady_state_mNrm.py

Here is the output from that:

run_to_steady_state

While it's still quite choppy, I'll set the starting aNrmInitMean to 6, which is where the process seems to settle given the current parameters.

@alanlujan91 any improvement on this rough cut is of course most welcome.

@alanlujan91
Copy link
Collaborator

@sbenthall this is a good start, although now that we have this we should set aNrmIntMean to 6 and see if it stays around 6.

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