Skip to content

Commit b2e60e2

Browse files
committed
Initial upload.
0 parents  commit b2e60e2

10 files changed

+3032
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
code/modeling_language
2+
*.pyc
3+
*.pdf
4+
*.xlsx
5+
*.svg
6+
*.png
7+
*ipynb_checkpoints*

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
This code replicates the graphs from the paper *Managing Capital Outflows: The Role of Foreign. Exchange Intervention.* by Suman S. Basu, Atish R. Ghosh, Jonathan D. Ostry and Pablo E. Winant.
2+
3+
The code requires Python 3.6 and depends on two libraries:
4+
5+
- [dolo](https://github.com/EconForge/dolo)
6+
- [backtothetrees](https://github.com/albop/backtothetrees)
7+
8+
An up-to-date version of the code can be found on [github](https://github.com/albop/managing_capital_outflows_with_limited_reserves
9+
10+
11+
To generate the results run:
12+
13+
- `python compute_simulations.py` : creates files with various simulation results
14+
- `precomputed_decision_rules.pickle`
15+
- `precomputed_moving_target.pickle`
16+
- `precomputed_simulations.pickle`
17+
18+
- `python compute_welfares.py`: create welfare comparison files:
19+
- `simple_rules_welfare.xlsx` (p=1.0)
20+
- `simple_rules_welfare_9.xlsx` (p=0.9)
21+
- `simple_rules_welfare_8.xlsx` (p=0.8)
22+
23+
24+
The graphs are then created in the notebooke `gen_graphs.ipynb` which can be opened and run using Jupyter.

calibrations.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
import copy
3+
from collections import OrderedDict
4+
5+
params = dict(
6+
beta=0.8/(0.8+0.15),
7+
a=0.8,
8+
c=0.15,
9+
estar=-0.0,
10+
Rbar=0.5,
11+
min_f=0,
12+
kappa=1.0,
13+
N=40,
14+
zbar=0.1,
15+
p=1,
16+
model='optimal'
17+
)
18+
19+
20+
reserve_levels = [0.01, 0.5, 1.0, 1.5, 2.0, 3.0]
21+
policies = ['volume','peg','optimal','time-consistent']
22+
cases = {
23+
'baseline': {},
24+
'accumulation': {'min_f': -10000},
25+
'low_beta': {'beta': 0.8},
26+
'high_beta': {'beta': 0.9},
27+
'super_low_a': {'a': 0.01},
28+
'low_a': {'a': 0.4},
29+
'high_a': {'a': 1.6},
30+
'low_c': {'c': 0.075},
31+
'high_c': {'c': 0.30},
32+
'p_8': {'p': 0.8},
33+
'p_85': {'p': 0.85},
34+
'p_9': {'p': 0.9},
35+
'p_95': {'p': 0.95},
36+
}
37+
38+
list_of_calibrations = OrderedDict()
39+
for case in cases.keys():
40+
for pol in policies:
41+
for r in reserve_levels:
42+
calib = copy.copy(params)
43+
calib.update(cases[case])
44+
calib['Rbar'] = r
45+
calib['model'] = pol
46+
list_of_calibrations[(case,pol,r)] = calib.copy()

compute_alpha.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
######## Solve
2+
import pandas
3+
import numpy
4+
from collections import OrderedDict
5+
# from solution import *
6+
from calibrations import *
7+
from time_consistent import solve as solve_time_consistent
8+
from time_consistent import simulate
9+
from bttt.trees import DeterministicTree, get_ts
10+
from matplotlib import pyplot as plt
11+
from bttt.trees import DeathTree
12+
from bttt.model import import_tree_model
13+
from matplotlib import pyplot as plt
14+
from numpy import *
15+
16+
17+
18+
N = 25
19+
T = 25
20+
21+
22+
calib0 = calib.copy()
23+
beta = calib0['beta']
24+
a = calib0['a']
25+
p = calib0['p']
26+
zbar = calib0['zbar']
27+
max_R=5
28+
29+
30+
tree = DeterministicTree(N)
31+
for s in tree.nodes:
32+
tree.values[s] = zbar
33+
model = import_tree_model('models.yaml', key='stochastic', tree=tree)
34+
35+
def solve_it(**cc):
36+
tree = DeterministicTree(N)
37+
for s in tree.nodes:
38+
tree.values[s] = zbar
39+
model = import_tree_model('models.yaml', key='optimal', tree=tree)
40+
model.calibration.update(cc)
41+
sol = model.solve(verbose=True)
42+
df = numpy.concatenate( [get_ts(tree, sol, varname)[:,None] for varname in ['e','f', 'Gamma']], axis=1 )
43+
df = pandas.DataFrame(df, columns=['e','f','Gamma'])
44+
return df
45+
46+
from collections import OrderedDict
47+
48+
49+
Rvec0 = linspace(0.01, 3.0, 20)
50+
51+
52+
53+
pvec = [0.8, 0.85, 0.9, 0.95, 1.0]
54+
55+
# Unconstrained solutions
56+
57+
unconstrained_sols = OrderedDict()
58+
for p in pvec:
59+
dfs = [solve_it(Rbar=i, min_f=0, p=p) for i in Rvec0]
60+
unconstrained_sols[p] = dfs
61+
62+
all_gammas = OrderedDict()
63+
for p in pvec:
64+
dfs = unconstrained_sols[p]
65+
max_gammas = numpy.array([dfs[i]['Gamma'].max() for i,r in enumerate(Rvec0)])
66+
all_gammas[p] = max_gammas
67+
68+
for p in pvec:
69+
plt.plot(Rvec0, all_gammas[p])
70+
71+
alpha = 0.5
72+
73+
Rlimit = OrderedDict()
74+
75+
for p in pvec:
76+
dfs = unconstrained_sols[p]
77+
max_gammas = numpy.array([dfs[i]['Gamma'].max() for i,r in enumerate(Rvec0)])
78+
j = numpy.where(max_gammas<alpha)[0][0]
79+
a0 = max_gammas[j-1]
80+
a1 = max_gammas[j]
81+
r0 = Rvec0[j-1]
82+
r1 = Rvec0[j]
83+
rmax = r0 + (r1-r0)*(alpha-a0)/(a1-a0)
84+
Rlimit[p] = rmax
85+
86+
# Constrained solutions
87+
88+
R0 = 0.8
89+
90+
constrained_solutions = OrderedDict()
91+
92+
for p in pvec:
93+
Rm = Rlimit[p]
94+
R1 = min([R0, Rm])
95+
if Rm>0:
96+
df = solve_it(p=p, Rbar=R1)
97+
elif Rm<=0:
98+
df = solve_it(p=p, Rbar=0.001)
99+
df['R'] = R0 - df['f'].cumsum().shift()
100+
df['R'][0] = R0
101+
constrained_solutions[p] = df
102+
103+
d = {'dfs':constrained_solutions}
104+
105+
import pickle
106+
with open("precomputed_alpha_p.pickle",'wb') as f:
107+
pickle.dump(d,f)
108+
109+
###
110+
##
111+
###
112+
113+
114+
Rmax = 0.998
115+
nRvec0 = numpy.array([0.01, 0.5, 0.9, Rmax, 2.0, 3.0])
116+
ndfs = [solve_it(Rbar=i, min_f=0) for i in nRvec0]
117+
for i in [4,5]:
118+
df = ndfs[3].copy()
119+
ndfs[i] = df
120+
for i,df in enumerate(ndfs):
121+
df['R'] = nRvec0[i] - df['f'].cumsum()
122+
#
123+
#
124+
# # In[43]:
125+
#
126+
#
127+
# def plot_dfs(dfs, labels):
128+
# attributes = ['b', 'g', 'r']
129+
# if not isinstance(dfs, list):
130+
# dfs = [dfs]
131+
# fig = plt.figure(figsize=(15,10))
132+
# # plt.clear()
133+
# plt.subplot(131)
134+
# plt.plot(dfs[0].index,dfs[0].index*0+0.5,color='black', linestyle='--')
135+
# for i,df in enumerate(dfs):
136+
# plt.plot(df["Gamma"])
137+
#
138+
# plt.grid()
139+
# plt.title("Marginal Value of Intervention")
140+
# # plt.figure()
141+
# plt.subplot(132)
142+
# for i,df in enumerate(dfs):
143+
# plt.plot(df["e"], label=labels[i])
144+
# plt.legend(loc='lower right')
145+
# plt.grid()
146+
# plt.title("Exchange Rate")
147+
# plt.subplot(133)
148+
# for i,df in enumerate(dfs):
149+
# plt.plot(df["R"], label=labels[i])
150+
# plt.grid()
151+
# plt.title("Reserves")
152+
# return fig
153+
#
154+
#
155+
# # In[44]:
156+
157+
158+
import pickle
159+
with open("precomputed_option_value.pickle","wb") as f:
160+
pickle.dump({"commitment":ndfs},f)
161+
162+
#
163+
# # In[82]:
164+
#
165+
#
166+
# f = plot_dfs(ndfs, labels=['$R_0={}$'.format(i) for i in Rvec0])
167+
# plt.savefig("optimal_choice_noconstraint.png", bbox_inches="tight")
168+
# plt.savefig("optimal_choice_noconstraint.pdf", bbox_inches="tight")
169+
# f
170+
#
171+
#
172+
# # In[11]:
173+
#
174+
#
175+
# Rvec0 = linspace(0.3, 3.0, 10)
176+
# dfs = [solve_it(Rbar=i) for i in Rvec0]
177+
#
178+
#
179+
# # In[12]:
180+
#
181+
#
182+
# f = plot_dfs(dfs, labels=['$R_0={}$'.format(i) for i in Rvec0])
183+
# plt.savefig("optimal_choice_constraint.png", bbox_inches="tight")
184+
# plt.savefig("optimal_choice_constraint.pdf", bbox_inches="tight")
185+
# f

0 commit comments

Comments
 (0)