In [1]:
# This line configures matplotlib to show figures embedded in the notebook,
# instead of opening a new window for each figure. More about that later.
# If you are using an old version of IPython, try using '%pylab inline' instead.
%matplotlib inline
import matplotlib.pyplot as plt
from pysolve.model import Model
from pysolve.utils import is_close,round_solution
In [2]:
def create_pc_model():
model = Model()
model.set_var_default(0)
model.var('Bcb', desc='Government bills held by the Central Bank')
model.var('Bh', desc='Government bills held by households')
model.var('Bs', desc='Government bills supplied by the government')
model.var('C', desc='Consumption goods')
model.var('Hh', desc='Cash held by households')
model.var('Hs', desc='Cash supplied by the central bank')
model.var('R', desc='Interest rate on government bills')
model.var('T', desc='Taxes')
model.var('V', desc='Household wealth')
model.var('Y', desc='Income = GDP')
model.var('YD', desc='Disposable income of households')
model.param('alpha1', desc='Propensity to consume out of income', default=0.6)
model.param('alpha2', desc='Propensity to consume out of wealth', default=0.4)
model.param('lambda0', desc='Parameter in asset demand function', default=0.635)
model.param('lambda1', desc='Parameter in asset demand function', default=5.0)
model.param('lambda2', desc='Parameter in asset demand function', default=0.01)
model.param('theta', desc='Tax rate', default=0.2)
model.param('G', desc='Government goods', default=20.)
model.param('Rbar', desc='Interest rate as policy instrument')
model.add('Y = C + G') # 4.1
model.add('YD = Y - T + R(-1)*Bh(-1)') # 4.2
model.add('T = theta*(Y + R(-1)*Bh(-1))') #4.3, theta < 1
model.add('V = V(-1) + (YD - C)') # 4.4
model.add('C = alpha1*YD + alpha2*V(-1)') # 4.5, 0<alpha2<alpha1<1
model.add('Hh = V - Bh') # 4.6
model.add('Bh = V*lambda0 + V*lambda1*R - lambda2*YD') # 4.7
model.add('Bs - Bs(-1) = (G + R(-1)*Bs(-1)) - (T + R(-1)*Bcb(-1))') # 4.8
model.add('Hs - Hs(-1) = Bcb - Bcb(-1)') # 4.9
model.add('Bcb = Bs - Bh') # 4.10
model.add('R = Rbar') # 4.11
return model
In [3]:
steady = create_pc_model()
steady.set_values({'alpha1': 0.6,
'alpha2': 0.4,
'lambda0': 0.635,
'lambda1': 5.0,
'lambda2': 0.01,
'G': 20,
'Rbar': 0.025})
for _ in xrange(100):
steady.solve(iterations=100, threshold=1e-5)
if is_close(steady.solutions[-2], steady.solutions[-1], atol=1e-4):
break
In [4]:
def create_pcex_model():
model = Model()
model.set_var_default(0)
model.var('Bcb', desc='Government bills held by the Central Bank')
model.var('Bd', desc='Demand for government bills')
model.var('Bh', desc='Government bills held by households')
model.var('Bs', desc='Government bills supplied by the government')
model.var('C', desc='Consumption goods')
model.var('Hd', desc='Demand for cash')
model.var('Hh', desc='Cash held by households')
model.var('Hs', desc='Cash supplied by the central bank')
model.var('R', desc='Interest rate on government bills')
model.var('T', desc='Taxes')
model.var('V', desc='Household wealth')
model.var('Ve', desc='Expected household wealth')
model.var('Y', desc='Income = GDP')
model.var('YD', desc='Disposable income of households')
model.var('YDe', desc='Expected disposable income of households')
model.set_param_default(0)
model.param('alpha1', desc='Propensity to consume out of income', default=0.6)
model.param('alpha2', desc='Propensity to consume o of wealth', default=0.4)
model.param('lambda0', desc='Parameter in asset demand function', default=0.635)
model.param('lambda1', desc='Parameter in asset demand function', default=5.0)
model.param('lambda2', desc='Parameter in asset demand function', default=0.01)
model.param('theta', desc='Tax rate', default=0.2)
model.param('G', desc='Government goods', default=20.)
model.param('Ra', desc='Random shock to expectations', default=0.0)
model.param('Rbar', desc='Interest rate as policy instrument', default=0.025)
model.add('Y = C + G') # 4.1
model.add('YD = Y - T + R(-1)*Bh(-1)') # 4.2
model.add('T = theta*(Y + R(-1)*Bh(-1))') #4.3, theta < 1
model.add('V = V(-1) + (YD - C)') # 4.4
model.add('C = alpha1*YDe + alpha2*V(-1)') # 4.5E
model.add('Bd = Ve*lambda0 + Ve*lambda1*R - lambda2*YDe') # 4.7E
model.add('Hd = Ve - Bd') # 4.13
model.add('Ve = V(-1) + (YDe - C)') # 4.14
model.add('Hh = V - Bh') # 4.6
model.add('Bh = Bd') # 4.15
model.add('Bs - Bs(-1) = (G + R(-1)*Bs(-1)) - (T + R(-1)*Bcb(-1))') # 4.8
model.add('Hs - Hs(-1) = Bcb - Bcb(-1)') # 4.9
model.add('Bcb = Bs - Bh') # 4.10
model.add('R = Rbar') # 4.11
model.add('YDe = YD * (1 + Ra)') # 4.16
return model
In [5]:
pcex_steady = create_pcex_model()
pcex_steady.set_values([('alpha1', 0.6),
('alpha2', 0.4),
('lambda0', 0.635),
('lambda1', 5.0),
('lambda2', 0.01),
('theta', 0.2),
('G', 20),
('Rbar', 0.025),
('Ra', 0),
('Bcb', 116.36),
('Bh', 363.59),
('Bs', 'Bh + Bcb'),
('Hh', 116.35),
('Hs', 'Hh'),
('V', 'Bh + Hh'),
('R', 'Rbar')])
for _ in xrange(100):
pcex_steady.solve(iterations=100, threshold=1e-5)
if is_close(pcex_steady.solutions[-2], pcex_steady.solutions[-1], atol=1e-4):
break
In [6]:
import random
random.seed(6)
shocks = create_pcex_model()
shocks.set_values(pcex_steady.solutions[-1], ignore_errors=True)
for _ in xrange(50):
shocks.parameters['Ra'].value = random.gauss(0,1) / 10.
shocks.solve(iterations=100, threshold=1e-3)
In [7]:
caption = '''
Figure 4.1 Money demand and held money balances, when the economy is subjected
to random shocks.'''
hddata = [s['Hd'] for s in shocks.solutions[25:]]
hhdata = [s['Hh'] for s in shocks.solutions[25:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(min(hddata+hhdata)-2, max(hddata+hhdata)+2)
axes.plot(hhdata, 'b')
axes.plot(hddata, linestyle='--', color='r')
# add labels
plt.text(13, 35, 'Held money balances')
plt.text(13, 34, '(continuous line)')
plt.text(16, 12, 'Money demand')
plt.text(16, 11, '(dotted line)')
fig.text(0.1, -.05, caption);
In [8]:
caption = '''
Figure 4.2 Changes in money demand and in money balances held (first differences),
when the economy is subjected to random shocks. '''
hddata = [s['Hd'] for s in shocks.solutions[24:]]
hhdata = [s['Hh'] for s in shocks.solutions[24:]]
for i in xrange(len(hddata)-1, 0, -1):
hddata[i] -= hddata[i-1]
hhdata[i] -= hhdata[i-1]
hddata = hddata[1:]
hhdata = hhdata[1:]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(min(hddata+hhdata)-2, max(hddata+hhdata)+2)
axes.plot(hhdata, 'b')
axes.plot(hddata, linestyle='--', color='r')
# add labels
plt.text(13, 20, 'Held money balances')
plt.text(13, 18, '(continuous line)')
plt.text(15, -18, 'Money demand')
plt.text(15, -20, '(dotted line)')
fig.text(0.1, -.05, caption);
In [9]:
rate_shock = create_pc_model()
rate_shock.set_values({'Bcb': 21.576,
'Bh': 64.865,
'Bs': 86.441,
'Hh': 21.62,
'Hs': 21.62,
'V': 86.485,
'alpha1': 0.6,
'alpha2': 0.4,
'lambda0': 0.635,
'lambda1': 5.0,
'lambda2': 0.01,
'G': 20,
'Rbar': 0.025})
# solve until stable
for i in xrange(50):
rate_shock.solve(iterations=100, threshold=1e-5)
if is_close(rate_shock.solutions[-2], rate_shock.solutions[-1], atol=1e-4):
break
rate_shock.parameters['Rbar'].value = 0.035
for i in xrange(40):
rate_shock.solve(iterations=100, threshold=1e-5)
In [10]:
caption = '''
Figure 4.3 Evolution of the shares of bills and money balances in the portfolio of
households, following an increase of 100 points in the rate of interest on bills.'''
hhdata = [s['Hh']/s['V'] for s in rate_shock.solutions[15:]]
bhdata = [s['Bh']/s['V'] for s in rate_shock.solutions[15:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off')
axes.spines['top'].set_visible(False)
axes.set_ylim(0.19, 0.26)
axes.plot(hhdata, 'b')
axes2 = axes.twinx()
axes2.tick_params(top='off')
axes2.spines['top'].set_visible(False)
axes2.set_ylim(0.74, 0.81)
axes2.plot(bhdata, linestyle='--', color='r')
plt.text(1, 0.81, 'Share of')
plt.text(1, 0.807, 'money balances')
plt.text(45, 0.81, 'Share of')
plt.text(45, 0.807, 'bills')
plt.text(15, 0.795, 'Share of bills in')
plt.text(15, 0.792, 'household portfolios')
plt.text(15, 0.755, 'Share of money balances')
plt.text(15, 0.752, 'in household portfolios')
fig.text(0.1, -.05, caption);
In [11]:
caption = '''
Figure 4.4 Evolution of disposable income and household consumption following an
increase of 100 points in the rate of interest on bills. '''
yddata = [s['YD'] for s in rate_shock.solutions[20:]]
cdata = [s['C'] for s in rate_shock.solutions[20:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(86, 91)
axes.plot(yddata, 'b')
axes.plot(cdata, linestyle='--', color='r')
# add labels
plt.text(10, 90.2, 'Disposable')
plt.text(10, 90.0, 'Income')
plt.text(10, 88, 'Consumption')
fig.text(0.1, -0.05, caption);
In [12]:
def create_pcex1_model():
model = Model()
model.set_var_default(0)
model.var('Bcb', desc='Government bills held by the Central Bank')
model.var('Bd', desc='Demand for government bills')
model.var('Bh', desc='Government bills held by households')
model.var('Bs', desc='Government bills supplied by the government')
model.var('C', desc='Consumption goods')
model.var('Hd', desc='Demand for cash')
model.var('Hh', desc='Cash held by households')
model.var('Hs', desc='Cash supplied by the central bank')
model.var('R', 'Interest rate on government bills')
model.var('T', desc='Taxes')
model.var('V', desc='Household wealth')
model.var('Ve', desc='Expected household wealth')
model.var('Y', desc='Income = GDP')
model.var('YD', desc='Disposable income of households')
model.var('YDe', desc='Expected disposable income of households')
model.set_param_default(0)
model.param('alpha1', desc='Propensity to consume out of income', default=0.6)
model.param('alpha2', desc='Propensity to consume o of wealth', default=0.4)
model.param('lambda0', desc='Parameter in asset demand function', default=0.635)
model.param('lambda1', desc='Parameter in asset demand function', default=5.0)
model.param('lambda2', desc='Parameter in asset demand function', default=0.01)
model.param('theta', desc='Tax rate', default=0.2)
model.param('G', desc='Government goods', default=20.)
model.param('Rbar', desc='Interest rate as policy instrument', default=0.025)
model.add('Y = C + G') # 4.1
model.add('YD = Y - T + R(-1)*Bh(-1)') # 4.2
model.add('T = theta*(Y + R(-1)*Bh(-1))') #4.3, theta < 1
model.add('V = V(-1) + (YD - C)') # 4.4
model.add('C = alpha1*YDe + alpha2*V(-1)') # 4.5E
model.add('Bd = Ve*lambda0 + Ve*lambda1*R - lambda2*YDe') # 4.7E
model.add('Hd = Ve - Bd') # 4.13
model.add('Ve = V(-1) + (YDe - C)') # 4.14
model.add('Hh = V - Bh') # 4.6
model.add('Bh = Bd') # 4.15
model.add('Bs - Bs(-1) = (G + R(-1)*Bs(-1)) - (T + R(-1)*Bcb(-1))') # 4.8
model.add('Hs - Hs(-1) = Bcb - Bcb(-1)') # 4.9
model.add('Bcb = Bs - Bh') # 4.10
model.add('R = Rbar') # 4.11
model.add('YDe = YD(-1)') # 4.16A
return model
In [13]:
pcex1 = create_pcex1_model()
pcex1.set_values({'Bcb': 21.576,
'Bh': 64.865,
'Bs': 86.441,
'Hh': 21.62,
'Hs': 21.62,
'V': 86.485,
'YD': 90,
'alpha1': 0.6,
'alpha2': 0.4,
'lambda0': 0.635,
'lambda1': 5.0,
'lambda2': 0.01,
'G': 20,
'Rbar': 0.025})
for i in xrange(10):
pcex1.solve(iterations=100, threshold=1e-5)
pcex1.parameters['alpha1'].value = 0.7
for i in xrange(40):
pcex1.solve(iterations=100, threshold=1e-5)
In [14]:
caption = '''
Figure 4.5 Rise and fall of national income (GDP) following an increase in the
propensity to consume out of expected disposable income ($\\alpha_1$) '''
ydata = [s['Y'] for s in pcex1.solutions[8:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(104, 123)
axes.plot(ydata, 'b')
# add labels
plt.text(10, 116, 'National Income (GDP)')
fig.text(0.1, -0.05, caption);
In [15]:
caption = '''
Figure 4.6 Evolution of consumtion, expected disposable income and lagged wealth,
following an increase in the propensity to consume out of expected disposable
income ($\\alpha_1$).'''
vdata = [s['V'] for s in pcex1.solutions[8:]]
ydedata = [s['YDe'] for s in pcex1.solutions[8:]]
cdata = [s['C'] for s in pcex1.solutions[8:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(60, 106)
axes.plot(cdata, linestyle=':', color='r')
axes.plot(ydedata, linestyle='--', color='b')
axes.plot(vdata, color='k')
# add labels
plt.text(5, 102, 'Consumption')
plt.text(5, 90, 'Expected')
plt.text(5, 88, 'disposable')
plt.text(5, 86, 'income')
plt.text(10, 70, 'Lagged wealth')
fig.text(0.1, -.1, caption);
In [16]:
def create_pcex2_model():
model = Model()
model.set_var_default(0)
model.var('Bcb', desc='Government bills held by the Central Bank')
model.var('Bd', desc='Demand for government bills')
model.var('Bh', desc='Government bills held by households')
model.var('Bs', desc='Government bills supplied by the government')
model.var('C', desc='Consumption goods')
model.var('Hd', desc='Demand for cash')
model.var('Hh', desc='Cash held by households')
model.var('Hs', desc='Cash supplied by the central bank')
model.var('R', 'Interest rate on government bills')
model.var('T', desc='Taxes')
model.var('V', desc='Household wealth')
model.var('Ve', desc='Expected household wealth')
model.var('Y', desc='Income = GDP')
model.var('YD', desc='Disposable income of households')
model.var('YDe', desc='Expected disposable income of households')
model.var('alpha1', desc='Propensity to consume out of income')
model.set_param_default(0)
model.param('alpha2', desc='Propensity to consume out of wealth', default=0.6)
model.param('alpha10', desc='Propensity to consume out of income - exogenous')
model.param('iota', desc='Impact of interest rate on the propensity to consume out of income')
model.param('lambda0', desc='Parameter in asset demand function', default=0.635)
model.param('lambda1', desc='Parameter in asset demand function', default=5.0)
model.param('lambda2', desc='Parameter in asset demand function', default=0.01)
model.param('theta', desc='Tax rate', default=0.2)
model.param('G', desc='Government goods')
model.param('Rbar', desc='Interest rate as policy instrument')
model.add('Y = C + G') # 4.1
model.add('YD = Y - T + R(-1)*Bh(-1)') # 4.2
model.add('T = theta*(Y + R(-1)*Bh(-1))') #4.3, theta < 1
model.add('V = V(-1) + (YD - C)') # 4.4
model.add('C = alpha1*YDe + alpha2*V(-1)') # 4.5E
model.add('Bd = Ve*lambda0 + Ve*lambda1*R - lambda2*YDe') # 4.7E
model.add('Hd = Ve - Bd') # 4.13
model.add('Ve = V(-1) + (YDe - C)') # 4.14
model.add('Hh = V - Bh') # 4.6
model.add('Bh = Bd') # 4.15
model.add('Bs - Bs(-1) = (G + R(-1)*Bs(-1)) - (T + R(-1)*Bcb(-1))') # 4.8
model.add('Hs - Hs(-1) = Bcb - Bcb(-1)') # 4.9
model.add('Bcb = Bs - Bh') # 4.10
model.add('R = Rbar') # 4.11
model.add('YDe = YD(-1)') # 4.16A
model.add('alpha1 = alpha10 - iota*R(-1)')
return model
In [17]:
pcex2 = create_pcex2_model()
pcex2.set_values({'Bcb': 21.576,
'Bh': 64.865,
'Bs': 86.441, # Bs = Bh + Bcb
'Hh': 21.62,
'Hs': 21.62, # Hs = Hh
'R': 0.025,
'V': 86.485, # V = Bh + Hh
'YD': 90,
'alpha1': 0.6,
'alpha2': 0.4,
'alpha10': 0.7,
'iota': 4,
'lambda0': 0.635,
'lambda1': 5,
'lambda2': 0.01,
'theta': 0.2,
'G': 20,
'Rbar': 0.025})
for i in xrange(15):
pcex2.solve(iterations=100, threshold=1e-5)
# Introduce the rate shock
pcex2.parameters['Rbar'].value += 0.01
for i in xrange(40):
pcex2.solve(iterations=100, threshold=1e-5)
In [18]:
caption = '''
Figure 4.9 Evolution of GDP, disposable income, consumptiona and wealth,
following an increase of 100 points in the rate of interest on bills, in Model PCEX2
where the propensity to consume reacts negatively to higher interest rates'''
vdata = [s['V'] for s in pcex2.solutions[12:]]
ydata = [s['Y'] for s in pcex2.solutions[12:]]
yddata = [s['YD'] for s in pcex2.solutions[12:]]
cdata = [s['C'] for s in pcex2.solutions[12:]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(80, 116)
axes.plot(ydata, linestyle=':', color='b')
axes.plot(vdata, linestyle='-', color='r')
axes.plot(yddata, linestyle='-.', color='k')
axes.plot(cdata, linestyle='--', color='g')
# add labels
plt.text(15, 112, 'National income (GDP)')
plt.text(15, 101, 'Household wealth')
plt.text(8, 89, 'Disposable')
plt.text(8, 87.5, 'income')
plt.text(12, 84, 'Consumption')
fig.text(0.1, -0.1, caption);
In [19]:
caption = '''
Figure 4.10 Evolution of tax revenues and government expenditures including net
debt servicing, following an increase of 100 points in the rate of interest on bills,
in Model PCEX2 where the propensity to consume reacts negatively to higher
interest rates'''
tdata = list()
sumdata = list()
for i in xrange(12, len(pcex2.solutions)):
s = pcex2.solutions[i]
s_1 = pcex2.solutions[i-1]
sumdata.append( s['G'] + s_1['R']*s_1['Bh'])
tdata.append(s['T'])
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1.1, 1.1])
axes.tick_params(top='off', right='off')
axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.set_ylim(20.5, 23)
axes.plot(sumdata, linestyle='-', color='r')
axes.plot(tdata, linestyle='--', color='k')
# add labels
plt.text(6, 22.9, 'Government expenditures plus net debt service')
plt.text(15, 22, 'Tax revenues')
fig.text(0.1, -0.15, caption);
In [ ]: