Generator: BufferStockTheory-make/notebooks_byname
The TractableBufferStock model is a (relatively) simple framework that captures all of the qualitative, and many of the quantitative features of optimal consumption in the presence of labor income uncertainty.
# This cell has a bit of (uninteresting) initial setup.
# Import the model from the toolkit
from HARK.ConsumptionSaving.TractableBufferStockModel import TractableConsumerType
import ipywidgets as widgets
from ipywidgets import interact, fixed
import matplotlib.pyplot as plt
import numpy as np
def mystr(number):
return "{:.3f}".format(number)The key assumption behind the model’s tractability is that there is only a single, stark form of uncertainty: So long as an employed consumer remains employed, that consumer’s labor income will rise at a constant rate :
But, between any period and the next, there is constant hazard that the consumer will transition to the “unemployed” state. Unemployment is irreversible, like retirement or disability. When unemployed, the consumer receives a fixed amount of income (for simplicity, zero). (See the linked handout for details of the model).
Defining as the growth rate of aggregate wages/productivity, we assume that idiosyncratic wages grow by where is the growth rate of idiosyncratic productivity (‘on-the-job learning’, say). (This assumption about the relation between idiosyncratic income growth and idiosyncratic risk means that an increase in is a mean-preserving spread in human wealth; again see the lecture notes).
Under CRRA utility , the problem can be normalized by . Using lower case for normalized varibles (e.g., ), the normalized problem can be expressed by the Bellman equation:
No such environment: eqnarray* at position 7: \begin{̲e̲q̲n̲a̲r̲r̲a̲y̲*̲}̲
v_t({m}_t) &=&…
\begin{eqnarray*}
v_t({m}_t) &=& \max_{{c}_t} ~ U({c}_t) + \beta \Gamma^{1-\rho} \overbrace{\mathbb{E}[v_{t+1}^{\bullet}]}^{=p v_{t+1}^{u}+(1-p)v_{t+1}^{e}} \\
& s.t. & \\
{m}_{t+1} &=& (m_{t}-c_{t})\mathcal{R} + \mathbb{1}_{t+1},
\end{eqnarray*}where , and if the consumer is employed (and zero if unemployed).
Under plausible parameter values the model has a target level of (market resources to permanent income) with an analytical solution that exhibits plausible relationships among all of the parameters.
Defining and , the handout shows that an approximation of the target is given by the formula:
# Define a parameter dictionary and representation of the agents for the tractable buffer stock model
TBS_dictionary = {
"UnempPrb": 0.00625, # Prob of becoming unemployed; working life of 1/UnempProb = 160 qtrs
"DiscFac": 0.975, # Intertemporal discount factor
"Rfree": 1.01, # Risk-free interest factor on assets
"PermGroFac": 1.0025, # Permanent income growth factor (uncompensated)
"CRRA": 2.5,
} # Coefficient of relative risk aversion
MyTBStype = TractableConsumerType(**TBS_dictionary)Target Wealth¶
Whether the model exhibits a “target” or “stable” level of the wealth-to-permanent-income ratio for employed consumers depends on whether the ‘Growth Impatience Condition’ (the GIC) holds:
and recall (from PerfForesightCRRA) that the perfect foresight ‘Growth Impatience Factor’ is
so since , uncertainty makes it harder to be ‘impatient.’ To understand this, think of someone who, in the perfect foresight model, was ‘poised’: Exactly on the knife edge between patience and impatience. Now add a precautionary saving motive; that person will now (to some degree) be pushed off the knife edge in the direction of ‘patience.’ So, in the presence of uncertainty, the conditions on parameters other than must be stronger in order to guarantee ‘impatience’ in the sense of wanting to spend enough for your wealth to decline despite the extra precautionary motive.
# Define a function that plots the employed consumption function and sustainable consumption function
# for given parameter values
def makeTBSplot(
DiscFac,
CRRA,
Rfree,
PermGroFac,
UnempPrb,
mMax,
mMin,
cMin,
cMax,
plot_emp,
plot_ret,
plot_mSS,
show_targ,
):
MyTBStype.DiscFac = DiscFac
MyTBStype.CRRA = CRRA
MyTBStype.Rfree = Rfree
MyTBStype.PermGroFac = PermGroFac
MyTBStype.UnempPrb = UnempPrb
try:
MyTBStype.solve()
except:
print(
"Unable to solve; parameter values may be too close to their limiting values"
)
plt.xlabel("Market resources ${m}_t$")
plt.ylabel("Consumption ${c}_t$")
plt.ylim([cMin, cMax])
plt.xlim([mMin, mMax])
m = np.linspace(mMin, mMax, num=100, endpoint=True)
if plot_emp:
c = MyTBStype.solution[0].cFunc(m)
c[m == 0.0] = 0.0
plt.plot(m, c, "-b")
if plot_mSS:
plt.plot(
[mMin, mMax],
[
(
MyTBStype.PermGroFacCmp / MyTBStype.Rfree
+ mMin * (1.0 - MyTBStype.PermGroFacCmp / MyTBStype.Rfree)
),
(
MyTBStype.PermGroFacCmp / MyTBStype.Rfree
+ mMax * (1.0 - MyTBStype.PermGroFacCmp / MyTBStype.Rfree)
),
],
"--k",
)
if plot_ret:
c = MyTBStype.solution[0].cFunc_U(m)
plt.plot(m, c, "-g")
if show_targ:
mTarg = MyTBStype.mTarg
cTarg = MyTBStype.cTarg
# + mystr(mTarg) + '\n$\hat{c}^* = $ ' + mystr(cTarg)
targ_label = r"$\left(\frac{1}{(\gamma-r)+(1+(\gamma/\mho)(1-(\gamma/\mho)(\rho-1)/2))}\right) $"
plt.annotate(
targ_label,
xy=(0.0, 0.0),
xytext=(0.2, 0.1),
textcoords="axes fraction",
fontsize=18,
)
plt.plot(mTarg, cTarg, "ro")
plt.annotate(
"↙️ m target",
(mTarg, cTarg),
xytext=(0.25, 0.2),
ha="left",
textcoords="offset points",
)
plt.show()
return None
# Define widgets to control various aspects of the plot
# Define a slider for the discount factor
DiscFac_widget = widgets.FloatSlider(
min=0.9,
max=0.99,
step=0.0002,
value=TBS_dictionary["DiscFac"], # Default value
continuous_update=False,
readout_format=".4f",
description="$\\beta$",
)
# Define a slider for relative risk aversion
CRRA_widget = widgets.FloatSlider(
min=1.0,
max=5.0,
step=0.01,
value=TBS_dictionary["CRRA"], # Default value
continuous_update=False,
readout_format=".2f",
description="$\\rho$",
)
# Define a slider for the interest factor
Rfree_widget = widgets.FloatSlider(
min=1.01,
max=1.04,
step=0.0001,
value=TBS_dictionary["Rfree"], # Default value
continuous_update=False,
readout_format=".4f",
description="$R$",
)
# Define a slider for permanent income growth
PermGroFac_widget = widgets.FloatSlider(
min=1.00,
max=1.015,
step=0.0002,
value=TBS_dictionary["PermGroFac"], # Default value
continuous_update=False,
readout_format=".4f",
description="$G$",
)
# Define a slider for unemployment (or retirement) probability
UnempPrb_widget = widgets.FloatSlider(
min=0.000001,
max=TBS_dictionary["UnempPrb"] * 2, # Go up to twice the default value
step=0.00001,
value=TBS_dictionary["UnempPrb"],
continuous_update=False,
readout_format=".5f",
description="$\\mho$",
)
# Define a text box for the lower bound of {m}_t
mMin_widget = widgets.FloatText(
value=0.0, step=0.1, description="$m$ min", disabled=False
)
# Define a text box for the upper bound of {m}_t
mMax_widget = widgets.FloatText(
value=50.0, step=0.1, description="$m$ max", disabled=False
)
# Define a text box for the lower bound of {c}_t
cMin_widget = widgets.FloatText(
value=0.0, step=0.1, description="$c$ min", disabled=False
)
# Define a text box for the upper bound of {c}_t
cMax_widget = widgets.FloatText(
value=1.5, step=0.1, description="$c$ max", disabled=False
)
# Define a check box for whether to plot the employed consumption function
plot_emp_widget = widgets.Checkbox(
value=True, description="Plot employed $c$ function", disabled=False
)
# Define a check box for whether to plot the retired consumption function
plot_ret_widget = widgets.Checkbox(
value=False, description="Plot retired $c$ function", disabled=False
)
# Define a check box for whether to plot the sustainable consumption line
plot_mSS_widget = widgets.Checkbox(
value=True, description="Plot sustainable $c$ line", disabled=False
)
# Define a check box for whether to show the target annotation
show_targ_widget = widgets.Checkbox(
value=True, description="Show target $(m,c)$", disabled=False
)
# Make an interactive plot of the tractable buffer stock solution
# To make some of the widgets not appear, replace X_widget with fixed(desired_fixed_value) in the arguments below.
interact(
makeTBSplot,
DiscFac=DiscFac_widget,
CRRA=CRRA_widget,
# We can fix a parameter using the fixed() operator
Rfree=fixed(TBS_dictionary["Rfree"]),
# Rfree = Rfree_widget, # This is the line which, when uncommented, would make Rfree a slider
PermGroFac=PermGroFac_widget,
UnempPrb=UnempPrb_widget,
mMin=mMin_widget,
mMax=mMax_widget,
cMin=cMin_widget,
cMax=cMax_widget,
show_targ=show_targ_widget,
plot_emp=plot_emp_widget,
plot_ret=plot_ret_widget,
plot_mSS=plot_mSS_widget,
);