Back to Openbb

Calculating the USD Liquidity Index with the OpenBB Platform

examples/usdLiquidityIndex.ipynb

4.7.05.4 KB
Original Source

Calculating the USD Liquidity Index with the OpenBB Platform

This popular indicator is made from a simple subtraction of three FRED series that are published every Wednesday, and is often overlayed with risk assets like the S&P 500 Index or Bitcoin. The OpenBB SDK is well suited for this task, let's take a look to create this index.

The formula is defined as:

console
WALCL (All Liabilities) – WLRRAL (RRP) – WDTGAL (TGA)

To get these data series, we will use the openbb-fred data extension and the economy module. First thing is to import the Python interface, and we will also import Pandas to conduct some DataFrame operations.

python
from openbb import obb
from pandas import DataFrame

There are two fred functions in the openbb-economy router:

  • obb.economy.fred_search()
  • obb.economy.fred_series()
python
data = obb.economy.fred_series(["WALCL", "WLRRAL", "WDTGAL", "SP500"])

data

There is metadata from each series in the warnings of the response object. It can be recovered as a JSON dictionary.

python
metadata = data.extra["results_metadata"]

display(metadata.keys())
display(metadata["WALCL"].get("title"))
display(metadata["WALCL"].get("units"))

Querying FRED

If we didn't already know the ID for the series, we can search with:

python
# The first result is the series we are looking for as the starting value.

obb.economy.fred_search("Wednesday Levels").to_df().head(3)
python
# Adding "Reverse Repo" to the search returns the second series in the equation, as the first result.

obb.economy.fred_search("Wednesday Levels Reverse Repo").to_df().head(3)
python
# Refining the search for the Treasury General Account, returns the final series in the equation, as the first result.

obb.economy.fred_search("Wednesday Levels Treasury General").to_df().head(3)
python
# Several major equity indices are published to FRED, S&P 500 is one of them.

obb.economy.fred_search("SP500").to_df().head(2)

By looking at the descriptions, we can confirm that all three Federal Reserve series are numbers as Millions of USD. If they were not all equivalent, some adjustments would need to be made before applying the equation.

python
for id in metadata:
    display(f"{id}: {metadata[id]['units']}")

Inspecting the time series element shows that the S&P 500 data (as published to FRED) does not extend as far back as the others. Let's drop the NaN values and start the time series at a common starting point, which is approximately ten years ago.

python
display(data.to_df().head(4))
display(data.to_df().dropna().head(4))

# We'll create a new DataFrame object with the dropped rows.
liquidity_index = DataFrame(data.to_df().dropna())

Applying the formula will simply be a matter of subtracting the first, three, columns.

python
liquidity_index["USD Liquidity Index"] = (
    liquidity_index["WALCL"] - liquidity_index["WLRRAL"] - liquidity_index["WDTGAL"]
)

liquidity_index.tail(4)

Now that there are two items to compare, let's draw it!

python
import plotly.graph_objects as go

fig = go.Figure()

fig.add_scatter(
    x=liquidity_index.index,
    y=liquidity_index["USD Liquidity Index"] / 1000,
    name="USD Liquidity Index (Billions)",
    yaxis="y1",
)

fig.add_scatter(
    x=liquidity_index.index,
    y=liquidity_index["SP500"],
    name="S&P 500 Index",
    yaxis="y2",
)

fig.update_layout(
    yaxis=dict(
        title="USD Liquidity Index (Billions)",
        side="left",
        position=0,
        titlefont=dict(size=12),
        showgrid=False,
    ),
    yaxis2=dict(
        title="S&P 500 Index",
        side="right",
        overlaying="y",
        position=1,
        titlefont=dict(size=12),
    ),
    title="USD Liquidity Index vs. S&P 500 Index",
    title_y=0.90,
    title_x=0.5,
    autosize=True,
)

To draw them both on the same y-axis, they will need to be normalized. There are several methods for normalizing a series, the fourth function in the block below paramaterizes a few of them, making it easy to A/B them.

python
y_axis = liquidity_index[["USD Liquidity Index", "SP500"]]


def absolute_maximum_scale(series):
    return series / series.abs().max()


def min_max_scaling(series):
    return (series - series.min()) / (series.max() - series.min())


def z_score_standardization(series):
    return (series - series.mean()) / series.std()


methods = {
    "z": z_score_standardization,
    "m": min_max_scaling,
    "a": absolute_maximum_scale,
}


def normalize(data: DataFrame, method: str = "z") -> DataFrame:
    for col in data.columns:
        data.loc[:, col] = methods[f"{method}"](data.loc[:, col])

    return data


normalized = normalize(y_axis, method="m")

normalized.tail(3)

Now they can be easily plotted using the built-in DataFrame.plot method.

python
import pandas as pd

pd.options.plotting.backend = "plotly"
normalized.plot()

If you just want to visualize the results, this is a fast way of doing it. However, titles and other customizatons clean things up.

python
fig = go.Figure()

fig.add_scatter(
    x=normalized.index, y=normalized["USD Liquidity Index"], name="USD Liquidity Index"
)

fig.add_scatter(x=normalized.index, y=normalized["SP500"], name="S&P 500 Index")

fig.update_layout(
    title="USD Liquidity Index vs. S&P 500 Index (Normalized)",
    title_y=0.90,
    title_x=0.5,
    autosize=True,
)

The combinations are endless and we love seeing your creations, tag us on social media with your custom indexes and indicators.