The predictive power of information state changes #

Get packages and JPMaQS data #

# >>> Define constants <<< #
import os
import warnings
warnings.filterwarnings("ignore")

# Minimum Macrosynergy package version required for this notebook
REQUIRED_VERSION: str = "0.1.32"

# DataQuery credentials: Remember to replace with your own client ID and secret
DQ_CLIENT_ID: str = os.getenv("DQ_CLIENT_ID")
DQ_CLIENT_SECRET: str = os.getenv("DQ_CLIENT_SECRET")

# Define any Proxy settings required (http/https)
PROXY = {}

# Start date for the data (argument passed to the JPMaQSDownloader class)
START_DATE: str = "1995-01-01"
# Check installed Macrosynergy package meets version requirement
import macrosynergy as msy
msy.check_package_version(required_version=REQUIRED_VERSION)
# Standard library imports
from typing import List, Tuple, Dict

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
from scipy.stats import chi2

# Macrosynergy package imports
import macrosynergy.management as msm
import macrosynergy.panel as msp
import macrosynergy.pnl as msn
import macrosynergy.visuals as msv
import macrosynergy.signal as mss

from macrosynergy.download import JPMaQSDownload

Specify and download the data #

# Cross sections to be explored
cids_dm = ["AUD", "CAD", "CHF", "EUR", "GBP", "JPY", "NOK", "NZD", "SEK", "USD"]
cids_em = [
    "CLP",
    "COP",
    "CZK",
    "HUF",
    "IDR",
    "ILS",
    "INR",
    "KRW",
    "MXN",
    "PLN",
    "THB",
    "TRY",
    "TWD",
    "ZAR",
]
cids = cids_dm + cids_em

cids_wild = ["CNY", "HKD", "RON", "RUB", "SGD"]
cids_non_tradable = ["IDR", "NZD"]
cids_emx = sorted(list(set(cids_em) - set(cids_wild) - set(cids_non_tradable)))
cids_dmx = sorted(list(set(cids_dm) - set(cids_non_tradable)))
cids_du = sorted(cids_dmx + cids_emx)
cids_duxi = np.sort(list(set(cids_du) - set(["INR"])))
# Nested notebook of quantamental groups and categories

isc_feats = {
    "growth": {
        "RGDPTECH_SA_P1M1ML12": {
            "freq": "M",   # frequency of the underlying series
            "sign": "NEG",  # assumed direction of impact
            "desc": "Technical real GDP, %oya",  # label for charts and tables
        },
        "INTRGDP_NSA_P1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Intuitive real GDP, %oya"
        },
        "IP_SA_P6M6ML6AR": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Industrial Production",
        },
        "RPCONS_SA_P1M1ML12": {
            "freq": "M", 
            "sign": "NEG",
            "desc": "Real Private Consumption (monthly)",
        },
        "RPCONS_SA_P1Q1QL4": {
            "freq": "Q",
            "sign": "NEG",
            "desc": "Real Private consumption (quarterly)",
        },
        "IMPORTS_SA_P6M6ML6AR": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Import growth",
        },
        "RRSALES_SA_P1M1ML12_3MMA": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Real retail sales"
        },
        "RRSALES_SA_P1Q1QL4": {
            "freq": "Q",
            "sign": "NEG",
            "desc": "Real retail sales"
        },
    },
    "inflation": {
        "CPIHX_SA_P1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Headline consumer price inflation",
        },
        "CPICX_SA_P1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Core consumer price inflation",
        },
        "PPIH_NSA_P1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Producer Price Index %oya",
        },
    },
    "financial": {
        "PCREDITGDP_SJA_D1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Private credit as percent of GDP - changes",
        },
        "MNARROW_SJA_P1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Narrow money yoy change",
        },
        "MBROAD_SJA_P1M1ML12 ": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Broad money yoy change",
        },
        "IIPLIABGDP_NSA": {
            "freq": "Q",
            "sign": "NEG",
            "desc": "international investment position liabilities (ratio to GDP)",
        },
        "NIIPGDP_NSA": {
            "freq": "Q",
            "sign": "NEG",
            "desc": "Net international investment position (ratio to GDP)",
        },
    },
    "labour": {
        "UNEMPLRATE_SA_3MMA": {
            "freq": "M",
            "sign": "POS",
            "desc": "Unemployment rate",
        },
        "EMPL_NSA_P1M1ML12": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Employment growth"
        },
        "EMPL_NSA_P1Q1QL4": {
            "freq": "Q",
            "sign": "NEG",
            "desc": "Employment growth",
        },
    },
    "surveys": {
        "MBCSCORE_SA": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Manufacturing confidence scores",
        },
        "SBCSCORE_SA": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Service confidence scores",
        },
        "CBCSCORE_SA": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Construction confidence score "
        },
        "CCSCORE_SA": {
            "freq": "M",
            "sign": "NEG",
            "desc": "Consumer confidence score "
        }
    },
}
# Dictionary of indicators by frequency

pe_freqs = {
    ff: [
        k + "_" + v["sign"]
        for cats in isc_feats.values()
        for k, v in cats.items()
        if v["freq"] == ff
    ]
    for ff in ("D", "W", "M", "Q")
}

# Lists of categories by frequency for scaling to volatility

daily = pe_freqs["D"]
weekly = pe_freqs["W"]
monthly = pe_freqs["M"]
quarterly = pe_freqs["Q"]
# Modify tickers to include the sign in the name

