External Debt Vulnerability Dashboard #

Get packages and JPMaQS data #

This notebook primarily relies on the standard packages available in the Python data science stack. However, there is an additional package, macrosynergy that is required for two purposes:

  • Downloading JPMaQS data: The macrosynergy package facilitates the retrieval of JPMaQS data, which is used in the notebook.

  • For the analysis of quantamental data and value propositions: The macrosynergy package provides functionality for performing quick analyses of quantamental data and exploring value propositions.

For detailed information and a comprehensive understanding of the macrosynergy package and its functionalities, please refer to the “Introduction to Macrosynergy package” notebook on the Macrosynergy Quantamental Academy or visit the following link on Kaggle .

# Run only if needed!
"""
%%capture
! pip install macrosynergy --upgrade"""
'\n%%capture\n! pip install macrosynergy --upgrade'
import numpy as np
import pandas as pd
from pandas import Timestamp
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.colors import LinearSegmentedColormap
import seaborn as sns
import os

import macrosynergy.management as msm
import macrosynergy.panel as msp
import macrosynergy.signal as mss
import macrosynergy.pnl as msn

from macrosynergy.download import JPMaQSDownload
pd.set_option('display.width', 400)
import warnings

warnings.simplefilter("ignore")
C:\Users\GlennRegis\AppData\Roaming\Python\Python38\site-packages\pandas\core\computation\expressions.py:21: UserWarning: Pandas requires version '2.7.3' or newer of 'numexpr' (version '2.7.1' currently installed).
  from pandas.core.computation.check import NUMEXPR_INSTALLED

Framework #

We create a dashboard which shows z-scored Macrosynergy indicators as of the latest trading date in a heatmap. We choose the indicators that we believe have the largest effect on CDS returns. The indicators we choose are:

  • external debt (GGIEDGDP_NSA)

  • Fiscal ratios: General government debt and deficit ratios Net investment ratios: Net international investment and international liability ratios Balance of payment ratios: External balance ratios (current and basic external)

Literature #

External balance: The current account balance comprises external goods and services trade balances, net factor income, and net transfer payments (such as foreign aid). A positive balance means a positive net demand for the domestic currency related to these transactions.

Therefore we would expect to find a positive relationship between external balance and CDS returns.

Bank of International Settlements

Overall balance: the lower the overall balance, the higher the governments costs, including interest rate expenditures. Therefore, the lower the balance, the higher the likelyhood of fiscal difficulties. So we would expect there to be a positive relationship between overall balance and CDS returns.

The higher the external debt, the more difficult it is for a country to pay its coupons if its currency depreciates. Therefore, the higher the external debt, the more vulnerable a country is to such shocks. We would expect therefore external debt to be negatively correlated with CDS returns.

Respectively, the NIIP provides an aggregate view of the net financial position (assets minus liabilities) of a country via-à-vis the rest of the world. The higher the assets, the lower the country’s vulnerability to the rest of the world. So we would expect high NIIP to be correlated positively to CDS returns.

Methodology #

Once the z-scores are built, we show an initial heatmap of those, windsorised at 3 standard deviations.

Subsequently, we study the actual correlations of our end of month indicator values with end of month government bond returns throughout the whole history. Once we have these correlations, we apply a sign adjustment to the z-scores. If we expect a negative relationship, as per the literature above, with the returns, we will apply a negative sign and viceversa.

The final heatmap will show the sign-adjusted heatmap.

We also build a composite in the following way:

Government funding needs: - 50% Government borrowing requirements/ Net borrowing requirement ratios: GNBRGDP_NSA - 50% General government finance ratios/ General government balance ratios: GGOBGDPRATIO_NSA / GGSBGDPRATIO_NSA

Government debt burden: - 50% General government finance ratios/ General government debt ratios: GGDGDPRATIO_NSA / GGNDGDPRATIO_NSA - 50% Government debt sustainability/ Extrapolated debt ratio in 10 years: GGDGDPRATIOX10_NSA

External debt burden - 25% External and foreign-currency debt/ All issuers external debt to GDP ratio: ALLIEDGDP_NSA - 25% Foreign-currency debt securities/ All issuers foreign-currency debt securities: ALLIFGDSGDP_NSA - 25% International investment position/ Net international investment position as % of GDP: NIIPGDP_NSA - 25% International investment position/ International liabilities as % of GDP: IIPLIABGDP_NSA

Government & external funding costs

- 25% Real interest rates/ Real short-term interest rates: RIR_NSA
- 25% Real interest rates/ Longer-term real IRS yields: RYLDIRS02Y_NSA / RYLDIRS05Y_NSA
- 50% Sovereign CDS spreads and carry/ Sovereign CDS spreads: CDS05YSPRD_NSA

Growth-inflation tradeoff - 50% GDP growth/ Excess intuitive growth: INTRGDPv5Y_NSA_P1M1ML12_3MMA - 50% Consumer price inflation trends/ Annual headline consumer price inflation: CPIH_SA_P1M1ML12 - 2

# Bond-specific cross-sections

cids_dmea = ["FRF", "DEM", "ITL", "ESP", "EUR"]

cids_dmxe = [ "CHF", "GBP", "JPY", "SEK","USD"]

cids_dm = cids_dmea + cids_dmxe
cids_g10 = ["AUD", "DEM", "FRF", "ESP", "ITL", "JPY", "NZD", "GBP", "USD"]

cids_latm = ["BRL", "CLP", "COP", "MXN", "PEN" ]  # Latam sovereigns
cids_emea = ["CZK",
"HUF",
"ILS",
"PLN",
    "RON",
    "ZAR",
    "TRY",
]  # EMEA sovereigns
cids_emas = [
   
    "CNY",
    "IDR",
    "KRW",
    "MYR",
    "PHP",
    "THB",
]  # EM Asia sovereigns

cids_ea = ["DEM", "FRF", "ESP", "ITL"]  # major Euro currencies before EUR


