GDP growth #

This category group includes simple measures of short- and long-term real GDP growth based on national accounts alone. Unlike “intuitive” and “technical” GDP growth estimates they do not use higher-frequency activity indicators. Long-term growth rates are typically used as benchmarks for the performance of concurrent activity and real interest rates. In strategy development, long-term real GDP growth serves as a proxy for “potential growth”, the sustainable trend path of the economy. Traditional measures of potential GDP growth would require elaborate estimation and are subject to much methodological debate.

Simple GDP growth rates #

Ticker : RGDP_SA_P1Q1QL1AR / _P2Q2QL2AR / RGDP_SA_P1Q1QL4

Label : Real GDP: %q/q, saar / %2q/2q, saar / % oya

Definition : Real GDP based on quarterly national accounts: %quarter-on-quarter, seasonally adjusted annualized / %2quarters-over-2quarters, seasonally adjusted annualized / % over a year ago

Notes :

  • In general all these growth indicators rate used vintages of national accounts data only.

  • For some countries and older vintages where quarterly national countries were not available, annual data history has been used.

5-year real GDP growth #

Ticker : RGDP_SA_P1Q1QL4_20QMA / _P1Q1QL4_20QMM

Label : Long-term real GDP growth: 5-year moving average / 5-year moving median

Definition : Long-term real GDP growth, % over a year ago, based on a trailing lookback window: 5-year (20 quarters) moving average / 5-year (20 quarters) moving median

Notes :

  • This average uses only quarterly national accounts data of the concurrently available vintages. For some older history where quarterly reports were not available, annual data history has been used.

10-year real GDP growth #

Ticker : RGDP_SA_P1Q1QL4_40QMA / _P1Q1QL4_40QMM

Label : Long-term real GDP growth: 10-year moving average / 10-year moving median.

Definition : Long-term real GDP growth, % over a year ago, based on a trailing lookback window: 10-year (40 quarters) moving average / 10-year (40 quarters) moving median.

Notes :

  • This average uses only quarterly national accounts data of the concurrently available vintages. For some older history where quarterly reports were not available, annual data history has been used.

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 obtain the data. Here tickers is an array of ticker strings, start_date is the first release date to be considered and metrics denotes the types of information requested.

# Cross-sections of interest

cids_dmca = [
    "AUD",
    "CAD",
    "CHF",
    "EUR",
    "GBP",
    "JPY",
    "NOK",
    "NZD",
    "SEK",
    "USD",
]  # DM currency areas
cids_dmec = ["DEM", "ESP", "FRF", "ITL", "NLG"]  # DM euro area countries
cids_latm = ["BRL", "COP", "CLP", "MXN", "PEN"]  # Latam countries
cids_emea = ["CZK", "HUF", "ILS", "PLN", "RON", "RUB", "TRY", "ZAR"]  # EMEA countries
cids_emas = [
    "CNY",
    "HKD",
    "IDR",
    "INR",
    "KRW",
    "MYR",
    "PHP",
    "SGD",
    "THB",
    "TWD",
]  # EM Asia countries

cids_dm = cids_dmca + cids_dmec
cids_em = cids_latm + cids_emea + cids_emas

cids = sorted(cids_dm + cids_em)
# Quantamental categories of interest

main = [
    "RGDP_SA_P1Q1QL4",
    "RGDP_SA_P2Q2QL2AR",
    "RGDP_SA_P1Q1QL1AR",
    "RGDP_SA_P1Q1QL4_20QMA",
    "RGDP_SA_P1Q1QL4_20QMM",
    "RGDP_SA_P1Q1QL4_40QMA",
    "RGDP_SA_P1Q1QL4_40QMM",
]
econ = [
    "INTRGDPv5Y_NSA_P1M1ML12_3MMA",
    "INTRGDPv10Y_NSA_P1M1ML12_3MMA",
]  # economic context
mark = [
    "EQXR_NSA",
    "EQXR_VT10",
    "FXXR_NSA",
    "FXXR_VT10",
    "DU05YXR_NSA",
    "DU05YXR_VT10",
    "FXTARGETED_NSA",
    "FXUNTRADABLE_NSA",
]  # market links

xcats = main + econ + mark
# Download series from J.P. Morgan DataQuery by tickers

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

# Retrieve credentials

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

# Download from DataQuery

with JPMaQSDownload(client_id=client_id, client_secret=client_secret) as downloader:
    start = timer()
    df = downloader.download(
        tickers=tickers,
        start_date=start_date,
        metrics=["value", "eop_lag", "mop_lag", "grading"],
        suppress_warning=True,
        show_progress=True,
    )
    end = timer()

dfd = df