pe_growth = [xc + "_" + v["sign"] for xc, v in isc_feats["growth"].items()]
pe_inflation = [xc + "_" + v["sign"] for xc, v in isc_feats["inflation"].items()]
pe_financial = [xc + "_" + v["sign"] for xc, v in isc_feats["financial"].items()]
pe_labour = [xc + "_" + v["sign"] for xc, v in isc_feats["labour"].items()]
pe_surveys = [xc + "_" + v["sign"] for xc, v in isc_feats["surveys"].items()]

pe_feats = pe_growth + pe_inflation + pe_financial + pe_labour + pe_surveys
# Category ticker lists for download

main = [
    xc for cats in isc_feats.values() for xc in cats.keys()
    if xc not in ("CPIHX_SA_P1M1ML12", "CPICX_SA_P1M1ML12")
] + [
    "CPIH_SA_P1M1ML12", "CPIHE_SA_P1M1ML12",
    "CPIC_SA_P1M1ML12", "CPICE_SA_P1M1ML12",
]
misc = ["USDGDPWGT_SA_3YMA", "EXMOPENNESS_NSA_1YMA", "EXALLOPENNESS_NSA_1YMA"]
mark = ["DU05YXR_VT10", "DU05YXR_NSA"]

xcats = main + mark + misc

# Construct tickers
tickers: List[str] = [
    cid + "_" + xcat
    for cid in cids
    for xcat in xcats
]
print(f"Maximum number of JPMaQS tickers to be downloaded is {len(tickers)}")
Maximum number of JPMaQS tickers to be downloaded is 720
# Download series from J.P. Morgan DataQuery by tickers

with JPMaQSDownload(
    client_id=DQ_CLIENT_ID, client_secret=DQ_CLIENT_SECRET, proxy=PROXY
) as downloader:
    df: pd.DataFrame = downloader.download(
        tickers=tickers,
        start_date=START_DATE,
        metrics=["value", "eop_lag"],  # TODO use mop_lag for time temporal weights (together with eop)
        suppress_warning=True,
        show_progress=True,
        report_time_taken=True,
    )
Downloading data from JPMaQS.
Timestamp UTC:  2024-09-27 11:26:38
Connection successful!
Requesting data: 100%|██████████| 72/72 [00:15<00:00,  4.51it/s]
Downloading data: 100%|██████████| 72/72 [00:27<00:00,  2.61it/s]
Time taken to download data: 	49.27 seconds.
Some expressions are missing from the downloaded data. Check logger output for complete list.
268 out of 1440 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 7762 dates are missing.
# Deep copy and fill
dfx = df.copy()
dfx.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3949672 entries, 0 to 3949671
Data columns (total 5 columns):
 #   Column     Dtype         
---  ------     -----         
 0   real_date  datetime64[ns]
 1   cid        object        
 2   xcat       object        
 3   value      float64       
 4   eop_lag    float64       
dtypes: datetime64[ns](1), float64(2), object(2)
memory usage: 150.7+ MB

Blacklist dictionary #

dublack = {"TRY": (pd.Timestamp("2020-01-01 00:00:00"), pd.Timestamp("2100-01-01 00:00:00"))}

Availability #

msm.check_availability(df=df, xcats=main, cids=cids_du, missing_recent=False)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/fc1af4e22c27c161b650354dde37fa82a26ff01534ee080e907fac53e6145a73.png

Transformations and checks #

Extended best CPI changes through hierarchical merging #

# Dictionary for merged core CPI and hierarchies of merged constituents
dict_cpicx = {
    "CPICX_" + chg: [cpi + chg for cpi in ["CPICE_", "CPIC_"]]
    for chg in ["SA_P1M1ML12"]
}

# Dictionary for merged headline CPI and hierarchies of merged constituents
dict_cpihx = {
    "CPIHX_" + chg: [cpi + chg for cpi in ["CPIHE_", "CPIH_"]]
    for chg in ["SA_P1M1ML12"]
}

# Merge dictionary of new tickers and hierarchies of merged constituents
dict_cpix = {**dict_cpicx, **dict_cpihx}

store = [
    msm.merge_categories(dfx, xcats=v, new_xcat=k)
    for k, v in dict_cpix.items()
]

dfx = msm.update_df(dfx, pd.concat(store, axis=0, ignore_index=True))

Explicit positive and negative impact categories #

dfa = dfx[dfx['xcat'].isin([xc[:-4] for xc in pe_feats if xc[-3:] == "NEG"])].copy()
dfa.loc[:, 'value'] = dfa['value'] * -1
dfa.loc[:, 'xcat'] = dfa['xcat']  + "_NEG"
dfx = msm.update_df(dfx, dfa)

dfa = dfx[dfx['xcat'].isin([xc[:-4] for xc in pe_feats if xc[-3:] == "POS"])].copy()
dfa.loc[:, 'xcat'] = dfa['xcat']  + "_POS"
dfx = msm.update_df(dfx, dfa)
# Check availability of new tickers

xcatx = [k for k in dict_cpix.keys()]
msm.check_availability(dfx, xcats = xcatx, cids=cids, missing_recent=False)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/ccb1c1eb9f5eb74d4f49532d1b869fce89701b074729ca568f3842ae3a5e6914.png
# Compare original and extended measures

xcatx = ["CPICX_SA_P1M1ML12", "CPIC_SA_P1M1ML12"]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=4,
    cumsum=False,
    start="1990-01-01",
    same_y=False,
    all_xticks=True,
    title =None,
    title_fontsize=28,
    aspect=1.4,
    size=(8, 8),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d7d5d4ee4ac245d71d1ef06e3b0bc2d57f701a2f2b5dc4bed567cfb1e0cd5cf5.png
