Technical GDP growth estimates #

The category group contains real-time GDP growth trends based on vintages of standard econometric (“technical”) estimates. Historic and current models are based on the simplest conventions and are recurrently reconstructed based on learning (view basic principles here ). This process reduces the contamination of model hyperparameters by hindsight, makes backtests more meaningful, and sets out clear rules for the generation of estimates in the future.

This category group is an instance of “technical macro trends”, real-time econometric trend estimates of fundamental developments that complement and qualify market trends for the purpose of algorithmic trading.

Technical real GDP growth trend changes #

Ticker : RGDPTECH_SA_P1M1ML12_D3M3ML3

Label : Change in technical real GDP trend over the past 3 months

Definition : Real GDP growth, % over a year ago, 3-month average, change over the last three estimable months.

Notes :

  • This metric is measuring estimations of growth changes, not changes in estimations. The changes are always calculated based on the latest available vintage of growth estimations.

  • Technical RGDP growth trend means the latest estimated GDP growth trend based on pre-selected monthly economic indicators related to RGDP growth based on a two-stage supervised learning method. See Appendix 1 below.

  • For further details, see the tickers RGDPTECH_SA_P1M1ML12_3MMA / RGDPTECH_SA_P1M1ML12 .

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 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_dm = ["USD", "GBP", "EUR", "JPY", "AUD", "CAD", "CHF", "NZD", "SEK", "NOK"]

cids_em = [
    "CNY",
    "KRW",
    "SGD",
    "MXN",
    "INR",
    "RUB",
    "ZAR",
    "TRY",
    "BRL",
    "TWD",
    "PLN",
    "THB",
    "IDR",
    "HUF",
    "CZK",
    "ILS",
    "CLP",
    "PHP",
    "COP",
    "MYR",
    "RON",
    "PEN",
]

cids = cids_dm + cids_em
main = [
    "RGDPTECH_SA_P1M1ML12",
    "RGDPTECH_SA_P1M1ML12_3MMA",
    "RGDPTECH_SA_P1M1ML12_D3M3ML3",
    "RGDPTECHv10Y_SA_P1M1ML12_3MMA",
    "RGDPTECHv5Y_SA_P1M1ML12_3MMA",
]

econ = [
    "RIR_NSA",
    "FXCRR_NSA",
    "INTRGDP_NSA_P1M1ML12_3MMA",
    "FXTARGETED_NSA",
    "FXUNTRADABLE_NSA",
]  # economic context

mark = [
    "EQXR_NSA",
    "EQXR_VT10",
    "DU05YXR_NSA",
    "DU05YXR_VT10",
    "FXXR_NSA",
    "FXXR_VT10",
]  # market links


xcats = main + econ + mark
# 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,
        show_progress=True,
        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 512
Downloading data from JPMaQS.
Timestamp UTC:  2023-07-14 16:17:12
Connection successful!
Number of expressions requested: 2048
Requesting data: 100%|███████████████████████████████████████████████████████████████| 103/103 [00:32<00:00,  3.13it/s]
Downloading data: 100%|██████████████████████████████████████████████████████████████| 103/103 [00:59<00:00,  1.72it/s]
Download time from DQ: 0:02:09.746329

Availability #

cids_exp = cids_dm + cids_em  # cids expected in category panels

msm.missing_in_df(dfd, xcats=main, cids=cids_exp)
Missing xcats across df:  set()
Missing cids for RGDPTECH_SA_P1M1ML12:  set()
Missing cids for RGDPTECH_SA_P1M1ML12_3MMA:  set()
Missing cids for RGDPTECH_SA_P1M1ML12_D3M3ML3:  set()
Missing cids for RGDPTECHv10Y_SA_P1M1ML12_3MMA:  set()
Missing cids for RGDPTECHv5Y_SA_P1M1ML12_3MMA:  set()

In developed markets and a portion of the emerging world, real-time measures of technical real GDP trends are available from the early 2000s. However, for some emerging countries these trends could only be estimated from the late 2000s due to lack of meaningful high-frequency growth indicators. Excess growth versus 10-year medians have significantly shorter history than outright growth trend estimates for some EM countries.

xcatx = main
cidx = cids_exp

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

