International investment position #

This category group focuses on real-time broad measures of international investment positions of currency areas that characterize the financial relations between residents and non-residents.

These are slow-moving semi-structural indicators, often used to assess the vulnerability of currency areas to disruptions in international capital flows. Hence the international investment position indicators provide investors with investment risk that may manifest upon changes in financial conditions.

“The international investment position (IIP)…shows at a point in time the value and composition of (1) external financial assets of residents of an economy that are claims on non-residents and gold bullion held as reserve assets, and (2) external financial liabilities of residents of an economy to non-residents. The difference between an economy’s external financial assets and liabilities is the economy’s net international investment position (NIIP) , which may be positive or negative. Respectively, the NIIP provides an aggregate view of the net financial position (assets minus liabilities) of a country via-à-vis the rest of the world. A positive NIIP (assets higher than liabilities) qualifies an economy as net creditor, a negative NIIP (liabilities higher than assets) as net debtor nation, allowing for measuring the extent of external financial exposure of a country.” eurostat

Net international investment position as % of GDP #

Ticker : NIIPGDP_NSA

Label : Net international investment position as % of GDP.

Definition : Latest official statistic of the difference between the stock of external financial assets of residents and the stock of external financial liabilities of residents (to non-residents), as % of nominal GDP.

Notes :

  • The nominal GDP is the sum of the latest concurrently available four quarters of nominal GDP from the national accounts.

  • The international investment positions have been taken from national sources and the IMF.

International liabilities as % of GDP #

Ticker : IIPLIABGDP_NSA

Label : International liabilities as % of GDP.

Definition : Stock of external financial liabilities of residents (to non-residents), as % of nominal GDP.

Notes :

  • The nominal GDP is the sum of the latest concurrently available four quarters of nominal GDP from the national accounts.

  • The international liability data have been taken from national sources and the IMF.

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.

# 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 = ["NIIPGDP_NSA", "IIPLIABGDP_NSA"]
econ = ["NIR_NSA", "RIR_NSA", "FXUNTRADABLE_NSA", "FXTARGETED_NSA"]  # economic context
mark = [
    "EQXR_NSA",
    "EQXR_VT10",
    "FXXR_NSA",
    "FXXRHvGDRB_NSA",
    "FXXR_VT10",
]  # market links

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

start_date = "1996-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 407
Downloading data from JPMaQS.
Timestamp UTC:  2023-09-07 10:39:58
Connection successful!
Number of expressions requested: 1628
Requesting data: 100%|█████████████████████████████████████████████████████████████████| 82/82 [00:26<00:00,  3.15it/s]
Downloading data: 100%|████████████████████████████████████████████████████████████████| 82/82 [00:51<00:00,  1.60it/s]
Download time from DQ: 0:01:38.436791

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)
Missing xcats across df:  []
Missing cids for IIPLIABGDP_NSA:  []
Missing cids for NIIPGDP_NSA:  []

Real-time quantamental indicators of international investment positions are available back to the 1990s for most countries. China and Colombia are notable late-starters. Average grading of the date is on the low side as original vintages for older history are not available in standard vintage databases.

For the explanation of currency symbols, which correspond 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=(18, 3))

print("Last updated:", date.today())
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/1c997b912c0f36b13e596623bf83be5fdb9ee8c306440c2e8baef5b0210a3f56.png
Last updated: 2023-09-07
xcatx = main
cidx = cids_exp

