Skip to content
  • Research
    Macro Information Inefficiency
    • Understanding Macro Information Efficiency
    • Quantitative Methods for Macro Information Efficiency
    • Managing Systemic Risk
    • Understanding Macro Information Efficiency
    • Quantitative Methods for Macro Information Efficiency
    • Managing Systemic Risk
    Types of Systematic Macro Strategies
    • Fundamental Value Estimates
    • Macro Trends
    • Implicit Subsidies in Financial Markets
    • Endogenous Market Risk
    • Price Distortions
    • Fundamental Value Estimates
    • Macro Trends
    • Implicit Subsidies in Financial Markets
    • Endogenous Market Risk
    • Price Distortions
    Our Research
  • Quantamental Academy
    Macro-Quantamental Indicators
    • What Are Macro Quantamental Indicators?
    • Introductory Tutorials
    • Quantamental Indicators on JPMaQS
    • What Are Macro Quantamental Indicators?
    • Introductory Tutorials
    • Quantamental Indicators on JPMaQS
    Developing Macro Trading Factors
    • Value Generation Based on Quantamental Factors
    • Data Science with Quantamental Indicators
    • Examples of Macro Trading Factors
    • Value Generation Based on Quantamental Factors
    • Data Science with Quantamental Indicators
    • Examples of Macro Trading Factors
    Quantamental Academy
  • About Us
    About Macrosynergy
    • The Opportunity
    • Our Leadership
    • Our History
    • Careers
    • The Opportunity
    • Our Leadership
    • Our History
    • Careers
    About Us
Skip to main content
Ctrl + K

The power of macro trends in rates markets

  • .ipynb

The power of macro trends in rates markets

Contents

  • Get packages and JPMaQS data
    • Availability
    • Blacklist dictionary
  • Transformations and checks
    • Features (explanatory variables) of the analysis
      • Excess growth
      • Excess inflation
      • Excess credit growth
      • Composite macro trend pressures and rate-pressure gaps
      • Rate-pressure gaps
    • Target
  • Value checks
    • Simple macro trend pressure and IRS receiver returns. U.S. and the euro area
    • Simple macro trend pressure and IRS receiver returns. Other currency areas
    • Rate-pressure gaps and IRS receiver returns. U.S. and the euro area
    • Rate-pressure gaps and IRS receiver returns. Other currency areas

The power of macro trends in rates markets #

This notebook serves as an illustration of the points discussed in the post “The power of macro trends in rates markets” available on the Macrosynergy website. The post highlights the importance of broad macroeconomic trends, such as inflation , economic growth , and credit creation , in influencing shifts in monetary policy. These trends play a crucial role in determining whether monetary policy will lean towards tightening or easing.

The post emphasizes that markets may not always fully anticipate policy shifts that follow macro trends due to a possible lack of attention or conviction. In such cases, macro trends can serve as predictors of returns in fixed-income markets. Even a simple point-in-time macro pressure indicator, which is an average of excess inflation, economic growth, and private credit trends, has exhibited a significant correlation with subsequent interest rate swap returns for 2-year fixed rate receivers in both large and small currency areas.

The post also highlights that considering the gap between real rates and macro trend pressure provides an even higher forward correlation and remarkable directional accuracy in predicting fixed-income returns.

The notebook covers the three main parts:

  • Get Packages and JPMaQS Data: This section is responsible for installing and importing the necessary Python packages used throughout the analysis.

  • Transformations and Checks: In this part, the notebook performs calculations and transformations on the data to derive the relevant signals and targets used for the analysis, including the normalization of feature variables using z-score or building simple linear composite indicators.

  • Value Checks: This is the most critical section, where the notebook calculates and implements the trading strategies based on the hypotheses tested in the post. This section involves backtesting selected trading strategies targeting rates returns. In particular, the post investigates the predictive power of economic growth, inflation and private credit growth on subsequent rates returns.

It is important to note that while the notebook covers a selection of indicators and strategies used for the post’s main findings, users can explore countless other possible indicators and approaches. Users can modify the code to test different hypotheses and strategies based on their research and ideas. Best of luck with your research!

Get packages and JPMaQS data #

This notebook primarily relies on the standard packages available in the Python data science stack. However, there is an additional package, macrosynergy that is required for two purposes:

  • Downloading JPMaQS data: The macrosynergy package facilitates the retrieval of JPMaQS data, which is used in the notebook.

  • For the analysis of quantamental data and value propositions: The macrosynergy package provides functionality for performing quick analyses of quantamental data and exploring value propositions.

For detailed information and a comprehensive understanding of the macrosynergy package and its functionalities, please refer to the “Introduction to Macrosynergy package” notebook on the Macrosynergy Quantamental Academy or visit the following link on Kaggle .

# Run only if needed!
"""
%%capture
! pip install macrosynergy --upgrade
"""
'\n%%capture\n! pip install macrosynergy --upgrade\n'
import numpy as np
import pandas as pd
from pandas import Timestamp
import matplotlib.pyplot as plt
import seaborn as sns
import os

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 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 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 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. For more information see here