cids_em = cids_emea + cids_latm + cids_emas
cids = cids_dm + cids_em
cat_mapping = {
    'GGDGDPRATIOX10_NSA': 'Debt in 10 years',
    'GGDGDPRATIOX10_NSA_ZN': 'Debt in 10 years zn',
    'GGNDGDPRATIO_NSA': 'Net Debt',
    'GGNDGDPRATIO_NSA_ZN': 'Net Debt zn',
    'ALLIEDGDP_NSA': 'External debt all issuers',
    'ALLIEDGDP_NSA_ZN': 'External debt all issuers zn',
    'ALLIFCDSGDP_NSA': 'Foreign currency debt all issuers',
    'ALLIFCDSGDP_NSA_ZN': 'Foreign currency debt all issuers zn',
    'GGIEDGDP_NSA': 'External debt',
    'GGIEDGDP_NSA_ZN': 'External debt zn',
    'NIIPGDP_NSA': 'Net International Investment Position',
    'NIIPGDP_NSA_ZN': 'Net International Investment Position zn',
    'IIPLIABGDP_NSA': 'International Investment Position',
    'IIPLIABGDP_NSA_ZN': 'International Investment Position zn',
    'CABGDPRATIO_NSA_12MMA': 'External balance',
    'CABGDPRATIO_NSA_12MMA_ZN': 'External balance zn',    
    'CPIH_SA_P1M1ML12_ZN': 'CPI zn',
    'CPIH_SA_P1M1ML12': 'CPI',
    'INFE1Y_JA_ZN': 'Inflation expectations zn',
    'INFE1Y_JA': 'Inflation expectations',
    'RGDP_SA_P1Q1QL1AR_ZN': 'Real GDP zn',
    'INTRGDP_NSA_P1M1ML12_3MMA_ZN': 'Intuitive GDP zn',
    'INTRGDP_NSA_P1M1ML12_3MMA': 'Intuitive GDP',
    'INTRGDPv5Y_NSA_P1M1ML12_3MMA': 'Excess Intuitive GDP',
    'INTRGDPv5Y_NSA_P1M1ML12_3MMA_ZN': 'Excess Intuitive GDP zn',
    'WAGES_NSA_P1M1ML12_ZN': 'Wages zn',
    'GGOBGDPRATIO_NSA_ZN' : 'Overall Balance zn',
    'GGOBGDPRATIO_NSA' : 'Overall Balance',
    'GGPBGDPRATIO_NSA_ZN': 'Primary Balance zn',
    'GGPBGDPRATIO_NSA': 'Primary Balance', 
    'GNBRGDP_NSA_ZN': 'Net Borrowing Requirements zn',
    'GNBRGDP_NSA': 'Net Borrowing Requirements',    
    'XGGPBGDPRATIO_NSA_ZN': 'Excess Primary Balance zn',
    'CRESFXGDP_NSA_D1M1ML1_ZN': 'Currency Reserves zn',
    'RIR_NSA': 'Real interest rate',
    'RIR_NSA_ZN': 'Real interest rate zn',
    'RYLDIRS05Y_NSA' : 'Long term real rate',
    'RYLDIRS05Y_NSA_ZN': 'Long term real rate zn',
    'DU02YETP_NSA_ZN': 'Duration term premia 2-year zn',
    'CDS02YXRxEASD_NSA_ZN': '2 year CDS return volatility zn',
    'DU02YXRxEASD_NSA_ZN': '2 year swap volatility zn',
    'EQXRxEASD_NSA_ZN': 'Equity return volatility zn',
    'GB10YXRxEASD_NSA_ZN': 'Government Bond Return Volatility zn',
    'CDS05YSPRD_NSA' : '5-year CDS spreads ',
    'CDS05YSPRD_NSA_ZN': '5-year CDS spreads zn',
    'DU05YXR_NSA': '5-year swap returns',
    'GB05YR_NSA': '5-year govy returns',
    'CDS05YXR_NSA': '5-year CDS returns'
}


macro_mapping = [
    'Inflation expectations zn',
#     'Effective inflation',
#    'Real GDP zn',
    'Intuitive GDP zn',
#     'Wages',
]

fiscal_mapping = [
    'External debt zn',
    'International Investment Position zn',
    'External balance zn',
#     'Current Account Balance', 
#     'Primary Balance zn',
     'Overall Balance zn',
#     'Net Borrowing Requirements',
#    'Net Borrowing Requirements zn',
#     'Excess Primary Balance',
#     'Net international investment position',
]

composite_list = []

The description of each JPMaQS category is available under Macro quantamental academy , or JPMorgan Markets (password protected). For tickers used in this notebook see Government debt sustainability , Sovereign CDS returns , Equity index future returns , and Government bond returns

# Category tickers  

ex_d = ['GGIEDGDP_NSA', 'ALLIEDGDP_NSA', 'ALLIFCDSGDP_NSA']
debt = ['GGNDGDPRATIO_NSA', 'GGDGDPRATIOX10_NSA']
π = ['INFE1Y_JA', 'CPIH_SA_P1M1ML12'] # 'CPIH_SA_P1M1ML12', 
gdp = ['INTRGDP_NSA_P1M1ML12_3MMA', 'INTRGDPv5Y_NSA_P1M1ML12_3MMA']
wages = ['WAGES_NSA_P1M1ML12']
ex_bal = ['CABGDPRATIO_NSA_12MMA']
gov_ob = ['GGOBGDPRATIO_NSA']
bor_reqs = ['GNBRGDP_NSA']
xpb = ['XGGPBGDPRATIO_NSA']
nip = ['NIIPGDP_NSA', 'IIPLIABGDP_NSA']
mp = ['CRESFXGDP_NSA_D1M1ML1']
rir = ['RIR_NSA', 'RYLDIRS05Y_NSA']
cds = ['CDS05YSPRD_NSA']
tp = ['DU02YETP_NSA']

macro = π + gdp# + wages
fiscal = ex_d + ex_bal + gov_ob + nip +  bor_reqs + debt   #gov_ob +# + xpb + nip ex_bal
price = rir + cds
#mon_pol = mp + rir + tp
#vol = cds_vol + dur_vol + eq_vol + gb_vol + cds

main = fiscal + macro + price

# Target returns

rets = ['CDS05YXR_NSA']

# Tickers

xcats = main + rets

