Emerging market bond index carry #
The category group features approximate daily carry of two major emerging market indices, the JP Morgan Government Bond Index in local currency, and the EMBI Global (EMBIG), in hard currency.
Local currency bond index carry #
Ticker : LCBICRY_NSA / LCBICRY_VT10
Label : Local currency bond index (GBI-EM): carry / carry for 10% vol target
Definition : Local currency bond index (J.P. Morgan GBI-EM): carry / carry for 10% vol target
Notes :
-
The J.P. Morgan Government Bond Index Emerging Markets (GBI-EM) provides investors with a benchmark that tracks local currency bonds issued by emerging market governments. The GBI-EM closely follows the methodology of JPM’s family of GBI Indices, which are widely used as benchmarks for investing in developed government bond markets. More information on index specifications is presented in Appendix 1 .
-
The level of the index is calculated via the Superbond method, where the level is the yield to maturity of a synthetic bond built by deconstructing and reconstructing the cashflows of the bonds in the index. More information on this methodology can be found here
-
For Chile and Egypt we use the aggregate traded index, due to no data after 2019.
-
We excluded the Dominican Republic and Uruguay for carry calculation due to absence of meaningful daily local funding rates.
-
The Philippines have stale data for the yield index levels in 2024.
-
For volatility targeting positions are scaled to 10% vol target based on historic standard deviation for an exponential moving average with a half-time of 11 days. Positions are rebalanced at the end of each month.
Foreign currency bond index carry #
Ticker : FCBICRY_NSA / FCBICRY_VT10
Label : Foreign-currency bond index (EMBIG): carry / carry for 10% vol target
Definition : Foreign-currency bond index (J.P. Morgan EMBIG): carry / carry for 10% vol target
Notes :
-
The EMBI Global (EMBIG) includes USD-denominated bonds from EM sovereign & quasi-sovereign issuers. The EMBI suite of indices considers US dollar-denominated bonds issued by sovereign and quasi-sovereign EM entities eligible for inclusion. More information on index specifications is presented in Appendix 1 .
-
The level of the index is calculated via the Superbond method, where the level is the yield to maturity of a synthetic bond built by deconstructing and reconstructing the cashflows of the bonds in the index. More information on this methodology can be found here
-
Since Thailand’s data are available until 2004 we excluded the country. Nigeria (NGN) dropped out of the index in 2007 but was included again in 2011.
-
For volatility targeting positions are scaled to 10% vol target based on historic standard deviation for an exponential moving average with a half- time of 11 days. Positions are rebalanced at the end of each month.
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 matplotlib.pyplot as plt
import seaborn as sns
import math
import json
import yaml
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
from timeit import default_timer as timer
from datetime import timedelta, date, datetime
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
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.
cids_lc_latam = [ # Latam local currency debt countries
"BRL",
"CLP",
"COP",
"MXN",
"PEN",
]
cids_lc_emeu = [ # EM Europe local currency debt countries
"CZK",
"HUF",
"PLN",
"RON",
"RUB",
"RSD",
"TRY",
]
cids_lc_meaf = [ # Middle-East and Africa local currency debt countries
"EGP",
"NGN",
"ZAR",
]
cids_lc_asia = [ # Asia local currency debt countries
"CNY",
"IDR",
"MYR",
"PHP",
"THB",
]
cids_lc = sorted(list(set(cids_lc_latam + cids_lc_emeu + cids_lc_meaf + cids_lc_asia)))
cids_fc_latam = [ # Latam foreign currency debt countries
"BRL",
"CLP",
"COP",
"DOP",
"MXN",
"PEN",
"UYU",
]
cids_fc_emeu = [ # EM Europe foreign currency debt countries
"HUF",
"PLN",
"RON",
"RUB",
"RSD",
"TRY",
]
cids_fc_meaf = [ # Middle-East and Africa foreign currency debt countries
"AED",
"BHD",
"EGP",
"NGN",
"OMR",
"QAR",
"ZAR",
]
cids_fc_asia = [ # Asia foreign currency debt countries
"CNY",
"IDR",
"INR",
"PHP",
"SAR",
]
cids_fc = sorted(list(set(cids_fc_latam + cids_fc_emeu + cids_fc_meaf + cids_fc_asia)))
cids = sorted(list(set(cids_lc + cids_fc)))
locs = ["LCBICRY_NSA", "LCBICRY_VT10"]
fors = ["FCBICRY_NSA", "FCBICRY_VT10"]
main = locs + fors
xtra = [
"LCBIR_NSA",
"FCBIR_NSA",
"LCBIXR_VT10",
"FCBIXR_VT10",
"REER_NSA_P1W4WL1",
"NIIPGDP_NSA",
]
xcats = main + xtra
tix_lc = [cid + "_" + xcat for cid in cids_lc for xcat in locs]
tix_fc = [cid + "_" + xcat for cid in cids_fc for xcat in fors]
tix_xtra = [cid + "_" + xcat for cid in cids for xcat in xcats]
tickers = tix_lc + tix_fc + tix_xtra
# Download series from J.P. Morgan DataQuery by tickers
start_date = "2000-01-01"
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:
start = timer()
assert downloader.check_connection()
df = downloader.download(
tickers=tickers,
start_date=start_date,
metrics=["value", "eop_lag", "mop_lag", "grading"],
suppress_warning=True,
)
end = timer()
print("Download time from DQ: " + str(timedelta(seconds=end - start)))
Maximum number of tickers is 370
Downloading data from JPMaQS.
Timestamp UTC: 2024-05-09 12:13:20
Connection successful!
Some expressions are missing from the downloaded data. Check logger output for complete list.
232 out of 1120 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.
6356 out of 6356 dates are missing.
Download time from DQ: 0:00:56.665510
Availability #
dfd = df.copy()
msm.missing_in_df(dfd, xcats=locs, cids=cids_lc)
No missing XCATs across DataFrame.
Missing cids for LCBICRY_NSA: []
Missing cids for LCBICRY_VT10: []
msm.missing_in_df(dfd, xcats=fors, cids=cids_fc)
No missing XCATs across DataFrame.
Missing cids for FCBICRY_NSA: []
Missing cids for FCBICRY_VT10: []
cids_exp = cids
msm.check_availability(dfd, xcats=main, cids=cids_exp)
Blacklisted periods #
Following the Russian invasion of Ukraine and internation sanctions, all Russian and Belarus debt was excluded from the JPM indexes on March 31st. In the period prior to that, the debt continued to reflect valuations provided by the pricing provider. More information on the methodology used can be found here
We also exclude some bried periods from PHP and NGN due to the unavailability of data.
current_date = pd.Timestamp('now').strftime('%Y-%m-%d')
ngn_na = ["2007-04-30", "2007-05-07"]
php_na = ["2024-01-31", current_date]
rub_na = ["2022-02-24", current_date]
black = {
"RUB": rub_na,
}
# Restricted Tradability of Russia and no-price days for Nigeria
dfd = msm.reduce_df(dfd, blacklist=black).reset_index(drop=True)
black = {"NGN": ngn_na}
dfd = msm.reduce_df(dfd, blacklist=black).reset_index(drop=True)
black = {"PHP": php_na}
dfd = msm.reduce_df(dfd, blacklist=black).reset_index(drop=True)
History #
Local currency bond carry #
Cross-country heterogeneity of local-currency carry has been striking in terms of means and variances.
xcats_sel = ["LCBICRY_NSA"]
cids_exp = cids_lc
msp.view_ranges(
dfd,
xcats=xcats_sel,
cids=cids_exp,
sort_cids_by="mean",
start="2000-01-01",
kind="box",
size=(16, 8),
)
xcats_sel = ["LCBICRY_NSA"]
msp.view_timelines(
dfd,
xcats=xcats_sel,
cids=cids_exp,
start="2000-01-01",
title="Local currency bond index carry across key market segments",
title_fontsize=20,
cumsum=False,
ncol=3,
same_y=False,
aspect=1.7,
)
plt.show()
Foreign currency bond carry #
Foreign-currency bond carry has been less heterogeneous across countries than local-currency bond carry due mainly to the uniform application of USD funding rates.
xcats_sel = ["FCBICRY_NSA"]
cids_exp = cids_lc
msp.view_ranges(
dfd,
xcats=xcats_sel,
cids=cids_exp,
sort_cids_by="mean",
start="2000-01-01",
kind="box",
size=(16, 8),
)
cids_exp = cids_fc
xcats_sel = ["FCBICRY_NSA"]
msp.view_timelines(
dfd,
xcats=xcats_sel,
cids=cids_exp,
start="2004-01-01",
title="Foreign currency bond index carry across key market segments",
title_fontsize=20,
cumsum=False,
ncol=3,
same_y=False,
aspect=1.7,
)
Vol-targeted bond index carry #
cids_exp = cids_lc
xcats_sel = ["LCBICRY_VT10", "FCBICRY_VT10"]
msp.view_timelines(
dfd,
xcats=xcats_sel,
cids=cids_exp,
start="2004-01-01",
title="Bond index volatility adjusted carry across key market segments, local and foreign currency",
cumsum=False,
ncol=3,
same_y=False,
)
Importance #
Research Links #
“A portfolio of long-only government bond positions based on the global carry strategy outperformed the J.P. Morgan Global Government Bond Index (JPM GBI) by 1.37% a year after transaction costs.” CFA
“Bond carry is the expected return on a bond when the yield curve does not change. The curve carry strategy within each country constructs buckets based on bond maturities on a monthly basis and buys the government bond buckets with high carry while selling those with low carry. Combining these curve carry strategies for 13 countries, we found a global curve carry factor with an information ratio of 1.0.” Martens
Empirical Clues #
There has been a strong positive predictive relation between local-currency carry and subsequent monthly index returns. This corresponds to the common view that carry is indicative of policy subsidies and risk premia.
cidx = cids_lc
xcatx = ["LCBICRY_NSA", "LCBIR_NSA"]
cr = msp.CategoryRelations(
dfd,
xcats=xcatx,
cids=cidx,
freq="M",
lag=1,
slip=1, # one-day slippage to avoid time zone distortions
start="2000-01-01",
years=None,
xcat_aggs=["last", "sum"],
)
cr.reg_scatter(
title="Local currency bond index carry and subsequent bond index returns, 20 countries, since 2000",
labels=False,
coef_box="lower right",
ylab="Local currency bond index returns, % next month",
xlab="Local currency bond index carry, end of month, change over end of previous month",
prob_est="map",
)
However, the change in carry a negative predictor of next month’s bond returns. This is consistent with the idea that rising carry reflects deteriorating fundamentals in the short run that ultimately can escalate.
cidx = cids_lc
xcatx = ["LCBICRY_NSA", "LCBIR_NSA"]
cr = msp.CategoryRelations(
dfd,
xcats=xcatx,
cids=cidx,
freq="M",
lag=1,
slip=1, # one-day slippage to avoid time zone distortions
start="2000-01-01",
years=None,
xcat_aggs=["last", "sum"],
xcat1_chg="diff",
)
cr.reg_scatter(
title="Local currency bond index carry changes and subsequent bond index returns, 20 countries, since 2000",
labels=False,
coef_box="lower right",
ylab="Local currency bond index returns, % next month",
xlab="Local currency bond index carry, end of month, change over end of previous month",
prob_est="map",
)
There has been an even stronger positive relation between foreign currency bond carry and subsequent index returns.
cidx = cids_fc
xcatx = ["FCBICRY_NSA", "FCBIR_NSA"]
cr = msp.CategoryRelations(
dfd,
xcats=xcatx,
cids=cidx,
freq="M",
lag=1,
slip=1, # one-day slippage to avoid time zone distortions
start="2000-01-01",
years=None,
xcat_aggs=["last", "sum"],
)
cr.reg_scatter(
title="USD bond index carry and subsequent bond index returns, 25 countries, since 2000",
labels=False,
coef_box="lower right",
ylab="Foreign currency bond index returns, % next month",
xlab="Foreign currency bond index carry, end of month, change over end of previous month",
prob_est="map",
)
Appendix 1 #
Government Bond Index - Emerging Markets (GBI-EM) #
The J.P. Morgan Government Bond Index - Emerging Markets (GBI-EM) Indices provide investors with a benchmark that tracks local currency bonds issued by emerging market governments. The index was launched in June 2005 and is the first comprehensive global local Emerging Markets index.
As Emerging Market governments look increasingly toward their domestic market for sources of finance, investors continue to look more closely at local markets in search for higher yield and greater diversification. The GBI-EM Indices are comprised of only those countries from the GBI universe that meet the JP Morgan criteria for an Emerging Market, resulting in 18 countries from four regions.
For a country to be eligible for inclusion in our GBI-EM indices, GNI per capita must be below the Index Income Ceiling (IIC) for three consecutive years. J.P. Morgan defines the IIC as the GNI per capita level that is adjusted every year by the growth rate of the World GNI per capita, Atlas method (current US$), provided by the World Bank annually.
The GBI-EM consists of regularly traded, fixed-rate, domestic currency government bonds which international investors can readily access. We determine eligibility for local currency issues using the following criteria: instrument type, current amount outstanding, liquidity, maturity. The GBI-EM indices only include fixed coupon instruments. Additionally, bonds with callable, puttable or convertible features are not part of the indices. Only instruments with a current face amount outstanding of US $1 billion equivalent for onshore local currency bonds and USD 500 million equivalent for global bonds (offshore currency linked bonds) or more will be considered for inclusion.
More information can be found in the documantation
EMBI Global (EMBIG) #
The J.P. Morgan Emerging Markets Bond Index Global (EMBIG) (and Emerging Markets Bond Index Global Diversified (EMBIGD) ) are J.P. Morgan’s most comprehensive US dollar emerging markets debt benchmarks. The EMBI suite of indices considers US dollar-denominated bonds issued by sovereign and quasi-sovereign EM entities eligible for inclusion.
The EMBI suite classifies countries as Emerging Markets or Developed Markets by applying a combination of income-based and purchasing power-based criteria. These multi-dimensional rules allow the EMBIG to include a number of higher-rated countries that international investors have nevertheless considered part of the emerging markets universe.
A country is eligible for inclusion in the EMBIG/EMBIGD if either the GNI per capita of the country’s economy is below the Index Income Ceiling (IIC) for three consecutive years or the nation’s cost of living (purchasing power) is below the Index PPP Ratio (IPR) for three consecutive years.
More information can be found in the documentation
Appendix 2 #
Carry calculation #
Carry calculations are built upon the yield to maturity index levels. These index levels are not simple weighted averages of yields - they are calculated using the Superbond methodology. According to this methodology, the cashflows of each bond in the index are deconstructed and recostructed into one ‘Super bond’. The IRR of this theoretical instrument is therefore the yield of the portfolio.
We calculate carry by taking the yield level of the index at the end of day and calculating the present value of this index by including the risk-free rate. This is done in a similar way to the carry calculated in our government bond carry notebook , so that we can appreciate carry as a measure of the return on an index position when taking into account its cost of funding.
where I is the yield level of the bond index on day t and related funding rate. For local currency indices, the funding rate will be the local currency funding rate. For hard currency indices, we use the dollar funding rate. When we don’t have the funding rate available, we remove that country from the group.
Appendix 2: Currency symbols #
The word ‘cross-section’ refers to currencies, currency areas or economic areas. In alphabetical order, these are
-
AED (Emirates dirham)
-
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)
-
EUR (Euro)
-
FRF (French franc)
-
GBP (British pound)
-
HKD (Hong Kong dollar)
-
HUF (Hungarian forint)
-
IDR (Indonesian rupiah)
-
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 (Phillipine peso)
-
PLN (Polish zloty)
-
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).