[1]
import numpy as np
import pandas as pd
import pandas_datareader
from types import SimpleNamespace
%load_ext autoreload
%autoreload 2

%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')

# Import additional libraries: 

1. Regional CO2_2 emissions

In this exercise, we will investigate the development in CO2 emissions relative to GDP across the world. For this purpose, we apply data obtained from the World Bank Indicators.

You will need to use the following data sets for the period 1990-2016: 1. EN.ATM.CO2E.KT : CO2 emissions in kilotons. WB link 2. NY.GDP.MKTP.PP.KD : GDP, PPP-corrected in constant 2017 international dollars WB link 3. SP.POP.TOTL : total population WB link 4. country_region.xlsx : key between country names and world regions

Data sets 1-3 contain annual records for all the world's countries plus a large set of country aggregates. You can download each data_set using the following API call

[2]
from pandas_datareader import wb
df = wb.download(indicator=data_set, country=[], start=1990, end=2016)

Notes: The data set country_region.xlsx is available together with this notebook.
Setting countrty=[] implies getting all countries in a data set by the syntax of the World Bank API.
Follow the links above if there is a problem with the API call and download manually.

Question 1: Data cleaning.

  • Download data sets 1-3. Exclude all entries in the data sets that are not a country listed in country_region.xlsx.
  • Assign a world region to each country in data sets 1-3 using country_region.xlsx.
  • If a data-point in one data set is NaN for country xx in year yy, then delete it together with the corresponding data-points for country xx in year yy in the 2 other data sets.

Check that the resulting number of rows for a dataset containing GDP, population and CO2 is 4660.

Question 2: Regional CO2 emissions. Calculate the regional CO2 emissions per dollar GDP on an annual basis. That is, for region RR in year tt compute

jRCO2j,tjRYj,t\frac{\sum_{j \in R} \text{CO2}_{j,t}}{\sum_{j \in R} Y_{j,t}}

where YjY_{j} denotes the GDP of country jj.

Plot CO2 emissions per dollar GDP for all regions in the way you find most presentable and comment.

Question 3: Growth rates.

  • For each region RR, calculate population weighted average CO2R,t\text{CO2}_{R,t} and GDP pr year. See weighted average definition below.
  • Calculate the annual growth rates of averaged GDP and CO2 for each region.
  • Finally, create one subplot per region containing the two associated growth rates. Make a brief comment. (tip: better use a loop for this instead of code repetition)

The weighted averages of of GDP and CO2 for region RR is obtained by first calculating the weights:

wi,t=POPi,tkRPOPk,tw_{i,t} = \frac{POP_{i,t}}{\sum \limits_{k \in R}POP_{k,t}}

for each country iRi \in R.
Then get average regional GDP by

YˉR,t=iRwi,tYi,t\bar{Y}_{R,t} = \sum \limits_{i \in R}w_{i,t}Y_{i,t}

and similarly for CO2.

The growth rate for regional GDP per capita is then

YˉR,tΔ=YˉR,tYˉR,t11\bar{Y}^{\Delta}_{R,t} = \frac{\bar{Y}_{R,t}}{\bar{Y}_{R,t-1}} - 1

and similarly for regional CO2 pr capita

2. Risky assets

The consumption savings model with uncertainty in both income and interest rate.

A household lives two periods.

In the second period it gets utility from consuming and leaving a bequest,

v2(m2)=maxc2c21ρ1ρ+ν(a2+κ)1ρ1ρs.t.a2=m2c2a20\begin{aligned} v_{2}(m_{2})&= \max_{c_{2}}\frac{c_{2}^{1-\rho}}{1-\rho}+\nu\frac{(a_2+\kappa)^{1-\rho}}{1-\rho}\\ \text{s.t.} \\ a_2 &= m_2-c_2 \\ a_2 &\geq 0 \end{aligned}
  • m2m_2 is cash-on-hand
  • c2c_2 is consumption
  • a2a_2 is end-of-period assets
  • ρ>1\rho > 1 is the risk aversion coefficient
  • ν>0\nu > 0 is the strength of the bequest motive
  • κ>0\kappa > 0 is the degree of luxuriousness in the bequest motive
  • a20a_2\geq0 ensures the household cannot die in debt