tickers = [cid + "_" + xcat for cid in cids for xcat in xcats]
print(f"Maximum number of tickers is {len(tickers)}")
print(tickers)
Maximum number of tickers is 504
['FRF_GGIEDGDP_NSA', 'FRF_ALLIEDGDP_NSA', 'FRF_ALLIFCDSGDP_NSA', 'FRF_CABGDPRATIO_NSA_12MMA', 'FRF_GGOBGDPRATIO_NSA', 'FRF_NIIPGDP_NSA', 'FRF_IIPLIABGDP_NSA', 'FRF_GNBRGDP_NSA', 'FRF_GGNDGDPRATIO_NSA', 'FRF_GGDGDPRATIOX10_NSA', 'FRF_INFE1Y_JA', 'FRF_CPIH_SA_P1M1ML12', 'FRF_INTRGDP_NSA_P1M1ML12_3MMA', 'FRF_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'FRF_RIR_NSA', 'FRF_RYLDIRS05Y_NSA', 'FRF_CDS05YSPRD_NSA', 'FRF_CDS05YXR_NSA', 'DEM_GGIEDGDP_NSA', 'DEM_ALLIEDGDP_NSA', 'DEM_ALLIFCDSGDP_NSA', 'DEM_CABGDPRATIO_NSA_12MMA', 'DEM_GGOBGDPRATIO_NSA', 'DEM_NIIPGDP_NSA', 'DEM_IIPLIABGDP_NSA', 'DEM_GNBRGDP_NSA', 'DEM_GGNDGDPRATIO_NSA', 'DEM_GGDGDPRATIOX10_NSA', 'DEM_INFE1Y_JA', 'DEM_CPIH_SA_P1M1ML12', 'DEM_INTRGDP_NSA_P1M1ML12_3MMA', 'DEM_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'DEM_RIR_NSA', 'DEM_RYLDIRS05Y_NSA', 'DEM_CDS05YSPRD_NSA', 'DEM_CDS05YXR_NSA', 'ITL_GGIEDGDP_NSA', 'ITL_ALLIEDGDP_NSA', 'ITL_ALLIFCDSGDP_NSA', 'ITL_CABGDPRATIO_NSA_12MMA', 'ITL_GGOBGDPRATIO_NSA', 'ITL_NIIPGDP_NSA', 'ITL_IIPLIABGDP_NSA', 'ITL_GNBRGDP_NSA', 'ITL_GGNDGDPRATIO_NSA', 'ITL_GGDGDPRATIOX10_NSA', 'ITL_INFE1Y_JA', 'ITL_CPIH_SA_P1M1ML12', 'ITL_INTRGDP_NSA_P1M1ML12_3MMA', 'ITL_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'ITL_RIR_NSA', 'ITL_RYLDIRS05Y_NSA', 'ITL_CDS05YSPRD_NSA', 'ITL_CDS05YXR_NSA', 'ESP_GGIEDGDP_NSA', 'ESP_ALLIEDGDP_NSA', 'ESP_ALLIFCDSGDP_NSA', 'ESP_CABGDPRATIO_NSA_12MMA', 'ESP_GGOBGDPRATIO_NSA', 'ESP_NIIPGDP_NSA', 'ESP_IIPLIABGDP_NSA', 'ESP_GNBRGDP_NSA', 'ESP_GGNDGDPRATIO_NSA', 'ESP_GGDGDPRATIOX10_NSA', 'ESP_INFE1Y_JA', 'ESP_CPIH_SA_P1M1ML12', 'ESP_INTRGDP_NSA_P1M1ML12_3MMA', 'ESP_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'ESP_RIR_NSA', 'ESP_RYLDIRS05Y_NSA', 'ESP_CDS05YSPRD_NSA', 'ESP_CDS05YXR_NSA', 'EUR_GGIEDGDP_NSA', 'EUR_ALLIEDGDP_NSA', 'EUR_ALLIFCDSGDP_NSA', 'EUR_CABGDPRATIO_NSA_12MMA', 'EUR_GGOBGDPRATIO_NSA', 'EUR_NIIPGDP_NSA', 'EUR_IIPLIABGDP_NSA', 'EUR_GNBRGDP_NSA', 'EUR_GGNDGDPRATIO_NSA', 'EUR_GGDGDPRATIOX10_NSA', 'EUR_INFE1Y_JA', 'EUR_CPIH_SA_P1M1ML12', 'EUR_INTRGDP_NSA_P1M1ML12_3MMA', 'EUR_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'EUR_RIR_NSA', 'EUR_RYLDIRS05Y_NSA', 'EUR_CDS05YSPRD_NSA', 'EUR_CDS05YXR_NSA', 'CHF_GGIEDGDP_NSA', 'CHF_ALLIEDGDP_NSA', 'CHF_ALLIFCDSGDP_NSA', 'CHF_CABGDPRATIO_NSA_12MMA', 'CHF_GGOBGDPRATIO_NSA', 'CHF_NIIPGDP_NSA', 'CHF_IIPLIABGDP_NSA', 'CHF_GNBRGDP_NSA', 'CHF_GGNDGDPRATIO_NSA', 'CHF_GGDGDPRATIOX10_NSA', 'CHF_INFE1Y_JA', 'CHF_CPIH_SA_P1M1ML12', 'CHF_INTRGDP_NSA_P1M1ML12_3MMA', 'CHF_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'CHF_RIR_NSA', 'CHF_RYLDIRS05Y_NSA', 'CHF_CDS05YSPRD_NSA', 'CHF_CDS05YXR_NSA', 'GBP_GGIEDGDP_NSA', 'GBP_ALLIEDGDP_NSA', 'GBP_ALLIFCDSGDP_NSA', 'GBP_CABGDPRATIO_NSA_12MMA', 'GBP_GGOBGDPRATIO_NSA', 'GBP_NIIPGDP_NSA', 'GBP_IIPLIABGDP_NSA', 'GBP_GNBRGDP_NSA', 'GBP_GGNDGDPRATIO_NSA', 'GBP_GGDGDPRATIOX10_NSA', 'GBP_INFE1Y_JA', 'GBP_CPIH_SA_P1M1ML12', 'GBP_INTRGDP_NSA_P1M1ML12_3MMA', 'GBP_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'GBP_RIR_NSA', 'GBP_RYLDIRS05Y_NSA', 'GBP_CDS05YSPRD_NSA', 'GBP_CDS05YXR_NSA', 'JPY_GGIEDGDP_NSA', 'JPY_ALLIEDGDP_NSA', 'JPY_ALLIFCDSGDP_NSA', 'JPY_CABGDPRATIO_NSA_12MMA', 'JPY_GGOBGDPRATIO_NSA', 'JPY_NIIPGDP_NSA', 'JPY_IIPLIABGDP_NSA', 'JPY_GNBRGDP_NSA', 'JPY_GGNDGDPRATIO_NSA', 'JPY_GGDGDPRATIOX10_NSA', 'JPY_INFE1Y_JA', 'JPY_CPIH_SA_P1M1ML12', 'JPY_INTRGDP_NSA_P1M1ML12_3MMA', 'JPY_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'JPY_RIR_NSA', 'JPY_RYLDIRS05Y_NSA', 'JPY_CDS05YSPRD_NSA', 'JPY_CDS05YXR_NSA', 'SEK_GGIEDGDP_NSA', 'SEK_ALLIEDGDP_NSA', 'SEK_ALLIFCDSGDP_NSA', 'SEK_CABGDPRATIO_NSA_12MMA', 'SEK_GGOBGDPRATIO_NSA', 'SEK_NIIPGDP_NSA', 'SEK_IIPLIABGDP_NSA', 'SEK_GNBRGDP_NSA', 'SEK_GGNDGDPRATIO_NSA', 'SEK_GGDGDPRATIOX10_NSA', 'SEK_INFE1Y_JA', 'SEK_CPIH_SA_P1M1ML12', 'SEK_INTRGDP_NSA_P1M1ML12_3MMA', 'SEK_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'SEK_RIR_NSA', 'SEK_RYLDIRS05Y_NSA', 'SEK_CDS05YSPRD_NSA', 'SEK_CDS05YXR_NSA', 'USD_GGIEDGDP_NSA', 'USD_ALLIEDGDP_NSA', 'USD_ALLIFCDSGDP_NSA', 'USD_CABGDPRATIO_NSA_12MMA', 'USD_GGOBGDPRATIO_NSA', 'USD_NIIPGDP_NSA', 'USD_IIPLIABGDP_NSA', 'USD_GNBRGDP_NSA', 'USD_GGNDGDPRATIO_NSA', 'USD_GGDGDPRATIOX10_NSA', 'USD_INFE1Y_JA', 'USD_CPIH_SA_P1M1ML12', 'USD_INTRGDP_NSA_P1M1ML12_3MMA', 'USD_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'USD_RIR_NSA', 'USD_RYLDIRS05Y_NSA', 'USD_CDS05YSPRD_NSA', 'USD_CDS05YXR_NSA', 'CZK_GGIEDGDP_NSA', 'CZK_ALLIEDGDP_NSA', 'CZK_ALLIFCDSGDP_NSA', 'CZK_CABGDPRATIO_NSA_12MMA', 'CZK_GGOBGDPRATIO_NSA', 'CZK_NIIPGDP_NSA', 'CZK_IIPLIABGDP_NSA', 'CZK_GNBRGDP_NSA', 'CZK_GGNDGDPRATIO_NSA', 'CZK_GGDGDPRATIOX10_NSA', 'CZK_INFE1Y_JA', 'CZK_CPIH_SA_P1M1ML12', 'CZK_INTRGDP_NSA_P1M1ML12_3MMA', 'CZK_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'CZK_RIR_NSA', 'CZK_RYLDIRS05Y_NSA', 'CZK_CDS05YSPRD_NSA', 'CZK_CDS05YXR_NSA', 'HUF_GGIEDGDP_NSA', 'HUF_ALLIEDGDP_NSA', 'HUF_ALLIFCDSGDP_NSA', 'HUF_CABGDPRATIO_NSA_12MMA', 'HUF_GGOBGDPRATIO_NSA', 'HUF_NIIPGDP_NSA', 'HUF_IIPLIABGDP_NSA', 'HUF_GNBRGDP_NSA', 'HUF_GGNDGDPRATIO_NSA', 'HUF_GGDGDPRATIOX10_NSA', 'HUF_INFE1Y_JA', 'HUF_CPIH_SA_P1M1ML12', 'HUF_INTRGDP_NSA_P1M1ML12_3MMA', 'HUF_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'HUF_RIR_NSA', 'HUF_RYLDIRS05Y_NSA', 'HUF_CDS05YSPRD_NSA', 'HUF_CDS05YXR_NSA', 'ILS_GGIEDGDP_NSA', 'ILS_ALLIEDGDP_NSA', 'ILS_ALLIFCDSGDP_NSA', 'ILS_CABGDPRATIO_NSA_12MMA', 'ILS_GGOBGDPRATIO_NSA', 'ILS_NIIPGDP_NSA', 'ILS_IIPLIABGDP_NSA', 'ILS_GNBRGDP_NSA', 'ILS_GGNDGDPRATIO_NSA', 'ILS_GGDGDPRATIOX10_NSA', 'ILS_INFE1Y_JA', 'ILS_CPIH_SA_P1M1ML12', 'ILS_INTRGDP_NSA_P1M1ML12_3MMA', 'ILS_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'ILS_RIR_NSA', 'ILS_RYLDIRS05Y_NSA', 'ILS_CDS05YSPRD_NSA', 'ILS_CDS05YXR_NSA', 'PLN_GGIEDGDP_NSA', 'PLN_ALLIEDGDP_NSA', 'PLN_ALLIFCDSGDP_NSA', 'PLN_CABGDPRATIO_NSA_12MMA', 'PLN_GGOBGDPRATIO_NSA', 'PLN_NIIPGDP_NSA', 'PLN_IIPLIABGDP_NSA', 'PLN_GNBRGDP_NSA', 'PLN_GGNDGDPRATIO_NSA', 'PLN_GGDGDPRATIOX10_NSA', 'PLN_INFE1Y_JA', 'PLN_CPIH_SA_P1M1ML12', 'PLN_INTRGDP_NSA_P1M1ML12_3MMA', 'PLN_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'PLN_RIR_NSA', 'PLN_RYLDIRS05Y_NSA', 'PLN_CDS05YSPRD_NSA', 'PLN_CDS05YXR_NSA', 'RON_GGIEDGDP_NSA', 'RON_ALLIEDGDP_NSA', 'RON_ALLIFCDSGDP_NSA', 'RON_CABGDPRATIO_NSA_12MMA', 'RON_GGOBGDPRATIO_NSA', 'RON_NIIPGDP_NSA', 'RON_IIPLIABGDP_NSA', 'RON_GNBRGDP_NSA', 'RON_GGNDGDPRATIO_NSA', 'RON_GGDGDPRATIOX10_NSA', 'RON_INFE1Y_JA', 'RON_CPIH_SA_P1M1ML12', 'RON_INTRGDP_NSA_P1M1ML12_3MMA', 'RON_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'RON_RIR_NSA', 'RON_RYLDIRS05Y_NSA', 'RON_CDS05YSPRD_NSA', 'RON_CDS05YXR_NSA', 'ZAR_GGIEDGDP_NSA', 'ZAR_ALLIEDGDP_NSA', 'ZAR_ALLIFCDSGDP_NSA', 'ZAR_CABGDPRATIO_NSA_12MMA', 'ZAR_GGOBGDPRATIO_NSA', 'ZAR_NIIPGDP_NSA', 'ZAR_IIPLIABGDP_NSA', 'ZAR_GNBRGDP_NSA', 'ZAR_GGNDGDPRATIO_NSA', 'ZAR_GGDGDPRATIOX10_NSA', 'ZAR_INFE1Y_JA', 'ZAR_CPIH_SA_P1M1ML12', 'ZAR_INTRGDP_NSA_P1M1ML12_3MMA', 'ZAR_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'ZAR_RIR_NSA', 'ZAR_RYLDIRS05Y_NSA', 'ZAR_CDS05YSPRD_NSA', 'ZAR_CDS05YXR_NSA', 'TRY_GGIEDGDP_NSA', 'TRY_ALLIEDGDP_NSA', 'TRY_ALLIFCDSGDP_NSA', 'TRY_CABGDPRATIO_NSA_12MMA', 'TRY_GGOBGDPRATIO_NSA', 'TRY_NIIPGDP_NSA', 'TRY_IIPLIABGDP_NSA', 'TRY_GNBRGDP_NSA', 'TRY_GGNDGDPRATIO_NSA', 'TRY_GGDGDPRATIOX10_NSA', 'TRY_INFE1Y_JA', 'TRY_CPIH_SA_P1M1ML12', 'TRY_INTRGDP_NSA_P1M1ML12_3MMA', 'TRY_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'TRY_RIR_NSA', 'TRY_RYLDIRS05Y_NSA', 'TRY_CDS05YSPRD_NSA', 'TRY_CDS05YXR_NSA', 'BRL_GGIEDGDP_NSA', 'BRL_ALLIEDGDP_NSA', 'BRL_ALLIFCDSGDP_NSA', 'BRL_CABGDPRATIO_NSA_12MMA', 'BRL_GGOBGDPRATIO_NSA', 'BRL_NIIPGDP_NSA', 'BRL_IIPLIABGDP_NSA', 'BRL_GNBRGDP_NSA', 'BRL_GGNDGDPRATIO_NSA', 'BRL_GGDGDPRATIOX10_NSA', 'BRL_INFE1Y_JA', 'BRL_CPIH_SA_P1M1ML12', 'BRL_INTRGDP_NSA_P1M1ML12_3MMA', 'BRL_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'BRL_RIR_NSA', 'BRL_RYLDIRS05Y_NSA', 'BRL_CDS05YSPRD_NSA', 'BRL_CDS05YXR_NSA', 'CLP_GGIEDGDP_NSA', 'CLP_ALLIEDGDP_NSA', 'CLP_ALLIFCDSGDP_NSA', 'CLP_CABGDPRATIO_NSA_12MMA', 'CLP_GGOBGDPRATIO_NSA', 'CLP_NIIPGDP_NSA', 'CLP_IIPLIABGDP_NSA', 'CLP_GNBRGDP_NSA', 'CLP_GGNDGDPRATIO_NSA', 'CLP_GGDGDPRATIOX10_NSA', 'CLP_INFE1Y_JA', 'CLP_CPIH_SA_P1M1ML12', 'CLP_INTRGDP_NSA_P1M1ML12_3MMA', 'CLP_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'CLP_RIR_NSA', 'CLP_RYLDIRS05Y_NSA', 'CLP_CDS05YSPRD_NSA', 'CLP_CDS05YXR_NSA', 'COP_GGIEDGDP_NSA', 'COP_ALLIEDGDP_NSA', 'COP_ALLIFCDSGDP_NSA', 'COP_CABGDPRATIO_NSA_12MMA', 'COP_GGOBGDPRATIO_NSA', 'COP_NIIPGDP_NSA', 'COP_IIPLIABGDP_NSA', 'COP_GNBRGDP_NSA', 'COP_GGNDGDPRATIO_NSA', 'COP_GGDGDPRATIOX10_NSA', 'COP_INFE1Y_JA', 'COP_CPIH_SA_P1M1ML12', 'COP_INTRGDP_NSA_P1M1ML12_3MMA', 'COP_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'COP_RIR_NSA', 'COP_RYLDIRS05Y_NSA', 'COP_CDS05YSPRD_NSA', 'COP_CDS05YXR_NSA', 'MXN_GGIEDGDP_NSA', 'MXN_ALLIEDGDP_NSA', 'MXN_ALLIFCDSGDP_NSA', 'MXN_CABGDPRATIO_NSA_12MMA', 'MXN_GGOBGDPRATIO_NSA', 'MXN_NIIPGDP_NSA', 'MXN_IIPLIABGDP_NSA', 'MXN_GNBRGDP_NSA', 'MXN_GGNDGDPRATIO_NSA', 'MXN_GGDGDPRATIOX10_NSA', 'MXN_INFE1Y_JA', 'MXN_CPIH_SA_P1M1ML12', 'MXN_INTRGDP_NSA_P1M1ML12_3MMA', 'MXN_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'MXN_RIR_NSA', 'MXN_RYLDIRS05Y_NSA', 'MXN_CDS05YSPRD_NSA', 'MXN_CDS05YXR_NSA', 'PEN_GGIEDGDP_NSA', 'PEN_ALLIEDGDP_NSA', 'PEN_ALLIFCDSGDP_NSA', 'PEN_CABGDPRATIO_NSA_12MMA', 'PEN_GGOBGDPRATIO_NSA', 'PEN_NIIPGDP_NSA', 'PEN_IIPLIABGDP_NSA', 'PEN_GNBRGDP_NSA', 'PEN_GGNDGDPRATIO_NSA', 'PEN_GGDGDPRATIOX10_NSA', 'PEN_INFE1Y_JA', 'PEN_CPIH_SA_P1M1ML12', 'PEN_INTRGDP_NSA_P1M1ML12_3MMA', 'PEN_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'PEN_RIR_NSA', 'PEN_RYLDIRS05Y_NSA', 'PEN_CDS05YSPRD_NSA', 'PEN_CDS05YXR_NSA', 'CNY_GGIEDGDP_NSA', 'CNY_ALLIEDGDP_NSA', 'CNY_ALLIFCDSGDP_NSA', 'CNY_CABGDPRATIO_NSA_12MMA', 'CNY_GGOBGDPRATIO_NSA', 'CNY_NIIPGDP_NSA', 'CNY_IIPLIABGDP_NSA', 'CNY_GNBRGDP_NSA', 'CNY_GGNDGDPRATIO_NSA', 'CNY_GGDGDPRATIOX10_NSA', 'CNY_INFE1Y_JA', 'CNY_CPIH_SA_P1M1ML12', 'CNY_INTRGDP_NSA_P1M1ML12_3MMA', 'CNY_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'CNY_RIR_NSA', 'CNY_RYLDIRS05Y_NSA', 'CNY_CDS05YSPRD_NSA', 'CNY_CDS05YXR_NSA', 'IDR_GGIEDGDP_NSA', 'IDR_ALLIEDGDP_NSA', 'IDR_ALLIFCDSGDP_NSA', 'IDR_CABGDPRATIO_NSA_12MMA', 'IDR_GGOBGDPRATIO_NSA', 'IDR_NIIPGDP_NSA', 'IDR_IIPLIABGDP_NSA', 'IDR_GNBRGDP_NSA', 'IDR_GGNDGDPRATIO_NSA', 'IDR_GGDGDPRATIOX10_NSA', 'IDR_INFE1Y_JA', 'IDR_CPIH_SA_P1M1ML12', 'IDR_INTRGDP_NSA_P1M1ML12_3MMA', 'IDR_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'IDR_RIR_NSA', 'IDR_RYLDIRS05Y_NSA', 'IDR_CDS05YSPRD_NSA', 'IDR_CDS05YXR_NSA', 'KRW_GGIEDGDP_NSA', 'KRW_ALLIEDGDP_NSA', 'KRW_ALLIFCDSGDP_NSA', 'KRW_CABGDPRATIO_NSA_12MMA', 'KRW_GGOBGDPRATIO_NSA', 'KRW_NIIPGDP_NSA', 'KRW_IIPLIABGDP_NSA', 'KRW_GNBRGDP_NSA', 'KRW_GGNDGDPRATIO_NSA', 'KRW_GGDGDPRATIOX10_NSA', 'KRW_INFE1Y_JA', 'KRW_CPIH_SA_P1M1ML12', 'KRW_INTRGDP_NSA_P1M1ML12_3MMA', 'KRW_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'KRW_RIR_NSA', 'KRW_RYLDIRS05Y_NSA', 'KRW_CDS05YSPRD_NSA', 'KRW_CDS05YXR_NSA', 'MYR_GGIEDGDP_NSA', 'MYR_ALLIEDGDP_NSA', 'MYR_ALLIFCDSGDP_NSA', 'MYR_CABGDPRATIO_NSA_12MMA', 'MYR_GGOBGDPRATIO_NSA', 'MYR_NIIPGDP_NSA', 'MYR_IIPLIABGDP_NSA', 'MYR_GNBRGDP_NSA', 'MYR_GGNDGDPRATIO_NSA', 'MYR_GGDGDPRATIOX10_NSA', 'MYR_INFE1Y_JA', 'MYR_CPIH_SA_P1M1ML12', 'MYR_INTRGDP_NSA_P1M1ML12_3MMA', 'MYR_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'MYR_RIR_NSA', 'MYR_RYLDIRS05Y_NSA', 'MYR_CDS05YSPRD_NSA', 'MYR_CDS05YXR_NSA', 'PHP_GGIEDGDP_NSA', 'PHP_ALLIEDGDP_NSA', 'PHP_ALLIFCDSGDP_NSA', 'PHP_CABGDPRATIO_NSA_12MMA', 'PHP_GGOBGDPRATIO_NSA', 'PHP_NIIPGDP_NSA', 'PHP_IIPLIABGDP_NSA', 'PHP_GNBRGDP_NSA', 'PHP_GGNDGDPRATIO_NSA', 'PHP_GGDGDPRATIOX10_NSA', 'PHP_INFE1Y_JA', 'PHP_CPIH_SA_P1M1ML12', 'PHP_INTRGDP_NSA_P1M1ML12_3MMA', 'PHP_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'PHP_RIR_NSA', 'PHP_RYLDIRS05Y_NSA', 'PHP_CDS05YSPRD_NSA', 'PHP_CDS05YXR_NSA', 'THB_GGIEDGDP_NSA', 'THB_ALLIEDGDP_NSA', 'THB_ALLIFCDSGDP_NSA', 'THB_CABGDPRATIO_NSA_12MMA', 'THB_GGOBGDPRATIO_NSA', 'THB_NIIPGDP_NSA', 'THB_IIPLIABGDP_NSA', 'THB_GNBRGDP_NSA', 'THB_GGNDGDPRATIO_NSA', 'THB_GGDGDPRATIOX10_NSA', 'THB_INFE1Y_JA', 'THB_CPIH_SA_P1M1ML12', 'THB_INTRGDP_NSA_P1M1ML12_3MMA', 'THB_INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'THB_RIR_NSA', 'THB_RYLDIRS05Y_NSA', 'THB_CDS05YSPRD_NSA', 'THB_CDS05YXR_NSA']
# Download series from J.P. Morgan DataQuery by tickers