plot = msm.check_availability(
    dfd, xcats=xcatx, cids=cidx, start_size=(18, 3), start_years=False
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/cbe1d726ee6021a58c21c2b01a92191fce5f489d719f4b86fe5cdc8f8f404aba.png

Average vintage grading is low across all cross-sections.

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/macroeconomic-balance-sheets/_images/253dc6f133086493b2740c4c726b5b621e97deb44eaf14c9e634f77170a24acb.png
msp.view_ranges(
    dfd,
    xcats=main,
    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=main,
    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),
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/2998fda17dd721504472737f2d1313e2c4452c51f1c3ecf429c2053c27695221.png https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/1dceb786607771cc95925aa9c09dad412ba86f404874725ded7e690d07d68814.png

History #

Net international investment position as % of GDP #

Average net international investment positions since the mid-1990s have ranged from net assets of over 200% of GDP in Singapore to a net liabilities of roughly 70% of GDP in Hungary.

xcatx = ["NIIPGDP_NSA"]
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 international investment positions (% of GDP) since 1996",
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/196610f6301213acee4b0dce933f87f791bb59c3ff2984f8e43c10b18f4a3026.png

Changes in net international investment positions often come in multi-year trends. Norway, Taiwan and Singapore stand out in terms of increases in net assets as ratio to GDP over the past 20 years.

xcatx = ["NIIPGDP_NSA"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start=start_date,
    title="Net international investment positions, % of GDP",
    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,
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/0ed8720e0e78a382a7efc3304032c54a1795c65b127bb5a4953ba06f1376bee4.png

Global correlations of investment positions have been very diverse.

xcatx = ["NIIPGDP_NSA"]
cidx = cids_exp

msp.correl_matrix(
    dfd,
    xcats="NIIPGDP_NSA",
    cids=cidx,
    size=(20, 14),
    cluster=True,
    freq="M",
    title="Cross-sectional correlations of net international investment positions, since 1996",
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/ac5255a41bace7c6c02c6d4154351b66b6024d03580f4154bf27fd613823f6a6.png

International liabilities as % of GDP #

International liabilities are semi-structural indicators. Countries with disproportionately large financial centers have the largest international liabilities as ratio of GDP. Developed countries and small countries also tend to have greater liabilities.

xcatx = ["IIPLIABGDP_NSA"]
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 international liabilities (% of GDP) since 1996",
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/35b4a6002d41638a458b1ecdbfc33044ec1d729ba052b57832b9b0b765fb7398.png

International liabilities as ratios to GDP have not typically been stationary since the mid-1990s but rather trending upward, indicative of the growth of international finance.

Great Britain, Switzerland and Singapore stand out in terms of accumulation of international liabilities as % of GDP over the last 30 years.

xcatx = ["IIPLIABGDP_NSA"]
cidx = cids_exp

msp.view_timelines(
    dfd,
    xcats=xcatx,
    cids=cidx,
    start=start_date,
    title="International liabilities, % of GDP",
    title_adj=1.02,
    title_fontsize=27,
    title_xadj=0.5,
    xcat_labels=["International liabilities"],
    ncol=4,
    same_y=False,
    size=(16, 8),
    aspect=1.7,
    all_xticks=True,
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/9cc0d4f59aec3af92f24e83ae706ea63a996a8bdffcc5af0e63514828b531256.png

Importance #

Empirical Clues #

There has been a negative correlation between net international investment position ratios and local real interest rates. Short-term real interest rates tend to be lower in countries with larger net external assets (such as Norway, Singapore, Switzerland and Taiwan), probably because those countries tend to keep local rates low, in order to discourage additional capital inflows in order to prevent excessive exchange rate strength.

xcatx = ["NIIPGDP_NSA", "RIR_NSA"]
cidx = cids_exp

cr = msp.CategoryRelations(
    dfd,
    xcats=xcatx,
    cids=cidx,
    freq="M",
    lag=0,
    xcat_aggs=["mean", "mean"],
    start=start_date,
    years=5,
    xcat_trims=[100, 100],
)

cr.reg_scatter(
    title="Net international investment positions as % of GDP and short-term real interest rates, 5-year periods since 1996",
    labels=True,
    ylab="Real 1-month local interest rate",
    xlab="Net international investment position",
    reg_robust=True,
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/813bd1bd82bc8d1f94628022058c8e6c2caef0635892eaaf569b11ed8e057b21.png

There is some evidence that greater international liabilities lead to smaller FX forward returns. Indeed, this is consistent across decades.

Due to the diversity in international liability means across cross-sections, it is necessary to normalise this indicator (relative to the cross-section) to see this relation. This can be done using the make_zn_scores() function in macrosynergy.panel .

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"
)  # exclude periods of FX targeting or illiquidity
# Compute Zn scores
xcatx = ["IIPLIABGDP_NSA", "NIIPGDP_NSA"]
cidx = cids_exp

for xcat in xcatx:
    dfa = msp.make_zn_scores(
        df=dfd,
        cids=cidx,
        xcat=xcat,
        start="2000-01-01",
        est_freq="m",
        neutral="mean",
        pan_weight=0,
    )
    dfd = msm.update_df(dfd, dfa)
xcatx = ["IIPLIABGDP_NSAZN", "FXXR_VT10"]
cidx = cids_exp

cr = msp.CategoryRelations(
    dfd,
    xcats=xcatx,
    cids=cidx,
    freq="Q",
    lag=1,
    xcat_aggs=["mean", "sum"],
    start="2000-01-01",
    blacklist=fxblack,
)
FXXR_VT10 misses: ['USD'].
cr.reg_scatter(
    coef_box="lower right",
    prob_est="map",
    separator=2009,
    title="International liabilities and next-quarter FX forward returns, 10% vol-target, since 2000",
    xlab="International liabilities, % of GDP, z-score based on cross-section statistics, quarterly average",
    ylab="FX forward returns, 10% vol-target, next quarter sum",
)
https://macrosynergy.com/notebooks.build/themes/macroeconomic-balance-sheets/_images/c3f18a75baede181287a6c4035f6fff9af50668d627339bac69cb69d5b096f8d.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).