Source code for ogzaf.macro_params
"""
This module uses data from World Bank WDI, World Bank Quarterly Public
Sector Debt (QPSD) database, the IMF, and UN ILO to find values for
parameters for the OG-ZAF model that rely on macro data for calibration.
"""
# imports
from pandas_datareader import wb
import pandas as pd
import numpy as np
import requests
import datetime
import statsmodels.api as sm
from io import StringIO
[docs]
def get_macro_params(
data_start_date=datetime.datetime(1947, 1, 1),
data_end_date=datetime.date.today(),
country_iso="ZAF",
):
"""
Compute values of parameters that are derived from macro data
Args:
data_start_date (datetime): start date for data
data_end_date (datetime): end date for data
country_iso (str): ISO code for country
Returns:
macro_parameters (dict): dictionary of parameter values
"""
# initialize a dictionary of parameters
macro_parameters = {}
# baseline date formatted for World Bank data
baseline_YYYYQ = (
str(data_end_date.year)
+ "Q"
+ str(pd.Timestamp(data_end_date).quarter)
)
"""
Retrieve data from the World Bank World Development Indicators.
"""
# Dictionaries of variables and their corresponding World Bank codes
# Annual data
wb_a_variable_dict = {
"GDP per capita (constant 2015 US$)": "NY.GDP.PCAP.KD",
"Real GDP (constant 2015 US$)": "NY.GDP.MKTP.KD",
"Nominal GDP (current US$)": "NY.GDP.MKTP.CD",
"General government final consumption expenditure (current US$)": "NE.CON.GOVT.CD",
}
# Quarterly data
wb_q_variable_dict = {
"Gross PSD USD - domestic creditors": "DP.DOD.DECD.CR.PS.CD",
"Gross PSD USD - external creditors": "DP.DOD.DECX.CR.PS.CD",
"Gross PSD Gen Gov - percentage of GDP": "DP.DOD.DECT.CR.GG.Z1",
}
try:
# pull series of interest from the WB using pandas_datareader
# Annual data
wb_data_a = wb.download(
indicator=wb_a_variable_dict.values(),
country=country_iso,
start=data_start_date,
end=data_end_date,
)
wb_data_a.rename(
columns=dict((y, x) for x, y in wb_a_variable_dict.items()),
inplace=True,
)
# Quarterly data
wb_data_q = wb.download(
indicator=wb_q_variable_dict.values(),
country=country_iso,
start=data_start_date,
end=data_end_date,
)
wb_data_q.rename(
columns=dict((y, x) for x, y in wb_q_variable_dict.items()),
inplace=True,
)
# Remove the hierarchical index (country and year) of
# wb_data_q and create a single row index using year
wb_data_q = wb_data_q.reset_index()
wb_data_q = wb_data_q.set_index("year")
# Compute macro parameters from WB data
macro_parameters["initial_debt_ratio"] = (
pd.Series(wb_data_q["Gross PSD Gen Gov - percentage of GDP"]).loc[
baseline_YYYYQ
]
) / 100
macro_parameters["initial_foreign_debt_ratio"] = pd.Series(
wb_data_q["Gross PSD USD - external creditors"]
/ (
wb_data_q["Gross PSD USD - domestic creditors"]
+ wb_data_q["Gross PSD USD - external creditors"]
)
).loc[baseline_YYYYQ]
# zeta_D = share of new debt issues from government that are
# purchased by foreigners
macro_parameters["zeta_D"] = [
pd.Series(
wb_data_q["Gross PSD USD - external creditors"]
/ (
wb_data_q["Gross PSD USD - domestic creditors"]
+ wb_data_q["Gross PSD USD - external creditors"]
)
).loc[baseline_YYYYQ]
]
macro_parameters["g_y_annual"] = (
wb_data_a["GDP per capita (constant 2015 US$)"]
.pct_change(-1)
.mean()
)
except:
print("Failed to retrieve data from World Bank")
print("Will not update the following parameters:")
print("[initial_debt_ratio, initial_foreign_debt_ratio, zeta_D, g_y]")
"""
Retrieve labour share data from the United Nations ILOSTAT Data API
(see https://rshiny.ilo.org/dataexplorer9/?lang=en)
"""
target = (
"https://rplumber.ilo.org/data/indicator/"
+ "?id=LAP_2GDP_NOC_RT_A"
+ "&ref_area="
+ str(country_iso)
+ "&timefrom="
+ str(data_start_date.year)
+ "&timeto="
+ str(data_end_date.year)
+ "&type=both&format=.csv"
)
response = requests.get(target)
if response.status_code == 200:
csv_content = StringIO(response.text)
df_temp = pd.read_csv(csv_content)
else:
print(
f"Failed to retrieve data. HTTP status code: {response.status_code}"
)
ilo_data = df_temp[["time", "obs_value"]]
# find gamma, capital's share of income
macro_parameters["gamma"] = [
1
- (
(
ilo_data.loc[
ilo_data["time"] == data_end_date.year, "obs_value"
].squeeze()
)
/ 100
)
]
"""
Calibrate parameters from IMF data
"""
# alpha_T, non-social security benefits as a fraction of GDP
# source: https://data.imf.org/?sk=b052f0f0-c166-43b6-84fa-47cccae3e219&hide_uv=1
macro_parameters["alpha_T"] = [0.041 - 0.0]
# alpha_G, gov't consumption expenditures as a fraction of GDP
# source: https://data.imf.org/?sk=edb0cd70-0af3-40e1-a9c3-bdef83ee4d1e&hide_uv=1
macro_parameters["alpha_G"] = [0.351 - 0.043 - 0.041]
""""
Esimate the discount on sovereign yields relative to private debt
Follow the methodology in Li, Magud, Werner, Witte (2021)
available at:
https://www.imf.org/en/Publications/WP/Issues/2021/06/04/The-Long-Run-Impact-of-Sovereign-Yields-on-Corporate-Yields-in-Emerging-Markets-50224
Steps:
1) Generate modelled corporate yields (corp_yhat) for a range of
sovereign yields (sov_y) using the estimated equation in col 2 of
table 8 (and figure 3). 2) Estimate the OLS using sovereign yields
as the dependent variable
"""
# # estimate r_gov_shift and r_gov_scale
sov_y = np.arange(20, 120) / 10
corp_yhat = 8.199 - (2.975 * sov_y) + (0.478 * sov_y**2)
corp_yhat = sm.add_constant(corp_yhat)
mod = sm.OLS(
sov_y,
corp_yhat,
)
res = mod.fit()
# First term is the constant and needs to be divided by 100 to have
# the correct unit. Second term is the coefficient
macro_parameters["r_gov_shift"] = [(-res.params[0] / 100)]
macro_parameters["r_gov_scale"] = [res.params[1]]
return macro_parameters