diff --git a/Documentation/CHANGELOG.md b/Documentation/CHANGELOG.md index 73722e108..e24fd84ee 100644 --- a/Documentation/CHANGELOG.md +++ b/Documentation/CHANGELOG.md @@ -14,6 +14,7 @@ Release Data: TBD #### Major Changes +* Input parameters for cyclical models now indexed by t [#1039](https://github.com/econ-ark/HARK/pull/1039) * A IndexDistribution class for representing time-indexed probability distributions [#1018](https://github.com/econ-ark/pull/1018/). * Adds new consumption-savings-portfolio model `RiskyContrib`, which represents an agent who can save in risky and risk-free assets but faces frictions to moving funds between them. To circumvent these frictions, he has access to an income-deduction scheme to accumulate risky assets. diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index 892737bbe..28f601c62 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -1729,7 +1729,7 @@ def sim_death(self): # Determine who dies DiePrb_by_t_cycle = 1.0 - np.asarray(self.LivPrb) DiePrb = DiePrb_by_t_cycle[ - self.t_cycle - 1 + self.t_cycle - 1 if self.cycles == 1 else self.t_cycle ] # Time has already advanced, so look back one # In finite-horizon problems the previous line gives newborns the @@ -2173,12 +2173,17 @@ def get_shocks(self): newborn = self.t_age == 0 for t in range(self.T_cycle): these = t == self.t_cycle + + # temporary, see #1022 + if self.cycles == 1: + t = t - 1 + N = np.sum(these) if N > 0: IncShkDstnNow = self.IncShkDstn[ - t - 1 + t ] # set current income distribution - PermGroFacNow = self.PermGroFac[t - 1] # and permanent growth factor + PermGroFacNow = self.PermGroFac[t] # and permanent growth factor # Get random draws of income shocks from the discrete distribution IncShks = IncShkDstnNow.draw(N) @@ -3047,7 +3052,7 @@ def construct_assets_grid(parameters): # 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['PermGroFac'] = [1.1, 1.082251, 2.8, 0.3] 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] diff --git a/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py b/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py index aae33d65a..c2f500020 100644 --- a/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py +++ b/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py @@ -313,7 +313,7 @@ def test_lifecyle(self): "Rfree": 1.03, # Interest factor on assets "DiscFac": 0.96, # Intertemporal discount factor "LivPrb": 4 * [0.98], # Survival probability - "PermGroFac": [1.082251, 2.8, 0.3, 1.1], + "PermGroFac": [1.1, 1.082251, 2.8, 0.3], # Parameters that specify the income distribution over the lifecycle "PermShkStd": [0.1, 0.1, 0.1, 0.1], "PermShkCount": 7, # Number of points in discrete approximation to permanent income shocks @@ -358,6 +358,11 @@ def test_cyclical(self): CyclicalExample.solution[3].cFunc(3).tolist(), 1.5958390056965004 ) + CyclicalExample.initialize_sim() + CyclicalExample.simulate() + + self.assertAlmostEqual(CyclicalExample.state_now['aLvl'][1], 0.41839957) + # %% Tests of 'stable points' diff --git a/HARK/core.py b/HARK/core.py index 8f00c43b8..557755d69 100644 --- a/HARK/core.py +++ b/HARK/core.py @@ -1004,10 +1004,12 @@ def solve_one_cycle(agent, solution_last): # Initialize the solution for this cycle, then iterate on periods solution_cycle = [] solution_next = solution_last - for t in range(T): + + cycles_range = [0] + list(range(T - 1, 0, -1)) + for k in (range(T-1, -1, -1) if agent.cycles == 1 else cycles_range): # Update which single period solver to use (if it depends on time) if hasattr(agent.solve_one_period, "__getitem__"): - solve_one_period = agent.solve_one_period[T - 1 - t] + solve_one_period = agent.solve_one_period[k] else: solve_one_period = agent.solve_one_period @@ -1019,8 +1021,7 @@ def solve_one_cycle(agent, solution_last): # Update time-varying single period inputs for name in agent.time_vary: if name in these_args: - # solve_dict[name] = eval('agent.' + name + '[t]') - solve_dict[name] = agent.__dict__[name][T - 1 - t] + solve_dict[name] = agent.__dict__[name][k] solve_dict["solution_next"] = solution_next # Make a temporary dictionary for this period