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
"aNrmInitMean": np.log(1.25) - (.5**2) / 2, # Mean of log initial assets "aNrmInitStd": .5, # Standard deviation of log initial assets "pLvlInitMean": 0, # Mean of log initial permanent income "pLvlInitStd": 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 } # %% [markdown] # # Solve # %% collapsed=true jupyter={"outputs_hidden": true, "source_hidden": true} fast = IndShockConsumerType(**Harmenberg_Dict, verbose=1) fast.cycles = 0 fast.Rfree = 1.2**.25 fast.PermGroFac = [1.02] fast.tolerance = fast.tolerance / 100 fast.track_vars = ['cNrm', 'pLvl'] fast.solve(verbose=False) # %% [markdown] # # Calculate Patience Conditions # %% collapsed=true jupyter={"outputs_hidden": true} fast.check_conditions(verbose=True) # %% jupyter={"source_hidden": true} # Simulate a population fast.initialize_sim() fast.simulate()