External balance ratios #
This category group contains key realtime measures of external balances of trade and finance, as a percentage of concurrent nominal GDP. These balances are typically viewed as 1year trailing moving averages or as shorterterm seasonallyadjusted averages.
External balance ratios serve as indicators of demand for the local currency and vulnerability to international financial market shocks.
Current accounttoGDP ratio #
Ticker : CABGDPRATIO_NSA_12MMA
Label : External current account as % of GDP.
Definition : External current account balance as % of nominal GDP, with latest month(s) predicted by customs trade balance reports, 1year moving average.
Notes :

The current account balance comprises external goods and services trade balances, net factor income, and net transfer payments (such as foreign aid).

A positive balance means a positive net demand for the domestic currency related to these transactions.

Often external goods trade balances are published before overall balance of payments. In these cases, JPMaQS estimates current account balances based on the latest customs merchandise trade balances. In particular, the latest monthly current balance is estimated as the balance a year ago plus the difference of the merchandise trade balance compared to a year ago.
Ticker : CABGDPRATIO_SA / CABGDPRATIO_SA_3MMA
Label : External current account as % of GDP: seasonally adjusted / seasonally adjusted, 3month moving average.
Definition : External current account balance as % of nominal GDP: seasonally adjusted / seasonally adjusted, 3month moving average.
Notes :

The current account balance comprises external goods and services trade balances, net factor income, and net transfer payments (such as foreign aid).

A positive balance means a positive net demand for the domestic currency related to these transactions.

Current account balances are published by the national sources as:

Quarterly, nonseasonally adjusted: AUD, CAD, CHF, CLP, CNY, COP, INR, IDR, MYR, MXN, NOK, NZD, PEN, RUB, SEK, SGD, TWD, ZAR.

Monthly, seasonally adjusted: BRL, CZK, EUR, JPY, KRW, PLN, PHP, THB, TRY.

Quarterly, seasonally adjusted: HUF, ILS, and USD.

Monthly, seasonally adjusted: GBP.


When JPMaQS does seasonal adjustment for vintages, it adjusts the current account balance ratio to GDP by applying the additive method of the US Census X13 seasonal adjustment algorithm for each release date, at their native observation frequency (monthly or quarterly). See Appendix 1 for further details.

For AUD, CAD, CHF, CLP, COP, INR, IDR, MXN, NOK, NZD, RUB, SEK, and ZAR the national sources series’ have been complemented with additional vintages provided by OECD’s ‘Revision Analysis’ dataset. See also Appendix 2 for details on OECD data integration.
Merchandise trade balancetoGDP ratio #
Ticker : MTBGDPRATIO_NSA_12MMA
Label : External merchandise trade balance as % of GDP: 1year average
Definition : External merchandise trade balance as % of nominal GDP: 1year moving average
Notes :

The merchandise trade balance is part of the external balance of payments. It only tracks trade in goods.

A positive balance means positive net demand for the domestic currency related to merchandise trade.

The indicator use customs trade data for the latest months for countries that publish a customs report before the balance of payments and in goodquality.
Shortterm trade balancetoGDP ratio #
Ticker : MTBGDPRATIO_SA_3MMA / _6MMA
Label : External merchandise trade balance as % of GDP: 3month average (sa) / 6month average (sa)
Definition : External merchandise trade balance as % of nominal GDP: seasonallyadjusted 3month moving average / 6month moving average
Notes :

The merchandise trade balance is part of the external balance of payments, but only tracks trade in goods.

Seasonal adjustment factors are sequentially reestimated as new data are being released. Every reestimation gives rise to a new data vintage which is the basis of concurrent trend estimation. See Appendix 1 for further details.

For most countries calendar adjustment is applied, accounting for working day effects or moving holidays (e.g. Chinese New Year, Easter, Diwali, Ramadan etc).
Net FDItoGDP ratio #
Ticker : NFDIGDPRATIO_NSA_12MMA
Label : Net foreign direct investment as % of GDP.
Definition : Net foreign direct investment as % of nominal GDP, 1year moving trimmed mean.
Notes :

