Government bond volatility #

The category group contains data for bond benchmarks which span 9 countries and 7 tenors. This data comprises volatility and leverage ratios of vol-targeted positions in government bond benchmarks.

Generic government bond volatility #

Ticker : GB01YXRxEASD_NSA / GB02YXRxEASD_NSA / GB03YXRxEASD_NSA / GB05YXRxEASD_NSA / GB07YXRxEASD_NSA / GB10YXRxEASD_NSA / GB30YXRxEASD_NSA

Label : Government bond return volatility: 1-year maturity / 2-year maturity / 3-year maturity / 5-year maturity / 7-year maturity / 10-year maturity / 30-year maturity.

Definition : Annualised return standard deviation of government bond excess returns: 1-year maturity / 2-year maturity / 3-year maturity / 5-year maturity / 7-year maturity / 10-year maturity / 30-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.

  • The government yields used are spot rates taken from zero coupon curves that are available on J.P. Morgan DataQuery.

Leverage ratio of vol-targeted bond position #

Ticker : GB01YXRxLEV10_NSA / GB02YXRxLEV10_NSA / GB03YXRxLEV10_NSA / GB05YXRxLEV10_NSA / GB07YXRxLEV10_NSA / GB10YXRxLEV10_NSA / GB30YXRxLEV10_NSA

Label : Leverage ratio of bond position for 10% annualized vol target: 1-year maturity / 2-year maturity / 3-year maturity / 5-year maturity / 7-year maturity / 10-year maturity / 30-year maturity.

Definition : Bond leverage ratio for a 10% annualized vol target: 1-year maturity / 2-year maturity / 3-year maturity / 5-year maturity / 7-year maturity / 10-year maturity / 30-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 5 (for notional to risk capital) has been applied to simulate capital and risk management limits to leverage.

Generic government bond future volatility #

Ticker : GBF02YXRxEASD_NSA / GBF03YXRxEASD_NSA / GBF05YXRxEASD_NSA / GBF10YXRxEASD_NSA / GBF20YXRxEASD_NSA / GBF30YXRxEASD_NSA

Label : Government bond future return volatility: 2-year maturity / 3-year maturity / 5-year maturity / 10-year maturity / 20-year maturity / 30-year maturity.

Definition : Annualised return standard deviation of government bond future excess returns: 2-year maturity / 3-year maturity / 5-year maturity / 10-year maturity / 20-year maturity / 30-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.

  • The government bond future returns used are those computed by our continuous series of government bond future returns. See here for details on their calculation.

Imports #

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

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 os

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.

cids = ["AUD", "DEM", "FRF", "ESP", "ITL", "JPY", "NZD", "GBP", "USD"]
vols = [
    "GB01YXRxEASD_NSA",
    "GB02YXRxEASD_NSA",
    "GB03YXRxEASD_NSA",
    "GB05YXRxEASD_NSA",
    "GB07YXRxEASD_NSA",
    "GB10YXRxEASD_NSA",
    "GB30YXRxEASD_NSA",
]
carry = [
    "GB01YCRY_VT10",
    "GB02YCRY_VT10",
    "GB03YCRY_VT10",
    "GB05YCRY_VT10",
    "GB07YCRY_VT10",
    "GB30YCRY_VT10",
    "GB01YCRY_NSA",
    "GB02YCRY_NSA",
    "GB03YCRY_NSA",
    "GB05YCRY_NSA",
    "GB07YCRY_NSA",
    "GB10YCRY_NSA",
    "GB30YCRY_NSA",
]
levs = [
    "GB01YXRxLEV10_NSA",
    "GB02YXRxLEV10_NSA",
    "GB03YXRxLEV10_NSA",
    "GB05YXRxLEV10_NSA",
    "GB07YXRxLEV10_NSA",
    "GB10YXRxLEV10_NSA",
    "GB30YXRxLEV10_NSA",
]
futs = [
    "GBF02YXRxEASD_NSA",
    "GBF03YXRxEASD_NSA",
    "GBF05YXRxEASD_NSA",
    "GBF10YXRxEASD_NSA",
    "GBF20YXRxEASD_NSA",
    "GBF30YXRxEASD_NSA",
]

xcats = vols + carry + levs + futs
# 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:
    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()

dfd = df