client_id: str = os.getenv("DQ_CLIENT_ID")
client_secret: str = os.getenv("DQ_CLIENT_SECRET")

with JPMaQSDownload(client_id=client_id, client_secret=client_secret) as dq:
    df = dq.download(
        tickers=tickers,
        start_date="2000-01-01",
        suppress_warning=True,
        metrics=[
            "value",
        ],
        show_progress=True,
    )
Downloading data from JPMaQS.
Timestamp UTC:  2024-05-07 10:46:39
Connection successful!
Requesting data: 100%|█████████████████████████████████████████████████████████████████| 26/26 [00:05<00:00,  4.66it/s]
Downloading data: 100%|████████████████████████████████████████████████████████████████| 26/26 [00:18<00:00,  1.41it/s]
Some expressions are missing from the downloaded data. Check logger output for complete list.
70 out of 504 expressions are missing. To download the catalogue of all available expressions and filter the unavailable expressions, set `get_catalogue=True` in the call to `JPMaQSDownload.download()`.
Some dates are missing from the downloaded data. 
6354 out of 6354 dates are missing.

The JPMaQS indicators we consider are downloaded using the J.P. Morgan Dataquery API interface within the macrosynergy package. This is done by specifying ticker strings, formed by appending an indicator category code to a currency area code <cross_section>. These constitute the main part of a full quantamental indicator ticker, taking the form DB(JPMAQS,<cross_section>_<category>,<info>) , where denotes the time series of information for the given cross-section and category. The following types of information are available:

