Sovereign credit rating indices #

This category group contains numeric indices of sovereign credit ratings, based on the ratings and outlooks of three large rating agencies. These categories can be used as qualifiers of other indicators, such as external liabilities, in order to adjust them for the credit risk of a currency area or a government. Information on index construction is provided in Appendix 1 .

Foreign currency credit ratings indices #

Ticker : LTFCRATING_NSA

Label : Long-term foreign-currency sovereign credit ratings index

Definition : Long-term foreign-currency sovereign credit index based on ratings and outlooks of three large rating agencies

Notes :

  • The ratings index level is a synthetic value calculated from the weighted average of ratings and outlook data of Fitch, S&P, and Moody’s. The values go from 1 to 23, with a higher value indicating a better credit rating and/or outlook. A single agency’s one-notch upgrade or downgrade is equivalent to a change of 1/3 in the index level. A single agency’s outlook change is equivalent to a change of 1/9 in the index level.

  • The ratings and outlook for most countries are available for their foreign currency debt, but if there are missing datapoints, the local rating is used as a proxy of the rating or outlook to calculate the index level. For details see Appendix 1 .

Local currency credit ratings indices #

Ticker : LTLCRATING_NSA

Label : Long-term local-currency sovereign credit ratings index

Definition : Long-term local-currency sovereign credit index based on ratings and outlooks of three large rating agencies

Notes :

  • The ratings index level is a synthetic value calculated from the weighted average of ratings and outlook data of Fitch, S&P, and Moody’s. The values go from 1 to 23, with a higher value indicating a better credit rating and/or outlook.

Imports #

Only the standard Python data science packages and the specialized macrosynergy package are needed.

import os
import numpy as np
import pandas as pd
import seaborn as sns


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

from macrosynergy.download import JPMaQSDownload

import warnings
warnings.simplefilter("ignore")

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 <category> 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 <info> 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.

Currency areas are identified by currency symbols as explained in Appendix 2

cids_dmca = ['AUD', 'CAD', 'CHF', 'GBP', 'JPY', 'NOK', 'NZD', 'SEK', 'USD']  # DM currency areas
cids_dmec = ['DEM', 'ESP', 'FRF', 'ITL', 'NLG']  # DM euro area countries
cids_latm = ['ARS', 'BRL', 'COP', 'CLP', 'DOP', 'MXN', 'PAB', 'PEN', 'UYU', 'VEF']  # Latam countries
cids_emea = ['AED', 'BHD', 'CZK', 'EGP', 'HUF', 'ILS', 'NGN', 'OMR', 'PLN', 'QAR', 'RON', 'RSD', 'RUB', 'SAR', 'TRY', 'ZAR']  # EMEA countries
cids_emas = ['CNY', 'HKD', 'IDR', 'INR', 'KRW', 'MYR', 'PHP', 'SGD', 'THB', 'TWD']  # EM Asia countries
cids_dm = cids_dmca + cids_dmec
cids_em = cids_latm + cids_emea + cids_emas

cids = sorted(cids_dm + cids_em)
main = ['LTFCRATING_NSA', 'LTLCRATING_NSA']


mark = [
    "FXXR_NSA",
    "LCBIR_NSA", 
    "CDS02YXR_NSA",
    "CDS05YXR_VT10",
    "CDS05YXR_NSA",
    "FXTARGETED_NSA", 
    "FXUNTRADABLE_NSA"
] 

xcats = main + mark
# Download series from J.P. Morgan DataQuery by tickers

start_date = "1990-01-01"
tickers = [cid + "_" + xcat for cid in cids for xcat in xcats]
print(f"Maximum number of tickers is {len(tickers)}")

# Retrieve credentials

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

# Download from DataQuery

with JPMaQSDownload(client_id=client_id, client_secret=client_secret) as downloader:

    df = downloader.download(
        tickers=tickers,
        start_date=start_date,
        metrics=["all"],
        suppress_warning=True,
        show_progress=True,
       
    )
Maximum number of tickers is 450
Downloading data from JPMaQS.
Timestamp UTC:  2024-08-29 16:00:47
Connection successful!
Requesting data: 100%|██████████| 90/90 [00:18<00:00,  4.86it/s]
Downloading data: 100%|██████████| 90/90 [00:33<00:00,  2.69it/s]
Some expressions are missing from the downloaded data. Check logger output for complete list.
572 out of 1800 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. 
1033 out of 9046 dates are missing.