print("Last updated:", date.today())
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/623a3fdf4561a886099f811daefed9e29ebe81c7ee5a4f3ed6e0b56f7a4030f8.png
Last updated: 2023-07-14
plot = msm.check_availability(
    dfd, xcats=main, cids=cids_exp, start_size=(20, 2), start_years=False
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/a81e2facfb4066998f83ca132125dfb65ad6d771f4636c2bf90d9b8511f76ebf.png

Average grading is high across all indicators and cross-sections. Brazil, the Czech Republic and India are the only currency areas to attain perfect grades.

plot = msp.heatmap_grades(
    dfd,
    xcats=main,
    cids=cids_exp,
    size=(19, 2),
    title=f"Average vintage grades from {start_date} onwards",
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/a9c14c78189abfb9b9a3882004ec2e068d725e958606e9ddbe3c17fbd46df559.png
xcatx = main
cidx = cids_exp

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    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=cidx,
    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),
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/5c7d9663bee07e4bb32e9de671ecc22a6c9ccd0573557b189d9a7b253f184ea7.png https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/84f471c5f54f96ea799e33bc9d203a76a030869292eefe735ddd3d4eb96032d7.png

History #

Technical real GDP growth trends #

There have been sizeable differences in the variations in technical real GDP trends. These are not only related to different economic structures, but also, and probably more so, to the availability of high-frequency predictors of real activity. More credible predictors also means more sources of variations in estimates. Conversely, economies with few meaningful higher-frequency growth indicators experiences less fluctuations in estimated growth. A prime example for the latter is China.

xcatx = ["RGDPTECH_SA_P1M1ML12"]
cidx = cids_exp

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    sort_cids_by="mean",
    start="2000-01-01",
    kind="bar",
    title="Means and standard deviations of annual technical real GDP trends, since 2000",
    size=(16, 8),
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/8a8607655aacbc474f0d69f680eb8bf9fb50ede9348eeae6249860d7c76953c9.png
xcatx = ["RGDPTECH_SA_P1M1ML12", "RGDPTECH_SA_P1M1ML12_3MMA"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="2000-01-01",
    title="Technical real GDP growth trends",
    title_fontsize=27,
    legend_fontsize=17,
    title_adj=1.02,
    title_xadj=0.45,
    label_adj=0.075,
    xcat_labels=["%oya, monthly", "3-month averages"],
    ncol=4,
    same_y=False,
    aspect=1.7,
    all_xticks=False,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/fabf7482609f096dac4ca3edc1c05888f55dd4bd656ad86c934daabc430561cb.png

Correlations of estimated growth trends have been almost uniformly positive across developed economies. Australia is the notable exception.

xcatx = "RGDPTECH_SA_P1M1ML12_3MMA"
cidx = cids_exp

msp.correl_matrix(
    dfd,
    xcats=xcatx,
    cids=cidx,
    title="Cross-sectional correlations of technical GDP growth trends, 3-month moving averages, across countries",
    size=(20, 14),
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/d50f467a95d2ac7021d49869c35d48d01ab71516dbf26c4cebc4f7918021cef4.png

Technical real growth trends have broadly tracked similar cyclical patterns as intuitive real growth trends (a separate quantamental growth trend indicator that mimics the more practical chart-based analysis of growth developments that is often employed by market economists). Neither of these two categories has had a clear and obvious information advantage over the other.

Yet there have been notable differences between the two concepts on various occasions. In Australia, the technical indicator was much less variable in the 2010s. In Switzerland and the Eurozone, the technical indicator suggested a less pronounced COVID recession. In New Zealand, the technical indicator showed more pronounced cyclical dynamics in the 2000s.

xcatx = ["RGDPTECH_SA_P1M1ML12_3MMA", "INTRGDP_NSA_P1M1ML12_3MMA"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="2000-01-01",
    title="Different types of real-time GDP growth trend estimations, %oya, 3mma",
    title_fontsize=27,
    legend_fontsize=17,
    title_adj=1.03,
    title_xadj=0.46,
    label_adj=0.075,
    xcat_labels=["Technical trend", "Intuitive trend"],
    ncol=4,
    same_y=False,
    aspect=1.7,
    all_xticks=False,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/901d2aa9560e5735c895cec23e3dae72de7da70c87e538a06c5770915785096f.png

Technical real GDP growth trend changes #

Technical real growth changes have displayed vastly different ranges across countries, accentuated by the COVID pandemic downturn and recovery. As with trend variation these differences partly reflect availability of timely relevant higher-frequency activity indicators. The more good-quality indicators are available, the more often ecometric models would they their output.

xcatx = ["RGDPTECH_SA_P1M1ML12_D3M3ML3"]
cidx = cids_exp

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    sort_cids_by="std",
    start="2000-01-01",
    title="Means and standard deviations of 3-month changes in annual technical real GDP growth trends",
    kind="box",
    size=(16, 8),
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/ef8007035c3b80fb7e91981843c8d45b85b556dba0c9490c6beb2546f4c5588c.png
xcatx = ["RGDPTECH_SA_P1M1ML12_D3M3ML3"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start="2000-01-01",
    title="Technical real GDP growth trend changes",
    title_fontsize=27,
    title_adj=1.02,
    title_xadj=0.515,
    legend_fontsize=17,
    ncol=4,
    same_y=False,
    aspect=1.7,
    all_xticks=False,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/55a49ffd96653ea317033f0401a2a4bb12d7b74d7cb63414502e04d24313d7ae.png

Like trends, technical real growth trend changes have been positively correlated across most available cross-sections.

xcatx = "RGDPTECH_SA_P1M1ML12_D3M3ML3"
cidx = cids_exp

msp.correl_matrix(
    dfd,
    xcats=xcatx,
    cids=cidx,
    title="Cross-sectional correlations of technical real GDP growth trend changes",
    size=(20, 14),
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/cb35a8116b664f002522f2f0ec24f4be15290591b8e45ea7056394cfd6b039d7.png

Importance #

Empirical clues #

As proposed by most theories, there has been a positive long-term relationship between observed technical GDP trends and real short-term interest rates in developed markets. While real rates are affected by many other factors, information efficiency in tracking growth almost certainly helps predictions. Real growth trends can also serve as a “gravity centre” for real interest rates in the longer term.

cr = msp.CategoryRelations(
    dfd,
    xcats=["RGDPTECH_SA_P1M1ML12", "RIR_NSA"],
    cids=cids_dm,
    freq="A",
    lag=0,
    xcat_aggs=["mean", "mean"],
    start="2000-01-01",
)

cr.reg_scatter(
    title="Technical GDP trends and real interest rates in developed markets, annual averages since 2000",
    labels=True,
    coef_box="upper left",
    xlab="Technical GDP growth trend, annual",
    ylab="Main real short-term interest rate",
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/1ea7a05558e8ef5dfb33ea9f39cd844589f7ccfe50ac9aec0ee35518890b1d5d.png

By contrast, the relation between GDP trends and real interest rates in the emerging world has been rather negative. This is plausibly due to “reverse causality”: countries or periods that impose high real policy rates or high implicit risk premia for local bonds and deposits provide less favorable growth conditions.

cr = msp.CategoryRelations(
    dfd,
    xcats=["RGDPTECH_SA_P1M1ML12", "RIR_NSA"],
    cids=cids_em,
    years=3,
    lag=0,
    xcat_aggs=["mean", "mean"],
    start="2000-01-01",
)

cr.reg_scatter(
    title="Technical GDP trends and real interest rates in EM countries, 3-year averages since 2000",
    labels=True,
    coef_box="lower left",
    xlab="Technical GDP growth trend 3MMA",
    ylab="Main real short-term interest rate",
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/6e1e09e92b1e99c99e5c903856294c2539a4b1353ef8da37cca4aca45c62fab4.png

In the developed world, technical GDP trends have been significant preductors of subsequent monthly 10% vol-targeted equity returns.

cr = msp.CategoryRelations(
    dfd,
    xcats=["RGDPTECH_SA_P1M1ML12", "EQXR_VT10"],
    cids=cids_dm,
    freq="M",
    lag=1,
    xcat_aggs=["last", "sum"],
    fwin=1,
    start="2002-01-01",
)

cr.reg_scatter(
    title="Technical real GDP trends and subsequent equity returns, 10% vol-target, since 2000",
    labels=False,
    coef_box="upper right",
    xlab="Observed technical GDP trend, %oya",
    ylab="Equity index future return, next month",
)
EQXR_VT10 misses: ['NOK', 'NZD'].
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/1758a30a54b3bb6dc44b63ecba60f8458ce9852bbf548285d1ee67094f41b2ef.png

Technical excess growth in the developed world has been negatively correlated with subsequent duration returns (measured by 5-year IRS fixed receiver positions), consistent with the intuition of a Taylor rule for monetary policy and some market inefficiency in pricing changes in excess growth trends consistently.

cr = msp.CategoryRelations(
    dfd,
    xcats=["RGDPTECHv5Y_SA_P1M1ML12_3MMA", "DU05YXR_NSA"],
    cids=cids_dm,
    freq="M",
    lag=1,
    xcat_aggs=["last", "sum"],
    fwin=1,
    start="2002-01-01",
    xcat_trims=[20, 200],
)

cr.reg_scatter(
    title="Technical GDP excess growth trend changes and subsequent IRS returns in developed countries since 2002",
    labels=False,
    coef_box="upper right",
    xlab="Excess technical real GDP growth trend, % oya, 3mma, based on 5 year lookback",
    ylab="Next month 5-year IRS returns, % mr",
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/4453a6a5f6a1cbeb2a99e339bd647260ef1929e0086b94c794db5965ff7488d6.png

Appendices #

Appendix 3: 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).