value giving the latest available values for the indicator eop_lag referring to days elapsed since the end of the observation period mop_lag referring to the number of days elapsed since the mean observation period grade denoting a grade of the observation, giving a metric of real-time information quality.

After instantiating the JPMaQSDownload class within the macrosynergy.download module, one can use the download(tickers,start_date,metrics) method to easily download the necessary data, where tickers is an array of ticker strings, start_date is the first collection date to be considered and metrics is an array comprising the times series information to be downloaded. For more information see here

dfx = df.copy().sort_values(["cid", "xcat", "real_date"])
dfx.info()
print(dfx['xcat'].unique())
dfx_rets = dfx[dfx['xcat'].isin(rets)]
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2550129 entries, 1473023 to 2550103
Data columns (total 4 columns):
 #   Column     Dtype         
---  ------     -----         
 0   real_date  datetime64[ns]
 1   cid        object        
 2   xcat       object        
 3   value      float64       
dtypes: datetime64[ns](1), float64(1), object(2)
memory usage: 97.3+ MB
['ALLIEDGDP_NSA' 'ALLIFCDSGDP_NSA' 'CABGDPRATIO_NSA_12MMA'
 'CDS05YSPRD_NSA' 'CDS05YXR_NSA' 'CPIH_SA_P1M1ML12' 'GGDGDPRATIOX10_NSA'
 'GGIEDGDP_NSA' 'GGNDGDPRATIO_NSA' 'GGOBGDPRATIO_NSA' 'IIPLIABGDP_NSA'
 'INFE1Y_JA' 'INTRGDP_NSA_P1M1ML12_3MMA' 'INTRGDPv5Y_NSA_P1M1ML12_3MMA'
 'NIIPGDP_NSA' 'RIR_NSA' 'GNBRGDP_NSA' 'RYLDIRS05Y_NSA']

