def setUp(self): """ Prepare to compare the models by initializing and solving them """ # Set up and solve infinite type # Define a test dictionary that should have the same solution in the # perfect foresight and idiosyncratic shocks models. test_dictionary = deepcopy(init_idiosyncratic_shocks) test_dictionary["LivPrb"] = [1.0] test_dictionary["DiscFac"] = 0.955 test_dictionary["PermGroFac"] = [1.0] test_dictionary["PermShkStd"] = [0.0] test_dictionary["TranShkStd"] = [0.0] test_dictionary["UnempPrb"] = 0.0 test_dictionary["T_cycle"] = 1 test_dictionary["T_retire"] = 0 test_dictionary["BoroCnstArt"] = None InfiniteType = IndShockConsumerType(**test_dictionary) InfiniteType.cycles = 0 InfiniteType.update_income_process() InfiniteType.solve() InfiniteType.unpack("cFunc") # Make and solve a perfect foresight consumer type with the same parameters PerfectForesightType = PerfForesightConsumerType(**test_dictionary) PerfectForesightType.cycles = 0 PerfectForesightType.solve() PerfectForesightType.unpack("cFunc") self.InfiniteType = InfiniteType self.PerfectForesightType = PerfectForesightType
def perturbParameterToGetcPlotList(base_dictionary, param_name, param_min, param_max, N=20, time_vary=False): param_vec = np.linspace( param_min, param_max, num=N, endpoint=True ) # vector of alternative values of the parameter to examine thisConsumer = IndShockConsumerType( **my_dictionary) # create an instance of the consumer type thisConsumer.cycles = 0 # Make this type have an infinite horizon x = np.linspace( mMinVal, mMaxVal, xPoints, endpoint=True ) # Define a vector of x values that span the range from the minimum to the maximum values of m for j in range( N): # loop from the first to the last values of the parameter if time_vary: # Some parameters are time-varying; others are not setattr(thisConsumer, param_name, [param_vec[j]]) else: setattr(thisConsumer, param_name, param_vec[j]) thisConsumer.update( ) # set up the preliminaries required to solve the problem thisConsumer.solve() # solve the problem y = thisConsumer.solution[0].cFunc( x ) # Get the values of the consumption function at the points in the vector of x points pylab.plot( x, y, label=str(round(param_vec[j], 3)) ) # plot it and generate a label indicating the rounded value of the parameter pylab.legend(loc='upper right') # put the legend in the upper right return pylab # return the figure
def setUp(self): """ Prepare to compare the models by initializing and solving them """ # Set up and solve infinite type import HARK.ConsumptionSaving.ConsumerParameters as Params InfiniteType = IndShockConsumerType(**Params.init_idiosyncratic_shocks) InfiniteType.assignParameters( LivPrb=[1.], DiscFac=0.955, PermGroFac=[1.], PermShkStd=[0.], TempShkStd=[0.], T_total=1, T_retire=0, BoroCnstArt=None, UnempPrb=0., cycles=0) # This is what makes the type infinite horizon InfiniteType.updateIncomeProcess() InfiniteType.solve() InfiniteType.timeFwd() InfiniteType.unpackcFunc() # Make and solve a perfect foresight consumer type with the same parameters PerfectForesightType = deepcopy(InfiniteType) PerfectForesightType.solveOnePeriod = solvePerfForesight PerfectForesightType.solve() PerfectForesightType.unpackcFunc() PerfectForesightType.timeFwd() self.InfiniteType = InfiniteType self.PerfectForesightType = PerfectForesightType
def test_NewbornStatesAndShocks(self): # Make agent, shock and initial condition histories agent = IndShockConsumerType(**self.base_params) agent.make_shock_history() # Find indices of agents and time periods that correspond to deaths # this will be non-nan indices of newborn_init_history for states # that are used in initializing the agent. aNrm is one of them. idx = np.logical_not(np.isnan(agent.newborn_init_history["aNrm"])) # Change the values a_init_newborns = 20 agent.newborn_init_history["aNrm"][idx] = a_init_newborns # Also change the shocks of newborns pshk_newborns = 0.5 agent.shock_history["PermShk"][idx] = pshk_newborns agent.shock_history["TranShk"][idx] = 0.0 # Solve and simulate the agent agent.solve() agent.initialize_sim() agent.simulate() # Given our manipulation of initial wealth and permanent shocks, # agents of age == 1 should have starting resources a_init_newborns/pshk_newborns # (no interest, no deterministic growth and no transitory shock) age = agent.history["t_age"] self.assertTrue( np.all(agent.history["bNrm"][age == 1] == a_init_newborns / pshk_newborns))
def test_infinite_horizon(self): baseEx_inf = IndShockConsumerType(cycles=0, **self.base_params) baseEx_inf.solve() baseEx_inf.unpack("cFunc") m1 = np.linspace( 1, baseEx_inf.solution[0].mNrmSS, 50 ) # m1 defines the plot range on the left of target m value (e.g. m <= target m) c_m1 = baseEx_inf.cFunc[0](m1) self.assertAlmostEqual(c_m1[0], 0.8527887545025995) self.assertAlmostEqual(c_m1[-1], 1.0036279936408656) x1 = np.linspace(0, 25, 1000) cfunc_m = baseEx_inf.cFunc[0](x1) self.assertAlmostEqual(cfunc_m[500], 1.8902146173138235) self.assertAlmostEqual(cfunc_m[700], 2.1591451850267176) m = np.linspace(0.001, 8, 1000) # Use the HARK method derivative to get the derivative of cFunc, and the values are just the MPC MPC = baseEx_inf.cFunc[0].derivative(m) self.assertAlmostEqual(MPC[500], 0.08415000641504392) self.assertAlmostEqual(MPC[700], 0.07173144137912524)
def test_cyclical(self): CyclicalExample = IndShockConsumerType(**CyclicalDict) CyclicalExample.cycles = 0 # Make this consumer type have an infinite horizon CyclicalExample.solve() self.assertAlmostEqual(CyclicalExample.solution[3].cFunc(3).tolist(), 1.5958390056965004)
def test_ConsIndShockSolverBasic(self): LifecycleExample = IndShockConsumerType(**init_lifecycle) LifecycleExample.cycles = 1 LifecycleExample.solve() solver = ConsIndShockSolverBasic( LifecycleExample.solution[1], LifecycleExample.IncomeDstn[0], LifecycleExample.LivPrb[0], LifecycleExample.DiscFac, LifecycleExample.CRRA, LifecycleExample.Rfree, LifecycleExample.PermGroFac[0], LifecycleExample.BoroCnstArt, LifecycleExample.aXtraGrid, LifecycleExample.vFuncBool, LifecycleExample.CubicBool) solver.prepareToSolve() self.assertAlmostEqual(solver.DiscFacEff, 0.9503999999999999) self.assertAlmostEqual(solver.PermShkMinNext, 0.850430160026919) self.assertAlmostEqual(solver.cFuncNowCnst(4).tolist(), 4.0) self.assertAlmostEqual(solver.prepareToCalcEndOfPrdvP()[0], -0.2491750859108316) self.assertAlmostEqual(solver.prepareToCalcEndOfPrdvP()[-1], 19.74982491408914) EndOfPrdvP = solver.calcEndOfPrdvP() self.assertAlmostEqual(EndOfPrdvP[0], 6622.251864311334) self.assertAlmostEqual(EndOfPrdvP[-1], 0.026301061207747087) solution = solver.makeBasicSolution(EndOfPrdvP, solver.aNrmNow, solver.makeLinearcFunc) solver.addMPCandHumanWealth(solution) self.assertAlmostEqual(solution.cFunc(4).tolist(), 1.7391265696400773)
def makeConvergencePlot(DiscFac, CRRA, Rfree, PermShkStd): # Construct finite horizon agent with baseline parameters baseAgent_Fin = IndShockConsumerType(verbose=0, **base_params) baseAgent_Fin.DiscFac = DiscFac baseAgent_Fin.CRRA = CRRA baseAgent_Fin.Rfree = Rfree baseAgent_Fin.PermShkStd = [PermShkStd] baseAgent_Fin.cycles = 100 baseAgent_Fin.updateIncomeProcess() baseAgent_Fin.solve() baseAgent_Fin.unpack('cFunc') # figure limits mMax = 6 # 11 mMin = 0 cMin = 0 cMax = 4 # 7 mPlotMin = 0 mLocCLabels = 5.6 # 9.6 # Defines horizontal limit of figure mPlotTop = 3.5 # 6.5 # Defines maximum m value where functions are plotted mPts = 1000 # Number of points at which functions are evaluated plt.figure(figsize=(12, 8)) plt.ylim([cMin, cMax]) plt.xlim([mMin, mMax]) mBelwLabels = np.linspace(mPlotMin, mLocCLabels - 0.1, mPts) # Range of m below loc of labels m_FullRange = np.linspace(mPlotMin, mPlotTop, mPts) # Full plot range c_Tm0 = m_FullRange # c_Tm0 defines the last period consumption rule (c=m) c_Tm1 = baseAgent_Fin.cFunc[-2]( mBelwLabels ) # c_Tm1 defines the second-to-last period consumption rule c_Tm5 = baseAgent_Fin.cFunc[-6]( mBelwLabels) # c_Tm5 defines the T-5 period consumption rule c_Tm10 = baseAgent_Fin.cFunc[-11]( mBelwLabels) # c_Tm10 defines the T-10 period consumption rule c_Limt = baseAgent_Fin.cFunc[0]( mBelwLabels ) # c_Limt defines limiting infinite-horizon consumption rule plt.plot(mBelwLabels, c_Limt, label="$c(m)$") plt.plot(mBelwLabels, c_Tm1, label="$c_{T-1}(m)$") plt.plot(mBelwLabels, c_Tm5, label="$c_{T-5}(m)$") plt.plot(mBelwLabels, c_Tm10, label="$c_{T-10}(m)$") plt.plot(m_FullRange, c_Tm0, label="$c_{T}(m) = 45$ degree line") plt.legend(fontsize='x-large') plt.tick_params( labelbottom=False, labelleft=False, left="off", right="off", bottom="off", top="off", ) plt.show() return None
def test_Harmenberg_mtd(self): example = IndShockConsumerType(**dict_harmenberg, verbose=0) example.cycles = 0 example.track_vars = ['aNrm', 'mNrm', 'cNrm', 'pLvl', 'aLvl'] example.T_sim = 20000 example.solve() example.neutral_measure = True example.update_income_process() example.initialize_sim() example.simulate() Asset_list = [] Consumption_list = [] M_list = [] for i in range(example.T_sim): Assetagg = np.mean(example.history['aNrm'][i]) Asset_list.append(Assetagg) ConsAgg = np.mean(example.history['cNrm'][i]) Consumption_list.append(ConsAgg) Magg = np.mean(example.history['mNrm'][i]) M_list.append(Magg) ######################################################### example2 = IndShockConsumerType(**dict_harmenberg, verbose=0) example2.cycles = 0 example2.track_vars = ['aNrm', 'mNrm', 'cNrm', 'pLvl', 'aLvl'] example2.T_sim = 20000 example2.solve() example2.initialize_sim() example2.simulate() Asset_list2 = [] Consumption_list2 = [] M_list2 = [] for i in range(example2.T_sim): Assetagg = np.mean(example2.history['aLvl'][i]) Asset_list2.append(Assetagg) ConsAgg = np.mean(example2.history['cNrm'][i] * example2.history['pLvl'][i]) Consumption_list2.append(ConsAgg) Magg = np.mean(example2.history['mNrm'][i] * example2.history['pLvl'][i]) M_list2.append(Magg) c_std2 = np.std(Consumption_list2) c_std1 = np.std(Consumption_list) c_std_ratio = c_std2 / c_std1 self.assertAlmostEqual(c_std2, 0.03768819564871894) self.assertAlmostEqual(c_std1, 0.004411745897568616) self.assertAlmostEqual(c_std_ratio, 8.542694099741672)
def test_ConsIndShockSolverBasic(self): LifecycleExample = IndShockConsumerType(**init_lifecycle) LifecycleExample.cycles = 1 LifecycleExample.solve() # test the solution_terminal self.assertAlmostEqual(LifecycleExample.solution[-1].cFunc(2).tolist(), 2) self.assertAlmostEqual(LifecycleExample.solution[9].cFunc(1), 0.79429538) self.assertAlmostEqual(LifecycleExample.solution[8].cFunc(1), 0.79391692) self.assertAlmostEqual(LifecycleExample.solution[7].cFunc(1), 0.79253095) self.assertAlmostEqual(LifecycleExample.solution[0].cFunc(1).tolist(), 0.7506184692092213) self.assertAlmostEqual(LifecycleExample.solution[1].cFunc(1).tolist(), 0.7586358637239385) self.assertAlmostEqual(LifecycleExample.solution[2].cFunc(1).tolist(), 0.7681247572911291) solver = ConsIndShockSolverBasic( LifecycleExample.solution[1], LifecycleExample.IncShkDstn[0], LifecycleExample.LivPrb[0], LifecycleExample.DiscFac, LifecycleExample.CRRA, LifecycleExample.Rfree, LifecycleExample.PermGroFac[0], LifecycleExample.BoroCnstArt, LifecycleExample.aXtraGrid, LifecycleExample.vFuncBool, LifecycleExample.CubicBool, ) solver.prepare_to_solve() self.assertAlmostEqual(solver.DiscFacEff, 0.9586233599999999) self.assertAlmostEqual(solver.PermShkMinNext, 0.6554858756904397) self.assertAlmostEqual(solver.cFuncNowCnst(4).tolist(), 4.0) self.assertAlmostEqual(solver.prepare_to_calc_EndOfPrdvP()[0], -0.19792871012285213) self.assertAlmostEqual(solver.prepare_to_calc_EndOfPrdvP()[-1], 19.801071289877118) EndOfPrdvP = solver.calc_EndOfPrdvP() self.assertAlmostEqual(EndOfPrdvP[0], 6657.839372100613) self.assertAlmostEqual(EndOfPrdvP[-1], 0.2606075215645896) solution = solver.make_basic_solution(EndOfPrdvP, solver.aNrmNow, solver.make_linear_cFunc) solver.add_MPC_and_human_wealth(solution) self.assertAlmostEqual(solution.cFunc(4).tolist(), 1.0028005137373956)
def makeTargetMfig(Rfree, DiscFac, CRRA, permShkStd, TranShkStd): inf_hor = IndShockConsumerType(quietly=True, **base_params) inf_hor.Rfree = Rfree inf_hor.DiscFac = DiscFac inf_hor.CRRA = CRRA inf_hor.permShkStd = [permShkStd] inf_hor.TranShkStd = [TranShkStd] inf_hor.update_income_process() mPlotMin = 0 mPlotMax = 250 inf_hor.aXtraMax = mPlotMax inf_hor.solve(quietly=True, messaging_level=logging.CRITICAL) soln = inf_hor.solution[0] Bilt, cFunc = soln.Bilt, soln.cFunc cPlotMin = 0, cFunc(mPlotMax) if Bilt.GICNrm: # tattle soln.check_GICNrm(soln, quietly=False, messaging_level=logging.WARNING) mBelwStE = np.linspace(mPlotMin, mPlotMax, 1000) EPermGroFac = inf_hor.PermGroFac[0] def EmDelEq0(mVec): return (EPermGroFac / Rfree) + (1.0 - EPermGroFac / Rfree) * mVec cBelwStE_Best = cFunc(mBelwStE) # "best" = optimal c cBelwStE_Sstn = EmDelEq0(mBelwStE) # "sustainable" c mNrmStE = Bilt.mNrmStE plt.figure(figsize=(12, 8)) plt.plot(mBelwStE, cBelwStE_Best, label="$c(m_{t})$") plt.plot(mBelwStE, cBelwStE_Sstn, label="$\mathsf{E}_{t}[\Delta m_{t+1}] = 0$") plt.xlim(mPlotMin, mPlotMax) plt.ylim(cPlotMin, cFunc(mPlotMax)) plt.plot( [mNrmStE, mNrmStE], [0, 2.5], color="black", linestyle="--", ) plt.tick_params( # labelbottom=False, # labelleft=False, # left="off", right="off", # bottom="off", top="off", ) plt.text(0, 1.47, r"$c$", fontsize=26) plt.text(3.02, 0, r"$m$", fontsize=26) plt.text(mNrmStE - 0.05, -0.1, "m̌", fontsize=26) plt.legend(fontsize='x-large') plt.show() return None
def makeTargetMfig(Rfree, DiscFac, CRRA, PermShkStd, TranShkStd): baseAgent_Inf = IndShockConsumerType(verbose=0, cycles=0, **base_params) baseAgent_Inf.Rfree = Rfree baseAgent_Inf.DiscFac = DiscFac baseAgent_Inf.CRRA = CRRA baseAgent_Inf.PermShkStd = [PermShkStd] baseAgent_Inf.TranShkStd = [TranShkStd] baseAgent_Inf.updateIncomeProcess() baseAgent_Inf.checkConditions() mPlotMin = 0 mPlotMax = 250 baseAgent_Inf.aXtraMax = mPlotMax baseAgent_Inf.solve() baseAgent_Inf.unpack('cFunc') cPlotMin = 0 cPlotMax = baseAgent_Inf.cFunc[0](mPlotMax) if (baseAgent_Inf.GPFInd >= 1): baseAgent_Inf.checkGICInd(verbose=3) mBelwTrg = np.linspace(mPlotMin, mPlotMax, 1000) EPermGroFac = baseAgent_Inf.PermGroFac[0] EmDelEq0 = lambda m: (EPermGroFac / Rfree) + (1.0 - EPermGroFac / Rfree ) * m cBelwTrg_Best = baseAgent_Inf.cFunc[0](mBelwTrg) # "best" = optimal c cBelwTrg_Sstn = EmDelEq0(mBelwTrg) # "sustainable" c mNrmTrg = baseAgent_Inf.solution[0].mNrmSS plt.figure(figsize=(12, 8)) plt.plot(mBelwTrg, cBelwTrg_Best, label="$c(m_{t})$") plt.plot(mBelwTrg, cBelwTrg_Sstn, label="$\mathsf{E}_{t}[\Delta m_{t+1}] = 0$") plt.xlim(mPlotMin, mPlotMax) plt.ylim(cPlotMin, cPlotMax) plt.plot( [mNrmTrg, mNrmTrg], [0, 2.5], color="black", linestyle="--", ) plt.tick_params( # labelbottom=False, # labelleft=False, # left="off", right="off", # bottom="off", top="off", ) plt.text(0, 1.47, r"$c$", fontsize=26) plt.text(3.02, 0, r"$m$", fontsize=26) plt.text(mNrmTrg - 0.05, -0.1, "m̌", fontsize=26) plt.legend(fontsize='x-large') plt.show() return None
def test_lifecyle(self): LifecycleExample = IndShockConsumerType(**LifecycleDict) LifecycleExample.cycles = 1 LifecycleExample.solve() self.assertEquals(len(LifecycleExample.solution), 11) mMin = np.min([LifecycleExample.solution[t].mNrmMin for t in range(LifecycleExample.T_cycle)]) self.assertAlmostEqual(LifecycleExample.solution[5].cFunc(3).tolist(), 2.129983771775666)
def test_cyclical(self): CyclicalExample = IndShockConsumerType(**CyclicalDict) CyclicalExample.cycles = 0 # Make this consumer type have an infinite horizon CyclicalExample.solve() self.assertAlmostEqual(CyclicalExample.solution[3].cFunc(3).tolist(), 1.5958390056965004) CyclicalExample.initialize_sim() CyclicalExample.simulate() self.assertAlmostEqual(CyclicalExample.state_now['aLvl'][1], 0.41839957)
def test_infinite_horizon(self): IndShockExample = IndShockConsumerType(**IdiosyncDict) IndShockExample.cycles = 0 # Make this type have an infinite horizon IndShockExample.solve() self.assertAlmostEqual(IndShockExample.solution[0].mNrmSS, 1.5488165705077026) self.assertAlmostEqual(IndShockExample.solution[0].cFunc.functions[0].x_list[0], -0.25017509) IndShockExample.track_vars = ['aNrmNow','mNrmNow','cNrmNow','pLvlNow'] IndShockExample.initializeSim() IndShockExample.simulate() self.assertAlmostEqual(IndShockExample.mNrmNow_hist[0][0], 1.0170176090252379)
def test_IndShock_stable_points(self): # Test for the target and individual steady state of the infinite # horizon solution using the parametrization in the "Buffer Stock # Theory" paper. # Create and solve the agent baseAgent_Inf = IndShockConsumerType(cycles=0, verbose=0, **bst_params) baseAgent_Inf.solve() # Extract stable points mNrmStE = baseAgent_Inf.solution[0].mNrmStE mNrmTrg = baseAgent_Inf.solution[0].mNrmTrg # Check against pre-computed values decimalPlacesTo = 10 self.assertAlmostEqual(mNrmStE, 1.37731133865, decimalPlacesTo) self.assertAlmostEqual(mNrmTrg, 1.39101653806, decimalPlacesTo)
def test_GICFails(self): GIC_fail_dictionary = dict(self.base_params) GIC_fail_dictionary["Rfree"] = 1.08 GIC_fail_dictionary["PermGroFac"] = [1.00] GICFailExample = IndShockConsumerType( cycles=0, # cycles=0 makes this an infinite horizon consumer **GIC_fail_dictionary) GICFailExample.solve() GICFailExample.unpack("cFunc") m = np.linspace(0, 5, 1000) c_m = GICFailExample.cFunc[0](m) self.assertAlmostEqual(c_m[500], 0.7772637042393458) self.assertAlmostEqual(c_m[700], 0.8392649061916746) self.assertFalse(GICFailExample.conditions["GIC"])
def test_infinite_horizon(self): IndShockExample = IndShockConsumerType(**IdiosyncDict) IndShockExample.assign_parameters( cycles=0) # Make this type have an infinite horizon IndShockExample.solve() self.assertAlmostEqual(IndShockExample.solution[0].mNrmStE, 1.5488165705077026) self.assertAlmostEqual( IndShockExample.solution[0].cFunc.functions[0].x_list[0], -0.25017509) IndShockExample.track_vars = ['aNrm', "mNrm", "cNrm", 'pLvl'] IndShockExample.initialize_sim() IndShockExample.simulate() self.assertAlmostEqual(IndShockExample.history["mNrm"][0][0], 1.0170176090252379)
def test_baseEx(self): baseEx = IndShockConsumerType(**self.base_params) baseEx.cycles = 100 # Make this type have a finite horizon (Set T = 100) baseEx.solve() baseEx.unpack("cFunc") m = np.linspace(0, 9.5, 1000) c_m = baseEx.cFunc[0](m) c_t1 = baseEx.cFunc[-2](m) c_t5 = baseEx.cFunc[-6](m) c_t10 = baseEx.cFunc[-11](m) self.assertAlmostEqual(c_m[500], 1.4008090582203356) self.assertAlmostEqual(c_t1[500], 2.9227437159255216) self.assertAlmostEqual(c_t5[500], 1.7350607327187664) self.assertAlmostEqual(c_t10[500], 1.4991390649979213) self.assertAlmostEqual(c_t10[600], 1.6101476268581576) self.assertAlmostEqual(c_t10[700], 1.7196531041366991)
def test_getShocks(self): agent = IndShockConsumerType( AgentCount = 2, T_sim = 10 ) agent.solve() agent.initializeSim() agent.simBirth(np.array([True,False])) agent.simOnePeriod() agent.simBirth(np.array([False,True])) agent.getShocks() self.assertEqual(agent.PermShkNow[0], 1.0050166461586711) self.assertEqual(agent.PermShkNow[1], 1.0050166461586711) self.assertEqual(agent.TranShkNow[0], 1.1176912196531754)
def create_agents(CRRA, TranShkStd): # Copy base dictionaries un_dict = copy(IdiosyncDict) pf_dict = copy(PFDict) # Update CRRA un_dict['CRRA'] = CRRA pf_dict['CRRA'] = CRRA # Update transitory shock sd un_dict["TranShkStd"] = [TranShkStd] IndShockConsumer = IndShockConsumerType(**un_dict) IndShockConsumer.cycles = 2 # Make this type have a two-period horizon IndShockConsumer.solve() PFConsumer = IndShockConsumerType(**pf_dict) PFConsumer.cycles = 2 PFConsumer.solve() return ((IndShockConsumer, PFConsumer))
def setUp(self): """ Prepare to compare the models by initializing and solving them """ # Set up and solve infinite type import HARK.ConsumptionSaving.ConsumerParameters as Params # Define a test dictionary that should have the same solution in the # perfect foresight and idiosyncratic shocks models. test_dictionary = deepcopy(Params.init_idiosyncratic_shocks) test_dictionary['LivPrb'] = [1.] test_dictionary['DiscFac'] = 0.955 test_dictionary['PermGroFac'] = [1.] test_dictionary['PermShkStd'] = [0.] test_dictionary['TranShkStd'] = [0.] test_dictionary['UnempPrb'] = 0. test_dictionary['T_cycle'] = 1 test_dictionary['T_retire'] = 0 test_dictionary['BoroCnstArt'] = None InfiniteType = IndShockConsumerType(**test_dictionary) InfiniteType.cycles = 0 InfiniteType.updateIncomeProcess() InfiniteType.solve() InfiniteType.timeFwd() InfiniteType.unpackcFunc() # Make and solve a perfect foresight consumer type with the same parameters PerfectForesightType = PerfForesightConsumerType(**test_dictionary) PerfectForesightType.cycles = 0 PerfectForesightType.solve() PerfectForesightType.unpackcFunc() PerfectForesightType.timeFwd() self.InfiniteType = InfiniteType self.PerfectForesightType = PerfectForesightType
def makeGrowthplot(PermGroFac, DiscFac): # cycles=0 tells the solver to find the infinite horizon solution baseAgent_Inf = IndShockConsumerType(verbose=0, cycles=0, **base_params) baseAgent_Inf.PermGroFac = [PermGroFac] baseAgent_Inf.DiscFac = DiscFac baseAgent_Inf.updateIncomeProcess() baseAgent_Inf.checkConditions() baseAgent_Inf.solve() baseAgent_Inf.unpack('cFunc') if (baseAgent_Inf.GPFInd >= 1): baseAgent_Inf.checkGICInd(verbose=3) elif baseAgent_Inf.solution[0].mNrmSS > 3.5: print('Solution exists but is outside the plot range.') else: def EcLev_tp1_Over_p_t(a): ''' Taking end-of-period assets a as input, return ratio of expectation of next period's consumption to this period's permanent income Inputs: a: end-of-period assets Returns: EcLev_tp1_Over_p_{t}: next period's expected c level / current p ''' # Extract parameter values to make code more readable permShkVals = baseAgent_Inf.PermShkDstn[0].X tranShkVals = baseAgent_Inf.TranShkDstn[0].X permShkPrbs = baseAgent_Inf.PermShkDstn[0].pmf tranShkPrbs = baseAgent_Inf.TranShkDstn[0].pmf Rfree = baseAgent_Inf.Rfree EPermGroFac = baseAgent_Inf.PermGroFac[0] PermGrowFac_tp1 = EPermGroFac * permShkVals # Nonstochastic growth times idiosyncratic permShk RNrmFac_tp1 = Rfree / PermGrowFac_tp1 # Growth-normalized interest factor # 'bank balances' b = end-of-last-period assets times normalized return factor b_tp1 = RNrmFac_tp1 * a # expand dims of b_tp1 and use broadcasted sum of a column and a row vector # to obtain a matrix of possible market resources next period # because matrix mult is much much faster than looping to calc E m_tp1_GivenTranAndPermShks = np.expand_dims(b_tp1, axis=1) + tranShkVals # List of possible values of $\mathbf{c}_{t+1}$ (Transposed by .T) cRat_tp1_GivenTranAndPermShks = baseAgent_Inf.cFunc[0]( m_tp1_GivenTranAndPermShks).T cLev_tp1_GivenTranAndPermShks = cRat_tp1_GivenTranAndPermShks * PermGrowFac_tp1 # compute expectation over perm shocks by right multiplying with probs EOverPShks_cLev_tp1_GivenTranShkShks = np.dot( cLev_tp1_GivenTranAndPermShks, permShkPrbs) # finish expectation over trans shocks by right multiplying with probs EcLev_tp1_Over_p_t = np.dot(EOverPShks_cLev_tp1_GivenTranShkShks, tranShkPrbs) # return expected consumption return EcLev_tp1_Over_p_t # Calculate the expected consumption growth factor # mBelwTrg defines the plot range on the left of target m value (e.g. m <= target m) mNrmTrg = baseAgent_Inf.solution[0].mNrmSS mBelwTrg = np.linspace(1, mNrmTrg, 50) c_For_mBelwTrg = baseAgent_Inf.cFunc[0](mBelwTrg) a_For_mBelwTrg = mBelwTrg - c_For_mBelwTrg EcLev_tp1_Over_p_t_For_mBelwTrg = [ EcLev_tp1_Over_p_t(i) for i in a_For_mBelwTrg ] # mAbveTrg defines the plot range on the right of target m value (e.g. m >= target m) mAbveTrg = np.linspace(mNrmTrg, 3.5, 50) # EcGro_For_mAbveTrg: E [consumption growth factor] when m_{t} is below target m EcGro_For_mBelwTrg = np.array( EcLev_tp1_Over_p_t_For_mBelwTrg) / c_For_mBelwTrg c_For_mAbveTrg = baseAgent_Inf.cFunc[0](mAbveTrg) a_For_mAbveTrg = mAbveTrg - c_For_mAbveTrg EcLev_tp1_Over_p_t_For_mAbveTrg = [ EcLev_tp1_Over_p_t(i) for i in a_For_mAbveTrg ] # EcGro_For_mAbveTrg: E [consumption growth factor] when m_{t} is bigger than target m_{t} EcGro_For_mAbveTrg = np.array( EcLev_tp1_Over_p_t_For_mAbveTrg) / c_For_mAbveTrg Rfree = 1.0 EPermGroFac = 1.0 mNrmTrg = baseAgent_Inf.solution[0].mNrmSS # Calculate Absolute Patience Factor Phi = lower bound of consumption growth factor APF = (Rfree * DiscFac)**(1.0 / CRRA) plt.figure(figsize=(12, 8)) # Plot the Absolute Patience Factor line plt.plot([0, 3.5], [APF, APF], label="\u03A6 = [(\u03B2 R)^(1/ \u03C1)]/R") # Plot the Permanent Income Growth Factor line plt.plot([0, 3.5], [EPermGroFac, EPermGroFac], label="\u0393") # Plot the expected consumption growth factor on the left side of target m plt.plot(mBelwTrg, EcGro_For_mBelwTrg, color="black") # Plot the expected consumption growth factor on the right side of target m plt.plot(mAbveTrg, EcGro_For_mAbveTrg, color="black", label="$\mathsf{E}_{t}[c_{t+1}/c_{t}]$") # Plot the target m plt.plot( [mNrmTrg, mNrmTrg], [0, 3.5], color="black", linestyle="--", label="", ) plt.xlim(1, 3.5) plt.ylim(0.94, 1.10) plt.text(2.105, 0.930, "$m_{t}$", fontsize=26, fontweight="bold") plt.text( mNrmTrg - 0.02, 0.930, "m̌", fontsize=26, fontweight="bold", ) plt.tick_params( labelbottom=False, labelleft=False, left="off", right="off", bottom="off", top="off", ) plt.legend(fontsize='x-large') plt.show() return None
class testIndShockConsumerType(unittest.TestCase): def setUp(self): self.agent = IndShockConsumerType(AgentCount=2, T_sim=10) self.agent.solve() def test_getShocks(self): self.agent.initializeSim() self.agent.simBirth(np.array([True, False])) self.agent.simOnePeriod() self.agent.simBirth(np.array([False, True])) self.agent.getShocks() self.assertEqual(self.agent.shocks["PermShkNow"][0], 1.0427376294215103) self.assertEqual(self.agent.shocks["PermShkNow"][1], 0.9278094171517413) self.assertEqual(self.agent.shocks["TranShkNow"][0], 0.881761797501595) def test_ConsIndShockSolverBasic(self): LifecycleExample = IndShockConsumerType(**init_lifecycle) LifecycleExample.cycles = 1 LifecycleExample.solve() # test the solution_terminal self.assertAlmostEqual(LifecycleExample.solution[10].cFunc(2).tolist(), 2) self.assertAlmostEqual(LifecycleExample.solution[9].cFunc(1), 0.97769632) self.assertAlmostEqual(LifecycleExample.solution[8].cFunc(1), 0.96624445) self.assertAlmostEqual(LifecycleExample.solution[7].cFunc(1), 0.95691449) self.assertAlmostEqual(LifecycleExample.solution[0].cFunc(1).tolist(), 0.87362789) self.assertAlmostEqual(LifecycleExample.solution[1].cFunc(1).tolist(), 0.9081621) self.assertAlmostEqual(LifecycleExample.solution[2].cFunc(1).tolist(), 0.9563899) solver = ConsIndShockSolverBasic( LifecycleExample.solution[1], LifecycleExample.IncomeDstn[0], LifecycleExample.LivPrb[0], LifecycleExample.DiscFac, LifecycleExample.CRRA, LifecycleExample.Rfree, LifecycleExample.PermGroFac[0], LifecycleExample.BoroCnstArt, LifecycleExample.aXtraGrid, LifecycleExample.vFuncBool, LifecycleExample.CubicBool, ) solver.prepareToSolve() self.assertAlmostEqual(solver.DiscFacEff, 0.9503999999999999) self.assertAlmostEqual(solver.PermShkMinNext, 0.850430160026919) self.assertAlmostEqual(solver.cFuncNowCnst(4).tolist(), 4.0) self.assertAlmostEqual(solver.prepareToCalcEndOfPrdvP()[0], -0.2491750859108316) self.assertAlmostEqual(solver.prepareToCalcEndOfPrdvP()[-1], 19.74982491408914) EndOfPrdvP = solver.calcEndOfPrdvP() self.assertAlmostEqual(EndOfPrdvP[0], 6622.251864311334) self.assertAlmostEqual(EndOfPrdvP[-1], 0.026301061207747087) solution = solver.makeBasicSolution(EndOfPrdvP, solver.aNrmNow, solver.makeLinearcFunc) solver.addMPCandHumanWealth(solution) self.assertAlmostEqual(solution.cFunc(4).tolist(), 1.7391265696400773) def test_simulated_values(self): self.agent.initializeSim() self.agent.simulate() self.assertAlmostEqual(self.agent.MPCnow[1], 0.5711503906043797) self.assertAlmostEqual(self.agent.aLvlNow[1], 0.18438326264597635)
class testIndShockConsumerType(unittest.TestCase): def setUp(self): self.agent = IndShockConsumerType( AgentCount = 2, T_sim = 10 ) self.agent.solve() def test_getShocks(self): self.agent.initializeSim() self.agent.simBirth(np.array([True,False])) self.agent.simOnePeriod() self.agent.simBirth(np.array([False,True])) self.agent.getShocks() self.assertEqual(self.agent.PermShkNow[0], 1.0050166461586711) self.assertEqual(self.agent.PermShkNow[1], 1.0050166461586711) self.assertEqual(self.agent.TranShkNow[0], 1.1176912196531754) def test_ConsIndShockSolverBasic(self): LifecycleExample = IndShockConsumerType( **Params.init_lifecycle) LifecycleExample.cycles = 1 LifecycleExample.solve() solver = ConsIndShockSolverBasic(LifecycleExample.solution[1], LifecycleExample.IncomeDstn[0], LifecycleExample.LivPrb[0], LifecycleExample.DiscFac, LifecycleExample.CRRA, LifecycleExample.Rfree, LifecycleExample.PermGroFac[0], LifecycleExample.BoroCnstArt, LifecycleExample.aXtraGrid, LifecycleExample.vFuncBool, LifecycleExample.CubicBool) solver.prepareToSolve() self.assertAlmostEqual(solver.DiscFacEff, 0.9503999999999999) self.assertAlmostEqual(solver.PermShkMinNext, 0.850430160026919) self.assertAlmostEqual(solver.cFuncNowCnst(4).tolist(), 4.0) self.assertAlmostEqual(solver.prepareToCalcEndOfPrdvP()[0], -0.2491750859108316) self.assertAlmostEqual(solver.prepareToCalcEndOfPrdvP()[-1], 19.74982491408914) EndOfPrdvP = solver.calcEndOfPrdvP() self.assertAlmostEqual(EndOfPrdvP[0], 6622.251864311334) self.assertAlmostEqual(EndOfPrdvP[-1], 0.026301061207747087) solution = solver.makeBasicSolution(EndOfPrdvP, solver.aNrmNow, solver.makeLinearcFunc) solver.addMPCandHumanWealth(solution) self.assertAlmostEqual(solution.cFunc(4).tolist(), 1.7391265696400773) def test_simulated_values(self): self.agent.initializeSim() self.agent.simulate() print(self.agent.aLvlNow) self.assertAlmostEqual(self.agent.MPCnow[1], 0.5535801655448935) self.assertAlmostEqual(self.agent.aLvlNow[1], 0.18832361)
# # The grid of assets above minimum $\texttt{aXtraGrid}$ is specified by its minimum and maximum level, the number of gridpoints, and the extent of exponential nesting. The greater the (integer) value of $\texttt{aXtraNestFac}$, the more dense the gridpoints will be at the bottom of the grid (and more sparse near the top); setting $\texttt{aXtraNestFac}$ to $0$ will generate an evenly spaced grid of $a_t$. # # The artificial borrowing constraint $\texttt{BoroCnstArt}$ can be set to $\texttt{None}$ to turn it off. # # It is not necessary to compute the value function in this model, and it is not computationally free to do so. You can choose whether the value function should be calculated and returned as part of the solution of the model with $\texttt{vFuncBool}$. The consumption function will be constructed as a piecewise linear interpolation when $\texttt{CubicBool}$ is \texttt{False}, and will be a piecewise cubic spline interpolator if $\texttt{True}$. # %% [markdown] {"heading_collapsed": true} # ## Solving and examining the solution of the idiosyncratic income shocks model # # The cell below creates an infinite horizon instance of $\texttt{IndShockConsumerType}$ and solves its model by calling its $\texttt{solve}$ method. # %% {"hidden": true} IndShockExample = IndShockConsumerType(**IdiosyncDict) IndShockExample.cycles = 0 # Make this type have an infinite horizon IndShockExample.solve() # %% [markdown] {"hidden": true} # After solving the model, we can examine an element of this type's $\texttt{solution}$: # %% {"hidden": true} print(vars(IndShockExample.solution[0])) # %% [markdown] {"hidden": true} # The single-period solution to an idiosyncratic shocks consumer's problem has all of the same attributes as in the perfect foresight model, with a couple additions. The solution can include the marginal marginal value of market resources function $\texttt{vPPfunc}$, but this is only constructed if $\texttt{CubicBool}$ is $\texttt{True}$, so that the MPC can be accurately computed; when it is $\texttt{False}$, then $\texttt{vPPfunc}$ merely returns $\texttt{NaN}$ everywhere. # # The $\texttt{solveConsIndShock}$ function calculates steady state market resources and stores it in the attribute $\texttt{mNrmSS}$. This represents the steady state level of $m_t$ if *this period* were to occur indefinitely, but with income shocks turned off. This is relevant in a "one period infinite horizon" model like we've specified here, but is less useful in a lifecycle model. # # Let's take a look at the consumption function by plotting it, along with its derivative (the MPC):
def makeGICFailExample(DiscFac, PermShkStd, UnempPrb): # Construct the "GIC fails" example. GIC_fails_dictionary = dict(base_params) GIC_fails_dictionary['Rfree'] = 1.04 GIC_fails_dictionary['PermGroFac'] = [1.00] GICFailsExample = IndShockConsumerType( verbose=0, cycles=0, # cycles=0 makes this an infinite horizon consumer **GIC_fails_dictionary) GICFailsExample.DiscFac = DiscFac GICFailsExample.PermShkStd = [PermShkStd] GICFailsExample.UnempPrb = UnempPrb GICFailsExample.updateIncomeProcess() GICFailsExample.checkConditions() # Get calibrated parameters to make code more readable LivPrb = GICFailsExample.LivPrb[0] Rfree = GICFailsExample.Rfree DiscFac = GICFailsExample.DiscFac CRRA = GICFailsExample.CRRA permShkPrbs = GICFailsExample.PermShkDstn[0].pmf permShkVals = GICFailsExample.PermShkDstn[0].X EPermGroFac = GICFailsExample.PermGroFac[0] # np.dot multiplies vectors; probability times value for each outcome is expectation EpermShkInv = np.dot(permShkPrbs, permShkVals**(-1)) # $ \Ex[\permShk^{-1}] $ InvEpermShkInv = (EpermShkInv)**(-1) # $ (\Ex[\permShk^{-1}])^{-1}$ PermGroFac = EPermGroFac * InvEpermShkInv # Uncertainty-adjusted permanent growth factor ERNrmFac = Rfree / PermGroFac # Interest factor normalized by uncertainty-adjusted growth ErNrmRte = ERNrmFac - 1 # Interest rate is interest factor - 1 # "sustainable" C = P + (discounted) interest income # "sustainable" c = 1 + (discounted, normalized) interest income EmDelEq0 = lambda m: 1 + (m - 1) * (ErNrmRte / ERNrmFac ) # "sustainable" c where E[Δ m] = 0 GICFailsExample.solve( ) # Above, we set up the problem but did not solve it GICFailsExample.unpack( 'cFunc' ) # Make the consumption function easily accessible for plotting mPlotMin = 0 mPts = 1000 m = np.linspace(mPlotMin, 5, mPts) c_Limt = GICFailsExample.cFunc[0](m) c_Sstn = EmDelEq0(m) # "sustainable" consumption plt.figure(figsize=(12, 8)) plt.plot(m, c_Limt, label="$c(m_{t})$") plt.plot(m, c_Sstn, label="$\mathsf{E}_{t}[\Delta m_{t+1}] = 0$") plt.xlim(0, 5.5) plt.ylim(0, 1.6) plt.tick_params( labelbottom=False, labelleft=False, left="off", right="off", bottom="off", top="off", ) plt.legend(fontsize='x-large') plt.show() print(f'Current Growth Impatience Factor is {GICFailsExample.GPFInd}') return None
# Under the given parameter values, [the paper's first figure](https://econ-ark.github.io/BufferStockTheory/#Convergence-of-the-Consumption-Rules) depicts the successive consumption rules that apply in the last period of life $(c_{T}(m))$, the second-to-last period, and earlier periods $(c_{T-n})$. The consumption function to which these converge is $c(m)$: # # $$ # c(m) = \lim_{n \uparrow \infty} c_{T-n}(m) \notag # $$ # # %% # Create a buffer stock consumer instance by invoking the IndShockConsumerType class # with the built-in parameter dictionary "base_params" # Construct finite horizon agent with baseline parameters baseAgent_Fin = IndShockConsumerType(**base_params) baseAgent_Fin.cycles = 100 # Set finite horizon (T = 100) baseAgent_Fin.solve() # Solve the model baseAgent_Fin.unpack('cFunc') # Make the consumption function easily accessible # %% # Plot the different consumption rules for the different periods mPlotMin = 0 mLocCLabels = 9.6 # Defines horizontal limit of figure mPlotTop = 6.5 # Defines maximum m value where functions are plotted mPts = 1000 # Number of points at which functions are evaluated mBelwLabels = np.linspace(mPlotMin,mLocCLabels-0.1,mPts) # Range of m below loc of labels m_FullRange = np.linspace(mPlotMin,mPlotTop,mPts) # Full plot range c_Tm0 = m_FullRange # c_Tm0 defines the last period consumption rule (c=m) c_Tm1 = baseAgent_Fin.cFunc[ -2](mBelwLabels) # c_Tm1 defines the second-to-last period consumption rule
# So, to give the consumer more credit, we just need to relax their borrowing constraint a tiny bit. # Declare how much we want to increase credit by credit_change = .0001 # Now increase the consumer's credit limit. # We do this by decreasing the artificial borrowing constraint. XtraCreditExample.BoroCnstArt = BaselineExample.BoroCnstArt - credit_change # + {"cell_marker": "\"\"\"", "cell_type": "markdown"} # Now we are ready to solve the consumers' problems. # In HARK, this is done by calling the solve() method of the ConsumerType. # + ### First solve the baseline example. BaselineExample.solve() ### Now solve the comparison example of the consumer with a bit more credit XtraCreditExample.solve() # + {"cell_marker": "\"\"\"", "cell_type": "markdown"} # Now that we have the solutions to the 2 different problems, we can compare them. # # We are going to compare the consumption functions for the two different consumers. # Policy functions (including consumption functions) in HARK are stored as attributes # of the *solution* of the ConsumerType. The solution, in turn, is a list, indexed by the time # period the solution is for. Since in this demo we are working with infinite-horizon models # where every period is the same, there is only one time period and hence only one solution. # e.g. BaselineExample.solution[0] is the solution for the BaselineExample. If BaselineExample # had 10 time periods, we could access the 5th with BaselineExample.solution[4] (remember, Python # counts from 0!) Therefore, the consumption function cFunc from the solution to the
def makeBoundsFigure(UnempPrb, PermShkStd, TranShkStd, DiscFac, CRRA): baseAgent_Inf = IndShockConsumerType(verbose=0, cycles=0, **base_params) baseAgent_Inf.UnempPrb = UnempPrb baseAgent_Inf.PermShkStd = [PermShkStd] baseAgent_Inf.TranShkStd = [TranShkStd] baseAgent_Inf.DiscFac = DiscFac baseAgent_Inf.CRRA = CRRA baseAgent_Inf.updateIncomeProcess() baseAgent_Inf.checkConditions() baseAgent_Inf.solve() baseAgent_Inf.unpack('cFunc') # Retrieve parameters (makes code readable) Rfree = baseAgent_Inf.Rfree CRRA = baseAgent_Inf.CRRA EPermGroFac = baseAgent_Inf.PermGroFac[0] mNrmTrg = baseAgent_Inf.solution[0].mNrmSS UnempPrb = baseAgent_Inf.UnempPrb κ_Min = 1.0 - (Rfree**(-1.0)) * (Rfree * DiscFac)**(1.0 / CRRA) h_inf = (1.0 / (1.0 - EPermGroFac / Rfree)) cFunc_Uncnst = lambda m: (h_inf - 1) * κ_Min + κ_Min * m cFunc_TopBnd = lambda m: (1 - UnempPrb**(1.0 / CRRA) * (Rfree * DiscFac)**(1.0 / CRRA) / Rfree) * m cFunc_BotBnd = lambda m: (1 - (Rfree * DiscFac)**(1.0 / CRRA) / Rfree) * m # Plot the consumption function and its bounds cMaxLabel = r"c̅$(m) = (m-1+h)κ̲$" # Use unicode kludge cMinLabel = r"c̲$(m)= (1-\Phi_{R})m = κ̲ m$" mPlotMax = 25 mPlotMin = 0 # mKnk is point where the two upper bounds meet mKnk = ((h_inf - 1) * κ_Min) / ( (1 - UnempPrb**(1.0 / CRRA) * (Rfree * DiscFac)**(1.0 / CRRA) / Rfree) - κ_Min) mBelwKnkPts = 300 mAbveKnkPts = 700 mBelwKnk = np.linspace(mPlotMin, mKnk, mBelwKnkPts) mAbveKnk = np.linspace(mKnk, mPlotMax, mAbveKnkPts) mFullPts = np.linspace(mPlotMin, mPlotMax, mBelwKnkPts + mAbveKnkPts) plt.figure(figsize=(12, 8)) plt.plot(mFullPts, baseAgent_Inf.cFunc[0](mFullPts), label=r'$c(m)$') plt.plot(mBelwKnk, cFunc_Uncnst(mBelwKnk), label=cMaxLabel, linestyle="--") plt.plot( mAbveKnk, cFunc_Uncnst(mAbveKnk), label= r'Upper Bound $ = $ Min $[\overline{\overline{c}}(m),\overline{c}(m)]$', linewidth=2.5, color='black') plt.plot(mBelwKnk, cFunc_TopBnd(mBelwKnk), linewidth=2.5, color='black') plt.plot(mAbveKnk, cFunc_TopBnd(mAbveKnk), linestyle="--", label=r"$\overline{\overline{c}}(m) = κ̅m = (1 - ℘^{1/ρ}Φᵣ)m$") plt.plot(mBelwKnk, cFunc_BotBnd(mBelwKnk), color='red', linewidth=2.5) plt.plot(mAbveKnk, cFunc_BotBnd(mAbveKnk), color='red', label=cMinLabel, linewidth=2.5) plt.tick_params(labelbottom=False, labelleft=False, left='off', right='off', bottom='off', top='off') plt.xlim(mPlotMin, mPlotMax) plt.ylim(mPlotMin, 1.12 * cFunc_Uncnst(mPlotMax)) plt.text(mPlotMin, 1.12 * cFunc_Uncnst(mPlotMax) + 0.05, "$c$", fontsize=22) plt.text(mPlotMax + 0.1, mPlotMin, "$m$", fontsize=22) plt.legend(fontsize='x-large') plt.show() return None