Sovereign CDS volatility #
This group contains generic return volatility metrics and leverage ratios for short protection positions though sovereign credit default swaps for various maturities and a range of developed and emerging markets.
Sovereign CDS volatility #
Ticker : CDS02YXRxEASD_NSA / CDS05YXRxEASD_NSA / CDS10YXRxEASD_NSA
Label : CDS return volatility: 2-year maturity / 5-year maturity / 10-year maturity.
Definition : Annualised standard deviation of CDS (short protection) excess returns: 2-year maturity / 5-year maturity / 10-year maturity.
Notes :
-
The standard deviation has been calculated based on an exponential moving average of daily returns with a half-life of 11 active trading days.
-
CDS calculations are based on CDS spreads from J.P. Morgan DataQuery.
Leverage ratio of vol-targeted CDS position #
Ticker : CDS02YXRxLEV10_NSA / CDS05YXRxLEV10_NSA / CDS10YXRxLEV10_NSA
Label : Leverage ratio of short CDS position for 10% annualized vol target: 2-year maturity / 5-year maturity / 10-year maturity.
Definition : CDS leverage ratio for a 10% annualized vol target: 2-year maturity / 5-year maturity / 10-year maturity.
Notes :
-
This serves as the leverage ratio for a 10% annualized vol target and is inversely proportional to the estimated annualized standard deviation of the return on a government bond position.
-
A leverage ratio of 25 (for notional to risk capital) has been applied to simulate capital and risk management limits to leverage.
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
from pandas import Timestamp
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
from datetime import timedelta, date
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
import requests
from timeit import default_timer as timer
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 obtain the data. Here
tickers
is an array of ticker strings,
start_date
is the first release date to be considered and
metrics
denotes the types of information requested.
# Cross-sections of interest
cids_dmca = ["AUD", "CHF", "GBP", "NOK", "NZD", "SEK", "USD"]
cids_dmeu = [
"FRF",
"DEM",
"ITL",
"ESP",
] # DM euro area sovereigns
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_dm = cids_dmca + cids_dmeu
cids_em = cids_emea + cids_latm + cids_emas
cids = cids_dm + cids_em
vols = ["CDS02YXRxEASD_NSA", "CDS05YXRxEASD_NSA", "CDS10YXRxEASD_NSA"]
levs = ["CDS02YXRxLEV10_NSA", "CDS05YXRxLEV10_NSA", "CDS10YXRxLEV10_NSA"]
xtra = ["CDS05YXR_NSA", "CDS05YXR_VT10", "CDS05YXRHvGDRB_NSA", "CDS05YCRY_VT10"]
main = vols + levs
xcats = main + xtra
# Download series from J.P. Morgan DataQuery by tickers
start_date = "1996-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:
start = timer()
df = downloader.download(
tickers=tickers,
start_date=start_date,
metrics=["value", "eop_lag", "mop_lag", "grading"],
suppress_warning=True,
show_progress=True,
)
end = timer()
dfd = df
print("Download time from DQ: " + str(timedelta(seconds=end - start)))
Maximum number of tickers is 290
Downloading data from JPMaQS.
Timestamp UTC: 2023-06-26 21:13:25
Connection successful!
Number of expressions requested: 1160
Requesting data: 100%|█████████████████████████████████████████████████████████████████| 58/58 [00:18<00:00, 3.15it/s]
Downloading data: 100%|████████████████████████████████████████████████████████████████| 58/58 [00:38<00:00, 1.52it/s]
Download time from DQ: 0:01:16.061056
Download time from DQ: 0:01:12.135530
Availability #
cids_exp = sorted(list(cids)) # cids expected in category panels
msm.missing_in_df(dfd, xcats=main, cids=cids_exp)
Missing xcats across df: set()
Missing cids for CDS02YXRxEASD_NSA: set()
Missing cids for CDS02YXRxLEV10_NSA: set()
Missing cids for CDS05YXRxEASD_NSA: set()
Missing cids for CDS05YXRxLEV10_NSA: set()
Missing cids for CDS10YXRxEASD_NSA: set()
Missing cids for CDS10YXRxLEV10_NSA: set()
Starting dates for sovereign CDS volatilities are mixed. For most cross-sections, data is available only from the mid-2000s onwards. The only countries for which data are available from the 1990s are Brazil, Colombia, Mexico and Poland.
For the explanation of currency symbols, which are related to currency areas or countries for which categories are available, please view Appendix 1 .
xcatx = main
cidx = cids_exp
dfx = msm.reduce_df(dfd, xcats=xcatx, cids=cidx)
dfs = msm.check_startyears(
dfx,
)
msm.visual_paneldates(dfs, size=(18, 6))
print("Last updated:", date.today())
Last updated: 2023-06-26
xcatx = main
cidx = cids_exp
plot = msm.check_availability(
dfd, xcats=xcatx, cids=cidx, start_size=(18, 3), start_years=False
)
xcatx = main
cidx = cids_exp
plot = msp.heatmap_grades(
dfd,
xcats=xcatx,
cids=cidx,
size=(18, 6),
title=f"Average vintage grades from {start_date} onwards",
)
xcatx = ["CDS05YXRxEASD_NSA", "CDS05YXRxLEV10_NSA"]
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cids,
val="eop_lag",
title="End of observation period lags (ranges of time elapsed since end of observation period in days)",
start="2000-01-01",
kind="box",
size=(16, 4),
)
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cids,
val="mop_lag",
title="Median of observation period lags (ranges of time elapsed since middle of observation period in days)",
start="2000-01-01",
kind="box",
size=(16, 4),
)
History #
CDS volatility #
Annualized volatility of sovereign CDS returns is fairly low by the standards of other asset classes, such as equity index futures or interest rate swaps. Mostly, it is below 2% annualized. However, in times of turmoil, volatility rises disproportionately.
xcatx = vols
cidx = cids
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="std",
start="2000-01-01",
title="Boxplots of sovereign CDS return volatilities, since 2000",
xcat_labels=["2-year maturity", "5-year maturity", "10-year maturity"],
kind="box",
size=(16, 8),
)
xcatx = vols
cidx = cids
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start="2000-01-01",
title="CDS return volatility (% ar)",
title_adj=1.01,
title_fontsize=27,
legend_fontsize=17,
title_xadj=0.39,
xcat_labels=["2-year maturity", "5-year maturity", "10-year maturity"],
label_adj=0.05,
cumsum=False,
ncol=4,
same_y=False,
height=3,
aspect=2,
all_xticks=True,
)
Leverage ratio #
For the sake of calculating vol-targeting returns (10% annualized), we calculate leverage ratios. However, in JPMaQS we impose a leverage limit of 25, reflecting reasonable risk management. This limit has often been binding for higher-grade countries.
xcatx = levs
cidx = cids
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="std",
start="2000-01-01",
title="Boxplots of vol-targeted CDS positions of leverage ratios",
xcat_labels=["2-year maturity", "5-year maturity", "10-year maturity"],
kind="box",
size=(16, 8),
)
xcatx = levs
cidx = cids
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start="2000-01-01",
title="Leverage for 10% annualized vol target (with limit of 25)",
title_adj=1.01,
title_fontsize=27,
legend_fontsize=17,
xcat_labels=["2-year maturity", "5-year maturity", "10-year maturity"],
title_xadj=0.39,
label_adj=0.05,
cumsum=False,
ncol=4,
same_y=False,
height=3,
aspect=2,
all_xticks=True,
)
Importance #
Relevant research #
“We find that sovereign CDS and bond markets are co-integrated. In five out of seven sovereigns (71%), the bond market leads in price discovery by adjusting to new information regarding credit risk before CDS.” Hassan, Ngene and Yu
Empirical clues #
There has been a strong positive relation between CDS return volatility and subsequent nominal returns.
xcatx = ["CDS05YXRxEASD_NSA", "CDS05YXR_NSA"]
cidx = cids
cr = msp.CategoryRelations(
dfd,
xcats=xcatx,
xcat_aggs=["last", "sum"],
cids=cidx,
freq="Q",
lag=1,
slip=1,
start="2000-01-01",
)
cr.reg_scatter(
title="CDS volatility and subsequent quarterly returns",
labels=False,
coef_box="lower right",
ylab="5-year CDS return, next quarter",
xlab="5-year CDS return volatility",
)
cr = msp.CategoryRelations(
dfd,
xcats=xcatx,
xcat_aggs=["last", "sum"],
cids=cidx,
freq="Q",
lag=1,
slip=1,
start="2000-01-01",
xcat_trims=[10, 10],
)
cr.reg_scatter(
title="CDS volatility and subsequent quarterly returns (excluding outliers)",
labels=False,
coef_box="lower right",
ylab="5-year CDS return, next quarter (trimmed at 10%)",
xlab="5-year CDS return volatility (trimmed at 10%)",
)
Appendices #
Appendix 1: Currency symbols #
The word ‘cross-section’ refers to currencies, currency areas or economic areas. In alphabetical order, these are AUD (Australian dollar), 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), 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), NLG (Dutch guilder), NOK (Norwegian krone), NZD (New Zealand dollar), PEN (Peruvian sol), PHP (Phillipine peso), PLN (Polish zloty), RON (Romanian leu), RUB (Russian ruble), SEK (Swedish krona), SGD (Singaporean dollar), THB (Thai baht), TRY (Turkish lira), TWD (Taiwanese dollar), USD (U.S. dollar), ZAR (South African rand).