The following cell fills in the Inflation expectation indicator for the primary Eurozone currencies [‘DEM’, ‘ESP’, ‘FRF’, ‘ITL’]. Essentially, it duplicates the EUR values and assigns them to their respective currencies.

cids_ea = ["DEM", "FRF", "ESP", "ITL"]
cidx = cids
# xcatx = ["INFE1Y_JA"]

# calcs = [f"{xc}=  iEUR_{xc} + GGOBGDPRATIO_NSA - GGOBGDPRATIO_NSA" for xc in xcatx]


# dfa = msp.panel_calculator(dfx, calcs=calcs, cids=cidx)
# dfx = msm.update_df(dfx, dfa)

Transformations and checks #

Z-score calculation #

xcatx = main
cidx = cidx

dfcorr = pd.DataFrame(columns=list(dfx.columns))

for xc in xcatx:
    dfaa = msp.make_zn_scores(
        dfx,
        xcat=xc,
        cids=cidx,
        sequential=True,
        min_obs=261 * 5,
        neutral="mean",
        pan_weight=0,
        thresh=3,
        postfix="_ZN",
        est_freq="m",
    )
    dfcorr = msm.update_df(dfcorr, dfaa)

dfx = msm.update_df(dfx, dfcorr)
dfxd = dfx.copy()
main_zn = [x+'_ZN'for x in main] + rets
last_date = pd.Timestamp.today().date() - pd.offsets.BDay(n=1)
dfxd['xcat'] = dfxd['xcat'].map(cat_mapping)
cats = fiscal_mapping
dfxd['xcat'].unique()
array(['External debt all issuers', 'External debt all issuers zn',
       'Foreign currency debt all issuers',
       'Foreign currency debt all issuers zn', 'External balance',
       'External balance zn', '5-year CDS spreads ',
       '5-year CDS spreads zn', '5-year CDS returns', 'CPI', 'CPI zn',
       'Debt in 10 years', 'Debt in 10 years zn', 'External debt',
       'External debt zn', 'Net Debt', 'Net Debt zn', 'Overall Balance',
       'Overall Balance zn', 'Net Borrowing Requirements',
       'Net Borrowing Requirements zn',
       'International Investment Position',
       'International Investment Position zn', 'Inflation expectations',
       'Inflation expectations zn', 'Intuitive GDP', 'Intuitive GDP zn',
       'Excess Intuitive GDP', 'Excess Intuitive GDP zn',
       'Net International Investment Position',
       'Net International Investment Position zn', 'Real interest rate',
       'Real interest rate zn', 'Long term real rate',
       'Long term real rate zn'], dtype=object)