print("Download time from DQ: " + str(timedelta(seconds=end - start)))
Maximum number of tickers is 646
Downloading data from JPMaQS.
Timestamp UTC:  2024-07-02 13:33:22
Connection successful!
Requesting data: 100%|██████████| 130/130 [00:29<00:00,  4.40it/s]
Downloading data: 100%|██████████| 130/130 [00:38<00:00,  3.37it/s]
Some expressions are missing from the downloaded data. Check logger output for complete list.
348 out of 2584 expressions are missing. To download the catalogue of all available expressions and filter the unavailable expressions, set `get_catalogue=True` in the call to `JPMaQSDownload.download()`.
Some dates are missing from the downloaded data. 
2 out of 7699 dates are missing.
Download time from DQ: 0:01:19.271962

Availability #

cids_exp = sorted(
    list(set(cids) - set(cids_dmec + ["ARS", "HKD"]))
)  # cids expected in category panels
msm.missing_in_df(dfd, xcats=main, cids=cids_exp)
No missing XCATs across DataFrame.
Missing cids for RGDP_SA_P1Q1QL1AR:      []
Missing cids for RGDP_SA_P1Q1QL4:        []
Missing cids for RGDP_SA_P1Q1QL4_20QMA:  []
Missing cids for RGDP_SA_P1Q1QL4_20QMM:  []
Missing cids for RGDP_SA_P1Q1QL4_40QMA:  []
Missing cids for RGDP_SA_P1Q1QL4_40QMM:  []
Missing cids for RGDP_SA_P2Q2QL2AR:      []

At present, choice of lookback window is a trade-off between length of history and availability of data. Real-time quantamental indicators of long-term GDP growth are typically available from the late 90s for developed markets. For some EM countries, the series’ only begin in the mid-2000s for the 5-year lookback and for some even after 2010 for the 10-year lookback.

For the explanation of currency symbols, which are related to currency areas or countries for which categories are available, please view Appendix 1 .

xcatx = main
cidx = cids_exp

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

print("Last updated:", date.today())
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/8454a56fe47859e3320231f89cf2e7e54709a0437cba7255899c44d407d6894a.png
Last updated: 2024-07-02
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/af57480777ebdcccda8653933a4caf7644756d457bfb44766a48c3d729b1c9ca.png

Vintage grading is mixed in EM space, whilst most developed markets post grade 1 vintages consistently across indicator categories.

plot = msp.heatmap_grades(
    dfd,
    xcats=main,
    cids=cids_exp,
    size=(19, 3),
    title=f"Average vintage grades from {start_date} onwards",
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/0d13db9bd6f31fd410986a79974837c19cacd7283d26f58ff2dd2238444c42ab.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=start_date,
    kind="box",
    size=(16, 4),
    legend_loc="best",
    legend_bbox_to_anchor=(1, 1),
)
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=start_date,
    kind="box",
    size=(16, 4),
    legend_loc="best",
    legend_bbox_to_anchor=(1, 1),
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/6cb01cce93149bc7fab000e5097f5058224dfe1d149e675b62c9383f34baaa2e.png https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/fae43cd5b92ff48508080b885acaac127f2fabaff0f080a37eed7d85a5b742bd.png

History #

Simple GDP growth rates #

Quarterly GDP growth rates can be very volatile. The 2-quarter-over-2-quarter growth rate is more stable and posts only slightly larger variance than the standard over-a-year ago growth rate.

xcatx = [
    "RGDP_SA_P1Q1QL4",
    "RGDP_SA_P2Q2QL2AR",
    "RGDP_SA_P1Q1QL1AR",
]
cidx = cids_exp

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    sort_cids_by="mean",
    start=start_date,
    kind="bar",
    size=(16, 8),
    title="Means and standard deviations of real GDP growth, seasonally-adjusted",
    xcat_labels=["% oya", "%2q/2q, saar", "%q/q, saar"],
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/a1ee36b77650ded54f54a9236e6438dc77fab504e631810dd383a78026c851d7.png
xcatx = [
    "RGDP_SA_P1Q1QL4",
    "RGDP_SA_P2Q2QL2AR",
    "RGDP_SA_P1Q1QL1AR",
]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start=start_date,
    title="Real GDP growth based on national accounts only",
    title_fontsize=27,
    legend_fontsize=17,
    label_adj=0.075,
    xcat_labels=["% oya", "%2q/2q, saar", "%q/q, saar"],
    ncol=5,
    same_y=False,
    size=(12, 7),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/a78787ee579f7266408018c76a18a481d5b0d199bea6533e73c01b39b29e9a0c.png

5-year lookback #

Over the recorded sample periods, long-term growth across countries has ranged from below 1% (Japan) to near 9% (China). The moving medians have been substantially more stable and robust to business cycles.

xcatx = ["RGDP_SA_P1Q1QL4_20QMA", "RGDP_SA_P1Q1QL4_20QMM"]
cidx = cids_exp