Availability #

msm.missing_in_df(df, xcats=main, cids=cids)
No missing XCATs across DataFrame.
Missing cids for LTFCRATING_NSA:  []
Missing cids for LTLCRATING_NSA:  []
msm.check_availability(df, xcats=main, cids=cids)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/3379710378246fa76bf90f788f4f0dc4e067279caf640da145c4512b0d7ca700.png https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/1e9f0fc0c5f9b2b861c198226e581d33e2e9acb3c9207884b9a753328b07f9c3.png

Blacklisted periods #

Following the Russian invasion of Ukraine in 2022 and international sanctions, the EU announced a ban on providing credit ratings to legal persons, entities, or bodies established in Russia. Following this, the ratings for Russia were withdrawn by rating agencies. Although the most recent ratings are still in the database, they are effectively meaningless due to the lack of ongoing monitoring. For further details, refer to S&P’s announcement . We have blacklisted Russian rating history starting from the date of the invasion.

# For analytical purposes Russia's ratings after 2022 should be blacklisted

current_date = pd.Timestamp('now').strftime('%Y-%m-%d')
rub_na = ["2022-02-24", current_date]

black = {"RUB": rub_na}

df = msm.reduce_df(df, blacklist=black).reset_index(drop=True)

History #

Average ratings differ between developed and emerging countries. The variation in rating values is greater for sovereigns with lower ratings. There are exceptions to developed countries’ high ratings and low variability, such as Italy and Spain, which have suffered several credit rating downgrades since 2000.

msp.view_ranges(df, xcats=main, cids=cids, sort_cids_by='mean', start = '2000-01-01',
               xcat_labels=["Foreign currency ratings index", "Local currency ratings index"])
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/8c8e5a8a78ec1c4cfbc922989ba5e83b94036c895200ab4d42ac7fe819fa887f.png

Rating indices are slow-moving indicators reflecting the gradual nature of changes in a country’s creditworthiness. For many countries, particularly those with stable economies and political systems, there may be little to no change in their credit ratings over extended periods. CHF (Swiss franc) and NOK (Norwegian krone) had no change in their (highest possible) rating since 2000.