The notebook uses the macrosynergy package, which supports financial market research and the development of trading strategies based on formats and conventions of the J.P. Morgan Macrosynergy Quantamental System (JPMaQS). For full documentation on macrosynergy package check out https://github.com/macrosynergy/macrosynergy or view the notebook on Kaggle for examples.

# Quantamental categories of interest

ecos = [
    "CPIC_SA_P1M1ML12",
    "CPIC_SJA_P3M3ML3AR",
    "CPIC_SJA_P6M6ML6AR",
    "CPIH_SA_P1M1ML12",
    "CPIH_SJA_P3M3ML3AR",
    "CPIH_SJA_P6M6ML6AR",
    "INFTEFF_NSA",
    "INTRGDP_NSA_P1M1ML12_3MMA",
    "INTRGDPv5Y_NSA_P1M1ML12_3MMA",
    "RGDP_SA_P1Q1QL4_20QMA",
    "RYLDIRS02Y_NSA",
    "PCREDITBN_SJA_P1M1ML12",
]
mkts = [
    "DU02YXR_NSA",
    "DU02YXR_VT10",
 ]

xcats = ecos + mkts

The description of each JPMaQS category is available either under Macro Quantamental Academy , JPMorgan Markets (password protected), or on Kaggle (limited set of tickers used in this notebook). In particular, the set used for this notebook is using Consumer price inflation trends , Inflation targets , Intuitive growth estimates , Domestic credit ratios , Long-term GDP growth , Real interest rates , Private credit expansion , Duration returns

# Cross-sections of interest

cids_dm = ["AUD", "CAD", "CHF", "EUR", "GBP", "JPY", "NOK", "SEK", "USD"]
cids_em = [
    "CLP",
    "COP",
    "CZK",
    "HUF",
    "ILS",
    "INR",
    "KRW",
    "MXN",
    "PLN",
    "THB",
    "TRY",
    "TWD",
    "ZAR",
]
cids = cids_dm + cids_em
# Download series from J.P. Morgan DataQuery by tickers

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


# Download series from J.P. Morgan DataQuery by tickers

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

with JPMaQSDownload(client_id=client_id, client_secret=client_secret) as dq:
    df = dq.download(
        tickers=tickers,
        start_date="2000-01-01",
        suppress_warning=True,
        metrics=[
            "value",
        ],
        show_progress=True,
    )
Maximum number of tickers is 308
Downloading data from JPMaQS.
Timestamp UTC:  2024-03-21 15:06:57
Connection successful!
Requesting data: 100%|██████████| 16/16 [00:03<00:00,  4.94it/s]
Downloading data: 100%|██████████| 16/16 [00:08<00:00,  1.98it/s]
Some dates are missing from the downloaded data. 
2 out of 6321 dates are missing.
#  uncomment if running on Kaggle
"""for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))
                                                   
df = pd.read_csv('../input/fixed-income-returns-and-macro-trends/JPMaQS_Quantamental_Indicators.csv', index_col=0, parse_dates=['real_date'])"""
"for dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n                                                   \ndf = pd.read_csv('../input/fixed-income-returns-and-macro-trends/JPMaQS_Quantamental_Indicators.csv', index_col=0, parse_dates=['real_date'])"

This example notebook contains a few select categories for a subset of developed and emerging markets: AUD (Australian dollar), CAD (Canadian dollar), CHF (Swiss franc), CLP (Chilean peso), COP (Colombian peso), CZK (Czech Republic koruna), EUR (euro), GBP (British pound), HUF (Hungarian forint), IDR (Indonesian rupiah), ILS (Israeli shekel), INR (Indian rupee), JPY (Japanese yen), KRW (Korean won), MXN (Mexican peso), NOK (Norwegian krone), NZD (New Zealand dollar), PLN (Polish zloty), SEK (Swedish krona), TRY (Turkish lira), TWD (Taiwanese dollar), USD (U.S. dollar) and ZAR (South African rand). The following cell displays the lists of downloaded categories, cross-sections, and displays the first 3 rows of downloaded dataframe.

display(df["xcat"].unique())
display(df["cid"].unique())
df["ticker"] = df["cid"] + "_" + df["xcat"]
df.head(3)
array(['CPIC_SA_P1M1ML12', 'CPIC_SJA_P3M3ML3AR', 'CPIC_SJA_P6M6ML6AR',
       'CPIH_SA_P1M1ML12', 'CPIH_SJA_P3M3ML3AR', 'CPIH_SJA_P6M6ML6AR',
       'INFTEFF_NSA', 'INTRGDP_NSA_P1M1ML12_3MMA',
       'INTRGDPv5Y_NSA_P1M1ML12_3MMA', 'PCREDITBN_SJA_P1M1ML12',
       'RGDP_SA_P1Q1QL4_20QMA', 'RYLDIRS02Y_NSA', 'DU02YXR_NSA',
       'DU02YXR_VT10'], dtype=object)