# Compare original and extended measures

xcatx = ["CPIHX_SA_P1M1ML12", "CPIH_SA_P1M1ML12"]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=4,
    cumsum=False,
    start="1990-01-01",
    same_y=False,
    all_xticks=True,
    title =None,
    title_fontsize=28,
    aspect=1.4,
    size=(8, 8),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/553e07725a2d09926519d934508382d00e0ac0f1e8f6aa52a7e9fc6d44224215.png

Normalized information changes in annualized change units #

df_red = msm.reduce_df(dfx, xcats=pe_feats, cids=cids_du)

# creates sparse dataframe with information state changes
isc_obj = msm.InformationStateChanges.from_qdf(
    df=df_red,
    norm=True,  # normalizes changes by first release values
    std="std",
    halflife=36,  # for volatility scaling only
    min_periods=36,
)

dfa = isc_obj.to_qdf(value_column="zscore", postfix="_NIC")
dfx = msm.update_df(dfx, dfa[["real_date", "cid", "xcat", "value"]])
# Information state changes in standard annualized change units

store = []
weights = [
    (pe_freqs["D"], np.sqrt(1/262)),  # annualization factors for random walks
    (pe_freqs["W"], np.sqrt(1/52)), 
    (pe_freqs["M"], np.sqrt(1/12)), 
    (pe_freqs["Q"], np.sqrt(1/4)),
]

for xcats, w in weights:
    _tmp = msm.reduce_df(dfx, xcats=[x + "_NIC" for x in xcats])
    _tmp["value"] *= w
    _tmp["xcat"] += "A"
    store.append(_tmp[["real_date", "cid", "xcat", "value"]].dropna())

dfa = pd.concat(store, axis=0, ignore_index=True)
dfx = msm.update_df(dfx, dfa)

Winsorized information changes #

# Winsorization 3 annual information state changes for any given release date
xcatx = [xc + "_NICA" for xc in pe_feats]
cidx = cids_du

dfa = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
dfa["value"] = dfa["value"].clip(lower=-3, upper=3)
dfa["xcat"] += "W"