print("Download time from DQ: " + str(timedelta(seconds=end - start)))
Maximum number of tickers is 297
Downloading data from JPMaQS.
Timestamp UTC:  2023-05-31 00:04:23
Connection successful!
Number of expressions requested: 1188
Download time from DQ: 0:03:38.802833

Availability #

cids_exp = cids  # cids expected in category panels
msm.missing_in_df(dfd, xcats=xcats, cids=cids_exp)
Missing xcats across df:  set()
Missing cids for GB01YCRY_NSA:  set()
Missing cids for GB01YCRY_VT10:  {'GBP'}
Missing cids for GB01YXRxEASD_NSA:  {'GBP'}
Missing cids for GB01YXRxLEV10_NSA:  set()
Missing cids for GB02YCRY_NSA:  {'AUD'}
Missing cids for GB02YCRY_VT10:  set()
Missing cids for GB02YXRxEASD_NSA:  set()
Missing cids for GB02YXRxLEV10_NSA:  set()
Missing cids for GB03YCRY_NSA:  set()
Missing cids for GB03YCRY_VT10:  set()
Missing cids for GB03YXRxEASD_NSA:  set()
Missing cids for GB03YXRxLEV10_NSA:  set()
Missing cids for GB05YCRY_NSA:  {'NZD', 'GBP'}
Missing cids for GB05YCRY_VT10:  set()
Missing cids for GB05YXRxEASD_NSA:  set()
Missing cids for GB05YXRxLEV10_NSA:  set()
Missing cids for GB07YCRY_NSA:  set()
Missing cids for GB07YCRY_VT10:  set()
Missing cids for GB07YXRxEASD_NSA:  set()
Missing cids for GB07YXRxLEV10_NSA:  {'GBP'}
Missing cids for GB10YCRY_NSA:  set()
Missing cids for GB10YXRxEASD_NSA:  {'USD'}
Missing cids for GB10YXRxLEV10_NSA:  set()
Missing cids for GB30YCRY_NSA:  {'ESP'}
Missing cids for GB30YCRY_VT10:  {'ITL', 'AUD'}
Missing cids for GB30YXRxEASD_NSA:  set()
Missing cids for GB30YXRxLEV10_NSA:  set()
Missing cids for GBF02YXRxEASD_NSA:  {'FRF', 'JPY', 'NZD', 'ESP', 'AUD'}
Missing cids for GBF03YXRxEASD_NSA:  {'GBP', 'FRF', 'DEM', 'JPY', 'NZD', 'ITL', 'ESP', 'USD'}
Missing cids for GBF05YXRxEASD_NSA:  {'FRF', 'JPY', 'NZD', 'ITL', 'ESP'}
Missing cids for GBF10YXRxEASD_NSA:  {'NZD'}
Missing cids for GBF20YXRxEASD_NSA:  {'GBP', 'FRF', 'DEM', 'NZD', 'ITL', 'ESP', 'USD'}
Missing cids for GBF30YXRxEASD_NSA:  {'FRF', 'JPY', 'NZD', 'ITL', 'ESP', 'AUD'}

U.S. data are available from the early 1990s but series of other bonds markets only start from post-2000.

xcatx = xcats
cidx = cids_exp

dfx = msm.reduce_df(dfd, xcats=xcatx, cids=cidx)
dfs = msm.check_startyears(
    dfx,
)
msm.visual_paneldates(dfs, size=(14, 10))

print("Last updated:", date.today())
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/ad04de53a6cfcf2368fe04740ffaa57e6ebe398f796a9d9dc954726871b1a138.png
xcatx = xcats
cidx = cids_exp