The indicator measures the net inward and outward flow of foreign direct investment of a currency area, with a 1year lookback horizon and as a % of GDP.

All other things equal, a positive balance means positive net demand for the domestic currency related to crossborder direct investment.

Due to occasional large transactions, the net FDI balance is prone to outliers. Therefore, instead of conventional 1year moving averages, JPMaQS uses medians (if original data are quarterly frequency) or 50% trimmed means (if original data are monthly frequency). In both cases the measure is based on the inner 50% of the values in the 1year lookback window. This delivers a more robust assessment of the underlying trends in direct investment flows.
Basic external balancetoGDP ratio #
Ticker : BXBGDPRATIO_NSA_12MMA
Label : Basic external balance as % of GDP.
Definition : Sum of external current account balance and net FDI inflows trend as % of GDP, 1year moving lookback (moving averages for the current account and moving trimmed mean or median for net FDI).
Notes :

This indicator is one of the broadest representations of stable external flows, taking into account both investment and trade flows into the currency area.

A positive balance means positive related net demand for the domestic currency.
Net foreign portfolio investmenttoGDP ratio #
Ticker : NFPIGDPRATIO_NSA / NFPIGDPRATIO_NSA_2QMA / _4QMA
Label : Net foreign portfolio investment, % of GDP: nsa, nsa, latest quarter / nsa, 2 quarter moving average / nsa, 4 quarter moving average
Definition : Net foreign portfolio investment, % of GDP: nonseasonally adjusted, latest quarter / nonseasonally adjusted, 2quarter moving average / nonseasonally adjusted, 4quarter moving average
Notes :

Portfolio investment is defined as crossborder transactions and positions involving debt or equity securities, other than those included in direct investment or reserve assets. Equity not in the form of securities (e.g., in unincorporated enterprises) is not included in portfolio investment; it is included in direct or other investment.

All other things equal, a positive balance means positive net demand for the domestic currency related to crossborder portfolio investment.

The indicator measures the net inward and outward flow of foreign portfolio investment of a currency area over the last quarter as a % of GDP, whereby the GDP is a 4quarter moving average.
Net foreign lendingtoGDP ratio #
Ticker : NFLGDPRATIO_NSA / NFLGDPRATIO_NSA_2QMA / _4QMA
Label : Net foreign lending, % of GDP: nsa, latest quarter / nsa, 2 quarter moving average / nsa, 4 quarter moving average
Definition : Net foreign lending, % of GDP: nonseasonally adjusted, latest quarter / nonseasonally adjusted, 2quarter moving average / nonseasonally adjusted, 4quarter moving average
Notes :

The indicator measures the net inward flow of foreign credit of a currency area over the last quarter as a % of GDP, whereby the GDP is a 4quarter moving average. All other things equal, a positive balance means positive net demand for the domestic currency related to crossborder net lending.

Foreign credit is based on two items of the “other investments” category of the balance of payments: trade credit and loans, including credit and loans from the IMF. Generally, other investment is a residual category that includes positions and transactions other than those included in direct investment, portfolio investment, financial derivatives and employee stock options, and reserve assets.