The value function vt(mt)v_t(m_t) measures the household's value of having mtm_t at the beginning of period tt.

In the first period, the household gets utility from consuming and takes into account that it will also live in the next-period, where it receives a stochastic income.

We assume that the consumption decision is made at the beginning of the period.

We denote the interest rate on savings from period 1 to 2 by r1,2r_{1,2}. It is assumed to be unknown until the end of the period 1; ie. after the consumption decision is made.

v1(m1)=maxc1c11ρ1ρ+βE1[v2(m2)]s.t.a1=m1c1m2=(1+r1,2)a1+y2r1,2={r0Δrwith prob. 12r0+Δrwith prob. 12y2={1Δywith prob. 121+Δywith prob. 12a10\begin{aligned} v_1(m_1) &= \max_{c_1}\frac{c_{1}^{1-\rho}}{1-\rho}+\beta\mathbb{E}_{1}\left[v_2(m_2)\right]\\&\text{s.t.}&\\ a_1 & = m_1-c_1\\ m_2 &= (1+r_{1,2})a_1+y_2 \\ r_{1,2} &= \begin{cases} r_0 - \Delta^r & \text{with prob. }\frac{1}{2}\\ r_0 + \Delta^r & \text{with prob. }\frac{1}{2} \\ \end{cases}\\ y_{2} &= \begin{cases} 1-\Delta^y & \text{with prob. }\frac{1}{2}\\ 1+\Delta^y & \text{with prob. }\frac{1}{2} \end{cases}\\ a_1 & \geq0 \end{aligned}
  • m1m_1 is cash-on-hand in period 1
  • c1c_1 is consumption in period 1
  • a1a_1 is end-of-period assets in period 1
  • β>0\beta > 0 is the discount factor
  • E1\mathbb{E}_1 is the expectation operator conditional on information in the beginning of period 1
  • y2y_2 is income in period 2
  • Δy(0,1)\Delta^y \in (0,1) is the level of income risk
  • r0r_0 is the expected interest rate
  • Δr(0,r0)\Delta^r \in (0,r_0) is the level of interest rate risk
  • a10a_1\geq0 ensures the household cannot borrow
[1]
# Parameters
rho = 8
kappa = 0.5
nu = 0.2
r0 = 0.3
Delta_r = 0.29
Delta_y = 0.5
beta = 0.98

Note: r0r_0 and Δr\Delta^r are somewhat extreme - that is just for exposition.

Question 1: Solve the model for both periods and obtain value functions v1(m1),v2(m2)v_1(m_1), v_2(m_2) together with the optimal consumption functions c1(m1),c2(m2)c^*_1(m_1), c^*_2(m_2).
Plot v1(m1),v2(m2)v_1(m_1), v_2(m_2) in one graph and c1(m1),c2(m2)c^*_1(m_1), c^*_2(m_2) in another.

Question 2: Now set Δr=0\Delta^r = 0 and solve the model once again. Plot the associated c1(m1),c2(m2)c^*_1(m_1), c^*_2(m_2) and compare them with the consumption functions from the solution in Question 1.

Question 3 Question 3 below has 2 options. You can freely choose which one you want to answer. (You can of course answer both if you like).

Question 3 - option 1: Simulate the period 2 choices of NN households both for the case where Δr=0.29\Delta^r=0.29 and where Δr=0\Delta^r=0.
You can use the same distribution of m1m_1 for both cases as specified below.
Plot the two distributions of c1c_1 and comment. Optionally, you can also inspect the two distributions of c2c_2 and check that you understand their shapes.

[ ]
np.random.seed(2021)
simN = 50000
sim_m1 = np.fmax(np.random.normal(1, 0.05, size = simN), 0)

Question 3 - option 2: Generalizing the set of possible interest rate outcomes.
We now consider the case where the interest rate has N=2nN = 2n different possible realizations.
Specifically, rr has nn possible outcomes higher than r0r_0, and nn outcomes lower than r0r_0, which are uniformly distributed:

r={r0nΔrwith prob. 1Nr0(n1)Δrwith prob. 1Nr0(n2)Δrwith prob. 1Nr0Δrwith prob. 1Nr0+Δrwith prob. 1Nr0+(n1)Δrwith prob. 1Nr0+nΔrwith prob. 1N\begin{aligned} r &= \begin{cases} r_0 - n\Delta^r & \text{with prob. }\frac{1}{N}\\ r_0 - (n-1)\Delta^r & \text{with prob. }\frac{1}{N}\\ r_0 - (n-2)\Delta^r & \text{with prob. }\frac{1}{N}\\ \vdots & \\ r_0 - \Delta^r & \text{with prob. }\frac{1}{N}\\ r_0 + \Delta^r & \text{with prob. }\frac{1}{N}\\ \vdots & \\ r_0 + (n-1)\Delta^r & \text{with prob. }\frac{1}{N} \\ r_0 + n\Delta^r & \text{with prob. }\frac{1}{N} \\ \end{cases}\\ \end{aligned}

Implement this generalized specification in code.
Test the model on the parameterization below and plot c1(m1),c2(m2)c^*_1(m_1), c^*_2(m_2).

[11]
# New parameters:
r0 = 0.3
Delta_r = 0.05
n = 5
N = 2*5
# Remaining parameters are the same as in Question 1

3. Interpolation by polynomial

We can use interpolation when dealing with some function ff that is very heavy to calculate. That is, we have a large set of points X={xi}i=1NX = \{x_i\}_{i=1}^{N} on which we want to know the function value f(xi)f(x_i), but we might not have sufficiently computing power for it.

Therefore, we take out a subset ZXZ \subset X and calulate ff on the elements of ZZ. Whenever we want to know f(x)f(x) for some xXx\in X that is not also in our pre-computation set ZZ, we use interpolation between neighboring points to xx in ZZ for which the function value has been calculated. To get an estimate of f(x)f(x), we then interpolate between these pre-calculated neighboring points.

In lecture 11, we saw how to write up a linear interpolation between a set of pre-calculated function values.

In the current exercise, we will use a polynomial to interpolate between pre-calculated data points.

(Note: the type of interpolation we consider below is only practical in a modified version. It is useful as an introduction, however.)

Polynomial interpolation
Assume we have a set of data points D={(yi,xi)}i=1nD = \{(y_i,x_i)\}_{i=1}^{n}.

We now want to create a polynomial pp of degree n1n-1 such that yi=p(xi)y_i = p(x_i) exactly for all xi,yiDx_i,y_i \in D.

We can obtain such a polynomial pp by the following steps:

KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ p(x) & = \sum…

Example
Say we have the function f(x)=x21f(x) = x^2 - 1. We can then construct our set of data points DD.
To do so, we evaluate ff in the points {1,3,5}\{1, 3, 5\}:

  • f(1)=0f(1) = 0
  • f(3)=8f(3) = 8
  • f(5)=24f(5) = 24

Thus we have D={(0,1),(8,3),(24,5)}D = \{(0,1), (8,3), (24,5)\}

Interpolating our function f(x)=x21f(x) = x^2 - 1 at some x^[1,5]\hat{x} \in [1,5] is then given by

p(x^)=0×l1(x^)+3×l2(x^)+5×l3(x^)p(\hat{x}) = 0 \times l_1(\hat{x}) + 3 \times l_2(\hat{x}) + 5 \times l_3 (\hat{x})
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ l_1(\hat{x}) …

Algorithm
First evaluate the function ff on the set of points XX so as to obtain the associated function values YY. Then follow the pseudo-code below.

Question 1: Implement the algorithm to interpolate function values of ff to the point x^\hat{x}

[15]
def polynomial_interpol(x, X, Y):
    pass

You can test your polynomial_interpol on the function f(x)=x3f(x) = x^3

[ ]
f = lambda x: x**3

X1 = np.array([1, 2, 2.5, 4])
X2 = np.array([0.5, 2.2, 7, 12.9])

Y1 = f(X1)
Y2 = f(X2)

x = 3.2 

# Note: the result should be the same in both cases below 
y1_interpol = polynomial_interpol(x, X1, Y1)
print(f'f(x) = {f(x): .7f}  interpolated y = {y1_interpol: .7f}')

y2_interpol = polynomial_interpol(x, X2, Y2)
print(f'f(x) = {f(x): .7f}  interpolated y = {y2_interpol: .7f}')