msp.view_timelines(
    df,
    xcats=main,
    cids=cids,
    start="2000-01-01",
    title="Foreign currency (blue) and local currency (orange) credit ratings indices",
    title_fontsize=30,
    ncol=4,
    same_y=True,
    size=(12, 7),
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/9dcd2f48b9c60b2ee13e43754946bdec53210c1ca5e6324c211f9a40892b39f7.png

Emerging countries in Latin America (LatAm) and Asia tend to exhibit strong positive correlations in their foreign currency credit ratings. In contrast, the correlation among foreign currency ratings for countries in the EMEA (Europe, Middle East, and Africa) region is mixed.

msp.correl_matrix(df, xcats='LTFCRATING_NSA', 
                  cids=cids_emas, 
                  title = "Correlation matrix of foreign currency ratings index for EM Asia countries",
                  size = (10, 5))
msp.correl_matrix(df, xcats='LTFCRATING_NSA', 
                  cids= list(set(cids_latm) - set(["VEF"])), 
                  title = "Correlation matrix of foreign currency ratings index for EM Latam countries",
                  size = (10, 5))
msp.correl_matrix(df, xcats='LTFCRATING_NSA', 
                  cids= cids_emea, 
                  title = "Correlation matrix of foreign currency ratings index for EMEA countries",
                  size = (10, 5))
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/648e0a0f7596eec5bebf809b9b99802560098bdfc68175807b96e3d02cd45ac6.png https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/88df3ae64a393cd7ab9c3f73980bf33b4454ace72fec3e98061647660b03531d.png https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/4bffee14792cbad81e03192a4c82dbad51879622ac168380c5702f30eeb4af78.png

Long-term local currency ratings and long-term foreign currency ratings are strongly, almost perfectly correlated, reflecting their shared but also distinct risk factors. Differences between the two ratings may arise from factors like currency risk, market perceptions, or external shocks, which may impact foreign currency ratings more significantly than local currency ratings.

xcatx = ["LTLCRATING_NSA", "LTFCRATING_NSA"]
cr = msp.CategoryRelations(
    df,
    xcats=xcatx,
    cids=cids,
    freq="M",
    lag=0,
    start="2000-01-01",
    years=None,
    xcat_aggs=["last", "last"],
)
cr.reg_scatter(
    title=f"Long-term local currency and foreign currency ratings, {len(cids)} Countries",
    labels=False,
    coef_box="lower right",
    ylab="Long-term local currency sovereign credit ratings index",
    xlab="Long-term foreign currency sovereign credit ratings index",
    prob_est="map",
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/34cc25f9d1b606e81c6220b66631b554092bbe88ab1028e684744a47bbdd552e.png

Importance #

Over the past 20 years, the influence of credit rating agencies (CRAs) has grown substantially. Credit ratings have become deeply integrated into investment processes, financial contracts, and regulatory frameworks. Ratings play a critical role in guiding investment decisions, determining the terms of financial agreements, and shaping regulatory policies. The reliance on these ratings has expanded the agencies’ impact on global financial markets.

Empirical Clues #

Sovereign rating index and CDS returns #

While the concurrent relation between rating changes and CDS returns has been positive, the subsequent relationship reveals significant payback. This means that the initial positive reaction to long-term foreign currency rating upgrades is typically followed by a negative reaction in the subsequent period and the opposite tends to be the case for downgrades.

xcatx = ["LTFCRATING_NSA", "CDS05YXR_NSA"]
cidx = msm.common_cids(df, xcatx)
start_date = "2000-01-01"

cr_cds = msp.CategoryRelations(
        df,
        xcats=xcatx,
        cids=cidx, 
        freq="q",
        lag=1,
        xcat1_chg="diff",
        xcat_aggs=["mean", "sum"],
        start=start_date,
        xcat_trims=[10, 10]
    )

cr_cds.reg_scatter(
    title=f"Sovereign credit rating changes and subsequent CDS returns, {len(cidx)} EM/DM countries, since 2000",
    xlab="Long-term foreign-currency sovereign credit ratings index, diff q/q",
    ylab="Next quarter's 5-year CDS return, %",
    prob_est="map",
    coef_box="lower right",
    size=(10, 6),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/03964f31114435f9e1ee810a530d57f68294abae5c638c5c044cc91fc5b06e4b.png

Sovereign credit rating indices and FX returns #

dfx=df.copy()


dfb = dfx[dfx["xcat"].isin(["FXTARGETED_NSA", "FXUNTRADABLE_NSA"])].loc[
    :, ["cid", "xcat", "real_date", "value"]
]
dfba = (
    dfb.groupby(["cid", "real_date"])
    .aggregate(value=pd.NamedAgg(column="value", aggfunc="max"))
    .reset_index()
)
dfba["xcat"] = "FXBLACK"
fxblack = msp.make_blacklist(dfba, "FXBLACK")
fxblack
{'BRL': (Timestamp('2012-12-03 00:00:00'), Timestamp('2013-09-30 00:00:00')),
 'CHF': (Timestamp('2011-10-03 00:00:00'), Timestamp('2015-01-30 00:00:00')),
 'CNY': (Timestamp('1999-01-01 00:00:00'), Timestamp('2024-08-28 00:00:00')),
 'CZK': (Timestamp('2014-01-01 00:00:00'), Timestamp('2017-07-31 00:00:00')),
 'HKD': (Timestamp('1999-01-01 00:00:00'), Timestamp('2024-08-28 00:00:00')),
 'ILS': (Timestamp('1999-01-01 00:00:00'), Timestamp('2005-12-30 00:00:00')),
 'INR': (Timestamp('1999-01-01 00:00:00'), Timestamp('2004-12-31 00:00:00')),
 'MYR_1': (Timestamp('1999-01-01 00:00:00'), Timestamp('2007-11-30 00:00:00')),
 'MYR_2': (Timestamp('2018-07-02 00:00:00'), Timestamp('2024-08-28 00:00:00')),
 'PEN': (Timestamp('2021-07-01 00:00:00'), Timestamp('2021-07-30 00:00:00')),
 'RON': (Timestamp('1999-01-01 00:00:00'), Timestamp('2005-11-30 00:00:00')),
 'RUB_1': (Timestamp('1999-01-01 00:00:00'), Timestamp('2005-11-30 00:00:00')),
 'RUB_2': (Timestamp('2022-02-01 00:00:00'), Timestamp('2022-02-23 00:00:00')),
 'SGD': (Timestamp('1999-01-01 00:00:00'), Timestamp('2024-08-28 00:00:00')),
 'THB': (Timestamp('2007-01-01 00:00:00'), Timestamp('2008-11-28 00:00:00')),
 'TRY_1': (Timestamp('1999-01-01 00:00:00'), Timestamp('2003-09-30 00:00:00')),
 'TRY_2': (Timestamp('2020-01-01 00:00:00'), Timestamp('2024-07-31 00:00:00'))}

Higher sovereign credit ratings tend to predict negatively directional FX forward returns for emerging markets, consistent with the idea of credit-related risk premia in FX markets. This applies to both directional FX forward returns and relative returns versus a basket of EM currencies.

xcatx = ["LTFCRATING_NSA", "FXXR_NSA", "FXXR_NSAvEFX"]
cidx =list(set( msm.common_cids(dfx, xcatx)) & set(cids_em))
start_date = "2000-01-01"

cr_fxem = msp.CategoryRelations(
        dfx,
        xcats=["LTFCRATING_NSA", "FXXR_NSA"],
        cids = cidx, 
        freq="q",
        lag=1,
        xcat_aggs=["last", "sum"],
        blacklist=fxblack,
        start=start_date,
    )

cr_rfxem = msp.CategoryRelations(
        dfx,
        xcats=["LTFCRATING_NSA", "FXXR_NSAvEFX"],
        cids = cidx, 
        freq="q",
        lag=1,
        xcat_aggs=["last", "sum"],
        blacklist=fxblack,
        start=start_date,
    )
      
msv.multiple_reg_scatter(
    cat_rels=[cr_fxem] + [cr_rfxem],
    title=f"Sovereign credit rating and subsequent FX returns, {len(cidx)} EMs, since 2000",
    xlab="Long-term foreign-currency sovereign credit ratings index",
    ylab="Next quarter's FX forward return, %",
    ncol=2,
    nrow=1,
    figsize=(15, 7),
    prob_est="map",
    coef_box="lower left",
    subplot_titles=["Directional EM FX forward returns", "Relative EM FX returns versus EM basket"],
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/8ef93fbd52dd18f2b557daac6e6953d0451c8f1c1f9513504dcb5e8e5a0c3365.png

Sovereign rating index and local currency bond index returns #

The risk-premium effect also shows for local-currency bond index returns. Sovereign credit ratings exhibit a strong and significant negative correlation with subsequent directional and relative local emerging markets bond returns on a monthly and quarterly basis.

xcatx = ["LTLCRATING_NSA", "LCBIR_NSA"]
cidx =list(set( msm.common_cids(dfx, xcatx)) & set(cids_em))
start_date = "2000-01-01"

dfa = msp.make_relative_value(
    dfx,
    xcats=["LCBIR_NSA"],
    cids=cidx,
    start="2000-01-01",
    rel_meth="subtract",
    postfix="vEB",
)
dfx = msm.update_df(dfx, dfa)


start_date = "2000-01-01"

cr_demb = msp.CategoryRelations(
        dfx,
        xcats=["LTLCRATING_NSA", "LCBIR_NSA"],
        cids = cidx, 
        freq="m",
        lag=1,
        xcat_aggs=["last", "sum"],
        start=start_date,
    )


cr_remb = msp.CategoryRelations(
        dfx,
        xcats=["LTLCRATING_NSA", "LCBIR_NSAvEB"],
        cids=cidx,
        freq="m",
        lag=1,
        xcat_aggs=["last", "sum"],
        start=start_date,
    )


msv.multiple_reg_scatter(
    cat_rels=[cr_demb] + [cr_remb],
    title=f"Sovereign credit rating and subsequent local bond index returns, {len(cidx)} EMs, since 2000",
    ylab="Next month's local currency bond index (GBI-EM): cash returns, %",
    ncol=2,
    nrow=1,
    figsize=(15, 7),
    prob_est="map",
    coef_box="lower left",
    subplot_titles=["Directional local-currency bond returns, %", "Relative local-currency bond returns, %"],
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/724a4c4ac268790a710c228895b48414d5a046ecf9ddf96afdd21f5fe0eee444.png

Appendix 1: Index levels #

This table maps numerical indices and credit ratings from three major rating agencies: Fitch, Moody’s, and S&P (Standard & Poor’s). “Standardized Rating” aligns these ratings across the different agencies.

Numerical Index

Fitch

Moody’s

S&P

Standardized Rating

23

AAA

Aaa

AAA

AAA

22

AA+

Aa1

AA+

AA+

21

AA

Aa2

AA

AA

20

AA-

Aa3

AA-

AA-

19

A+

A1

A+

A+

18

A

A2

A

A

17

A-

A3

A-

A-

16

BBB+

Baa1

BBB+

BBB+

15

BBB

Baa2

BBB

BBB

14

BBB-

Baa3

BBB-

BBB-

13

BB+

Ba1

BB+

BB+

12

BB

Ba2

BB

BB

11

BB-

Ba3

BB-

BB-

10

B+

B1

B+

B+

9

B

B2

B

B

8

B-

B3

B-

B-

7

CCC+

Caa1

CCC+

CCC+

6

CCC

Caa2

CCC

CCC

5

CCC-

Caa3

CCC-

CCC-

4

CC

CC

CC

3

Ca

CC/C

2

C

C

C

1

RD/D

C

SD/D

RD/D/SD

The formula for the Rating Index is designed to provide a composite score based on both credit ratings and outlooks from three major credit rating agencies: Fitch, Moody’s, and S&P (Standard & Poor’s). The Rating Index combines both the current credit ratings and the forward-looking outlooks to provide a more comprehensive assessment of a credit entity’s creditworthiness. The formula gives more weight to the current ratings than to the outlooks. This reflects the idea that current ratings are more indicative of the present credit status, while outlooks are more speculative.

The formula is structured as follows:

\[\begin{align*} \text{Rating Index} &= \frac{\text{Ratings (Fitch + Moody's + S\&P)}}{3} \\ &+ \frac{\text{Outlook (Fitch + Moody's + S\&P)}}{9} \end{align*}\]

Appendix 2: Currency symbols #

The word ‘cross-section’ refers to currencies, currency areas or economic areas. In alphabetical order, these are

  • AED (Emirates dirham)

  • ARS (Argentine pesos)

  • AUD (Australian dollar)

  • BHD (Bahraini Dinar)

  • BRL (Brazilian real)

  • CAD (Canadian dollar)

  • CHF (Swiss franc)

  • CLP (Chilean peso)

  • CNY (Chinese yuan renminbi)

  • COP (Colombian peso)

  • CZK (Czech Republic koruna)

  • DEM (German mark)

  • DOP (Dominican Peso)

  • EGP (Egyptian Pound)

  • ESP (Spanish peseta)

  • FRF (French franc)

  • GBP (British pound)

  • HKD (Hong Kong dollar)

  • HUF (Hungarian forint)

  • IDR (Indonesian rupiah)

  • ILS (Israeli shekel)

  • INR (Indian rupee)

  • ITL (Italian lira)

  • JPY (Japanese yen)

  • KRW (Korean won)

  • MXN (Mexican peso)

  • MYR (Malaysian ringgit)

  • NGN (Nigerian Naira)

  • NLG (Dutch guilder)

  • NOK (Norwegian krone)

  • NZD (New Zealand dollar)

  • OMR (Omani Rial)

  • QAR (Qatari Riyal)

  • PAB (Panamanian balboa)

  • PEN (Peruvian sol)

  • PHP (Philipine peso)

  • PLN (Polish zloty)

  • QAR (Qatari riyal)

  • RON (Romanian leu)

  • RSD (Serbian Dinar)

  • RUB (Russian ruble)

  • SEK (Swedish krona)

  • SAR (Saudi riyal)

  • SGD (Singaporean dollar)

  • THB (Thai baht)

  • TRY (Turkish lira)

  • TWD (Taiwanese dollar)

  • UYU (Peso Uruguayo)

  • USD (U.S. dollar)

  • VEF (Venezuelan bolívar)

  • ZAR (South African rand).