class testPerfForesightConsumerType(unittest.TestCase): def setUp(self): self.agent = PerfForesightConsumerType() self.agent_infinite = PerfForesightConsumerType(cycles=0) PF_dictionary = { "CRRA": 2.5, "DiscFac": 0.96, "Rfree": 1.03, "LivPrb": [0.98], "PermGroFac": [1.01], "T_cycle": 1, "cycles": 0, "AgentCount": 10000, } self.agent_alt = PerfForesightConsumerType(**PF_dictionary) def test_default_solution(self): self.agent.solve() c = self.agent.solution[0].cFunc self.assertEqual(c.x_list[0], -0.9805825242718447) self.assertEqual(c.x_list[1], 0.01941747572815533) self.assertEqual(c.y_list[0], 0) self.assertEqual(c.y_list[1], 0.511321002804608) self.assertEqual(c.decay_extrap, False) def test_another_solution(self): self.agent_alt.DiscFac = 0.90 self.agent_alt.solve() self.assertAlmostEqual(self.agent_alt.solution[0].cFunc(10).tolist(), 3.9750093524820787) def test_check_conditions(self): self.agent_infinite.check_conditions() self.assertTrue(self.agent_infinite.conditions["AIC"]) self.assertTrue(self.agent_infinite.conditions["GICRaw"]) self.assertTrue(self.agent_infinite.conditions["RIC"]) self.assertTrue(self.agent_infinite.conditions["FHWC"]) def test_simulation(self): self.agent_infinite.solve() # Create parameter values necessary for simulation SimulationParams = { "AgentCount": 10000, # Number of agents of this type "T_sim": 120, # Number of periods to simulate "aNrmInitMean": -6.0, # Mean of log initial assets "aNrmInitStd": 1.0, # Standard deviation of log initial assets "pLvlInitMean": 0.0, # Mean of log initial permanent income "pLvlInitStd": 0.0, # Standard deviation of log initial permanent income "PermGroFacAgg": 1.0, # Aggregate permanent income growth factor "T_age": None, # Age after which simulated agents are automatically killed } self.agent_infinite.assign_parameters( **SimulationParams ) # This implicitly uses the assign_parameters method of AgentType # Create PFexample object self.agent_infinite.track_vars = ["mNrm"] self.agent_infinite.initialize_sim() self.agent_infinite.simulate() self.assertAlmostEqual( np.mean(self.agent_infinite.history["mNrm"], axis=1)[40], -23.008063500363942, ) self.assertAlmostEqual( np.mean(self.agent_infinite.history["mNrm"], axis=1)[100], -27.164608851546927, ) ## Try now with the manipulation at time step 80 self.agent_infinite.initialize_sim() self.agent_infinite.simulate(80) # This actually does nothing because aNrmNow is # epiphenomenal. Probably should change mNrmNow instead self.agent_infinite.state_now['aNrm'] += (-5.0) self.agent_infinite.simulate(40) self.assertAlmostEqual( np.mean(self.agent_infinite.history["mNrm"], axis=1)[40], -23.008063500363942, ) self.assertAlmostEqual( np.mean(self.agent_infinite.history["mNrm"], axis=1)[100], -29.140261331951606, ) def test_stable_points(self): # Solve the constrained agent. Stable points exists only with a # borrowing constraint. constrained_agent = PerfForesightConsumerType(cycles=0, BoroCnstArt=0.0) constrained_agent.solve() # Check against pre-computed values. self.assertEqual(constrained_agent.solution[0].mNrmStE, 1.0) # Check that they are both the same, since the problem is deterministic self.assertEqual(constrained_agent.solution[0].mNrmStE, constrained_agent.solution[0].mNrmTrg)
class testPerfForesightConsumerType(unittest.TestCase): def setUp(self): self.agent = PerfForesightConsumerType() self.agent_infinite = PerfForesightConsumerType(cycles=0) PF_dictionary = { 'CRRA': 2.5, 'DiscFac': 0.96, 'Rfree': 1.03, 'LivPrb': [0.98], 'PermGroFac': [1.01], 'T_cycle': 1, 'cycles': 0, 'AgentCount': 10000 } self.agent_alt = PerfForesightConsumerType(**PF_dictionary) def test_default_solution(self): self.agent.solve() c = self.agent.solution[0].cFunc self.assertEqual(c.x_list[0], -0.9805825242718447) self.assertEqual(c.x_list[1], 0.01941747572815533) self.assertEqual(c.y_list[0], 0) self.assertEqual(c.y_list[1], 0.511321002804608) self.assertEqual(c.decay_extrap, False) def test_another_solution(self): self.agent_alt.DiscFac = 0.90 self.agent_alt.solve() self.assertAlmostEqual(self.agent_alt.solution[0].cFunc(10).tolist(), 3.9750093524820787) def test_checkConditions(self): self.agent_infinite.checkConditions() self.assertTrue(self.agent_infinite.conditions['AIC']) self.assertTrue(self.agent_infinite.conditions['GICPF']) self.assertTrue(self.agent_infinite.conditions['RIC']) self.assertTrue(self.agent_infinite.conditions['FHWC']) def test_simulation(self): self.agent_infinite.solve() # Create parameter values necessary for simulation SimulationParams = { "AgentCount": 10000, # Number of agents of this type "T_sim": 120, # Number of periods to simulate "aNrmInitMean": -6.0, # Mean of log initial assets "aNrmInitStd": 1.0, # Standard deviation of log initial assets "pLvlInitMean": 0.0, # Mean of log initial permanent income "pLvlInitStd": 0.0, # Standard deviation of log initial permanent income "PermGroFacAgg": 1.0, # Aggregate permanent income growth factor "T_age": None, # Age after which simulated agents are automatically killed } self.agent_infinite( **SimulationParams ) # This implicitly uses the assignParameters method of AgentType # Create PFexample object self.agent_infinite.track_vars = ['mNrmNow'] self.agent_infinite.initializeSim() self.agent_infinite.simulate() self.assertAlmostEqual( np.mean(self.agent_infinite.history['mNrmNow'], axis=1)[40], -23.008063500363942) self.assertAlmostEqual( np.mean(self.agent_infinite.history['mNrmNow'], axis=1)[100], -27.164608851546927) ## Try now with the manipulation at time step 80 self.agent_infinite.initializeSim() self.agent_infinite.simulate(80) self.agent_infinite.aNrmNow += -5. # Adjust all simulated consumers' assets downward by 5 self.agent_infinite.simulate(40) self.assertAlmostEqual( np.mean(self.agent_infinite.history['mNrmNow'], axis=1)[40], -23.008063500363942) self.assertAlmostEqual( np.mean(self.agent_infinite.history['mNrmNow'], axis=1)[100], -29.140261331951606)
# %% [markdown] pycharm={"name": "#%% md\n"} # To generate simulated data, we need to specify which variables we want to track the "history" of for this instance. To do so, we set the $\texttt{track_vars}$ attribute of our $\texttt{PerfForesightConsumerType}$ instance to be a list of strings with the simulation variables we want to track. # # In this model, valid elments of $\texttt{track_vars}$ include $\texttt{mNrmNow}$, $\texttt{cNrmNow}$, $\texttt{aNrmNow}$, and $\texttt{pLvlNow}$. Because this model has no idiosyncratic shocks, our simulated data will be quite boring. # # ### Generating simulated data # # Before simulating, the $\texttt{initializeSim}$ method must be invoked. This resets our instance back to its initial state, drawing a set of initial $\texttt{aNrmNow}$ and $\texttt{pLvlNow}$ values from the specified distributions and storing them in the attributes $\texttt{aNrmNow_init}$ and $\texttt{pLvlNow_init}$. It also resets this instance's internal random number generator, so that the same initial states will be set every time $\texttt{initializeSim}$ is called. In models with non-trivial shocks, this also ensures that the same sequence of shocks will be generated on every simulation run. # # Finally, the $\texttt{simulate}$ method can be called. # %% pycharm={"name": "#%%\n"} PFexample.track_vars = ["mNrmNow"] PFexample.initializeSim() PFexample.simulate() # %% [markdown] pycharm={"name": "#%% md\n"} # Each simulation variable $\texttt{X}$ named in $\texttt{track_vars}$ will have the *history* of that variable for each agent stored in the attribute $\texttt{X_hist}$ as an array of shape $(\texttt{T_sim},\texttt{AgentCount})$. To see that the simulation worked as intended, we can plot the mean of $m_t$ in each simulated period: # %% pycharm={"name": "#%%\n"} plt.plot(np.mean(PFexample.history["mNrmNow"], axis=1)) plt.xlabel("Time") plt.ylabel("Mean normalized market resources") plt.show() # %% [markdown] pycharm={"name": "#%% md\n"} # A perfect foresight consumer can borrow against the PDV of his future income-- his human wealth-- and thus as time goes on, our simulated agents approach the (very negative) steady state level of $m_t$ while being steadily replaced with consumers with roughly $m_t=1$. # # The slight wiggles in the plotted curve are due to consumers randomly dying and being replaced; their replacement will have an initial state drawn from the distributions specified by the user. To see the current distribution of ages, we can look at the attribute $\texttt{t_age}$.
mystr(end_time - start_time) + " seconds.") PFexample.unpackcFunc() PFexample.timeFwd() # %% # Plot the perfect foresight consumption function print("Perfect foresight consumption function:") mMin = PFexample.solution[0].mNrmMin plotFuncs(PFexample.cFunc[0], mMin, mMin + 10) # %% if do_simulation: PFexample.T_sim = 120 # Set number of simulation periods PFexample.track_vars = ["mNrmNow"] PFexample.initializeSim() PFexample.simulate() # %% # Make and solve an example consumer with idiosyncratic income shocks IndShockExample = IndShockConsumerType() IndShockExample.cycles = 0 # Make this type have an infinite horizon # %% start_time = time() IndShockExample.solve() end_time = time() print("Solving a consumer with idiosyncratic shocks took " + mystr(end_time - start_time) + " seconds.") IndShockExample.unpackcFunc() IndShockExample.timeFwd()