array(['AUD', 'CAD', 'CHF', 'CLP', 'COP', 'CZK', 'EUR', 'GBP', 'HUF',
       'ILS', 'INR', 'JPY', 'KRW', 'MXN', 'NOK', 'PLN', 'SEK', 'THB',
       'TRY', 'TWD', 'USD', 'ZAR'], dtype=object)
real_date cid xcat value ticker
0 2000-01-03 AUD CPIC_SA_P1M1ML12 1.244168 AUD_CPIC_SA_P1M1ML12
1 2000-01-03 AUD CPIC_SJA_P3M3ML3AR 3.006383 AUD_CPIC_SJA_P3M3ML3AR
2 2000-01-03 AUD CPIC_SJA_P6M6ML6AR 1.428580 AUD_CPIC_SJA_P6M6ML6AR

Availability #

It is important to assess data availability before conducting any analysis. It allows for the identification of any potential gaps or limitations in the dataset, which can impact the validity and reliability of analysis and ensure that a sufficient number of observations for each selected category and cross-section is available and determining the appropriate time periods for analysis. The function missing_in_df() simply displays (1) categories that are missing across all expected cross-sections for a given category name list and (2) cross-sections that are missing within a category.

msm.missing_in_df(df, xcats=xcats, cids=cids)
Missing xcats across df:  []
Missing cids for CPIC_SA_P1M1ML12:  []
Missing cids for CPIC_SJA_P3M3ML3AR:  []
Missing cids for CPIC_SJA_P6M6ML6AR:  []
Missing cids for CPIH_SA_P1M1ML12:  []
Missing cids for CPIH_SJA_P3M3ML3AR:  []
Missing cids for CPIH_SJA_P6M6ML6AR:  []
Missing cids for DU02YXR_NSA:  []
Missing cids for DU02YXR_VT10:  []
Missing cids for INFTEFF_NSA:  []
Missing cids for INTRGDP_NSA_P1M1ML12_3MMA:  []
Missing cids for INTRGDPv5Y_NSA_P1M1ML12_3MMA:  []
Missing cids for PCREDITBN_SJA_P1M1ML12:  []
Missing cids for RGDP_SA_P1Q1QL4_20QMA:  []
Missing cids for RYLDIRS02Y_NSA:  []

Blacklist dictionary #

Before conducting any analysis, we take out bad data return periods for fixed-income markets. To check the rationality behind this removal, please see the period of non-tradability for TRY. We create a dictionary of the non-tradable period dublack for TRY and pass this dictionary to macrosynergy functions that exclude the blacklisted periods from related analyses.

msp.view_timelines(
    df,
    xcats=["DU02YXR_VT10"],
    cids=["TRY"],
    cumsum=False,
    start="2020-01-01",
    same_y=False,
    all_xticks=True,
    title="Duration return for 10% vol target: 2-year maturity, TRY",
)

dublack = {"TRY": (Timestamp("2020-01-01 00:00:00"), Timestamp("2100-01-01 00:00:00"))}
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/ed8b0449f44924848e9913bc30ab97882013dba543dba6a43142444b27b33df3.png

Transformations and checks #

Features (explanatory variables) of the analysis #

The basic hypothesis is that excess growth and inflation significantly shape the trend in real and nominal interest rates at all maturities. Positive excesses put upward pressure on rates while negative excesses (shortfalls) exert downward pressure. We call this pressure abstractly “macro trend pressure”. This pressure is unlikely to be fully priced in the market for lack of attention or conviction. In practice, financial markets often neglect the fundamental gravity of rates for the sake of abstract factors, such as carry, and risk management. Below example is a snippet of simple predictions that can be done with selected JPMaQs indicators.

Excess growth #

Excess growth is a ready-made category available in JPMaQS dataset. It is defined as Latest estimated “intuitive” GDP growth trend, % over a year ago, 3-month moving average minus a long-term median of that country’s actual GDP growth rate at that time: based on 5 year lookback of the latter. Please see full documentation here . For a description of the estimation of intuitive GDP growth see here . Here we simply plot ranges and timelines of the Excess Growth indicator with the help of view_ranges() and view_timelines() from the macrosynergy package:

xcatx = ["INTRGDPv5Y_NSA_P1M1ML12_3MMA"]
msp.view_ranges(
    df,
    cids=cids,
    xcats=xcatx,
    size=(12, 6),
    kind="bar",
    sort_cids_by="mean",
    ylab="% daily rate",
    start="2000-01-01",
)

