diff --git a/HARK/ConsumptionSaving/ConsBequestModel.py b/HARK/ConsumptionSaving/ConsBequestModel.py index 8a873555f..1bf976216 100644 --- a/HARK/ConsumptionSaving/ConsBequestModel.py +++ b/HARK/ConsumptionSaving/ConsBequestModel.py @@ -273,12 +273,8 @@ def make_warmglow_portfolio_solution_terminal( class BequestWarmGlowConsumerType(IndShockConsumerType): r""" - A consumer type with idiosyncratic shocks to permanent and transitory income. - Their problem is defined by a sequence of income distributions, survival probabilities - (:math:`1-\mathsf{D}`), and permanent income growth rates (:math:`\Gamma`), as well - as time invariant values for risk aversion (:math:`\rho`), discount factor (:math:`\beta`), - the interest rate (:math:`\mathsf{R}`), the grid of end-of-period assets, and an artificial - borrowing constraint (:math:`\underline{a}`). + A consumer type with based on IndShockConsumerType, with an additional bequest motive. + They gain utility for any wealth they leave when they die, according to a Stone-Geary utility. .. math:: \newcommand{\CRRA}{\rho} @@ -295,7 +291,7 @@ class BequestWarmGlowConsumerType(IndShockConsumerType): (\psi_{t+1},\theta_{t+1}) &\sim F_{t+1}, \\ \mathbb{E}[\psi]=\mathbb{E}[\theta] &= 1, \\ u(c) &= \frac{c^{1-\CRRA}}{1-\CRRA} \\ - u_{Beq} (a) = \textbf{BeqFac} \frac{(a+\textbf{BeqShift})^{1-\CRRA_{Beq}}}{1-\CRRA_{Beq}} + u_{Beq} (a) &= \textbf{BeqFac} \frac{(a+\textbf{BeqShift})^{1-\CRRA_{Beq}}}{1-\CRRA_{Beq}} \\ \end{align*} @@ -1277,7 +1273,7 @@ def calc_EndOfPrd_v(S, a, z): class BequestWarmGlowPortfolioType(PortfolioConsumerType): r""" - A consumer type with based on IndShockConsumerType, with an additional bequest motive. + A consumer type with based on PortfolioConsumerType, with an additional bequest motive. They gain utility for any wealth they leave when they die, according to a Stone-Geary utility. .. math:: @@ -1300,7 +1296,7 @@ class BequestWarmGlowPortfolioType(PortfolioConsumerType): (\psi_{t+1},\theta_{t+1},\phi_{t+1},p_t) &\sim F_{t+1}, \\ \mathbb{E}[\psi]=\mathbb{E}[\theta] &= 1. \\ u(c) &= \frac{c^{1-\CRRA}}{1-\CRRA} \\ - u_{Beq} (a) = \textbf{BeqFac} \frac{(a+\textbf{BeqShift})^{1-\CRRA_{Beq}}}{1-\CRRA_{Beq}} + u_{Beq} (a) &= \textbf{BeqFac} \frac{(a+\textbf{BeqShift})^{1-\CRRA_{Beq}}}{1-\CRRA_{Beq}} \\ \end{align*} diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py index b00ef1f50..e5aa6a893 100644 --- a/HARK/ConsumptionSaving/ConsIndShockModel.py +++ b/HARK/ConsumptionSaving/ConsIndShockModel.py @@ -2798,7 +2798,7 @@ class KinkedRconsumerType(IndShockConsumerType): \end{cases}\\ \Rfree_{boro} &> \Rfree_{save}, \\ (\psi_{t+1},\theta_{t+1}) &\sim F_{t+1}, \\ - \mathbb{E}[\psi]=\mathbb{E}[\theta] &= 1. + \mathbb{E}[\psi]=\mathbb{E}[\theta] &= 1.\\ u(c) &= \frac{c^{1-\CRRA}}{1-\CRRA} \\ \end{align*} diff --git a/HARK/ConsumptionSaving/ConsWealthPortfolioModel.py b/HARK/ConsumptionSaving/ConsWealthPortfolioModel.py index 736dff910..c87648b43 100644 --- a/HARK/ConsumptionSaving/ConsWealthPortfolioModel.py +++ b/HARK/ConsumptionSaving/ConsWealthPortfolioModel.py @@ -3,8 +3,8 @@ import numpy as np from HARK.ConsumptionSaving.ConsPortfolioModel import ( PortfolioConsumerType, - init_portfolio, PortfolioSolution, + make_portfolio_solution_terminal, ) from HARK.distributions import expected from HARK.interpolation import ( @@ -14,11 +14,22 @@ MargValueFuncCRRA, ValueFuncCRRA, ) +from HARK.Calibration.Assets.AssetProcesses import ( + make_lognormal_RiskyDstn, + combine_IncShkDstn_and_RiskyDstn, + calc_ShareLimit_for_CRRA, +) +from HARK.Calibration.Income.IncomeProcesses import ( + construct_lognormal_income_process_unemployment, + get_PermShkDstn_from_IncShkDstn, + get_TranShkDstn_from_IncShkDstn, +) +from HARK.ConsumptionSaving.ConsRiskyAssetModel import ( + make_simple_ShareGrid, +) from HARK.rewards import UtilityFuncCRRA -from HARK.utilities import NullFunc +from HARK.utilities import NullFunc, make_assets_grid - -import numpy as np from HARK.interpolation import LinearInterp @@ -100,6 +111,129 @@ def __call__(self, omega): return np.nan_to_num(chi) +# Trivial constructor function +def make_ChiFromOmega_function(CRRA, WealthShare, ChiFromOmega_N, ChiFromOmega_bound): + return ChiFromOmegaFunction( + CRRA, WealthShare, N=ChiFromOmega_N, z_bound=ChiFromOmega_bound + ) + + +############################################################################### + +# Make a dictionary of constructors for the wealth-in-utility portfolio choice consumer type +WealthPortfolioConsumerType_constructors_default = { + "IncShkDstn": construct_lognormal_income_process_unemployment, + "PermShkDstn": get_PermShkDstn_from_IncShkDstn, + "TranShkDstn": get_TranShkDstn_from_IncShkDstn, + "aXtraGrid": make_assets_grid, + "RiskyDstn": make_lognormal_RiskyDstn, + "ShockDstn": combine_IncShkDstn_and_RiskyDstn, + "ShareLimit": calc_ShareLimit_for_CRRA, + "ShareGrid": make_simple_ShareGrid, + "ChiFunc": make_ChiFromOmega_function, + "solution_terminal": make_portfolio_solution_terminal, +} + +# Default parameters to make IncShkDstn using construct_lognormal_income_process_unemployment +WealthPortfolioConsumerType_IncShkDstn_default = { + "PermShkStd": [0.1], # Standard deviation of log permanent income shocks + "PermShkCount": 7, # Number of points in discrete approximation to permanent income shocks + "TranShkStd": [0.1], # Standard deviation of log transitory income shocks + "TranShkCount": 7, # Number of points in discrete approximation to transitory income shocks + "UnempPrb": 0.05, # Probability of unemployment while working + "IncUnemp": 0.3, # Unemployment benefits replacement rate while working + "T_retire": 0, # Period of retirement (0 --> no retirement) + "UnempPrbRet": 0.005, # Probability of "unemployment" while retired + "IncUnempRet": 0.0, # "Unemployment" benefits when retired +} + +# Default parameters to make aXtraGrid using make_assets_grid +WealthPortfolioConsumerType_aXtraGrid_default = { + "aXtraMin": 0.001, # Minimum end-of-period "assets above minimum" value + "aXtraMax": 100, # Maximum end-of-period "assets above minimum" value + "aXtraNestFac": 1, # Exponential nesting factor for aXtraGrid + "aXtraCount": 200, # Number of points in the grid of "assets above minimum" + "aXtraExtra": None, # Additional other values to add in grid (optional) +} + +# Default parameters to make RiskyDstn with make_lognormal_RiskyDstn (and uniform ShareGrid) +WealthPortfolioConsumerType_RiskyDstn_default = { + "RiskyAvg": 1.08, # Mean return factor of risky asset + "RiskyStd": 0.18362634887, # Stdev of log returns on risky asset + "RiskyCount": 5, # Number of integration nodes to use in approximation of risky returns +} + +WealthPortfolioConsumerType_ShareGrid_default = { + "ShareCount": 25 # Number of discrete points in the risky share approximation +} + +# Default parameters to make ChiFunc with make_ChiFromOmega_function +WealthPortfolioConsumerType_ChiFunc_default = { + "ChiFromOmega_N": 501, # Number of gridpoints in chi-from-omega function + "ChiFromOmega_bound": 15, # Highest gridpoint to use for it +} + +# Make a dictionary to specify a risky asset consumer type +WealthPortfolioConsumerType_solving_default = { + # BASIC HARK PARAMETERS REQUIRED TO SOLVE THE MODEL + "cycles": 1, # Finite, non-cyclic model + "T_cycle": 1, # Number of periods in the cycle for this agent type + "constructors": WealthPortfolioConsumerType_constructors_default, # See dictionary above + # PRIMITIVE RAW PARAMETERS REQUIRED TO SOLVE THE MODEL + "CRRA": 5.0, # Coefficient of relative risk aversion + "Rfree": 1.03, # Return factor on risk free asset + "DiscFac": 0.90, # Intertemporal discount factor + "LivPrb": [0.98], # Survival probability after each period + "PermGroFac": [1.01], # Permanent income growth factor + "BoroCnstArt": 0.0, # Artificial borrowing constraint + "WealthShare": 0.5, # Share of wealth in Cobb-Douglas aggregator in utility function + "WealthShift": 0.1, # Shifter for wealth in utility function + "DiscreteShareBool": False, # Whether risky asset share is restricted to discrete values + "vFuncBool": False, # Whether to calculate the value function during solution + "CubicBool": False, # Whether to use cubic spline interpolation when True + # (Uses linear spline interpolation for cFunc when False) + "AdjustPrb": 1.0, # Probability that the agent can update their risky portfolio share each period + "sim_common_Rrisky": True, # Whether risky returns have a shared/common value across agents +} +WealthPortfolioConsumerType_simulation_default = { + # PARAMETERS REQUIRED TO SIMULATE THE MODEL + "AgentCount": 10000, # Number of agents of this type + "T_age": None, # Age after which simulated agents are automatically killed + "aNrmInitMean": 0.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 + # (The portion of PermGroFac attributable to aggregate productivity growth) + "NewbornTransShk": False, # Whether Newborns have transitory shock + # ADDITIONAL OPTIONAL PARAMETERS + "PerfMITShk": False, # Do Perfect Foresight MIT Shock + # (Forces Newborns to follow solution path of the agent they replaced if True) + "neutral_measure": False, # Whether to use permanent income neutral measure (see Harmenberg 2021) +} + +# Assemble the default dictionary +WealthPortfolioConsumerType_default = {} +WealthPortfolioConsumerType_default.update(WealthPortfolioConsumerType_solving_default) +WealthPortfolioConsumerType_default.update( + WealthPortfolioConsumerType_simulation_default +) +WealthPortfolioConsumerType_default.update( + WealthPortfolioConsumerType_aXtraGrid_default +) +WealthPortfolioConsumerType_default.update( + WealthPortfolioConsumerType_ShareGrid_default +) +WealthPortfolioConsumerType_default.update( + WealthPortfolioConsumerType_IncShkDstn_default +) +WealthPortfolioConsumerType_default.update( + WealthPortfolioConsumerType_RiskyDstn_default +) +WealthPortfolioConsumerType_default.update(WealthPortfolioConsumerType_ChiFunc_default) +init_wealth_portfolio = WealthPortfolioConsumerType_default + + class WealthPortfolioConsumerType(PortfolioConsumerType): time_inv_ = deepcopy(PortfolioConsumerType.time_inv_) time_inv_ = time_inv_ + ["WealthShare", "WealthShift", "ChiFunc"] @@ -114,10 +248,18 @@ def __init__(self, **kwds): self.solve_one_period = solve_one_period_WealthPortfolio + def update(self): + super().update() + self.update_ChiFunc() + + def update_ChiFunc(self): if self.WealthShare == 0.0: self.ChiFunc = None else: - self.ChiFunc = ChiFromOmegaFunction(self.CRRA, self.WealthShare) + self.construct("ChiFunc") + + +############################################################################### def utility(c, a, CRRA, share=0.0, intercept=0.0): @@ -502,8 +644,3 @@ def solve_one_period_WealthPortfolio( vFuncAdj=vFuncNow, ) return solution_now - - -init_wealth_portfolio = init_portfolio.copy() -init_wealth_portfolio["WealthShare"] = 0.5 -init_wealth_portfolio["WealthShift"] = 0.1 diff --git a/HARK/distribution.py b/HARK/distribution.py index 274765b2d..eb3f7ab38 100644 --- a/HARK/distribution.py +++ b/HARK/distribution.py @@ -963,11 +963,11 @@ def _approx_equiprobable( ) if np.array_equal(self.Sigma, np.diag(np.diag(self.Sigma))): - ind_atoms = np.empty((self.M, N)) + ind_atoms = np.empty((self.M, N + 2 * tail_N)) for i in range(self.M): if self.Sigma[i, i] == 0.0: - x_atoms = np.repeat(np.exp(self.mu[i]), N) + x_atoms = np.repeat(np.exp(self.mu[i]), N + 2 * tail_N) ind_atoms[i] = x_atoms else: x_atoms = ( @@ -983,7 +983,22 @@ def _approx_equiprobable( atoms = np.stack( [ar.flatten() for ar in list(np.meshgrid(*atoms_list))], axis=1 ).T - pmv = np.repeat(1 / (N**self.M), N**self.M) + + interiors = np.empty([self.M, (N + 2 * tail_N) ** (self.M)]) + + inners = np.zeros(N + 2 * tail_N) + + if tail_N > 0: + inners[:tail_N] = [(tail_N - i) for i in range(tail_N)] + inners[-tail_N:] = [(i + 1) for i in range(tail_N)] + + for i in range(self.M): + inners_i = [inners for _ in range((N + 2 * tail_N) ** i)] + + interiors[i] = np.repeat( + [*inners_i], (N + 2 * tail_N) ** (self.M - (i + 1)) + ) + else: if tail_bound is not None: if type(tail_bound) is float: @@ -1024,10 +1039,10 @@ def eval(params, z): excl = [] for j in range(len(z)): - if z[j, 0] != z[j, 1]: - inds.append(j) - else: + if z[j, 0] == z[j, 1]: excl.append(j) + elif params[j] != 0.0: + inds.append(j) dim = len(inds) @@ -1111,21 +1126,21 @@ def eval(params, z): atoms[i] = xi_atoms - max_locs = np.argmax(np.abs(interiors), axis=0) + max_locs = np.argmax(np.abs(interiors), axis=0) - max_inds = np.stack([max_locs, np.arange(len(max_locs))], axis=1) + max_inds = np.stack([max_locs, np.arange(len(max_locs))], axis=1) - prob_locs = interiors[max_inds[:, 0], max_inds[:, 1]] + prob_locs = interiors[max_inds[:, 0], max_inds[:, 1]] - def prob_assign(x): - if x == 0: - return 1 / (N**self.M) - else: - return 0.0 + def prob_assign(x): + if x == 0: + return 1 / (N**self.M) + else: + return 0.0 - prob_vec = np.vectorize(prob_assign) + prob_vec = np.vectorize(prob_assign) - pmv = prob_vec(prob_locs) + pmv = prob_vec(prob_locs) limit = { "dist": self, diff --git a/binder/postBuild b/binder/postBuild deleted file mode 100755 index 4e4b22864..000000000 --- a/binder/postBuild +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -jupyter contrib nbextension install --user -jupyter nbextension enable codefolding/main -python -m cite2c.install -result=$(python < no retirement)\n", - " # Parameters for constructing the \"assets above minimum\" grid\n", + " # Aggregates affecting the agent's decision\n", + " \"Rfree\": (1 + r_ss), # Interest factor for assets faced by agents\n", + " \"wage\": [w_ss], # Wage rate faced by agents\n", + " \"tax_rate\": [\n", + " 0\n", + " ], # set to 0.0 because we are going to assume that labor here is actually after tax income\n", + " \"labor\": [L_ss], # Aggregate (mean) labor supply\n", + " # Parameters for constructing \"assets above minimum\" grid\n", " \"aXtraMin\": 0.0001, # Minimum end-of-period \"assets above minimum\" value\n", " \"aXtraMax\": 2000, # Maximum end-of-period \"assets above minimum\" value\n", " \"aXtraCount\": 200, # Number of points in the base grid of \"assets above minimum\"\n", " # Exponential nesting factor when constructing \"assets above minimum\" grid\n", " \"aXtraNestFac\": 3,\n", " \"aXtraExtra\": None, # Additional values to add to aXtraGrid\n", - " # Transition Matrix simulation parameters\n", + " # Transition matrix simulation parameters\n", " \"mCount\": 200,\n", " \"mMax\": 2000,\n", " \"mMin\": 0.0001,\n", @@ -309,7 +311,7 @@ "id": "3be9593e", "metadata": {}, "source": [ - "# Create HARK agent" + "Let's create a temporary instance of a `NewKeynesianConsumerType` agent." ] }, { @@ -326,7 +328,7 @@ }, "outputs": [], "source": [ - "Agent = NewKeynesianConsumerType(**HANK_Dict)" + "tempAgent = NewKeynesianConsumerType(**HANK_Dict)" ] }, { @@ -334,10 +336,28 @@ "id": "fa266888", "metadata": {}, "source": [ - "# Find Steady state discount factor clear asset market\n", + "Given a discount factor, the agent will supply a steady state capital stock `A_ss`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ebe1792e", + "metadata": {}, + "outputs": [], + "source": [ + "A_ss = tempAgent.compute_steady_state()[0]\n", + "print(f\"Steady state agent asset supply for beta = 0.98 is: {A_ss:.3f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "911805ab", + "metadata": {}, + "source": [ + "### Steady State Assets \n", "\n", - "We will estimate the discount factor to ensure that asset supply equals the steady state capital we found earlier. \n", - "\n" + "Since we are interested in computing a steady state equilibrium, we find `discFac` such that `A_ss` clears the asset market given that `K_ss` is the steady state firm capital demand. " ] }, { @@ -365,7 +385,10 @@ "def A_ss_func(beta):\n", " HANK_Dict[\"DiscFac\"] = beta\n", "\n", + " # For a given value of beta, we need to re-create the Agent\n", " Agent_func = NewKeynesianConsumerType(**HANK_Dict, verbose=False)\n", + "\n", + " # And then solve for the steady state supply\n", " A_ss = Agent_func.compute_steady_state()[0]\n", "\n", " return A_ss\n", @@ -380,7 +403,15 @@ "\n", "DiscFac = optimize.brentq(ss_dif, 0.8, 0.9999)\n", "\n", - "print(\"Time taken to solve for steady state\", time.time() - start)" + "print(f\"Time taken to solve for steady state {time.time() - start:.3f} secs.\")" + ] + }, + { + "cell_type": "markdown", + "id": "01be6a8a", + "metadata": {}, + "source": [ + "We can now create the steady state agent using the general equilibrium discount factor." ] }, { @@ -399,8 +430,8 @@ "source": [ "# Create a new agent\n", "HANK_Dict[\"DiscFac\"] = DiscFac\n", - "Agent_GE = NewKeynesianConsumerType(**HANK_Dict, verbose=False)\n", - "A_ss, C_ss = Agent_GE.compute_steady_state()" + "steadyHANK = NewKeynesianConsumerType(**HANK_Dict, verbose=False)\n", + "A_ss, C_ss = steadyHANK.compute_steady_state()" ] }, { @@ -426,9 +457,12 @@ } ], "source": [ - "# to make sure goods and asset markets clear\n", - "print(\"goods_clearing\", Y_ss - C_ss - calibration[\"delta\"] * K_ss)\n", - "print(\"asset_clearing\", A_ss - K_ss)" + "# To make sure goods and asset markets clear\n", + "print(\n", + " \"Final goods clearing:\",\n", + " calibration[\"Y_ss\"] - C_ss - calibration[\"delta\"] * calibration[\"K_ss\"],\n", + ")\n", + "print(\"Asset clearing:\", A_ss - calibration[\"K_ss\"])" ] }, { @@ -436,7 +470,15 @@ "id": "a8167383", "metadata": {}, "source": [ - "# Computing Heterogenous Agent Jacobians" + "# Computing Jacobians using SSJ\n", + "\n", + "With the steady state agent in hand, we can compute the Jacobians of the steady state HANK agent's policy with respect to the aggregate state variables.\n", + "\n", + "The `calc_jacobian` method of our `NewKeynesianConsumerType` agent computes the Jacobians of the steady state aggregate consumption (`CJACW`) and assets (`AJACW`) with respect to a pertubation of a specified variable.\n", + "\n", + "Recall `CJACW[s,t]` is the time $t$ response to a shock at time $s$. \n", + "\n", + "Here is an example where we shock the wage rate. " ] }, { @@ -463,9 +505,9 @@ "source": [ "start = time.time()\n", "\n", - "CJACW, AJACW = Agent_GE.calc_jacobian(\"wage\", 300) # Wage jacobians\n", + "CJACW, AJACW = steadyHANK.calc_jacobian(\"wage\", 300) # Wage jacobians\n", "\n", - "print(\"Time taken to compute jacobians\", time.time() - start)" + "print(f\"Time taken to compute wage Jacobians: {time.time() - start:.3f} seconds\")" ] }, { @@ -493,15 +535,16 @@ } ], "source": [ - "plt.plot(CJACW.T[0])\n", - "plt.plot(CJACW.T[20])\n", - "plt.plot(CJACW.T[50])\n", - "plt.plot(CJACW.T[100])\n", + "plt.plot(CJACW.T[0], label=\"s=0\")\n", + "plt.plot(CJACW.T[20], label=\"s=20\")\n", + "plt.plot(CJACW.T[50], label=\"s=50\")\n", + "plt.plot(CJACW.T[100], label=\"s=100\")\n", "plt.xlim(-2, 300)\n", "plt.plot(np.arange(300), np.zeros(300), color=\"k\")\n", - "plt.title(\"Consumption Jacobian Wage\")\n", - "plt.xlabel(\"quarters\")\n", - "plt.ylabel(\"C response\")\n", + "plt.title(\"Consumption Jacobian (Wage) \")\n", + "plt.xlabel(\"Quarters\")\n", + "plt.ylabel(\"Consumption response\")\n", + "plt.legend()\n", "plt.show()" ] }, @@ -529,9 +572,19 @@ "source": [ "start = time.time()\n", "\n", - "CJACR, AJACR = Agent_GE.calc_jacobian(\"Rfree\", 300) # Rfree jacobians\n", + "CJACR, AJACR = steadyHANK.calc_jacobian(\"Rfree\", 300) # Rfree jacobians\n", "\n", - "print(\"Time taken to compute jacobians\", time.time() - start)" + "print(\n", + " f\"Time taken to compute return factor Jacobians: {time.time() - start:.3f} seconds\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "311a3a60", + "metadata": {}, + "source": [ + "Here is an example where we shock the return factor. " ] }, { @@ -559,16 +612,25 @@ } ], "source": [ - "plt.plot(CJACR.T[0])\n", - "plt.plot(CJACR.T[30])\n", - "plt.plot(CJACR.T[50])\n", + "plt.plot(CJACR.T[0], label=\"s =0\")\n", + "plt.plot(CJACR.T[20], label=\"s=20\")\n", + "plt.plot(CJACR.T[50], label=\"s=50\")\n", + "plt.plot(CJACR.T[100], label=\"s=100\")\n", "plt.plot(np.arange(300), np.zeros(300), color=\"k\")\n", - "plt.title(\"Consumption Jacobian interest rate\")\n", - "plt.xlabel(\"quarters\")\n", - "plt.ylabel(\"C response\")\n", + "plt.title(\"Consumption Jacobian (Return Factor)\")\n", + "plt.xlabel(\"Quarters\")\n", + "plt.ylabel(\"Consumption response\")\n", "plt.show()" ] }, + { + "cell_type": "markdown", + "id": "c5d0b70e", + "metadata": {}, + "source": [ + "Let's store the Jacobians in a dictionary for later use." + ] + }, { "cell_type": "code", "execution_count": 18, @@ -621,7 +683,7 @@ "id": "d3669fab", "metadata": {}, "source": [ - "## Other Blocks of the Model" + "## Impulse Response Functions and Simulations " ] }, { @@ -675,7 +737,7 @@ "id": "f3d569b5", "metadata": {}, "source": [ - "# Solving for Impulse Responses" + "### Solving for Impulse Responses" ] }, { @@ -692,8 +754,8 @@ }, "outputs": [], "source": [ - "T = 300 # <-- the length of the IRF\n", - "rho_Z = 0.8 # persistence of IRF shock\n", + "T = 300 # Length of the IRF\n", + "rho_Z = 0.8 # Persistence of IRF shock\n", "dZ = 0.001 * Z_ss * rho_Z ** np.arange(T)\n", "shocks = {\"Z\": dZ}\n", "\n", @@ -701,7 +763,6 @@ "unknowns = [\"K\"]\n", "targets = [\"asset_mkt\"]\n", "\n", - "\n", "irfs_Z = ks.solve_impulse_linear(SteadyState_Dict, unknowns, targets, shocks)" ] }, @@ -723,7 +784,7 @@ " irfs_list,\n", " variables,\n", " labels=[\" \"],\n", - " ylabel=r\"Percentage points (dev. from ss)\",\n", + " ylabel=r\"Percentage point (dev. from ss)\",\n", " T_plot=50,\n", " figsize=(18, 6),\n", "):\n", @@ -734,13 +795,17 @@ " for i in range(n_var):\n", " # plot all irfs\n", " for j, irf in enumerate(irfs_list):\n", - " ax[i].plot(irf[variables[i]][:50], label=labels[j])\n", + " ax[i].plot(irf[variables[i]][:50] * 1e2, label=labels[j])\n", " ax[i].set_title(variables[i])\n", - " ax[i].set_xlabel(r\"$t$\")\n", + " ax[i].set_xlabel(r\"Quarters\")\n", " if i == 0:\n", " ax[i].set_ylabel(ylabel)\n", - " ax[i].legend()\n", - " plt.show()" + " # ax[i].legend()\n", + " # ax[i].x\n", + "\n", + " plt.tight_layout()\n", + " plt.show()\n", + " # plt.savefig(\"irf.png\")" ] }, { @@ -777,7 +842,7 @@ "id": "a0130fc3", "metadata": {}, "source": [ - "# Simulating the model" + "### Simulating the model" ] }, { @@ -829,7 +894,6 @@ "rhos = {\"Z\": 0.8}\n", "impulses = {}\n", "\n", - "\n", "for i in inputs:\n", " own_shock = {i: sigmas[i] * rhos[i] ** np.arange(T)}\n", " impulses[i] = ks.solve_impulse_linear(\n", @@ -844,14 +908,6 @@ "data_simul = simulate(list(impulses.values()), outputs, T_sim)\n", "plot_timeseries(data_simul, (1, 3), figsize=(12, 4))" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "27732edd", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/examples/Journeys/Journey-Policymaker.ipynb b/examples/Journeys/Journey-Policymaker.ipynb index 8a8fe51c9..d3ce854c2 100644 --- a/examples/Journeys/Journey-Policymaker.ipynb +++ b/examples/Journeys/Journey-Policymaker.ipynb @@ -325,7 +325,7 @@ "metadata": {}, "source": [ "### 2.3 Simulation\n", - "After we solved the model backwards, we can simulate agents forward using Monte Carlo or [Transition Matrices](https://github.com/econ-ark/HARK/tree/master/examples/ConsIndShockModel/IndShockConsumerType_Transition_Matrix_Example.ipynb). These results can be used for in-model regressions or plotting distributions of assets or consumption." + "After we solved the model backwards, we can simulate agents forward using Monte Carlo or [Transition Matrices](https://github.com/econ-ark/HARK/tree/master/examples/ConsNewKeynesianModel/Transition_Matrix_Example.ipynb). These results can be used for in-model regressions or plotting distributions of assets or consumption." ] }, {