# We split data between developed and emerging markets
dfxd_dm = dfxd[dfxd['cid'].isin(cids_dm)]
dfxd_em = dfxd[dfxd['cid'].isin(cids_em)]

# We create our signals for DM and EM
signals_dm = dfxd_dm.loc[dfxd_dm.xcat.isin(cats) & (dfxd_dm.real_date == last_date)].pivot(index="xcat", columns="cid", values="value").sort_index()
signals_em = dfxd_em.loc[dfxd_em.xcat.isin(cats) & (dfxd_em.real_date == last_date)].pivot(index="xcat", columns="cid", values="value").sort_index()

#print(signals.loc[cids_dm, :].T)
# Prelimiary heatmap NOT adjusted by expected direction. DM
# Create a custom colormap from green to red
colors = ["#d62728",  "white", "#4CBB17"]  # Green to red
n_bins = 20  # Increase this number to have more fine transition in the color
cmap_name = "custom1"
custom_cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N=n_bins)


# coolwarm = plt.cm.get_cmap('coolwarm')
# inverted_coolwarm = mcolors.ListedColormap(coolwarm(np.linspace(1, 0, 256)))
# Plotting the heatmap
plt.figure(figsize=(14, 12))  # Adjust the figure size as necessary
sns.heatmap(signals_em, annot=True, cmap=custom_cmap, center=0)
plt.title('Correlation heatmap of economic indicators - Developed markets')
plt.xticks(rotation=45, ha='right')
plt.show()
https://macrosynergy.com/notebooks.build/dashboards/external-debt-vulnerability-dashboard/_images/c79e1094b7bb696531007ea1398c9a2e2aff295e9b02678228d027b3f82db066.png
# # Prelimiary heatmap NOT adjusted by expected direction. EM

# coolwarm = plt.cm.get_cmap('coolwarm')
# inverted_coolwarm = mcolors.ListedColormap(coolwarm(np.linspace(1, 0, 256)))
# # Plotting the heatmap
# plt.figure(figsize=(14, 12))  # Adjust the figure size as necessary
# sns.heatmap(signals_em, annot=True, cmap=inverted_coolwarm, center=0)
# plt.title('Correlation heatmap of economic indicators - Developed markets')
# plt.xticks(rotation=45, ha='right')
# plt.show()
dfxd['xcat'].unique()
array(['External debt all issuers', 'External debt all issuers zn',
       'Foreign currency debt all issuers',
       'Foreign currency debt all issuers zn', 'External balance',
       'External balance zn', '5-year CDS spreads ',
       '5-year CDS spreads zn', '5-year CDS returns', 'CPI', 'CPI zn',
       'Debt in 10 years', 'Debt in 10 years zn', 'External debt',
       'External debt zn', 'Net Debt', 'Net Debt zn', 'Overall Balance',
       'Overall Balance zn', 'Net Borrowing Requirements',
       'Net Borrowing Requirements zn',
       'International Investment Position',
       'International Investment Position zn', 'Inflation expectations',
       'Inflation expectations zn', 'Intuitive GDP', 'Intuitive GDP zn',
       'Excess Intuitive GDP', 'Excess Intuitive GDP zn',
       'Net International Investment Position',
       'Net International Investment Position zn', 'Real interest rate',
       'Real interest rate zn', 'Long term real rate',
       'Long term real rate zn'], dtype=object)

Calculations for subsequent end of month bond returns #

dfxx = dfxd.copy()

dfxx['real_date'] = pd.to_datetime(dfxx['real_date'])
# We separate returns from the macro data
dfx_rets = dfxx[dfxx['xcat'] == '5-year CDS returns']
dfx_x = dfxx.loc[dfxx.xcat.isin(cats)].reset_index(drop=True)

# Filter DataFrames and calculate sum of returns and end of month values for the macro data
df_eom = dfx_x.groupby(['cid', 'xcat', pd.Grouper(key='real_date', freq='M')]).agg('last').reset_index()
df_sum = dfx_rets.groupby(['cid', 'xcat', pd.Grouper(key='real_date', freq='M')]).agg({'value': 'sum'}).reset_index()
rets = df_sum.copy()
rets['nxt_ret'] = df_sum.groupby(['cid', 'xcat'])['value'].shift(-1).reset_index(drop=True)

# check we're dealing with datetime objects
df_eom['real_date'] = pd.to_datetime(df_eom['real_date'])
rets['real_date'] = pd.to_datetime(rets['real_date'])
# Create new dataframe with all cats needed to calculate correlations
unique_cats = df_eom['xcat'].unique()
rets_exp_list = []
for cat in unique_cats:
    rets_copy = rets.copy()
    rets_copy['xcat'] = cat
    rets_exp_list.append(rets_copy)

rets_exp = pd.concat(rets_exp_list, ignore_index=True)
merged_data = pd.merge(df_eom, rets_exp[['real_date', 'cid', 'xcat', 'nxt_ret']],
                       on=['real_date', 'cid', 'xcat'], how='left').reset_index(drop=True)

merged_data = merged_data.dropna(subset=['value', 'nxt_ret'])

Correlation studies #

# We study the correlations between our indicators and the subsequent month returns
correlation_results = merged_data.groupby(['cid', 'xcat']).apply(
    lambda group: group[['value', 'nxt_ret']].corr().iloc[0, 1]
).reset_index().rename(columns={0: 'correlation'})

# Display the correlation results
correlation_results.sort_values(by=['xcat', 'cid'])
cid xcat correlation
0 BRL External balance zn 0.083196
4 CHF External balance zn 0.046307
7 CLP External balance zn -0.051907
11 CNY External balance zn -0.060393
15 COP External balance zn 0.003703
... ... ... ...
80 SEK Overall Balance zn -0.134080
84 THB Overall Balance zn -0.018022
88 TRY Overall Balance zn 0.011036
92 USD Overall Balance zn -0.074804
96 ZAR Overall Balance zn -0.043991

97 rows × 3 columns

correlation_results.to_clipboard()
# We change the signs so that positive sign in the z-score means positive for returns according to the correlations above
correlation_matrix = correlation_results.pivot(index='xcat', columns='cid', values='correlation')
correlation_matrix = correlation_matrix.reindex_like(signals_em)
signals_em_updated = signals_em.multiply(correlation_matrix.apply(np.sign))
coolwarm = plt.cm.get_cmap('coolwarm')
inverted_coolwarm = mcolors.ListedColormap(coolwarm(np.linspace(1, 0, 256)))
# Plotting the heatmap
plt.figure(figsize=(14, 12))  # Adjust the figure size as necessary
sns.heatmap(signals_em_updated, annot=True, cmap=custom_cmap, center=0)
plt.title('Sign-adjusted heatmap of economic indicators - Developed markets')
plt.xticks(rotation=45, ha='right')
plt.show()
https://macrosynergy.com/notebooks.build/dashboards/external-debt-vulnerability-dashboard/_images/a9f8bb4a37874164fa69d7acc7e3edd4ee99b08b04dd6a2bdf32600b1e7628f7.png

Global Evolution #