msp.view_ranges(
    dfd,
    xcats=xcatx,
    cids=cidx,
    sort_cids_by="mean",
    start=start_date,
    kind="bar",
    size=(16, 8),
    title="Means and standard deviations of real GDP growth, 5-year lookback, seasonally-adjusted",
    xcat_labels=[
        "5-year moving average, % over a year ago",
        "5-year moving median, % over a year ago",
    ],
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/41ac2ac79fac2d145bc5d90ffd82622f78afe29f4e1a73ea5e385988454544c3.png
xcatx = ["RGDP_SA_P1Q1QL4_20QMA", "RGDP_SA_P1Q1QL4_20QMM"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start=start_date,
    title="Long-term GDP growth, % over a year ago, 5-year moving average/median",
    title_fontsize=27,
    legend_fontsize=17,
    label_adj=0.075,
    xcat_labels=["Moving average", "Moving median"],
    ncol=4,
    same_y=False,
    size=(12, 7),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/efc04f71a4728e9f9846e61fbbe181cd778d78cbc8d1160385b50bffe9f0199c.png

10 year lookback #

Over the sample period, the long-term growth trend has been downward for most countries.

xcatx = ["RGDP_SA_P1Q1QL4_40QMA", "RGDP_SA_P1Q1QL4_40QMM"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start=start_date,
    title="Long-term GDP growth, % over a year ago, 10-year moving average/median",
    title_fontsize=27,
    legend_fontsize=17,
    label_adj=0.075,
    xcat_labels=["Moving average", "Moving median"],
    ncol=4,
    same_y=False,
    size=(12, 7),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/3abff6d82c125a1c0de122030b61a8cebf9a4f2ec386fddac2c91d088dfdef94.png

Importance #

Empirical clues #

Real-time long-term growth rates are mainly a benchmark or building block for the construction of “excess” growth rates or the current cyclical position of the economy. For example, growth trends versus long-term growth rates are an indication of rising operating rates in an economy and the need for monetary policy adjustment.

For example, there has been clear negative correlation between excess growth and subsequent local currency returns in global panels since 2000. The relation has prevailed both in the developed and emerging markets.

dfb = dfd[dfd["xcat"].isin(["FXTARGETED_NSA", "FXUNTRADABLE_NSA"])].loc[
    :, ["cid", "xcat", "real_date", "value"]
]
dfba = (
    dfb.groupby(["cid", "real_date"])
    .aggregate(value=pd.NamedAgg(column="value", aggfunc="max"))
    .reset_index()
)
dfba["xcat"] = "FXBLACK"
fxblack = msp.make_blacklist(dfba, "FXBLACK")
xcatx = ["INTRGDPv10Y_NSA_P1M1ML12_3MMA", "FXXR_NSA"]
cidx = list(
    set(cids_dm) - set(["DEM", "ESP", "FRF", "ITL", "NLG", "USD"])
)  # remove missing cids

cr = msp.CategoryRelations(
    dfd,
    xcats=xcatx,
    cids=cidx,
    freq="Q",
    lag=1,
    xcat_aggs=["last", "sum"],
    start="2000-01-01",
    blacklist=fxblack,
)

cr.reg_scatter(
    title="Growth versus long-term trend and subsequent FX returns across non-U.S. developed markets since 2000",
    labels=False,
    coef_box="lower left",
    ylab="1-month FX forward return, next quarter",
    xlab="Growth trend above long-term trend (10-year lookback)",
    reg_robust=True,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/edb67c4ba3fa8f31d29100cb5cbde0291372f5ca49933fcbbcc63b547013e164.png
xcatx = ["INTRGDPv10Y_NSA_P1M1ML12_3MMA", "FXXR_NSA"]
cidx = list(set(cids_em) - set(["HKD"]))

cr = msp.CategoryRelations(
    dfd,
    xcats=xcatx,
    cids=cidx,
    freq="Q",
    lag=1,
    xcat_aggs=["last", "sum"],
    start="2000-01-01",
    blacklist=fxblack,
)

cr.reg_scatter(
    title="Growth versus long-term trend and subsequent FX returns across emerging markets since 2000",
    labels=False,
    coef_box="lower left",
    ylab="1-month FX forward return, next quarter",
    xlab="Growth trend above long-term trend (10-year lookback)",
    reg_robust=True,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/af82a1d9da13cd309f66d79cf186a1518f51c76f863dbf6e68159bfded18783b.png
xcatx = ["INTRGDPv10Y_NSA_P1M1ML12_3MMA", "FXXR_NSA"]
cidx = list(set(cids_exp) - set(["USD"]))

cr = msp.CategoryRelations(
    dfd,
    xcats=xcatx,
    cids=cidx,
    freq="Q",
    lag=1,
    xcat_aggs=["last", "sum"],
    start="2000-01-01",
    blacklist=fxblack,
)

cr.reg_scatter(
    title="Growth versus long-term trend and subsequent FX returns, non-USD cross-sections, since 2000",
    labels=False,
    coef_box="lower left",
    ylab="1-month FX forward return, next quarter",
    xlab="Growth trend above long-term trend (10-year lookback)",
    reg_robust=True,
)
https://macrosynergy.com/notebooks.build/themes/economic-trends/_images/c89a62396f23c8ba0e7b30920787c3b1d8b69afac26a47c79dbc15a6fa72ef96.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).