msp.view_timelines(
    df,
    xcats=xcatx,
    cids=cids,
    ncol=4,
    cumsum=False,
    start="2000-01-01",
    same_y=False,
    all_xticks=False,
    title="Latest economic growth trend (intuitive quantamental measure) in excess of 5-year median, % oya, 3-month average",
    
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/53a8ebc512d28695a9c0714b552f2a3e1ac7745baf950a70105fc2f9178b3878.png https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/273b01f7f6defd8571d80801e7e8202ca41b950ac5f44fbe7894b0731b5fb8cc.png

Excess inflation #

In this notebook, excess inflation is defined as the difference between the recorded seasonally and jump-adjusted inflation trend and the effective inflation target ( INFTEFF_NSA ). The resulting indicator receives postfix vIET . This operation is performed with the help of panel_calculator() function from the macrosynergy.panel module

See below for calculate of plausible metrics of excess inflation versus a country’s effective inflation target.

# Preparation: for relative target deviations, we need denominator bases that should never be less than 2

dfa = msp.panel_calculator(df, ["INFTEBASIS = INFTEFF_NSA.clip(lower=2)"], cids=cids)
df = msm.update_df(df, dfa)

# Calculate absolute and relative target deviations for a range of CPI inflation metrics

infs = [
    "CPIH_SA_P1M1ML12",
    "CPIH_SJA_P6M6ML6AR",
    "CPIH_SJA_P3M3ML3AR",
    "CPIC_SA_P1M1ML12",
    "CPIC_SJA_P6M6ML6AR",
    "CPIC_SJA_P3M3ML3AR",
]
for inf in infs:
    calcs = [
        f"{inf}vIET = ( {inf} - INFTEFF_NSA )",
        f"{inf}vIETR = ( {inf} - INFTEFF_NSA ) / INFTEBASIS",
    ]

    dfa = msp.panel_calculator(df, calcs=calcs, cids=cids)
    df = msm.update_df(df, dfa)

# Average excess inflation metrics across three different standard horizons

calcs = []
for cp in ["CPIH", "CPIC"]:
    for v in ["vIET", "vIETR"]:
        calc = f"{cp}_SA_PALL{v} = ( {cp}_SA_P1M1ML12{v} + {cp}_SJA_P6M6ML6AR{v} + {cp}_SJA_P3M3ML3AR{v} ) / 3"
        calcs += [calc]

dfa = msp.panel_calculator(df, calcs, cids=cids)
df = msm.update_df(df, dfa)

Here we simply plot newly created excess inflation indicators with the help of view_timelines() from the macrosynergy package:

xcatx = ["CPIH_SA_P1M1ML12vIET",
        "CPIH_SJA_P6M6ML6ARvIET", "CPIH_SJA_P3M3ML3ARvIET"]


msp.view_timelines(
    df,
    xcats=xcatx,
    cids=cids,
    ncol=4,
    cumsum=False,
    start="2000-01-01",
    same_y=False,
    all_xticks=False,
    title="CPI inflation rates, %ar, versus effective inflation target, market information state",
    xcat_labels=["% over a year ago", "% 6m/6m, saar", "% 3m/3m, saar"],
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/c9dd61b8aebb7d17322a28b37c9cfc4da22286c75ad707394116eeb9a2a66678.png

Excess credit growth #

Similar to excess inflation, excess credit growth metrics require transformations and a neutral benchmark. A neutral benchmark here serves as a medium-term nominal GDP growth estimate, calculated as the sum of the past 5-years’ growth and the effective estimated inflation target. As before, panel_calculator() function from the macrosynergy.panel module is used to create new time series

dfa = msp.panel_calculator(
    df,
    ["PCBASIS = INFTEFF_NSA + RGDP_SA_P1Q1QL4_20QMA"],
    cids=cids,
)
df = msm.update_df(df, dfa)

pcgs = [
    "PCREDITBN_SJA_P1M1ML12",
  
]
for pcg in pcgs:
    calc_pcx = f"{pcg}vLTB = {pcg} - PCBASIS "
    dfa = msp.panel_calculator(df, calcs=[calc_pcx], cids=cids)
    df = msm.update_df(df, dfa)

Excess ratios based on expansion relative to GDP and a nominal GDP benchmark are not plausible metrics for the central bank because the initial leverage of the economy strongly affects the expansion rate and must plausibly be considered for the benchmark. Put economically, countries with bank leverage will always produce low rates versus a nominal GDP growth benchmark and part of that shortfall may reflect other channels of leverage outside the banking system, just as the credit markets in the U.S. The macrosynergy package provides two useful functions, view_ranges() and view_timelines() , which assist in plotting means, standard deviations, and time series of the chosen indicators.

xcatx = ["PCREDITBN_SJA_P1M1ML12vLTB"]


msp.view_timelines(
    df,
    xcats=xcatx,
    cids=cids,
    ncol=4,
    cumsum=False,
    start="2000-01-01",
    same_y=False,
    all_xticks=True,
    title="Private credit growth, %oya, relative to the sum of inflation target and long-term growth, market information state",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/459d152c9d042bbc5657325a1e8811bce3d10fba9d4b0030fc3a2d33d8dc5b47.png

Composite macro trend pressures and rate-pressure gaps #

For the empirical analysis, we add excess inflation, economic growth, and private credit to arrive at a primitive composite macro trend pressure indicator. This is undoubtedly not the optimal or most plausible way to combine the three components, as most central banks would put greater emphasis on inflation than on credit growth. However, simplicity trumps sophistication to deliver a proof of concept that is not suspect of data mining. This indicator measures the pressure for monetary tightening (positive values) or easing (negative values).

Using the macrosynergy package, we can visualize the newly created indicator.

calcs = [
    "XGHI = ( INTRGDPv5Y_NSA_P1M1ML12_3MMA + CPIH_SJA_P6M6ML6ARvIET ) / 2",
    "XGHIPC = ( INTRGDPv5Y_NSA_P1M1ML12_3MMA + CPIH_SJA_P6M6ML6ARvIET + PCREDITBN_SJA_P1M1ML12vLTB ) / 3",
 
]

dfa = msp.panel_calculator(df, calcs, cids=cids)
df = msm.update_df(df, dfa)
xcatx = ["XGHIPC", "XGHI"]

msp.view_timelines(
    df,
    xcats=xcatx,
    cids=cids,
    ncol=4,
    cumsum=False,
    start="2000-01-01",
    same_y=False,
    all_xticks=False,
    title="Composite macro trend pressure, % ar, in excess of benchmarks",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/aa0c7566cd25ecdb3eaa4e7657a9ef2c9bc64f28d48f2105b4deee4a611910aa.png

Rate-pressure gaps #

For the analysis below, we merely subtract the composite macro trend pressure from the real interest rate, as both are denominated in % annualized. A large positive gap means that the real rate is high and the macro trend pressure is small or negative. This should bias policy towards easing and be positive for subsequent receiver returns. Over the past 20 years, rate pressure gaps show both cyclical and longer-term dynamics. Time series for some EM countries start later, due to the limited availability of swap yield data.

calcs = [
    "RPG = RYLDIRS02Y_NSA - XGHI"
]

dfa = msp.panel_calculator(df, calcs, cids=cids)
df = msm.update_df(df, dfa)

xcatx = ["RPG"]


msp.view_timelines(
    df,
    xcats=xcatx,
    cids=cids,
    ncol=4,
    cumsum=False,
    start="2000-01-01",
    same_y=False,
    all_xticks=False,
    title="Composite rate pressure gap, (real 2-year yield minus macro trend pressure)",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/722e46d266a5a6eef0c090fc47ab66ddb263cac2b11f85036513d57cacc06e5a.png

Target #

The target returns of the analysis below are fixed receiver positions in 2-year interest swaps, targeted at 10% volatility to allow comparable risk-taking across all currency areas. Outperformance or underperformance of countries has often been persistent over months or even years.

xcats_sel = ["DU02YXR_VT10"]

msp.view_timelines(
    df,
    xcats=xcats_sel,
    cids=cids,
    ncol=4,
    cumsum=True,
    start="2000-01-01",
    same_y=False,
    all_xticks=False,
    title="Duration return, in % of notional: 2-year maturity ",
    xcat_labels=None,
    
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/1d38813d54b8efd51b859d52fa3d2d53598addac7f21449015709822bb0b8db0.png

Value checks #

In this part of the analysis, the notebook calculates the naive PnLs (Profit and Loss) for macro demand-based rates strategies using the previously derived demand indicators. The PnLs are calculated based on simple trading strategies that utilize the yields as signals (no regression is involved). The strategies involve going long (buying) or short (selling) of rates positions based purely on the direction of the score signals.

To evaluate the performance of these strategies, the notebook computes various metrics and ratios, including:

  • Correlation: Measures the relationship between the macro pressure and rate-pressure gaps on consequent bond returns. Positive correlations indicate that the strategy moves in the same direction as the market, while negative correlations indicate an opposite movement.

  • Accuracy Metrics: These metrics assess the accuracy of the macro and rate gap indicaror based strategies in predicting market movements. Common accuracy metrics include accuracy rate, balanced accuracy, precision, etc.

  • Performance Ratios: Various performance ratios, such as Sharpe ratio, Sortino ratio, Max draws, etc.

This notebook investigates two hypotheses:

  • Predictive power of simple macro trend pressure on subsequent IRS receiver returns, and

  • Predictive power of rate-pressure gaps on subsequent IRS receiver returns.

The post investigates these relationships separately for the large currency areas (EUR and USD) and for the rest of the available currencies. The rationale behind this distinction is that the idea that the local markets depend disproportionately on returns in the U.S. and the Euro area, and that we would expect that the predictive power of country-specific macro trends for smaller countries should be less, cet. par., , for smaller countries than for larger countries.

It is important to note that the analysis deliberately disregards transaction costs and risk management considerations. This is done to provide a more straightforward comparison of the strategies’ raw performance without the additional complexity introduced by transaction costs and risk management, which can vary based on trading size, institutional rules, and regulations.

Simple macro trend pressure and IRS receiver returns. U.S. and the euro area #

In the large currency areas, there has been significant predictive power of macro trend pressure on subsequent interest rate swap receiver returns. A sizeable negative correlation of 10% or more prevailed in both countries and across the decades of the sample. The negative correlation has been driven mainly by excess growth and inflation, in accordance with the intuition of the popular Taylor rule . With the help of CategoryRelations() we can quickly visualize and analyze two categories (signal and target). We define the lag and frequency (monthly in our case)

crm = msp.CategoryRelations(
    df,
    xcats=["XGHIPC", "DU02YXR_VT10"],
    cids=["USD", "EUR"],
    freq="M",
    lag=1,
    xcat_aggs=["last", "sum"],
    start="2000-01-01",
    xcat_trims=[None, None],
)
crm.reg_scatter(
    labels=False,
    coef_box="lower right",
    title="US and Euro area: macro pressure and subsequent monthly IRS returns",
    xlab="Average of excess inflation, economic growth, and excess credit growth, %ar, end-of-month information state",
    ylab="2-year interest rate swap receiver returns over the next month, %",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/a416ba853247e8a20a106485bab345a7758b809632b22b759046cec475a0a4ff.png

It is useful to check if the diagnosed relation has been stable over time. Relevant subperiods are decades in our case. Indeed, the correlation has been negative in both the 2000s and the 2010s and early 2020s.

crm.reg_scatter(
    labels=False,
    coef_box="upper left",
    title="Main markets: Fixed Income trend-adjusted macro trend and subsequent monthly IRS returns, 2002-2021",
    xlab=None,
    ylab=None,
    size=(12, 8),
    separator=2010,
    
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/dc504a6092445166143cab841b8b9c25d8cd20c7e5257f260e29a4fa4dfcca29.png

The SignalReturnRelations class of the macrosynergy package facilitates a quick assessment of the power of a signal category in predicting the direction of subsequent returns for data in JPMaQS format.

Accuracy (rate of correctly predicted market return direction) has been very high by the standards of macro trading signals over the past 22 years, at 56-58% at a monthly frequency. The same is true for balanced accuracy, which reflects that the macro trend signal predicted both positive and negative returns well. In fact, the ratio of correctly predicted positive returns was over 60% and the ratio of positively predicted negative returns was over 52%.

xcats_sel = ["XGHIPC", "DU02YXR_VT10"]
srr = mss.SignalReturnRelations(
    df,
    cids=["USD", "EUR"],
    sigs=xcats_sel[0],
    sig_neg=[True],  # use the negative of signal category
    rets=xcats_sel[1],
    freqs="M",
    start="2000-01-01",
)
srr.cross_section_table()
accuracy bal_accuracy pos_sigr pos_retr pos_prec neg_prec pearson pearson_pval kendall kendall_pval auc
Panel 0.567 0.573 0.432 0.534 0.617 0.528 0.155 0.000 0.122 0.000 0.572
Mean 0.567 0.576 0.437 0.534 0.620 0.532 0.165 0.050 0.113 0.017 0.571
PosRatio 1.000 1.000 0.500 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
EUR 0.579 0.576 0.553 0.538 0.605 0.546 0.233 0.000 0.143 0.001 0.575
USD 0.555 0.576 0.321 0.531 0.634 0.518 0.097 0.101 0.084 0.033 0.567

Here is a brief explanations of the .summary_table() outputs of the SignalReturnRelations :

srr.accuracy_bars()
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/7d258f037e58d2d312a72d21ce3914ee99f8f0ca4c4bada8330134c751ee1d07.png
start_date = "2000-01-01"
end_date = "2023-01-01"
sigs = ["XGHIPC", "XGHI"]

naive_pnl = msn.NaivePnL(
    df,
    ret="DU02YXR_VT10",
    sigs=sigs,
    cids=["USD", "EUR"],
    start=start_date,
    end=end_date,
   
)

for sig in sigs:
    naive_pnl.make_pnl(
        sig,
        sig_neg=True,
        sig_op="zn_score_pan",
        thresh=2,
        rebal_freq="monthly",
        vol_scale=10,
        rebal_slip=1,
        pnl_name=sig + "_PZN",
    )

The signal_heatmap() method is used to create a heatmap of signals for a specific PnL across time and sections.

naive_pnl.signal_heatmap(pnl_name=sigs[0] + "_PZN")
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/f5b2b481c9f3088669b043921bb7a56bf5057d8cf0de24c039def9e0db256e5d.png

Simple macro trend pressure and IRS receiver returns. Other currency areas #

The correlation between macro trend pressure on rates and subsequent swap receiver returns has also been negative in the 16 smaller currency areas. The Pearson correlation coefficient has been a bit smaller but owing to the abundance of data, its conventional significance statistic has been near 100%.

The predictive power of country-specific macro trends should, all other things equal, be less for small countries, as their local markets depend disproportionately on returns in the U.S. and the euro area. Efficient prediction of small countries’ fixed income returns based on macro trends should use both local macro trends and those of the big two countries.

cids_small=list(set(cids)-set(["USD", "EUR"]))

crm = msp.CategoryRelations(
    df,
    xcats=["XGHIPC", "DU02YXR_VT10"],
    cids=cids_small,
    freq="M",
    lag=1,
    xcat_aggs=["last", "sum"],
    blacklist=dublack,
    start="2000-01-01",
    xcat_trims=[None, None],
)
crm.reg_scatter(
    labels=False,
    coef_box="lower right",
    title="Smaller countries: macro pressure and subsequent monthly IRS returns",
    xlab="Average of excess inflation, economic growth, and private credit growth, %ar, end-of-month information state",
    ylab="2-year interest rate swap receiver returns over the next month, %",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/2255d0d3350a39b6a15f097962074c009317b96f49fa31e15ebad7d85ddaed75.png

Accuracy has been materially lower when predicting local swap returns with local macro trend pressures alone in the smaller currency areas. This plausibly reflects two effects. First, as mentioned above, returns in smaller countries are disproportionately affected by the macro trends and other return factors of the large currency areas. Thus, U.S. markets strongly influence Australia, but not the other way round, Second, benchmarks for excess inflation and growth are much harder to estimate for some of the smaller countries for lack of data, particularly in the early part of the 2000s.

xcats_sel = ["XGHIPC", "DU02YXR_NSA"]
srr = mss.SignalReturnRelations(
    df,
    cids=cids_small,
    sigs=xcats_sel[0],
    sig_neg=[True],  # use the negative of signal category
    rets=xcats_sel[1],
    blacklist=dublack,
    freqs="M",
    start="2000-01-01",
)
srr.cross_section_table()
accuracy bal_accuracy pos_sigr pos_retr pos_prec neg_prec pearson pearson_pval kendall kendall_pval auc
Panel 0.524 0.532 0.399 0.536 0.575 0.490 0.076 0.000 0.063 0.000 0.531
Mean 0.522 0.534 0.392 0.536 0.578 0.491 0.084 0.303 0.070 0.194 0.529
PosRatio 0.800 0.850 0.250 0.950 0.950 0.300 0.950 0.800 0.950 0.900 0.850
AUD 0.484 0.507 0.304 0.557 0.566 0.447 0.015 0.800 0.055 0.174 0.506
CAD 0.510 0.521 0.297 0.517 0.547 0.495 0.115 0.051 0.060 0.130 0.517
CHF 0.548 0.548 0.503 0.541 0.589 0.507 0.188 0.001 0.125 0.002 0.548
CLP 0.478 0.488 0.266 0.527 0.509 0.467 0.014 0.837 0.027 0.568 0.491
COP 0.503 0.521 0.297 0.535 0.565 0.477 0.103 0.201 0.066 0.225 0.518
CZK 0.522 0.536 0.304 0.522 0.571 0.500 0.103 0.119 0.069 0.119 0.530
GBP 0.553 0.555 0.444 0.513 0.574 0.536 0.063 0.298 0.081 0.044 0.554
HUF 0.583 0.589 0.457 0.561 0.657 0.520 0.123 0.063 0.121 0.006 0.589
ILS 0.502 0.493 0.553 0.584 0.579 0.408 0.136 0.045 0.041 0.372 0.493
INR 0.484 0.476 0.405 0.465 0.437 0.516 -0.020 0.768 -0.018 0.687 0.477
JPY 0.572 0.548 0.728 0.576 0.602 0.494 0.046 0.438 0.060 0.126 0.539
KRW 0.526 0.535 0.381 0.530 0.573 0.496 0.082 0.233 0.132 0.004 0.533
MXN 0.498 0.554 0.164 0.548 0.639 0.470 0.015 0.830 0.034 0.449 0.530
NOK 0.510 0.522 0.234 0.510 0.544 0.500 0.114 0.053 0.085 0.031 0.516
PLN 0.543 0.543 0.496 0.504 0.548 0.539 0.050 0.431 0.068 0.109 0.543
SEK 0.534 0.573 0.307 0.572 0.674 0.473 0.191 0.001 0.135 0.001 0.564
THB 0.562 0.561 0.530 0.511 0.569 0.553 0.062 0.357 0.093 0.040 0.561
TRY 0.506 0.590 0.148 0.556 0.708 0.471 0.131 0.097 0.057 0.286 0.546
TWD 0.512 0.506 0.567 0.544 0.549 0.462 0.088 0.201 0.041 0.367 0.506
ZAR 0.515 0.518 0.453 0.536 0.556 0.480 0.070 0.245 0.059 0.145 0.518
srr.accuracy_bars()
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/3a57cf071a2c7954fd192daf9a4e9919373518bf4aa7a349b3c5e2aceb4f5e02.png

Rate-pressure gaps and IRS receiver returns. U.S. and the euro area #

The correlation of rate-pressure gaps and subsequent returns in the two large currency areas has been positive and significantly stronger than the correlation for macro trend pressure alone.

crm = msp.CategoryRelations(
    df,
    xcats=["RPG", "DU02YXR_VT10"],
    cids=["USD", "EUR"],
    freq="M",
    lag=1,
    xcat_aggs=["last", "sum"],
    start="2000-01-01",
    xcat_trims=[None, None],
)
crm.reg_scatter(
    labels=False,
    coef_box="lower right",
    title="US and Euro area: macro pressure and subsequent monthly IRS returns",
    xlab="Average of excess inflation and economic growth, %ar, end-of-month information state",
    ylab="2-year interest rate swap receiver returns over the next month, %",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/7c59b45f251032413215d488cb7c913d8453c7382d7db50c8ca908d097ca1f33.png
xcats_sel = ["RPG", "DU02YXR_VT10"]
srr = mss.SignalReturnRelations(
    df,
    cids=["USD", "EUR"],
    sigs=xcats_sel[0],
    rets=xcats_sel[1],
    freqs="M",
    start="2000-01-01",
    end="2023-01-01"
)
srr.accuracy_bars()
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/78c0ae07b7598c500eab9a032bf14cb42740df750a8911a0f61838fbd9c7019c.png

Rate-pressure gaps and IRS receiver returns. Other currency areas #

The predictive power of local rate-pressure gaps has been significantly lower for the 16 smaller currency areas. This difference plausibly reflects the dominant influence of the U.S. and – to a smaller extent – the euro area, as well as differences in data quality.

crm = msp.CategoryRelations(
    df,
    xcats=["RPG", "DU02YXR_VT10"],
    cids=cids_small,
    freq="M",
    lag=1,
    blacklist=dublack,
    xcat_aggs=["last", "sum"],
    start="2000-01-01",
    xcat_trims=[None, None],
)
crm.reg_scatter(
    labels=False,
    coef_box="lower right",
    title="Smaller countries: rate-pressure gap and subsequent monthly IRS returns",
    xlab="Real 2-year yield minus average of excess inflation, economic and private credit growth, %ar, end-of-month information state",
    ylab="2-year interest rate swap receiver returns over the next month, %",
)
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/f27b15eae23f7ad523fc29a3748e050582d7c455485ef0dd7fcf82bc316fef2e.png
xcats_sel = ["RPG", "DU02YXR_NSA"]
srr = mss.SignalReturnRelations(
    df,
    cids=cids_small,
    sigs=xcats_sel[0],
    blacklist=dublack,
    rets=xcats_sel[1],
    freqs="M",
    start="2000-01-01",
)

srr.accuracy_bars()
https://macrosynergy.com/notebooks.build/trading-factors/the-power-of-macro-trends-in-rates-markets/_images/e7d4c0b2d458255fbf5bfc2552b11718b3d4ba3a11700371ac060e19576a5652.png
Contents
  • Get packages and JPMaQS data
    • Availability
    • Blacklist dictionary
  • Transformations and checks
    • Features (explanatory variables) of the analysis
      • Excess growth
      • Excess inflation
      • Excess credit growth
      • Composite macro trend pressures and rate-pressure gaps
      • Rate-pressure gaps
    • Target
  • Value checks
    • Simple macro trend pressure and IRS receiver returns. U.S. and the euro area
    • Simple macro trend pressure and IRS receiver returns. Other currency areas
    • Rate-pressure gaps and IRS receiver returns. U.S. and the euro area
    • Rate-pressure gaps and IRS receiver returns. Other currency areas

By Macrosynergy Ltd.

© Copyright 2023.

ABOUT US

Macrosynergy is a London based macroeconomic research and technology company whose founders have developed and employed macro quantamental investment strategies in liquid, tradable asset classes, across many markets and for a variety of different factors to generate competitive, uncorrelated investment returns for institutional investors for two decades. Our quantitative-fundamental (quantamental) computing system tracks a broad range of real-time macroeconomic trends in developed and emerging countries, transforming them into macro systematic quantamental investment strategies. In June 2020 Macrosynergy and J.P. Morgan started a collaboration to scale the quantamental system and to popularize tradable economics across financial markets.

FOLLOW US
Linkedin
LEGAL
  • Terms of business
  • Cookie Policy
  • Acceptable use policy
  • Privacy Policy
  • Terms of business
  • Cookie Policy
  • Acceptable use policy
  • Privacy Policy
© 2023 Macrosynergy Ltd. | All rights reserved
  • The Opportunity
  • Our Leadership
  • Our History
  • Careers
  • The Opportunity
  • Our Leadership
  • Our History
  • Careers
Manage Cookie Consent
To provide the best experiences on macrosynergy.com, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
View preferences
{title} {title} {title}
  • Research
    • Macro Information Efficiency
    • Quantitative methods for macro information efficiency
    • Fundamental Value Estimates
    • Macro Trends
    • Implicit Subsidies in Financial Markets
    • Endogenous Market Risk
    • Price Distortions
    • Basics of systemic risk management
    • Non-Conventional Monetary Policies
    • Financial System Risk
    • Government Finances
  • Quantamental Academy
    • What Are Macro Quantamental Indicators?
    • Introductory Tutorials
    • Quantamental indicators on JPMaQS
    • Value Generation Based On Quantamental Factors
    • Statistics Packages With Quantamental Indicators
    • Examples of Macro Trading Factors
  • About Us
    • The Opportunity
    • Our Leadership
    • Our History
    • Careers
Research
Quantamental Academy
About Us