dfx = msm.update_df(dfx, dfa[["real_date", "cid", "xcat", "value"]].dropna())
xcatx = ['RGDPTECH_SA_P1M1ML12_NEG_NICA','RGDPTECH_SA_P1M1ML12_NEG_NICAW',]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=4,
    start="2000-01-01",
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/084d3460740b8275f1ae835ac8b4daebb5ce5e313d00839aaa62053816dbcebd.png
xcatx = ['INTRGDP_NSA_P1M1ML12_NEG_NICAW']
cidx = ["USD"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=1,
    start="2000-01-01",
    title="Example: U.S. GDP growth nowcast, normalized information state changes, inverted",
    xcat_labels=["based on higher-frequency activity indicators, GLS estimate of latest month GDP , %oya"],
    size=(12, 6),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/0df26500d8f3219cc3f6117244579e6ae8bec1abddfbb223a5d4f09e5369a356.png
xcatx = ['CPICX_SA_P1M1ML12_NEG_NICAW']
cidx = ["USD"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=1,
    start="2000-01-01",
    title="U.S. core inflation: normalized information state changes, inverted",
    xcat_labels=["based on core PCE and CPI, %oya"],
    size=(12, 6),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/da5582588dc9b6c0b72e803aace995a8a230ea81654572664b6943ff89141456.png

Moving averages of information changes #

xcatx = [xc + "_NICAW" for xc in pe_feats]
cidx = cids_du
hts=[5, 3]  # Half-times

dfa = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
dfa["ticker"] = dfa["cid"] + "_" + dfa["xcat"]
p = dfa.pivot(index="real_date", columns="ticker", values="value")

store = []
for ht in hts:
    proll = p.ewm(halflife=ht).sum()
    proll.columns += f"_{ht}DXMS"
    _df = proll.stack().to_frame("value").reset_index()
    _df[["cid", "xcat"]] = _df["ticker"].str.split("_", n=1, expand=True)
    store.append(_df[["cid", "xcat", "real_date", "value"]])
    
dfx = msm.update_df(dfx, pd.concat(store, axis=0, ignore_index=True))
tranx = [f"_NICAW_{ht}DXMS" for ht in hts]
xcatx = ['CPICX_SA_P1M1ML12_NEG_NICAW', "CPICX_SA_P1M1ML12_NEG_NICAW_3DXMS"]
cidx = ["USD"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=1,
    start="2023-01-01",
    end="2024-10-01",
    title="U.S. core inflation in 2023/24: normalized information state changes, inverted",
    xcat_labels=["daily change", "exponential moving average, 3-day half life"],
    size=(12, 6),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/64214c354a0d719df8adb5e6c9f09a1e33b95b733d2f9d064579c16b53f8a10d.png
xcatx = ['INTRGDP_NSA_P1M1ML12_NEG_NICAW', "INTRGDP_NSA_P1M1ML12_NEG_NICAW_3DXMS"]
cidx = ["USD"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=1,
    start="2023-01-01",
    end="2024-10-01",
    title="U.S. GDP growth nowcast 2023/24: normalized information state changes, inverted",
    xcat_labels=["daily change", "exponential moving average, 3-day half life"],
    size=(12, 6),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/c84ebae489137c5398a48183e12667de22a5ce78d7b211ef334deb835a3a43b5.png

Group aggregation #

Growth #

trans = tranx[0]
xcatx = [xc + trans for xc in pe_growth]

cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/b6c1e04646fe7e2b81d49d4fb8cd086b967fe3a9f0bd2eb08e7f820e13c3fa83.png
cidx = cids_du

dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)

for trans in tranx:
    xcatx = [xc + trans for xc in pe_growth]
    dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
    dfa = msp.linear_composite(
        df=dfr,
        xcats=xcatx,
        cids=cidx,
        new_xcat="GROWTH" + trans,
    )
    dfx = msm.update_df(dfx, dfa)
xcatx = ["GROWTH" + trans for trans in tranx]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=4,
    start="2000-01-01",
    aspect = 1.5,
    height=2.5,
    title="Economic growth-related information state changes, normalized and averaged across categories",
    title_fontsize=28,
    xcat_labels=["3-day half-life", "5-day half-life"],
    legend_fontsize=16,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/debed63d80eec8bf1d56f16849e29025aa8eecda7735b20a245d08767d81c41e.png
xcatx = ["GROWTH" + trans for trans in tranx]
cidx = ["USD"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=1,
    start="2023-01-01",
    end="2024-10-01",
    title="U.S. broad output and demand-growth-related normalized information state changes, 2023/24, inverted",
    xcat_labels=["3-day half life", "5-day half life"],
    size=(12, 6),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/2291c184e939355912eeff4f713a2d7c51b8a804083e2a855044d2548048d98a.png
msp.correl_matrix(
    dfx,
    xcats=["GROWTH" + tranx[0]],
    cids=cids_du,
    start="2000-01-01",
    cluster=True,
    freq="M",
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/92be0521fa5f3f7e1f0ba78fffc340af2a656e43a98895dfbfc33a111eb228dd.png

Inflation #

trans = "_NICAW_5DXMS"
xcatx = [xc + trans for xc in pe_inflation]

cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/7f41538fb94fd5f22f044bc5e684c4a946e8e042acd2d8743977127d319fe516.png
cidx = cids_du

dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)

for trans in tranx:
    xcatx = [xc + trans for xc in pe_inflation]
    dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
    dfa = msp.linear_composite(
        df=dfr,
        xcats=xcatx,
        cids=cidx,
        new_xcat="INFLATION" + trans,
    )
    dfx = msm.update_df(dfx, dfa)
xcatx = ["INFLATION" + trans for trans in tranx]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    aspect = 1.7,
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/35ff86ef464122a3a75c792508e7132750cba035ee467d3d4ca56c43f4fd8899.png
msp.correl_matrix(
    dfx,
    xcats=["INFLATION" + tranx[0]],
    cids=cids_du,
    start="2000-01-01",
    cluster=True,
    freq="M",
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/71a65a01b5af72d39aa0fb4b774d9e9227c985b610289c5089705a4309648c6c.png

Financial #

trans = tranx[0]
xcatx = [xc + trans for xc in pe_financial]

cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/5ca8d362d34ab5f2f7cffd4c1c28f7fa9be7ab5cc7916c5696b9f6a5a92d1827.png
cidx = cids_du

dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)

for trans in tranx:
    xcatx = [xc + trans for xc in pe_financial]
    dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
    dfa = msp.linear_composite(
        df=dfr,
        xcats=xcatx,
        cids=cidx,
        new_xcat="FINANCIAL" + trans,
    )
    dfx = msm.update_df(dfx, dfa)
xcatx = ["FINANCIAL" + trans for trans in tranx]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    aspect = 1.7,
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/bc1a5974a8709682e3eed22f94a77f4dfd4ca83ad16ac655458fcacee3c7350a.png
msp.correl_matrix(
    dfx,
    xcats=["FINANCIAL" + tranx[0]],
    cids=cids_du,
    start="2000-01-01",
    cluster=True,
    freq="M",
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/0ae24208cc8be823bfcffbdc6a8c083e0767608574c0f141f8db852842d104c7.png

Labour #

trans = tranx[0]
xcatx = [xc + trans for xc in pe_labour]

cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/de804c41915435a750d38bf98de3beee360bd65d22ec9c4cdcdca6aace4b01f4.png
cidx = cids_duxi

dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)

for trans in tranx:
    xcatx = [xc + trans for xc in pe_labour]
    dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
    dfa = msp.linear_composite(
        df=dfr,
        xcats=xcatx,
        cids=cidx,
        new_xcat="LABOUR" + trans,
    )
    dfx = msm.update_df(dfx, dfa)
xcatx = ["LABOUR" + trans for trans in tranx]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    aspect = 1.7,
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/91f4d89175ce8919c8d67f33b9ad7e224194ce7ec3afb953c45dba74a6f6fb52.png
msp.correl_matrix(
    dfx,
    xcats=["LABOUR" + tranx[0]],
    cids=cids_du,
    start="2000-01-01",
    cluster=True,
    freq="M",
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/0a0fe8092a8ebbc43da3d59ac9e756189a6e6983b615eb5a192fc74879be8f43.png

Surveys #

trans = tranx[0]
xcatx = [xc + trans for xc in pe_surveys]

cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d14d77fc346239ec325326c7e319b3642783fc38d6c5b3e02119b8995127e6e6.png
cidx = cids_du

dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)

for trans in tranx:
    xcatx = [xc + trans for xc in pe_surveys]
    dfr = msm.reduce_df(dfx, xcats=xcatx, cids=cidx)
    dfa = msp.linear_composite(
        df=dfr,
        xcats=xcatx,
        cids=cidx,
        new_xcat="SURVEYS" + trans,
    )
    dfx = msm.update_df(dfx, dfa)
xcatx = ["SURVEYS" + trans for trans in tranx]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    aspect = 1.7,
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d8880402b0159324498bc0c3e356e0e5dc31ba19aa2b6e132f88597391087bd9.png
msp.correl_matrix(
    dfx,
    xcats=["SURVEYS" + tranx[0]],
    cids=cids_du,
    start="2000-01-01",
    cluster=True,
    freq="M",
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d9ba3da9a4b5e0d3d6b01d32568ab9471e70100cc0ec56af6dbb67e6d2eba733.png

Cross-group aggregation #

cidx = cids_du
groups = ["GROWTH", "INFLATION", "FINANCIAL", "LABOUR", "SURVEYS"]

for trans in tranx:
    xcatx = [g + trans for g in groups]
    dfa = msp.linear_composite(
        df=dfx,
        xcats=xcatx,
        cids=cidx,
        new_xcat="ALL" + trans,
    )
    dfx = msm.update_df(dfx, dfa)
xcatx = ["ALL" + trans for trans in tranx]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=4,
    start="2000-01-01",
    aspect = 1.5,
    height=2.5,
    title="Composite macroeconomic information state changes for duration risk, average across groups",
    title_fontsize=28,
    xcat_labels=["3-day half-life", "5-day half-life"],
    legend_fontsize=16,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/9789d51214385675f8ba5491727c08dab4a4a75759305abe31c38abd76952978.png
xcatx = ["ALL" + trans for trans in tranx]
cidx = ["USD"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=1,
    start="2023-01-01",
    aspect = 1.7,
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/cff7c882a3010e98614904324d6931389238629769c6dddbad1d8ff11b2c293b.png

Global information state changes #

groups = ["GROWTH", "INFLATION", "FINANCIAL", "LABOUR", "SURVEYS", "ALL"]

xcats = [group + trans for trans in tranx for group in groups]
dfr = msm.reduce_df(dfx, xcats=xcats + ["USDGDPWGT_SA_3YMA"], cids=cids_du)
store = []
for group in groups:
    for trans in tranx:
        xc = group + trans
        dfa = msp.linear_composite(
            dfr,
            xcats=xc,
            cids=cids_duxi if group == "LABOUR" else cids_du,
            weights="USDGDPWGT_SA_3YMA",
            new_cid="GLB",
            complete_cids=False,
        )
        store.append(dfa)

dfx = msm.update_df(dfx, pd.concat(store, axis=0, ignore_index=True).dropna())
xcatx = [g + tranx[0] for g in groups]
group_labels = ["Growth", "Inflation", "Financial", "Labour", "Surveys", "Composite"]

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=["GLB"],
    xcat_grid=True,
    ncol=3,
    start="2000-01-01",
    aspect = 1.5,
    height=3,
    same_y=True,
    title="Global information state changes for duration risk, GDP-weighted average across countries",
    title_fontsize=24,
    xcat_labels=group_labels
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d81b5a2caf49374b1121aafa798a9a0b98524ce5743c701fda4dd7159f0c61e0.png

Average local-global information state changes #

cidx = cids_du
calcs = []

for g in groups:
    for trans in tranx:
        calcs += [
            f"{g}{trans}_LG = 0.5 * ( {g}{trans} + iGLB_{g}{trans} )"
        ]

dfa = msp.panel_calculator(dfx, calcs, cids=cidx)
dfx = msm.update_df(dfx, dfa)
xc = "ALL" + tranx[1]
xcatx = [xc,  xc + "_LG"]
cidx = cids_du

msp.view_timelines(
    dfx,
    xcats=xcatx,
    cids=cidx,
    ncol=3,
    start="2000-01-01",
    aspect = 1.7,
    title=None,
    same_y=True,
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/acc6083cc202109347ef24d310fa950a2f1366282ad56d0fdc801bf500dfebf8.png

Value checks #

Local signals #

Specs and panel test #

groups_ordered = ["ALL", "GROWTH", "LABOUR", "SURVEYS", "INFLATION", "FINANCIAL"]
glabels_ordered = ["Composite", "Growth", "Labour", "Surveys", "Inflation", "Financial"]
ics = [g + tranx[1] for g in groups_ordered]
display(ics)
['ALL_NICAW_3DXMS',
 'GROWTH_NICAW_3DXMS',
 'LABOUR_NICAW_3DXMS',
 'SURVEYS_NICAW_3DXMS',
 'INFLATION_NICAW_3DXMS',
 'FINANCIAL_NICAW_3DXMS']
dict_local = {
    "sigs": ics,
    "targs": ["DU05YXR_NSA", "DU05YXR_VT10",],
    "cidx": cids_du,
    "start": "2000-01-01",
    "black": dublack,
    "srr": None,
    "pnls": None,
}
dix = dict_local

sigs = dix["sigs"]
targ = dix["targs"][1] 
cidx = dix["cidx"]
blax = dix["black"]
start = dix["start"]

# Initialize the dictionary to store CategoryRelations instances

dict_cr = {}

for sig in sigs:
    dict_cr[sig] = msp.CategoryRelations(
        dfx,
        xcats=[sig, targ],
        cids=cidx,
        freq="W",
        lag=1,
        xcat_aggs=["last", "sum"],
        start=start,
        blacklist=blax,
    )

# Plotting the results

crs = list(dict_cr.values())
crs_keys = list(dict_cr.keys())

msv.multiple_reg_scatter(
    cat_rels=crs,
    title="Macroeconomic information state changes and subsequent weekly duration returns, 22 countries, since 2000",
    ylab="5-year IRS fixed receiver returns, %, vol-targeted position at 10% ar, next week",
    ncol=3,
    nrow=2,
    figsize=(15, 10),
    prob_est="map",
    coef_box="lower left",
    subplot_titles=glabels_ordered,
)
LABOUR_NICAW_3DXMS misses: ['INR'].
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/cd727cda38d69c03d3b51de8883d56cf94630828c1720c0c55ab26b009298798.png

Accuracy and correlation check #

dix = dict_local

sigx = dix["sigs"]
targx = [dix["targs"][1]]
cidx = dix["cidx"]
start = dix["start"]
blax = dix["black"]

srr = mss.SignalReturnRelations(
    dfx,
    cids=cidx,
    sigs=sigx,
    rets=targx,
    sig_neg=[False] * len(sigx),
    freqs="D",
    start=start,
    blacklist=blax,
)

dix["srr"] = srr
dix = dict_local
srr = dix["srr"]
display(srr.multiple_relations_table().astype("float").round(3))
accuracy bal_accuracy pos_sigr pos_retr pos_prec neg_prec pearson pearson_pval kendall kendall_pval auc
Return Signal Frequency Aggregation
DU05YXR_VT10 ALL_NICAW_3DXMS D last 0.506 0.506 0.489 0.527 0.534 0.479 0.024 0.000 0.017 0.000 0.506
FINANCIAL_NICAW_3DXMS D last 0.500 0.500 0.498 0.527 0.527 0.474 0.002 0.481 0.004 0.069 0.500
GROWTH_NICAW_3DXMS D last 0.501 0.501 0.508 0.527 0.528 0.473 0.012 0.000 0.005 0.006 0.501
INFLATION_NICAW_3DXMS D last 0.506 0.506 0.497 0.527 0.533 0.479 0.019 0.000 0.014 0.000 0.506
LABOUR_NICAW_3DXMS D last 0.502 0.504 0.461 0.529 0.534 0.475 0.012 0.000 0.010 0.000 0.504
SURVEYS_NICAW_3DXMS D last 0.500 0.501 0.496 0.527 0.528 0.473 0.010 0.000 0.008 0.000 0.501

Naive PnL #

dix = dict_local

sigx = dix["sigs"]
targ = dix["targs"][1]
cidx = dix["cidx"]
blax = dix["black"]
start = dix["start"]

dfxx = dfx[["real_date", "cid", "xcat", "value"]]

naive_pnl = msn.NaivePnL(
    dfxx,
    ret=targ,
    sigs=sigx,
    cids=cidx,
    start=start,
    blacklist=blax,
    bms=["USD_DU05YXR_NSA"],
)

for sig in sigx:
    for bias in [0, 1]:
        naive_pnl.make_pnl(
            sig,
            sig_neg=False,
            sig_op='zn_score_pan',
            sig_add=bias,
            thresh=2,
            rebal_freq="daily",
            vol_scale=10,
            rebal_slip=1,
            pnl_name=sig+"_PZN" + str(bias)
        )

naive_pnl.make_long_pnl(vol_scale=10, label="Long only")

dix["pnls"] = naive_pnl
dix = dict_local

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN" + str(bias) for s in sigx[:1] for bias in [0,1]] + ["Long only"]

naive_pnl.plot_pnls(
    pnl_cats=pnls,
    pnl_cids=["ALL"],
    start=start,
    title="Naive PnLs of IRS positions based on macroeconomic information state changes (22 countries)",
    xcat_labels=["Unbiased signals", "Long-biased signals", "Long only"],
    figsize=(16, 10),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/031673ee424f0be002e2b3c2e38a02b2e5b437bdbd43acf77947298e30c4b29f.png
dix = dict_local

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN0" for s in sigx[1:]]

naive_pnl.plot_pnls(
    pnl_cats=pnls,
    pnl_cids=["ALL"],
    start=start,
    title="Naive PnLs of global IRS positions based on macro group information state changes (unbiased signals)",
    xcat_labels=glabels_ordered[1:],
    figsize=(16, 10),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/14ea786eb143b682984187f976db701504889fb25c68ffd17782e64a69580c58.png
dix = dict_local

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN0" for s in sigx[1:]]

naive_pnl.plot_pnls(
    pnl_cats=["ALL_NICAW_3DXMS_PZN0"],
    pnl_cids=cids_du,
    start=start,
    title=None,
    xcat_labels=None,
    figsize=(16, 10),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/8d39dcb3b86ec0a3e0bfdf895fc0103cafc064f7f6ffe1d36819290be87163a9.png
dix = dict_local

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN" + str(bias) for s in sigx for bias in [0, 1]] + ["Long only"]

df_eval = naive_pnl.evaluate_pnls(
    pnl_cats=pnls,
    pnl_cids=["ALL"],
    start=start,
)
display(df_eval.transpose())

naive_pnl.signal_heatmap(
    pnl_name=pnls[0], 
    freq="m",
    title=None,  
    figsize=(15, 8)
)
Return % St. Dev. % Sharpe Ratio Sortino Ratio Max 21-Day Draw % Max 6-Month Draw % Peak to Trough Draw % Top 5% Monthly PnL Share USD_DU05YXR_NSA correl Traded Months
xcat
ALL_NICAW_3DXMS_PZN0 14.044601 10.0 1.40446 2.219272 -16.634165 -21.383134 -40.576936 0.460366 0.027031 297
ALL_NICAW_3DXMS_PZN1 10.382127 10.0 1.038213 1.53101 -16.464681 -19.320654 -38.479592 0.608575 0.509678 297
FINANCIAL_NICAW_3DXMS_PZN0 2.997544 10.0 0.299754 0.42673 -26.102869 -28.731884 -34.577809 1.403208 -0.014552 297
FINANCIAL_NICAW_3DXMS_PZN1 4.30893 10.0 0.430893 0.602708 -18.115622 -38.992121 -100.358854 1.370909 0.494643 297
GROWTH_NICAW_3DXMS_PZN0 5.942599 10.0 0.59426 0.905276 -13.668253 -33.684757 -64.477278 0.991143 0.042591 297
GROWTH_NICAW_3DXMS_PZN1 6.209233 10.0 0.620923 0.900314 -18.429364 -35.728056 -61.601485 0.943586 0.511139 297
INFLATION_NICAW_3DXMS_PZN0 10.102633 10.0 1.010263 1.535279 -21.110239 -25.424515 -29.09891 0.643903 0.011496 297
INFLATION_NICAW_3DXMS_PZN1 8.600704 10.0 0.86007 1.238629 -22.224386 -19.726602 -42.973482 0.717687 0.484937 297
LABOUR_NICAW_3DXMS_PZN0 7.733969 10.0 0.773397 1.17337 -15.348281 -22.557322 -26.249557 0.808816 -0.021452 297
LABOUR_NICAW_3DXMS_PZN1 7.261318 10.0 0.726132 1.030505 -20.014642 -25.091671 -61.928922 0.756011 0.537902 297
Long only 3.818532 10.0 0.381853 0.530836 -21.196039 -39.869799 -104.229615 1.445041 0.549019 297
SURVEYS_NICAW_3DXMS_PZN0 7.633798 10.0 0.76338 1.143302 -14.860064 -31.987637 -63.776494 0.712045 0.041963 297
SURVEYS_NICAW_3DXMS_PZN1 5.965138 10.0 0.596514 0.854811 -18.361336 -44.455155 -95.907129 1.061163 0.505012 297
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/aaeec6345ecd90205e1ef72f01e0feed2131c4a5476a16ee79e27498a826573a.png

Local-global signals #

Specs and panel test #

ics_g = [i + "_LG" for i in ics]

dict_lg = {
    "sigs": ics_g,
    "targs": ["DU05YXR_NSA", "DU05YXR_VT10"],
    "cidx": cids_du,
    "start": "2000-01-01",
    "black": dublack,
    "srr": None,
    "pnls": None,
}
dix = dict_lg

sigs = dix["sigs"]
targ = dix["targs"][1] 
cidx = dix["cidx"]
blax = dix["black"]
start = dix["start"]

# Initialize the dictionary to store CategoryRelations instances

dict_cr = {}

for sig in sigs:
    dict_cr[sig] = msp.CategoryRelations(
        dfx,
        xcats=[sig, targ],
        cids=cidx,
        freq="W",
        lag=1,
        xcat_aggs=["last", "sum"],
        start=start,
        blacklist=blax,
    )

# Plotting the results

crs = list(dict_cr.values())
crs_keys = list(dict_cr.keys())

msv.multiple_reg_scatter(
    cat_rels=crs,
    title="Global/local macro information changes and subsequent weekly duration returns, 22 countries, since 2000",
    ylab="5-year IRS fixed receiver returns, %, vol-targeted position at 10% ar, next week",
    ncol=3,
    nrow=2,
    figsize=(15, 10),
    prob_est="map",
    coef_box="lower left",
    subplot_titles=glabels_ordered,
)
LABOUR_NICAW_3DXMS_LG misses: ['INR'].
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d6c4f22a5ffc5a737bc9afaebb55c0c21590e5046e157adb67e5cdb60d962d87.png

Accuracy and correlation check #

dix = dict_lg

sigx = dix["sigs"]
targx = [dix["targs"][1]]
cidx = dix["cidx"]
start = dix["start"]
blax = dix["black"]

srr = mss.SignalReturnRelations(
    dfx,
    cids=cidx,
    sigs=sigx,
    rets=targx,
    sig_neg=[False] * len(sigx),
    freqs="D",
    start=start,
    blacklist=blax,
)

dix["srr"] = srr
dix = dict_lg
srr = dix["srr"]
display(srr.multiple_relations_table().astype("float").round(3))
accuracy bal_accuracy pos_sigr pos_retr pos_prec neg_prec pearson pearson_pval kendall kendall_pval auc
Return Signal Frequency Aggregation
DU05YXR_VT10 ALL_NICAW_3DXMS_LG D last 0.508 0.509 0.475 0.527 0.537 0.481 0.034 0.000 0.024 0.000 0.509
FINANCIAL_NICAW_3DXMS_LG D last 0.500 0.501 0.479 0.527 0.527 0.474 0.003 0.334 0.004 0.032 0.501
GROWTH_NICAW_3DXMS_LG D last 0.503 0.501 0.522 0.527 0.529 0.474 0.016 0.000 0.008 0.000 0.501
INFLATION_NICAW_3DXMS_LG D last 0.507 0.507 0.497 0.527 0.535 0.480 0.029 0.000 0.017 0.000 0.507
LABOUR_NICAW_3DXMS_LG D last 0.501 0.506 0.415 0.529 0.536 0.476 0.020 0.000 0.017 0.000 0.506
SURVEYS_NICAW_3DXMS_LG D last 0.505 0.505 0.491 0.527 0.533 0.478 0.018 0.000 0.013 0.000 0.505

Naive PnL #

dix = dict_lg

sigx = dix["sigs"]
targ = dix["targs"][1]
cidx = dix["cidx"]
blax = dix["black"]
start = dix["start"]

dfxx = dfx[["real_date", "cid", "xcat", "value"]]

naive_pnl = msn.NaivePnL(
    dfxx,
    ret=targ,
    sigs=sigx,
    cids=cidx,
    start=start,
    blacklist=blax,
    bms=["USD_DU05YXR_NSA"],
)

for sig in sigx:
    for bias in [0, 1]:
        naive_pnl.make_pnl(
            sig,
            sig_neg=False,
            sig_op='zn_score_pan',
            sig_add=bias,
            thresh=2,
            rebal_freq="daily",
            vol_scale=10,
            rebal_slip=1,
            pnl_name=sig+"_PZN" + str(bias)
        )

naive_pnl.make_long_pnl(vol_scale=10, label="Long only")

dix["pnls"] = naive_pnl
dix = dict_lg

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN" + str(bias) for s in sigx[:1] for bias in [0,1]] + ["Long only"]

naive_pnl.plot_pnls(
    pnl_cats=pnls,
    pnl_cids=["ALL"],
    start=start,
    title="Naive PnLs of IRS positions based on local and global macro information changes (22 countries)",
    xcat_labels=["Unbiased signals", "Long-biased signals", "Long only"],
    figsize=(16, 10),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/96a04f1882342b633ae66a9da4426af1311b041d8bfb31fab537fa80141c4192.png
dix = dict_lg

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN0" for s in sigx[1:]]

naive_pnl.plot_pnls(
    pnl_cats=pnls,
    pnl_cids=["ALL"],
    start=start,
    title=None,
    xcat_labels=None,
    figsize=(16, 10),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d33724279971c06725eba33652b6a81418087503633b75ef4db677c8aaea2ffa.png
dix = dict_lg

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

naive_pnl.plot_pnls(
    pnl_cats=["ALL_NICAW_3DXMS_LG_PZN0"],
    pnl_cids=cids_du,
    start=start,
    title=None,
    xcat_labels=None,
    figsize=(16, 10),
)
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/d26df38d7713e1e444778f94d018638afd2d58d5b3c374f4539bc52651fdc4d0.png
dix = dict_lg

sigx = dix["sigs"]
start = dix["start"]
cidx = dix["cidx"]
naive_pnl = dix["pnls"]

pnls = [s + "_PZN" + str(bias) for s in sigx for bias in [0, 1]] + ["Long only"]

df_eval = naive_pnl.evaluate_pnls(
    pnl_cats=pnls,
    pnl_cids=["ALL"],
    start=start,
)
display(df_eval.transpose())

naive_pnl.signal_heatmap(
    pnl_name=pnls[0], 
    freq="m",
    title=None,  
    figsize=(15, 8)
)
Return % St. Dev. % Sharpe Ratio Sortino Ratio Max 21-Day Draw % Max 6-Month Draw % Peak to Trough Draw % Top 5% Monthly PnL Share USD_DU05YXR_NSA correl Traded Months
xcat
ALL_NICAW_3DXMS_LG_PZN0 14.703615 10.0 1.470362 2.455916 -15.341293 -33.728573 -53.160224 0.503201 0.035687 297
ALL_NICAW_3DXMS_LG_PZN1 12.50951 10.0 1.250951 1.923538 -14.51174 -18.125523 -25.35905 0.531841 0.469634 297
FINANCIAL_NICAW_3DXMS_LG_PZN0 2.434834 10.0 0.243483 0.343614 -18.132188 -25.751513 -37.503764 1.802358 0.005879 297
FINANCIAL_NICAW_3DXMS_LG_PZN1 4.566521 10.0 0.456652 0.639657 -17.404879 -42.263079 -101.87145 1.301639 0.456752 297
GROWTH_NICAW_3DXMS_LG_PZN0 6.65891 10.0 0.665891 1.052453 -17.908078 -49.46279 -76.480263 1.018624 0.049199 297
GROWTH_NICAW_3DXMS_LG_PZN1 6.620522 10.0 0.662052 0.974406 -17.871221 -37.556838 -63.228454 0.946017 0.47564 297
INFLATION_NICAW_3DXMS_LG_PZN0 10.296776 10.0 1.029678 1.662189 -14.550585 -19.283698 -27.102031 0.810205 0.010414 297
INFLATION_NICAW_3DXMS_LG_PZN1 9.988736 10.0 0.998874 1.471623 -20.715996 -18.288434 -26.511343 0.682513 0.427007 297
LABOUR_NICAW_3DXMS_LG_PZN0 8.629493 10.0 0.862949 1.337339 -19.366226 -21.003906 -51.839471 0.732909 -0.022144 297
LABOUR_NICAW_3DXMS_LG_PZN1 8.919749 10.0 0.891975 1.286978 -19.456313 -22.423374 -34.542463 0.645029 0.499283 297
Long only 3.818532 10.0 0.381853 0.530836 -21.196039 -39.869799 -104.229615 1.445041 0.549019 297
SURVEYS_NICAW_3DXMS_LG_PZN0 8.213623 10.0 0.821362 1.260244 -22.208689 -33.260102 -48.744804 0.754814 0.053591 297
SURVEYS_NICAW_3DXMS_LG_PZN1 7.140803 10.0 0.71408 1.04503 -18.333643 -50.128001 -91.78611 0.949439 0.456572 297
https://macrosynergy.com/notebooks.build/trading-factors/macro-information-changes-and-fixed-income/_images/a119c8f64203e146e829d3dca68a8b5f790233f4baa9abfee9f74fa79492a366.png