diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index ac2377240..0257f2733 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -1974,6 +1974,8 @@ def checkConditions(self,verbose=False,verbose_reference=False,public_call=False if self.cycles!=0 or self.T_cycle > 1: return + self.violated = False + Thorn = (self.Rfree*self.DiscFac*self.LivPrb[0])**(1/self.CRRA) self.Thorn = Thorn diff --git a/HARK/ConsumptionSaving/tests/test_ConsPortfolioModel.py b/HARK/ConsumptionSaving/tests/test_ConsPortfolioModel.py new file mode 100644 index 000000000..456f9ed2d --- /dev/null +++ b/HARK/ConsumptionSaving/tests/test_ConsPortfolioModel.py @@ -0,0 +1,47 @@ +import copy +import HARK.ConsumptionSaving.ConsPortfolioModel as cpm +import HARK.ConsumptionSaving.ConsumerParameters as param +import unittest + +class testPortfolioConsumerType(unittest.TestCase): + + def setUp(self): + + # Parameters from Mehra and Prescott (1985): + Avg = 1.08 # equity premium + Std = 0.20 # standard deviation of rate-of-return shocks + + RiskyDstnFunc = cpm.RiskyDstnFactory(RiskyAvg=Avg, RiskyStd=Std) # Generates nodes for integration + RiskyDrawFunc = cpm.LogNormalRiskyDstnDraw(RiskyAvg=Avg, RiskyStd=Std) # Function to generate draws from a lognormal distribution + + init_portfolio = copy.copy(param.init_idiosyncratic_shocks) # Default parameter values for inf horiz model - including labor income with transitory and permanent shocks + init_portfolio['approxRiskyDstn'] = RiskyDstnFunc + init_portfolio['drawRiskyFunc'] = RiskyDrawFunc + init_portfolio['RiskyCount'] = 2 # Number of points in the approximation; 2 points is minimum + init_portfolio['RiskyShareCount'] = 25 # How many discrete points to allow for portfolio share + init_portfolio['Rfree'] = 1.0 # Riskfree return factor (interest rate is zero) + init_portfolio['CRRA'] = 6.0 # Relative risk aversion + + # Uninteresting technical parameters: + init_portfolio['aXtraMax'] = 100 + init_portfolio['aXtraCount'] = 50 + init_portfolio['BoroCnstArt'] = 0.0 # important for theoretical reasons + init_portfolio['DiscFac'] = 0.92 # Make them impatient even wrt a riskfree return of 1.08 + + # Create portfolio choice consumer type + self.pcct = cpm.PortfolioConsumerType(**init_portfolio) + + # %% {"code_folding": []} + # Solve the model under the given parameters + + self.pcct.solve() + + def test_RiskyShareFunc(self): + + self.assertAlmostEqual( + self.pcct.solution[0].RiskyShareFunc[0][0](2).tolist(), + 0.8796982720076255) + + self.assertAlmostEqual( + self.pcct.solution[0].RiskyShareFunc[0][0](8).tolist(), + 0.69738175) diff --git a/HARK/ConsumptionSaving/tests/test_PerfForesightConsumerType.py b/HARK/ConsumptionSaving/tests/test_PerfForesightConsumerType.py index 049c0fee0..0d4ae1d33 100644 --- a/HARK/ConsumptionSaving/tests/test_PerfForesightConsumerType.py +++ b/HARK/ConsumptionSaving/tests/test_PerfForesightConsumerType.py @@ -1,13 +1,16 @@ from HARK.ConsumptionSaving.ConsIndShockModel import PerfForesightConsumerType - +import numpy as np import unittest class testPerfForesightConsumerType(unittest.TestCase): + def setUp(self): + self.agent = PerfForesightConsumerType() + self.agent_infinite = PerfForesightConsumerType(cycles=0) + def test_default_solution(self): - agent = PerfForesightConsumerType() - agent.solve() - c = agent.solution[0].cFunc + 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) @@ -15,4 +18,60 @@ def test_default_solution(self): self.assertEqual(c.y_list[1], 0.511321002804608) self.assertEqual(c.decay_extrap, False) - + def test_checkConditions(self): + self.agent_infinite.checkConditions() + + self.assertTrue(self.agent_infinite.AIC) + self.assertTrue(self.agent_infinite.GICPF) + self.assertTrue(self.agent_infinite.RIC) + self.assertTrue(self.agent_infinite.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.mNrmNow_hist,axis=1)[40], + -23.008063500363942 + ) + + self.assertAlmostEqual( + np.mean(self.agent_infinite.mNrmNow_hist,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.mNrmNow_hist,axis=1)[40], + -23.008063500363942 + ) + + self.assertAlmostEqual( + np.mean(self.agent_infinite.mNrmNow_hist,axis=1)[100], + -29.140261331951606 + )