Term premia estimates #
The category group contains term premia estimates for fixed income contracts, based on macroquantamental indicators.
Interest rate swap term premia (Macrosynergy method) #
Ticker : DU02YETP_NSA / DU05YETP_NSA / DU10YETP_NSA
Label : Estimated IRS term premia, % ar, Macrosynergy method: 2year maturity / 5year maturity / 10year maturity.
Definition : Estimated IRS term premia, % ar, Macrosynergy method: 2year maturity / 5year maturity / 10year maturity.
Notes :

Conceptually the fixed income term premium refers to the gap between the yield of a longermaturity bond and the average expected riskfree shortterm rate for the same maturity. Essentially, it represents the cost of commitment. Although the term premium itself cannot be directly observed, it can be estimated by employing a term structure model that differentiates between expected shortterm rates and risk premia.

The simple Macrosynergy term premium model mainly makes an assumption about the expected path of the shortterm interest rate. It posits a longterm “convergence point” of the short rate at the estimated longterm rate of nominal GDP growth, which, in turn, is estimated as the sum of the 5year moving median of past GDP growth ( documentation here ) and the effective inflation targeted ( documentation here ). This reflects the idea that the longterm real interest rate should be near the real return on the existing capital stock. The assumption is that the shortterm nominal interest rate drifts towards a longterm convergence rate linearly over 5 years. The term premium is then the difference between the longterm yield on a swap and the geometric average of the forward shortterm rates implied by that drift.

The main calculations are summarized below in Appendix 1 and further details are given in Appendix 2 .

This version of the estimated term premium is an offtheshelf simple benchmark based on macroeconomics without complicated modelling. It is open to modification using other quantamental indicators. For example, the current state of inflation and “slack” in the economy will plausibly influence the path of a shortterm rate.

Term premia for Turkey have been rather volatile win the last two years due to a nonupdating shortterm interest rate.

Term premia for Taiwan have been negative throughout the observation period. This is due to our approximation of the trend in real rates (r*) and growth rates (g*). The growth rate of Taiwan has been very high and this has resulted in a very high steadystate rate which in turn has pushed the resulting term premia in negative territory.
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")
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 crosssection 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.
# Crosssections of interest
cids_dm = [
"AUD",
"CAD",
"CHF",
"EUR",
"GBP",
"JPY",
"NOK",
"NZD",
"SEK",
"USD",
] # DM currency areas
cids_latm = ["COP", "CLP", "MXN"] # Latam countries
cids_emea = ["CZK", "HUF", "ILS", "PLN", "RUB", "TRY", "ZAR"] # EMEA countries
cids_emas = [
"CNY",
"IDR",
"INR",
"KRW",
"SGD",
"THB",
"TWD",
] # EM Asia countries
cids_em = cids_latm + cids_emea + cids_emas
cids = sorted(cids_dm + cids_em)
tenors = ["02", "05", "10"]
main = ["DU02YETP_NSA", "DU05YETP_NSA", "DU10YETP_NSA"]
xtra = [
"DU02YYLD_NSA",
"DU05YYLD_NSA",
"DU10YYLD_NSA",
"DU02YCRY_NSA",
"DU05YCRY_NSA",
"DU10YCRY_NSA",
"INFTEFF_NSA",
"RGDP_SA_P1Q1QL4_20QMM",
]
rets = [
"DU02YXR_NSA",
"DU02YXR_VT10",
"DU05YXR_NSA",
"DU05YXR_VT10",
"DU10YXR_NSA",
"DU10YXR_VT10",
] # market links
xcats = main + xtra + rets
# Download series from J.P. Morgan DataQuery by tickers
start_date = "19960101"
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 459
Downloading data from JPMaQS.
Timestamp UTC: 20230823 09:56:56
Connection successful!
Number of expressions requested: 1836
Requesting data: 100%█████████████████████████████████████████████████████████████████ 92/92 [00:27<00:00, 3.30it/s]
Downloading data: 100%████████████████████████████████████████████████████████████████ 92/92 [03:59<00:00, 2.60s/it]
Download time from DQ: 0:04:59.668652
Availability #
cids_exp = cids # cids expected in category panels
msm.missing_in_df(dfd, xcats=main, cids=cids_exp)
Missing xcats across df: []
Missing cids for DU02YETP_NSA: ['SGD', 'NOK', 'AUD', 'EUR', 'IDR']
Missing cids for DU05YETP_NSA: []
Missing cids for DU10YETP_NSA: ['MXN', 'JPY', 'CZK']
xcatx = main
cidx = cids_exp
dfx = msm.reduce_df(dfd, xcats=xcatx, cids=cidx)
dfs = msm.check_startyears(
dfx,
)
msm.visual_paneldates(dfs, size=(14, 2))
print("Last updated:", date.today())
Last updated: 20230823
xcatx = main
cidx = cids_exp
plot = msm.check_availability(
dfd, xcats=xcatx, cids=cids_exp, start_size=(14, 3), start_years=False
)
xcatx = main
cidx = cids_exp
plot = msp.heatmap_grades(
dfd,
xcats=xcatx,
cids=cidx,
size=(14, 3),
title=f"Average vintage grades from {start_date} onwards",
)
History #
IRS term premia according to the Macrosynergy method #
Estimated IRS term premia have shown the following stylized features since 2000:

10year term premia have been mostly positive, but the those for shorter maturities have been mixed and predominantly negative for many developed and emerging markets.

In most countries term premia decined after the great financial crisis.

The volatility of term premia in emerging markets has been higher than that in developed markets.
xcatx = main
cidx = cids
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="std",
start="20000101",
kind="box",
size=(16, 8),
)
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start="20000101",
title="Estimated term premia according to the Macrosynergy methodology",
xcat_labels=["2year", "5year", "10year"],
title_adj=1.01,
title_fontsize=22,
label_adj=0.05,
ncol=4,
cumsum=False,
same_y=False,
size=(12, 7),
aspect=2,
all_xticks=True,
)
Estimated termpremia correlations have been high, above 50%, across the panel. Correlation between 2year and 5year estimated term premia has been larger than between the other maturities.
xcats_sel = main
msp.correl_matrix(
df,
xcats=xcats_sel,
cids=cids,
freq="M",
start="20030101",
size=(6, 3),
)
Importance #
Research links #
“This paper proposes a semistructural dynamic term structure model augmented with macroeconomic factors to include cyclical dynamics with a focus on medium to longrun forecasts. Our results clearly show that a macroeconomic approach is warranted: While term premium estimates are in line with those from other studies, we provide (i) plausible, stable estimates of expected longterm interest rates and (ii) forecasts of short and longterm interest rates as well as cyclical macroeconomic variables that are stunningly close to those generated from largescale macroeconomic models.” IMF .
“Equilibrium models suggest that as long as the policy rate is firmly near zero, the term premium on longerdated yields is compressed by a reduced sensitivity of rates to economic change. However, when policy rates are on the move again this sensitivity recovers, while proximity of the zero lower bound implies high economic risks and a surcharge on the term premia. Hence, term premium uncertainty would be highest at the time of “liftoff”, when policy rates are expected to move upward from near zero.” Macrosynergy .
“Furthermore, our estimates indicate that term premia have been close to zero, as well as negative in periods, during the last decade of global extraordinary monetary policy measures”. See Risstad et al. .
“We find that the recent rise in yields due to increasing inflation and related uncertainty with respect to future levels of inflation and economic growth has triggered corresponding increases in term premia.” See Risstad et al. .
Empirical clues #
There has been strong and significant correlation of estimated term premia and subsequent monthly or quarterly returns. This is consistent with the notion of term premia indicating risk premia being paid for duration exposure.
Remember that the JPMaQS definition of duration returns is for going long the duration exposure by receiving the fixed rate and paying the floating rate. Hence when duration increases, by failing shortterm interest rates, we see positive returns (and wise versa).
cr = msp.CategoryRelations(
dfd,
xcats=["DU05YETP_NSA", "DU05YXR_NSA"],
cids=cids,
freq="Q",
lag=1,
xcat_aggs=["last", "sum"],
start="20000101",
)
cr.reg_scatter(
title="Estimated term premia and subsequent IRS returns, all markets, since 2000",
labels=False,
prob_est="map",
coef_box="lower right",
ylab="5year IRS return, next quarter",
xlab="Estimated 5year IRS term premium",
)
DU05YXR_NSA misses: ['ZAR'].
Appendices #
Appendix 1: Calculation of estimated term premia according to the macrosynergy method #
Here a term premium is the difference between a longer maturity yield and an average of estimated expected shortterm yields over the maturity. In order to proxy the average shortterm rate, we use the following method.
As localcurrency shortterm interest rate we use the main 1month money market rate or closest proxy. For many countries the shortterm interest rate has been the 1month localcurrency LIBOR rate until 2021. As of the end of 2021 LIBOR are being replaced in many countries by overnight index swap (OIS) rates. These rates have different economic meaning (as they imply almost no credit risk) but have become the new standard. For more details see the documentation on JPMaQS shortterm interest rates here .
We estimate a natural shortterm interest rate as the sum of expected longterm real GDP growth and expected inflation. The longterm growth rate is estimated as the last 5year moving median of the real GDP growth rate, as documented here . Longterm expected inflation is assumed to be equal to the effective inflation target of the central bank here .
The estimated natural rate is given by the sum of the longterm real GDP growth and the effective inflation target like so:
Where \(g^{*}\) is the 5year GDP growth rate and \(\pi^{*}\) represents the effective inflation target.
We assume that the shortterm interest rate converges to the natural rate linearly over a 5year period. Accordingly, we calculate a naive curve of forward rates by computing the simple yield increment starting from the shortterm yield and leading up to our proxy of the longterm GDP growth.
The expected drift in the shortterm interest rate per month is given by two stages. Firstly, the increment is calculated by taking the difference between the estimated natural rate and the current shortterm rate and dividing by the number of months to the 5year convergence date. This drift applies to the first 60 months of the contract.
where \(di\) is the monthly drift or increment in the short rate, and \(i_{0}\) is the initial (current) short term rate and \(N=60\) months (5 years).
The second stage is a zero drift after the 60 months have passed, whereby we expect the steady state natural rate to prevail.
The average shortterm interest rate is the mean of a vector of the shortterm interest rates that results from applying the two drifts to the months to maturity of the contract. The following formula applies:
Where \(n\) represents the tenor of the contract.
We can then calculate the mean interest rate towards convergence of a 2year, 5year and 10year yield as:
Where \(\hat{y}_{n}\) is the convergence towards the longterm steady state of the IRS yield with tenor \(n\) .
The term premium is the difference between the interest rate swap yield and the average shortterm interest rate.
Appendix 2: Convergence of shortterm interest rates and the termpremia #
To simplify notation in the following, we use the arithmetic termstructure decomposition as in Bauer and Rudebusch (2020) . With this assumption we can write the decomposition of the fixed yields as:
where \(y_{t}^{(n)}\) is the fixed yield at tenor \(n\) , \(i_{t}\) is the shortterm (nominal) interest rate ( \(\mathbb{E}_{t}(i_{t+j})\) is the expectation for period \(j\) , and \({TP}_{t}^{(n)}\) is the unobserved termpremium.
We can split the above equation into it’s longterm convergence path of \(i_{t}^{*}\) and the shortterm deviations:
where \(i_{t+j}^{c} = i_{t+j}  i_{t}^{*}\) .
Bauer and Rudebusch who defines \(i_{t}^{*}\) as the BeveridgeNelson trend in the shortterm nominal interest rate,
In a similar spirit to Bauer and Rudebusch (2020) we use the Fisher equation of:
Assumign we are in the longrun (steady state) we have
Our assumption is that the trend in realrates (
\(r_{t}^{*}\)
) can be approximated by stochastic trends in realgrowth rates (
\(g_{t}^{*}\)
), which in JPMaQS is captured by the 20month (5year) moving median (
RGDP_SA_P1Q1QL4_20QMM
).
We approximate the stochastic endpoints for shortterm rates (
\(i_{t}^{*}\)
), with longterm inflation trend (
\(\pi_{t}^{*}\)
) set by our effective inflation targets of each country (
INFTEFF_NSA
) and the equilibrium trend of real shortterm rates (
\(r_{t}^{*}\)
) by the trend in real GDP (
\(r_{t}^{*}=g_{t}^{*}\)
i.e. 5year moving median:
RGDP_SA_P1Q1QL4_20QMM
).
We assume convergence in 5years ( \(K=60\) months) with a linear path for shortterm interests rates to the trend value of \(i_{t}^{*}\) . We model a linear path to the convergence of the shortterm interest rates over the next 5years:
where \(w(j,K) = \min\left(\frac{j}{K}, 1\right) \;\forall j\ge 0\) .
We define \(\hat{y}_{t}^{(n)}\) as the expectation component of the fixed yield ( \(y_{t}^{(n)}\) ):
which once we substitute in our path of convergence is equal to:
Subtracting our estimate of the expectations components from observed fixed IRS yields, we can estimate the term premiums as:
# Constants
K_CONVERGENCE: int = 60 # 60months = 5years
# Initial parameters
istar = 5.5 # i*(t)
i0_low = 3.5 # i(t) from a low starting point below i*(t)
i0_high = 7.5 # i(t) from a high starting point above i*(t)
months = np.array([mm for mm in range(120 + 1)]) # Set up of months
def expected_short_term_rate(i0, istar, n, k_converge: int = K_CONVERGENCE) > float:
weight = min(n / k_converge, 1)
return weight * istar + (1  weight) * i0
def yhat_fn(i0: float, istar: float, n: int, k_converge: int = 60) > float:
if n == 0:
# Return shortterm rate for notenor
return i0
# Calculate expected yield for convergence
yhat: float = (
sum(expected_short_term_rate(i0=i0, istar=istar, n=jj) for jj in range(n)) / n
)
return yhat
# Plot model
fig = plt.figure(1)
# Plot shortterm rate convergence
ax = fig.add_subplot(211)
plt.scatter([0], [i0_low])
plt.scatter([0], [i0_high])
plt.plot(
months / 12,
[expected_short_term_rate(istar=istar, i0=i0_low, n=mm) for mm in months],
ls="",
label=f"Initial low ($i_{{t}}$): {i0_low:0.1f}%",
)
plt.plot(
months / 12,
[expected_short_term_rate(istar=istar, i0=i0_high, n=mm) for mm in months],
ls="",
label=f"Initial high ($i_{{t}}$): {i0_high:0.1f}%",
)
plt.plot(
[min(months), max(months)],
[istar, istar],
ls="",
c="g",
label=f"Trend shortterm rate ($i_{{t}}^{{*}}$): {istar:0.1f}%",
)
plt.title("Convergence paths of shortterm rates: $\mathbb{E}_{t}(i_{t+n})$")
plt.ylabel("Percent")
plt.xlabel("Tenor ($n$) in years")
plt.xlim(xmin=0, xmax=120 / 12)
# Plot convergence longer fixed yields paths
ax = fig.add_subplot(212)
plt.scatter([0], [i0_low])
plt.scatter([0], [i0_high])
plt.plot(
months / 12,
[yhat_fn(istar=istar, i0=i0_low, n=mm) for mm in months],
ls="",
label=f"Initial low ($i_{{t}}$): {i0_low:0.1f}%",
)
plt.plot(
months / 12,
[yhat_fn(istar=istar, i0=i0_high, n=mm) for mm in months],
ls="",
label=f"Initial high ($i_{{t}}$): {i0_high:0.1f}%",
)
plt.plot(
[min(months), max(months)],
[istar, istar],
ls="",
c="g",
label=f"Trend shortterm rate ($i_{{t}}^{{*}}$): {istar:0.1f}%",
)
plt.title("Expectations component of fixedyields: $\hat{y}_{t}^{(n)}$")
plt.ylabel("Percent")
plt.xlabel("Tenor ($n$) in years")
plt.xlim(xmin=0, xmax=120 / 12)
plt.grid(True)
for ax in fig.get_axes():
ax.label_outer()
legend = plt.legend(
loc="lower center",
ncol=4,
frameon=True,
fontsize=9,
bbox_to_anchor=(0.5, 0.03),
bbox_transform=plt.gcf().transFigure,
)
legend.set_zorder(60)
fig.tight_layout()
plt.show()
Natural convergence point: #
From JPMaQS we have the convergence point of shortterm rates ( \(i_{t}^{*}\) ) given by the two components of trend growth and effective inflation targets. Both are available as seperate indicators in JPMaQS, and hence for convenience we show them below.
Remember our assumption that we approximate the trend in realrates ( \(r_{t}^{*}\) ) by growth rates ( \(g_{t}^{*}\) ). As can be seen both inflation trends and growth trends show persistenty changes to their trends throughout the periods. This is in line with findings such as Bauer and Rudebusch (2020) .
cidx = cids
msp.view_timelines(
dfd,
xcats=["INFTEFF_NSA", "RGDP_SA_P1Q1QL4_20QMM"],
cids=cidx,
start="20000101",
title="Natural shortterm rate estimate components",
xcat_labels=[
"Effective inflation target ($\pi^{*}_{t}$)",
"Real GDP growth trend ($g_{t}^{*}$)",
],
title_adj=1.01,
title_fontsize=22,
label_adj=0.05,
ncol=4,
cumsum=False,
same_y=False,
size=(12, 7),
aspect=2,
all_xticks=True,
)