#We calculate yearly averages 
dfxd['year'] = dfxd['real_date'].dt.year
yearly_scores = dfxd.groupby(['year', 'cid', 'xcat'], as_index=False).agg(yearly_average=('value', 'mean'))
yearly_scores.to_clipboard()
print(yearly_scores.head())
catx = 'Overall Balance'
dfxy = yearly_scores[yearly_scores['xcat'] == catx].copy()
evolution = dfxy.pivot(index='cid', columns='year', values='yearly_average')
evolution.to_clipboard()
   year  cid                   xcat  yearly_average
0  2000  BRL     5-year CDS returns       -0.002308
1  2000  BRL    5-year CDS spreads         5.390577
2  2000  BRL  5-year CDS spreads zn       -0.843310
3  2000  BRL                    CPI        7.496472
4  2000  BRL                 CPI zn       -0.545558
dfxy.to_clipboard()
# Plotting the heatmap
plt.figure(figsize=(14, 12))  # Adjust the figure size as necessary
sns.heatmap(evolution, annot=True, cmap=custom_cmap, center=0)
plt.title('Overall Balance')
plt.yticks(rotation=45, ha='right')
plt.show()
https://macrosynergy.com/notebooks.build/dashboards/external-debt-vulnerability-dashboard/_images/d605435aa1101557b237e9ada835aacd7cfc9e755b44b971590bea2477694cb9.png

For Debt indicator #

dfd = dfx.copy()
dfd.head()
print(dfd['xcat'].unique())
['ALLIEDGDP_NSA' 'ALLIEDGDP_NSA_ZN' 'ALLIFCDSGDP_NSA' 'ALLIFCDSGDP_NSA_ZN'
 'CABGDPRATIO_NSA_12MMA' 'CABGDPRATIO_NSA_12MMA_ZN' 'CDS05YSPRD_NSA'
 'CDS05YSPRD_NSA_ZN' 'CDS05YXR_NSA' 'CPIH_SA_P1M1ML12'
 'CPIH_SA_P1M1ML12_ZN' 'GGDGDPRATIOX10_NSA' 'GGDGDPRATIOX10_NSA_ZN'
 'GGIEDGDP_NSA' 'GGIEDGDP_NSA_ZN' 'GGNDGDPRATIO_NSA' 'GGNDGDPRATIO_NSA_ZN'
 'GGOBGDPRATIO_NSA' 'GGOBGDPRATIO_NSA_ZN' 'GNBRGDP_NSA' 'GNBRGDP_NSA_ZN'
 'IIPLIABGDP_NSA' 'IIPLIABGDP_NSA_ZN' 'INFE1Y_JA' 'INFE1Y_JA_ZN'
 'INTRGDP_NSA_P1M1ML12_3MMA' 'INTRGDP_NSA_P1M1ML12_3MMA_ZN'
 'INTRGDPv5Y_NSA_P1M1ML12_3MMA' 'INTRGDPv5Y_NSA_P1M1ML12_3MMA_ZN'
 'NIIPGDP_NSA' 'NIIPGDP_NSA_ZN' 'RIR_NSA' 'RIR_NSA_ZN' 'RYLDIRS05Y_NSA'
 'RYLDIRS05Y_NSA_ZN']
cidx = cids

calcs = [
    "FUNDNEEDS_NSA = GNBRGDP_NSA_ZN * 0.5 + GGOBGDPRATIO_NSA_ZN * 0.5 ",
    "DEBT_NSA = GGNDGDPRATIO_NSA_ZN * 0.5 + GGDGDPRATIOX10_NSA_ZN * 0.5 ",
    "EXDEBT_NSA =  0.25 * ALLIEDGDP_NSA_ZN + 0.25 * ALLIFCDSGDP_NSA_ZN + 0.25 * NIIPGDP_NSA_ZN + 0.25 * IIPLIABGDP_NSA_ZN ",
    "FUNDCOSTS_NSA = 0.25 * RIR_NSA_ZN * 0.25 * RYLDIRS05Y_NSA_ZN + 0.5 * CDS05YSPRD_NSA_ZN ",
    "GRINFL_NSA = 0.5 * INTRGDPv5Y_NSA_P1M1ML12_3MMA_ZN + 0.5 * CPIH_SA_P1M1ML12_ZN "
]

dfa = msp.panel_calculator(dfd, calcs=calcs, cids=cidx)
dfd = msm.update_df(dfd, dfa)
dfd['xcat'].unique()
array(['ALLIEDGDP_NSA', 'ALLIEDGDP_NSA_ZN', 'ALLIFCDSGDP_NSA',
       'ALLIFCDSGDP_NSA_ZN', 'CABGDPRATIO_NSA_12MMA',
       'CABGDPRATIO_NSA_12MMA_ZN', 'CDS05YSPRD_NSA', 'CDS05YSPRD_NSA_ZN',
       'CDS05YXR_NSA', 'CPIH_SA_P1M1ML12', 'CPIH_SA_P1M1ML12_ZN',
       'DEBT_NSA', 'EXDEBT_NSA', 'FUNDCOSTS_NSA', 'FUNDNEEDS_NSA',
       'GGDGDPRATIOX10_NSA', 'GGDGDPRATIOX10_NSA_ZN', 'GGIEDGDP_NSA',
       'GGIEDGDP_NSA_ZN', 'GGNDGDPRATIO_NSA', 'GGNDGDPRATIO_NSA_ZN',
       'GGOBGDPRATIO_NSA', 'GGOBGDPRATIO_NSA_ZN', 'GNBRGDP_NSA',
       'GNBRGDP_NSA_ZN', 'GRINFL_NSA', 'IIPLIABGDP_NSA',
       'IIPLIABGDP_NSA_ZN', 'INFE1Y_JA', 'INFE1Y_JA_ZN',
       'INTRGDP_NSA_P1M1ML12_3MMA', 'INTRGDP_NSA_P1M1ML12_3MMA_ZN',
       'INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'INTRGDPv5Y_NSA_P1M1ML12_3MMA_ZN',
       'NIIPGDP_NSA', 'NIIPGDP_NSA_ZN', 'RIR_NSA', 'RIR_NSA_ZN',
       'RYLDIRS05Y_NSA', 'RYLDIRS05Y_NSA_ZN'], dtype=object)
cidx = cids

calcs = [
    "COMP_VULBIL = 0.25 * FUNDNEEDS_NSA + 0.25 * DEBT_NSA + 0.25 * EXDEBT_NSA + 0.25 * FUNDCOSTS_NSA + 0.25 * GRINFL_NSA "
]

dfa = msp.panel_calculator(dfd, calcs=calcs, cids=cidx)
dfd = msm.update_df(dfd, dfa)
xcats_sel = ['COMP_VULBIL']
msp.view_timelines(dfd, xcats=xcats_sel, cids=cids, start='2000-01-01',
title="Composite Vulnerability Indicator", title_adj=0.88, cumsum=False,
ncol=3, same_y=False, size=(12, 7), aspect=1.7)
plt.show()
print("Cumulative returns imply daily rebalancing.")
https://macrosynergy.com/notebooks.build/dashboards/external-debt-vulnerability-dashboard/_images/6080cdf8e5d172c8c91fc85796c5dfef01455a0239ba1fd40a60c643ed393d3c.png
Cumulative returns imply daily rebalancing.