plot = msm.check_availability(
    dfd, xcats=xcatx, cids=cids_exp, start_size=(18, 6), start_years=False
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/a6b49c0d4790ac4c6e34886761be125df83fa0af99e0614a4977464441ec9ab7.png
xcatx = xcats
cidx = cids_exp

plot = msp.heatmap_grades(
    dfd,
    xcats=xcatx,
    cids=cidx,
    size=(18, 15),
    title=f"Average vintage grades from {start_date} onwards",
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/1f77e3d75ee18989f28a8e7e734bea8372073b687578cc626649261dc85cab51.png
xcats_bond_vol = ["GB01YXRxEASD_NSA", "GB02YXRxEASD_NSA"]

msp.view_ranges(
    dfd,
    xcats=xcats_bond_vol,
    cids=cids,
    val="eop_lag",
    title="End of observation period lags (ranges of time elapsed since end of observation period in days), government bond volatility",
    start="2000-01-01",
    kind="box",
    size=(16, 4),
)

msp.view_ranges(
    dfd,
    xcats=xcats_bond_vol,
    cids=cids,
    val="mop_lag",
    title="Median of observation period lags (ranges of time elapsed since middle of observation period in days), government bond volatility",
    start="2000-01-01",
    kind="box",
    size=(16, 4),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/ac9276ea7c4ad9a385ab16410624c7fdb9f0f3983e7ef47d42999e46bbec6db1.png https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/29145ec95dcb229b72f4967da182468554e58cf704b0dc6f4f4997db62f2433e.png
xcats_lev = ["GB01YXRxLEV10_NSA", "GB02YXRxLEV10_NSA"]

msp.view_ranges(
    dfd,
    xcats=xcats_lev,
    cids=cids,
    val="eop_lag",
    title="End of observation period lags (ranges of time elapsed since end of observation period in days), leverage ratio of vol-targeted bond position",
    start="2000-01-01",
    kind="box",
    size=(16, 4),
)

msp.view_ranges(
    dfd,
    xcats=xcats_lev,
    cids=cids,
    val="mop_lag",
    title="Median of observation period lags (ranges of time elapsed since middle of observation period in days), leverage ratio of vol-targeted bond position",
    start="2000-01-01",
    kind="box",
    size=(16, 4),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/b6361547929a0f8462978037c423baa219641c35edf233e46c83791bc6c73994.png https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/7b7e12cd475310c8d19c8cb802a359f16999faf20d250bfbef550f67563c9e7e.png
xcats_future = ["GBF02YXRxEASD_NSA", "GBF03YXRxEASD_NSA"]

msp.view_ranges(
    dfd,
    xcats=xcats_future,
    cids=cids,
    val="eop_lag",
    title="End of observation period lags (ranges of time elapsed since end of observation period in days), government bond future volatility",
    start="2000-01-01",
    kind="box",
    size=(16, 4),
)

msp.view_ranges(
    dfd,
    xcats=xcats_future,
    cids=cids,
    val="mop_lag",
    title="Median of observation period lags (ranges of time elapsed since middle of observation period in days), government bond future volatility",
    start="2000-01-01",
    kind="box",
    size=(16, 4),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/4abade6d58c4605528ec43e1bcdc220fa7c637b77624b0ea306cb85e9ef45ef9.png https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/ff33e7dbc0f34fc79ea8db11fe2b7789f7cb7f7c3d6a1ec3cdee301c82619657.png

History #

Government bond volatility #

Return volatility increases with maturity across all available countries. Japan’s volatility level and ranges have been compressed over the sample period.

xcatx = ["GB01YXRxEASD_NSA", "GB05YXRxEASD_NSA", "GB10YXRxEASD_NSA"]
cidx = cids_exp

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    sort_cids_by="mean",
    start="2000-01-01",
    title="Means and standard deviations of government bond volatilities for 1-year, 5-year and 10-year tenors",
    xcat_labels=["1-year", "5-year", "10-year"],
    kind="bar",
    size=(16, 8),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/23a860d5a6352693b2e8db53b905177b731abea8c8e533b5b6481547cf552bd0.png

Government bond volatility has been higher in periods of financial stress, for instance during the 2008 crisis, during the european debt crisis in 2011 and especially at the beginning of the COVID-19 pandemic.

xcatx = ["GB01YXRxEASD_NSA", "GB05YXRxEASD_NSA", "GB10YXRxEASD_NSA"]
cidx = cids

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="1990-01-01",
    title="Generic government bond volatilitilities for 1-year, 5-year and 10-year tenors",
    title_adj=1.05,
    title_xadj=0.42,
    xcat_labels=["1-year", "5-year", "10-year"],
    label_adj=0.1,
    ncol=3,
    same_y=True,
    size=(12, 7),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/16d56b04a081b0ce025c807305a1c62e6251f7ad82b8e5cabb4b0b85848a68fb.png

Government bond return volatility has been highly positively correlated across countries.

xcatx = "GB05YXRxEASD_NSA"
cidx = cids

msp.correl_matrix(
    dfd,
    xcats=xcatx,
    cids=cidx,
    title="Cross-sectional correlations for 5-year tenor government bond excess return volatilities",
    size=(20, 14),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/ae98e86949dd46637ee3f63bcfac799016ad33dc09fb28e4c1a4d398556ad7b0.png

Leverage ratio #

Required leverage ratios for 10% volatility targets averaged between 1.5 and 5 across currency areas. Due to short yield compression near the zero boundary, a 10% volatility target would mostly have required more leverage than allowed by our standard parameters.

xcatx = ["GB01YXRxLEV10_NSA", "GB05YXRxLEV10_NSA", "GB10YXRxLEV10_NSA"]
cidx = cids

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    sort_cids_by="mean",
    start="2000-01-01",
    kind="bar",
    title="Means and standard deviations of vol-targeted bond position leverage ratios for 1-year, 5-year and 10-year tenors",
    xcat_labels=["1-year", "5-year", "10-year"],
    size=(16, 8),
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/b1961c24369de3c3cd2b60b78215565a10d76305b69734db3491310758fa0d0b.png
xcatx = ["GB01YXRxLEV10_NSA", "GB05YXRxLEV10_NSA", "GB10YXRxLEV10_NSA"]
cidx = cids

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="2000-01-01",
    title_adj=1.05,
    title_xadj=0.43,
    title="Generic government bond position leverage required for 10% annualized volatility target, for 1-year, 5-year and 10-year tenors",
    xcat_labels=["1-year", "5-year", "10-year"],
    label_adj=0.1,
    cumsum=False,
    ncol=3,
    same_y=True,
    size=(12, 7),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/aea9e35538a35756f6d0e6a43c8b888a8241ef43988e4f23b5aec7bd89a58cd5.png

Government bond future volatility #

Bond future volatility seems to average 5% in most cases, increasing in periods of market stress – such as during the global financial crisis and right after the COVID-19 pandemic outbreak. Volatility has remained compressed during the period of ample purchases by central banks, from the year 2011 to the year 2018.

xcatx = ["GBF02YXRxEASD_NSA", "GBF05YXRxEASD_NSA", "GBF10YXRxEASD_NSA"]
cidx = cids

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="1990-01-01",
    title="Generic government bond future volatilities for 2-year, 5-year and 10-year tenors",
    title_adj=1.05,
    title_xadj=0.43,
    xcat_labels=["2-year", "5-year", "10-year"],
    label_adj=0.1,
    ncol=3,
    same_y=True,
    size=(12, 7),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/43e9fee034342fd6b8531345eb7a60ae6232d648d6ef524ada0df9c3ab769c36.png

In the United States, bond future volatility has been consistently lower than the volatility of the cash product. This makes sense because the bond future is more liquid than the cash, therefore will see its volatility being compressed.

xcatx = ["GB05YXRxEASD_NSA", "GBF05YXRxEASD_NSA"]
cidx = ["USD"]
msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="2000-01-01",
    title="USD: Government bond volatility and government bond future volatility, 5-year tenor",
    xcat_labels=["cash", "future"],
    ncol=1,
    same_y=False,
    size=(12, 7),
    aspect=1.7,
)
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/608c7694dbfe57d7bc30b723b78b1c48c8945c0a2dc8d8ca19baecf8a25cfafd.png

Importance #

Empirical clues #

There has been a strong positive correlation between bond carry and return volatility across the panel.

xcatx = ["GB05YCRY_NSA", "GB05YXRxEASD_NSA"]
cidx = cids

cr = msp.CategoryRelations(
    dfd,
    xcats=xcatx,
    cids=cidx,
    freq="A",
    lag=0,
    xcat_aggs=["mean", "mean"],
    start="1990-01-01",
    years=None,
)

cr.reg_scatter(
    title="Government bond carry (5-year tenor) and volatility across all available history, annual frequency",
    labels=True,
    reg_robust=True,
    coef_box="upper left",
    xlab="Bond carry (5-year tenor)",
    ylab="Annualized volatility of 5-year bond returns",
)
GB05YCRY_NSA misses: ['GBP', 'NZD'].
https://macrosynergy.com/notebooks.build/themes/shock-and-risk-measures/_images/ccc4bdaf0e63b11bad0ec951b2f1d4cf2714f23a75d54577ffb24a67310851f6.png

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).