SGD only release foreign lending data annually.
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 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_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)
cids_fx = list(set(cids)  set(["USD"] + cids_dmec))
# Quantamental categories of interest
main = [
"CABGDPRATIO_NSA_12MMA",
"CABGDPRATIO_SA",
"CABGDPRATIO_SA_3MMA",
"NFDIGDPRATIO_NSA_12MMA",
"BXBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_SA_6MMA",
"MTBGDPRATIO_SA_3MMA",
"NFPIGDPRATIO_NSA_4QMA",
"NFLGDPRATIO_NSA_4QMA",
"NFPIGDPRATIO_NSA_2QMA",
"NFLGDPRATIO_NSA_2QMA",
"NFPIGDPRATIO_NSA",
"NFLGDPRATIO_NSA",
]
econ = ["REER_NSA_P1M60ML1"] # economic context
mark = [
"FXCRR_NSA",
"FXXR_NSA",
"FXXR_VT10",
"DU05YXR_NSA",
"DU05YXR_VT10",
"FXXRHvGDRB_NSA",
"FXTARGETED_NSA",
"FXUNTRADABLE_NSA",
"FXXRxEASD_NSA"
] # market links
xcats = main + econ + mark
# 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 888
Downloading data from JPMaQS.
Timestamp UTC: 20240712 12:57:28
Connection successful!
Requesting data: 100%██████████ 178/178 [00:40<00:00, 4.37it/s]
Downloading data: 100%██████████ 178/178 [00:45<00:00, 3.88it/s]
Some expressions are missing from the downloaded data. Check logger output for complete list.
652 out of 3552 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.
7447 out of 7447 dates are missing.
Download time from DQ: 0:01:38.154709
Availability #
cids_exp = sorted(list(set(cids)  set(cids_dmec))) # cids expected in category panels
msm.missing_in_df(dfd, xcats=main, cids=cids_exp)
No missing XCATs across DataFrame.
Missing cids for BXBGDPRATIO_NSA_12MMA: []
Missing cids for CABGDPRATIO_NSA_12MMA: []
Missing cids for CABGDPRATIO_SA: ['RON']
Missing cids for CABGDPRATIO_SA_3MMA: ['AUD', 'CAD', 'CHF', 'CLP', 'CNY', 'COP', 'HUF', 'IDR', 'ILS', 'INR', 'MXN', 'MYR', 'NOK', 'NZD', 'PEN', 'RON', 'RUB', 'SEK', 'SGD', 'TWD', 'USD', 'ZAR']
Missing cids for MTBGDPRATIO_NSA_12MMA: []
Missing cids for MTBGDPRATIO_SA_3MMA: []
Missing cids for MTBGDPRATIO_SA_6MMA: []
Missing cids for NFDIGDPRATIO_NSA_12MMA: []
Missing cids for NFLGDPRATIO_NSA: ['PEN']
Missing cids for NFLGDPRATIO_NSA_2QMA: ['PEN', 'SGD']
Missing cids for NFLGDPRATIO_NSA_4QMA: ['PEN', 'SGD']
Missing cids for NFPIGDPRATIO_NSA: []
Missing cids for NFPIGDPRATIO_NSA_2QMA: []
Missing cids for NFPIGDPRATIO_NSA_4QMA: []
Realtime quantamental indicators of external balance ratios are available from the late 1990s for most crosssections. Colombia and the Phillipines are notable latestarters across all external balance ratio indicators.
xcatx = [
"CABGDPRATIO_NSA_12MMA",
"CABGDPRATIO_SA",
"CABGDPRATIO_SA_3MMA",
"NFDIGDPRATIO_NSA_12MMA",
"BXBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_SA_6MMA",
"MTBGDPRATIO_SA_3MMA",
"NFPIGDPRATIO_NSA_4QMA",
"NFLGDPRATIO_NSA_4QMA",
]
cidx = cids_exp
dfx = msm.reduce_df(dfd, xcats=xcatx, cids=cidx)
dfs = msm.check_startyears(
dfx,
)
msm.visual_paneldates(dfs, size=(18, 8))
print("Last updated:", date.today())
Last updated: 20240712
xcatx = main
cidx = cids_exp
plot = msm.check_availability(
dfd, xcats=xcatx, cids=cidx, start_size=(18, 8), start_years=False
)
For most countries, only recent years’ full set of external balances are pure vintages based only on unrevised data.
plot = msp.heatmap_grades(
dfd,
xcats=[
"CABGDPRATIO_NSA_12MMA",
"CABGDPRATIO_SA",
"CABGDPRATIO_SA_3MMA",
"NFDIGDPRATIO_NSA_12MMA",
"BXBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_SA_6MMA",
"MTBGDPRATIO_SA_3MMA",
"NFPIGDPRATIO_NSA_4QMA",
"NFLGDPRATIO_NSA_4QMA",
],
cids=cids_exp,
size=(20, 4),
title=f"Average external balance ratio vintage grades from {start_date} onwards",
)
categories = [
"NFDIGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_NSA_12MMA",
"MTBGDPRATIO_SA_6MMA",
"MTBGDPRATIO_SA_3MMA",
]
msp.view_ranges(
dfd,
xcats=categories,
cids=cids_exp,
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),
)
msp.view_ranges(
dfd,
xcats=categories,
cids=cids_exp,
val="mop_lag",
title="Median of observation period lags (ranges of time elapsed since end of observation period in days)",
start=start_date,
kind="box",
size=(16, 4),
)
categories = [
"CABGDPRATIO_NSA_12MMA",
"CABGDPRATIO_SA",
"CABGDPRATIO_SA_3MMA",
"BXBGDPRATIO_NSA_12MMA",
]
msp.view_ranges(
dfd,
xcats=categories,
cids=cids_exp,
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),
)
msp.view_ranges(
dfd,
xcats=categories,
cids=cids_exp,
val="mop_lag",
title="Median of observation period lags (ranges of time elapsed since end of observation period in days)",
start=start_date,
kind="box",
size=(16, 4),
)
categories = [
"NFPIGDPRATIO_NSA_4QMA",
"NFLGDPRATIO_NSA_4QMA",
]
msp.view_ranges(
dfd,
xcats=categories,
cids=cids_exp,
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),
)
msp.view_ranges(
dfd,
xcats=categories,
cids=cids_exp,
val="mop_lag",
title="Median of observation period lags (ranges of time elapsed since end of observation period in days)",
start=start_date,
kind="box",
size=(16, 4),
)
History #
External current account ratios #
External current account ratios have displayed persistent differences across countries, emphasising their characteristic as slowlyevolving differentiating features. Persistence of external deficits or surpluses reflects a variety of causes, such as government interventions (FX interventions, sovereign wealth funds), evolution of financial relations (longterm credit flows), and unobserved external transactions.
xcatx = ["CABGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="mean",
start=start_date,
title="Means and standard deviations of external current account ratios since 1996",
xcat_labels=["External current account, 1year moving average"],
kind="bar",
size=(16, 8),
)
xcatx = ["CABGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Current account balance ratios, % of GDP, 1year moving averages",
title_adj=1.02,
title_xadj=0.49,
title_fontsize=27,
legend_fontsize=17,
xcat_labels=["Current account balance (12month moving average)"],
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Correlations have been mixed, emphasizing the point that external current account balances are a differentiating macro factor across currency areas.
cidx = cids_exp
msp.correl_matrix(
dfd,
xcats="CABGDPRATIO_NSA_12MMA",
cids=cidx,
size=(20, 14),
title="Correlations between crosssections for current account balance ratios since 1996",
)
Seasonally adjusted external current account ratios #
We see a similar pattern in the seasonally adjusted current accounts ratio to the 1year moving averages, albeit more volatile as is to be expected for monthly and quarterly data flows. The persistence observed in the 1year trends, are however still clearly visible in the timeseries.
xcatx = ["CABGDPRATIO_SA", "CABGDPRATIO_SA_3MMA"]
cidx = cids_exp
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="mean",
start=start_date,
title="Means and standard deviations of external current account ratios since 1996",
xcat_labels=["External current account, seasonal adjusted", "3month moving averages (monthly)"],
kind="bar",
size=(16, 8),
)
xcatx = ["CABGDPRATIO_SA", "CABGDPRATIO_SA_3MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Current account balance ratios, % of GDP, seasonally adjusted",
title_adj=1.02,
title_xadj=0.49,
title_fontsize=27,
legend_fontsize=17,
xcat_labels=["Current account balance", "3month moving averages (monthly)"],
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Similar to the 1year trend, the correlation patterns for the seasonal adjusted quarterly (and monthly) balances stays roughly the same, despite higher volaility.
cidx = cids_exp
msp.correl_matrix(
dfd,
xcats="CABGDPRATIO_SA",
cids=cidx,
size=(20, 14),
title="Correlations between crosssections for current account balance ratios since 1996",
)
Merchandise trade balance ratios #
Whilst merchandise and current account balances have naturally been strongly correlated, average levels have displayed disparities for some countries that have a sizable external services trade or net factor income.
xcatx = ["MTBGDPRATIO_NSA_12MMA", "CABGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="mean",
start=start_date,
title="Means and standard deviations of merchandise trade balance & account balance ratios since 1996",
xcat_labels=[
"Merchandise trade balances, 1year moving average",
"Current account balances, 1year moving average",
],
kind="bar",
size=(16, 8),
)
While external current account balances are slowmoving indicators most of the time, they can change rapidly in times of market turmoil or economic change and  thereby  alter the risk properties of local asset markets.
xcatx = ["MTBGDPRATIO_NSA_12MMA", "CABGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Merchandise trade balance & current account balance ratios, % of GDP, 1year moving averages",
title_adj=1.02,
title_fontsize=27,
legend_fontsize=17,
title_xadj=0.42,
label_adj=0.075,
xcat_labels=["Merchandise trade balances", "Current account balances"],
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Shortterm trade balance ratios #
The two short term trade balance ratios appear consistent across currency areas. This extends to extreme observations.
xcatx = ["MTBGDPRATIO_SA_3MMA", "MTBGDPRATIO_SA_6MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Shortterm merchandise balance ratios, % of GDP, seasonally adjusted",
title_adj=1.02,
title_fontsize=27,
legend_fontsize=17,
label_adj=0.075,
title_xadj=0.42,
xcat_labels=["3month moving average", "6month moving average"],
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Merchandise trade balance ratios that are based only on a few months of seasonally adjusted data are typically leading the traditional 12month ratios at the expense of ample added volatility. The shortterm ratios are better indicators of external adjustments to economic shocks, while the longerhorizon ratios better reflect mediumterm trends.
xcatx = ["MTBGDPRATIO_SA_3MMA", "MTBGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Merchandise trade balance ratios, % of GDP",
title_adj=1.02,
title_xadj=0.39,
title_fontsize=27,
legend_fontsize=17,
label_adj=0.075,
xcat_labels=[
"3month moving average (seasonally adjusted)",
"12month moving average (nonseasonally adjusted)",
],
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Net FDI ratios #
Net FDI ratios exhibit greater variability than trade balances, notwithstanding the exclusion of monthly outliers in our calculations. On balance, EM economies have been recipients of net currency demand for foreign direct investment purposes.
xcatx = ["NFDIGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Net FDI ratios, % of GDP, 1year moving averages",
title_adj=1.02,
title_fontsize=27,
title_xadj=0.5,
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Basic external balance ratios #
For some countries, such as Singapore, Poland and Peru, basic external balances have deviated substantially from current account balances in the long run. However, for most currency areas such differences have been episodic.
xcatx = ["BXBGDPRATIO_NSA_12MMA", "CABGDPRATIO_NSA_12MMA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Basic external balance ratios & current account balance ratios, % of GDP, 1year moving averages",
xcat_labels=[
"Basic external balance",
"Current account balance",
],
title_adj=1.02,
title_fontsize=27,
legend_fontsize=17,
title_xadj=0.435,
label_adj=0.075,
ncol=4,
same_y=False,
size=(16, 8),
aspect=1.7,
all_xticks=True,
)
Net foreign portfolio investmenttoGDP ratios #
Average net foreign portfolio investmenttoGDP ratios have been diverse across countries. Generally, countries with large external current account surpluses and sovereign wealth funds have recorded large outflows.
xcatx = ["NFPIGDPRATIO_NSA_4QMA"]
cidx = cids_exp
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="mean",
start=start_date,
title="Means and standard deviations of net foreign portfolio investment ratios since 1996",
xcat_labels=["Net foreign portfolio investment, 4quarter moving average",],
kind="bar",
size=(16, 8),
)
Although net external portfolio flows have been notoriously volatile, they also have displayed pronounced cycles and mediumterm trends.
xcatx = ["NFPIGDPRATIO_NSA_4QMA",
"NFPIGDPRATIO_NSA_2QMA",
"NFPIGDPRATIO_NSA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Net foreign portfolio investment ratios, % of GDP",
title_adj=1.02,
title_fontsize=30,
legend_fontsize=17,
title_xadj=0.435,
label_adj=0.075,
ncol=4,
same_y=False,
size=(16, 8),
xcat_labels=[
"Net foreign portfolio investment, 4quarter moving average",
"Net foreign portfolio investment, 2quarter moving average",
"Net foreign portfolio investment"
],
aspect=1.7,
all_xticks=True,
)
Correlations of net portfolio flows of countries have been very diverse, suggesting that this a diversifying factor in a global portfolio.
cidx = cids_exp
msp.correl_matrix(
dfd,
xcats="NFPIGDPRATIO_NSA_4QMA",
cids=cidx,
size=(20, 14),
title="Correlations between crosssections for current account balance ratios since 1996",
cluster=True,
)
Net foreign lending investmenttoGDP ratios #
The longterm averages in net lending have been less diverse than those for net portfolio investment and relative to volatility.
xcatx = ["NFLGDPRATIO_NSA_4QMA"]
cidx = cids_exp
msp.view_ranges(
dfd,
xcats=xcatx,
cids=cidx,
sort_cids_by="mean",
start=start_date,
title="Means and standard deviations of net foreign lending ratios since 1996",
xcat_labels=["Net foreign lending, 4quarter moving average"],
kind="bar",
size=(16, 8),
)
Beyond volatility, the net lending ratios have also displayed cycles and sometimes structural trends and shifts.
xcatx = ["NFLGDPRATIO_NSA_4QMA", "NFLGDPRATIO_NSA_2QMA", "NFLGDPRATIO_NSA"]
cidx = cids_exp
msp.view_timelines(
dfd,
xcats=xcatx,
cids=cidx,
start=start_date,
title="Net foreign lending ratios, % of GDP",
title_adj=1.02,
title_fontsize=27,
legend_fontsize=17,
title_xadj=0.435,
label_adj=0.075,
ncol=4,
same_y=False,
size=(16, 8),
xcat_labels=[
"Net foreign lending, 4quarter moving average",
"Net foreign lending, 2quarter moving average",
"Net foreign lending",
],
aspect=1.7,
all_xticks=True,
)
Importance #
Research links #
“Backtesting exercises show that although both metrics are noisy, the basic balance is a better leading indicator of FX returns than the current account balance, particularly in EM.” Chandan/JPMorgan
“External balance and FX carry (nominal or real) tend to be negatively correlated, so in effect, one is short carry when long surplus vs. deficit currencies. This provides diversification opportunities in a multifactor context. Simply a combination of two factors—carry and growth or carry and external balances—is adequate to boost FX riskadjusted returns.” Chandan, DuranVara/ JPMorgan
“Currency areas with negative external balances are – all other things equal – more vulnerable to financing shocks. Jumps in market price volatility often indicate such shocks. Realistically it takes a few days for the market to fully price the consequences of shocks consistently across currencies. Hence, the products of external balancesbased “resilience scores” and volatility shocks are plausible indicators of “postshock currency hazards”. This means that they should serve as signals for differences in currency returns after market volatility has surged or dropped. An empirical analysis based on 28 currencies since 2000 shows that a most simple “postshock currency hazard” measure has significantly helped predict subsequent shortterm returns and would have added positive PnL to FX trading strategies, particularly in times of turbulence.” Macrosynergy
“The current account occupies a central position in international economics and policy debates. Indeed, in G20 policy debates the term ‘global imbalances’ is treated as almost synonymous with ‘current account imbalances’.” Borio
“Countries whose currencies will be most vulnerable…are those that have the largest external financing needs. One simple gauge of this vulnerability is the size of the country’s basic external balance as a share of GDP, i.e., the current account deficit minus the stable sources of financing such as net FDI inflows and (for EU member countries) inflows of EU convergence and cohesion funds.” AllianceBernstein
“There is clear evidence that for emerging market economies that experience large bond outflows, their exchange rates subsequently depreciate significantly, generating large negative currency excess returns.” Hördahl, Valente BIS Working Papers
Empirical clues #
External deficits have historically been a counterweight to (real and nominal) FX carry. Often, highcarry countries compensate investors for helping them to sustain an elevated currency value in the face of external deficits and lowcarry countries compensate investors for helping them to prevent currency appreciation in the face of external surpluses.
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")
fxblack
{'BRL': (Timestamp('20121203 00:00:00'), Timestamp('20130930 00:00:00')),
'CHF': (Timestamp('20111003 00:00:00'), Timestamp('20150130 00:00:00')),
'CNY': (Timestamp('19990101 00:00:00'), Timestamp('20240711 00:00:00')),
'CZK': (Timestamp('20140101 00:00:00'), Timestamp('20170731 00:00:00')),
'ILS': (Timestamp('19990101 00:00:00'), Timestamp('20051230 00:00:00')),
'INR': (Timestamp('19990101 00:00:00'), Timestamp('20041231 00:00:00')),
'MYR_1': (Timestamp('19990101 00:00:00'), Timestamp('20071130 00:00:00')),
'MYR_2': (Timestamp('20180702 00:00:00'), Timestamp('20240711 00:00:00')),
'PEN': (Timestamp('20210701 00:00:00'), Timestamp('20210730 00:00:00')),
'RON': (Timestamp('19990101 00:00:00'), Timestamp('20051130 00:00:00')),
'RUB_1': (Timestamp('19990101 00:00:00'), Timestamp('20051130 00:00:00')),
'RUB_2': (Timestamp('20220201 00:00:00'), Timestamp('20240711 00:00:00')),
'SGD': (Timestamp('19990101 00:00:00'), Timestamp('20240711 00:00:00')),
'THB': (Timestamp('20070101 00:00:00'), Timestamp('20081128 00:00:00')),
'TRY_1': (Timestamp('19990101 00:00:00'), Timestamp('20030930 00:00:00')),
'TRY_2': (Timestamp('20200101 00:00:00'), Timestamp('20240711 00:00:00'))}
cidx = cids_fx
cr = msp.CategoryRelations(
dfd,
xcats=["CABGDPRATIO_NSA_12MMA", "FXCRR_NSA"],
cids=cidx,
blacklist=fxblack,
freq="M",
lag=0,
xcat_aggs=["mean", "mean"],
start=start_date,
years=3,
)
cr.reg_scatter(
title="Current account ratios and real FX forward carry across all countries, 3year periods since 1996",
labels=True,
coef_box="upper right",
ylab="Real 1month forwardimplied FX carry",
xlab="Current account ratio as % of GDP, 1year moving average",
reg_robust=True,
)
Pooled OLS regression shows a highly significant positive intercept, implying that the current accounttoGDP ratio has to be relatively large before the expected real 1month FX forward carry is negative.
cr.ols_table()
OLS Regression Results
==============================================================================
Dep. Variable: FXCRR_NSA Rsquared: 0.106
Model: OLS Adj. Rsquared: 0.102
Method: Least Squares Fstatistic: 27.33
Date: Fri, 12 Jul 2024 Prob (Fstatistic): 3.86e07
Time: 14:00:55 LogLikelihood: 515.78
No. Observations: 232 AIC: 1036.
Df Residuals: 230 BIC: 1042.
Df Model: 1
Covariance Type: nonrobust
=========================================================================================
coef std err t P>t [0.025 0.975]

const 1.5375 0.149 10.332 0.000 1.244 1.831
CABGDPRATIO_NSA_12MMA 0.1407 0.027 5.227 0.000 0.194 0.088
==============================================================================
Omnibus: 59.761 DurbinWatson: 1.337
Prob(Omnibus): 0.000 JarqueBera (JB): 174.896
Skew: 1.094 Prob(JB): 1.05e38
Kurtosis: 6.648 Cond. No. 5.58
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
There has been a positive relation between changes in the observed shortterm trade balance ratios and subsequent FX returns.
cidx = cids_fx
cr = msp.CategoryRelations(
dfd,
xcats=["MTBGDPRATIO_SA_6MMA", "FXXR_VT10"],
cids=cidx,
blacklist=fxblack,
freq="M",
lag=1,
xcat_aggs=["last", "sum"],
xcat1_chg="diff",
xcat_trims=[20, 20],
n_periods=1,
start=start_date,
years=None,
)
cr.reg_scatter(
title="Changes in observed shortterm trade balances and subsequent monthly FX returns",
labels=False,
coef_box="lower right",
xlab="Change in seasonallyadjusted 6month merchandise trade balance over the past month, % of GDP",
ylab="Next month FX forward return",
)
Net portfolio flows have displayed persistent mediumterm trends in the past. As a result, we also see a subtle but statistically significant relation between net portfolio flows and subsequent (volatilitytargeted) FX returns for a wide panel of 31 emerging and developed currency areas.
cidx = cids_fx
cr = msp.CategoryRelations(
dfd,
xcats=["NFPIGDPRATIO_NSA", "FXXR_VT10"],
cids=cidx,
blacklist=fxblack,
freq="q",
lag=1,
xcat_aggs=["last", "sum"],
start=start_date,
years=None,
xcat_trims=[50, 50], # remove single return outlier
)
cr.reg_scatter(
title="External portfolio investement inflow and subsequent FX returns, 31 EM and DM currencies",
labels=False,
coef_box="lower left",
xlab="Net external portfolio inflow, % of GDP, endofquarter information state",
ylab="FX forward return, voltarged, next quarter",
prob_est="map",
)
The predictive relation between net portfolio inflows and subsequent quarterly FX returns has been a bit stronger for the EM countries. It has been significant at the 10% level at both a monthly and quarterly frequency.
cidx = cids_em
cr = msp.CategoryRelations(
dfd,
xcats=["NFPIGDPRATIO_NSA", "FXXR_VT10"],
cids=cidx,
blacklist=fxblack,
freq="q",
lag=1,
xcat_aggs=["last", "sum"],
start=start_date,
years=None,
xcat_trims=[50, 50],
)
cr.reg_scatter(
title="External portfolio investement inflow and subsequent FX returns, 22 EM currencies",
labels=False,
coef_box="lower left",
xlab="Net external portfolio inflow, % of GDP, endofquarter information state",
ylab="FX forward return, voltarged, next quarter",
prob_est="map"
)
Appendices #
Appendix 1: Seasonal adjustment procedure #
We deploy the stateoftheart US Census X13 algorithm to handle seasonality in economic series. There are two characteristics of the model worth noting in connection to the pointintime estimation JPMaQS is delivering:

The underlying econometric model is a seasonal ARIMA model leveraging a twosided filter. As both the earliest and latest observations are included in the historical seasonal component estimation, JPMaQS forces the model (and seasonal component) to being reestimated for each release date’s timeseries. This ensures that only information available at a given pointintime is used, avoiding leakage of future information.

The algorithm has an embedded endogenous model specification using an Akaike Information Criteria, ensuring the parameters are dynamically chosen using only information available at each pointintime.
For our seasonally adjustment of the Merchandise Trade Balances , we sequentially apply the multiplicative method of the U.S. Census X13 algorithm to the levels of imports and exports respectively for each of their vintages. We then subtract the imports from the exports to get the seasonally adjusted merchandise trade balances, and take ratios to nominal GDP at the end. This contrast with the Current Account Balances , were we first take the ratio to GDP to deal deal with nonstationarity in the data, and then apply the additive X13 method to these ratios for each release date. As current account balances can be both in surplus and deficit, we cannot use the multiplicative method to deal with the nonstationarity of the data.
Appendix 2: Notes on OECD data integration #
Some indicators in this notebook are constructed using vintages provided by the OECD’s Revision Analysis Dataset in addition to national sources series’. The integration of the OECD datasets follows the following rules:

The following priority order is applied for combining vintages. First, JPMaQS uses seasonally and calendar adjusted original vintages from national sources. Beyond that JPMaQS uses OECD vintages.

OECD vintages inform on the month of release but not the exact date. Actual release dates for these vintages are estimated based on release days of subsequent vintages.

Inconsistencies, data errors and missing values in the OECD vintages have been corrected for JPMaQS.
OECD data is seasonally adjusted and denominated in native currency. No such consistency is found in national sources. Often figures are stated in a foreign denomination (EUR or USD) and no seasonal adjustment has been applied. To integrate these two data sources we first currency convert national sources into their native currency and then apply seasonal adjustment.
Appendix 3: Currency symbols #
The word ‘crosssection’ 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).