Private‑Credit Impulse
Abstract
The Private‑Credit Impulse signal quantifies acceleration or deceleration in aggregate private‑sector credit growth. Version 1.1 blends a short‑horizon momentum measure (3‑month annualised growth) with a slower trend measure (year‑over‑year growth) for total bank credit, business lending, and consumer credit. Each growth series is robust‑standardised and averaged to create a composite that identifies Accelerating, Stable, and Decelerating credit regimes, with simple confirmation rules to reduce whipsaws.
1. Data
The signal uses three public credit aggregates sourced from the Federal Reserve and distributed via FRED. Two inputs come from the Federal Reserve’s H.8 release (Assets and Liabilities of Commercial Banks in the United States), and one comes from the G.19 Consumer Credit release.
TOTBKCR — Bank Credit, All Commercial Banks (H.8). Weekly, levels; seasonally adjusted.
- Concept: broad bank credit (loans and securities) held by U.S. commercial banks.
- Use in model: baseline proxy for bank-intermediated credit availability and broad balance-sheet expansion/contraction.
- Revision profile: updated weekly; recent observations can be revised as reporting is updated and seasonal factors are re-estimated.
BUSLOANS — Commercial and Industrial Loans, All Commercial Banks (H.8). Monthly, levels; seasonally adjusted.
- Concept: bank lending to businesses for working capital and investment.
- Use in model: cyclical, demand-sensitive credit component that tends to respond to funding conditions and business sentiment.
- Revision profile: subject to revisions tied to H.8 compilation and reporting updates.
TOTALSL — Total Consumer Credit Owned and Securitized (G.19). Monthly, levels; seasonally adjusted (default FRED presentation).
- Concept: total consumer credit outstanding (revolving + nonrevolving), owned and securitized.
- Use in model: household credit momentum; complements business lending and broad bank credit.
- Revision profile: can be revised as source data are updated; revisions are typically less frequent than weekly H.8 but still material for recent months.
Units & frequency harmonisation. Inputs are levels (USD; as published by FRED). The model converts each series to growth measures and then standardises them. Where frequencies differ (weekly vs monthly), align to a monthly calendar using end‑of‑month values and carry forward only when the source has not yet updated (publish a missing/stale flag when forward-filling).
Tip: For real-time robustness, consider retrieving vintages using ALFRED (archival FRED) when backtesting regime flips near turning points.
2. Growth‑Rate Transformation
Credit aggregates are level series. To separate trend from momentum, v1.1 computes two growth transforms for each component:
For legacy continuity, you may also compute the prior six‑month annualised growth:
Revision note: weekly bank credit series are frequently revised. Short-horizon growth (3m/6m annualised) should be interpreted with a revision-risk discount, especially at the sample endpoint.
3. Normalisation
4. Composite Construction
- Compute g^{yoy} and g^{3m} growth for each input series.
- Macro adjustment (recommended): deflate nominal credit growth by inflation and benchmark against GDP growth:
- g^{real} \approx g^{nominal} - \pi (using CPI or PCE inflation \pi).
- g^{excess} \approx g^{nominal} - (\pi + g^{real\ GDP}) to approximate credit growth above “nominal trend”.
This reduces false “acceleration” signals in high-inflation or strong-nominal-GDP environments. - Robust-standardise each growth series with a rolling median/MAD z‑score.
- Build two composites:
- Trend composite: average of component z‑scores on g^{yoy}.
- Momentum composite: average of component z‑scores on g^{3m}.
- Combine trend and momentum:
C_t = w_m\,C^{mom}_t + (1-w_m)\,C^{trend}_tDefault w_m=0.6 (momentum-weighted) to keep the signal responsive while anchoring to the slower YoY trend.
5. Regime Mapping
Regimes map the composite C_t into discrete states. v1.1 introduces a small transition band and recommends macro-adjusted calibration.
- Default threshold: h=0.75 (heuristic).
- Transition / hysteresis: require two consecutive monthly closes beyond ±h to confirm a new regime, and treat |C_t|\in[0.60,0.75] as “transition risk” rather than a clean flip.
- Inflation/GDP-aware calibration: if using nominal growth without macro adjustment, consider widening h during high inflation or unusually strong nominal GDP growth to avoid overstating “credit acceleration”.
6. Implementation (Python)
import pandas as pd
import numpy as np
def robust_z(s, win=48, min_win=18):
x = pd.to_numeric(s, errors="coerce").astype(float)
w = max(min_win, min(win, x.dropna().size))
med = x.rolling(w, min_periods=min_win).median()
mad = (x - med).abs().rolling(w, min_periods=min_win).median()
return (x - med) / (1.4826 * mad.replace(0, np.nan))
def yoy(series): # trend
return (series / series.shift(12)) - 1.0
def ann3(series): # momentum (3m annualised)
return (series / series.shift(3))**4 - 1.0
d = df_priv_credit.copy()
# Optionally join CPI/PCE inflation and real GDP growth to compute real/excess measures.
# Example (approx): g_real = g_nominal - inflation; g_excess = g_nominal - (inflation + real_gdp)
components = ["TOTBKCR","BUSLOANS","TOTALSL"]
# growth transforms
for col in components:
d[f"{col}_yoy"] = yoy(d[col])
d[f"{col}_ann3"] = ann3(d[col])
# z-score each transform
z_trend, z_mom = [], []
for col in components:
zt = robust_z(d[f"{col}_yoy"])
zm = robust_z(d[f"{col}_ann3"])
d[f"Z_{col}_trend"] = zt
d[f"Z_{col}_mom"] = zm
z_trend.append(f"Z_{col}_trend")
z_mom.append(f"Z_{col}_mom")
d["C_trend"] = d[z_trend].mean(axis=1)
d["C_mom"] = d[z_mom].mean(axis=1)
w_m = 0.6
d["Private_Credit_Impulse"] = w_m*d["C_mom"] + (1-w_m)*d["C_trend"]
h = 0.75
def regime(series, hi=h, confirm=2):
# two-close confirmation to reduce whipsaws
out = pd.Series(index=series.index, dtype="object")
state = "Stable"
count = 0
for i, v in enumerate(series.values):
if pd.isna(v):
out.iat[i] = np.nan
continue
target = "Accelerating" if v > hi else ("Decelerating" if v < -hi else "Stable")
if target == state:
count = 0
else:
count = count + 1 if target != "Stable" else 0
if target == "Stable":
state, count = "Stable", 0
elif count >= confirm:
state, count = target, 0
out.iat[i] = state
return out
d["Credit_Impulse_Regime"] = regime(d["Private_Credit_Impulse"])
df_sig_priv_credit = d
display(df_sig_priv_credit.tail())
7. Interpretation
What the signal is measuring
- Momentum: whether private credit creation is speeding up or slowing down over the last ~quarter (3m annualised).
- Trend: whether credit growth is elevated or depressed relative to its recent history (YoY).
- Composite: a robust, cross-component view of bank credit + business lending + consumer credit; reduces single-series noise.
Regime meanings (practical)
- Accelerating: credit growth is rising relative to recent history. Historically associated with improving demand conditions and easier financing—often early/mid-cycle.
- Stable: credit momentum is near trend; interpret as “no strong impulse” rather than benign/negative by itself.
- Decelerating: credit creation is slowing; historically a leading indicator for growth slowdowns when sustained.
How to interpret in context (rules of thumb)
- Endpoint caution: weekly bank credit data can be revised; treat the most recent 1–2 months as provisional and confirm with later vintages.
- Inflation/GDP lens: if nominal credit growth rises mainly because inflation and nominal GDP are higher, the “impulse” for real activity may be weaker—use real/excess adjustments where possible.
- Turning points: focus on the direction and persistence (two-close confirmation) rather than a single monthly print.
- Decomposition: check component contributions—business-loan momentum often drives cyclical swings; consumer credit can be influenced by securitisation and lending standards.
8. Evidence base & model interpretation
9. Limitations
- Weekly bank credit series are subject to revisions; near-term regime classifications can change as reporting is updated. Consider real-time (ALFRED) evaluation for backtests.
- Loan aggregates can shift due to accounting, securitisation, and reclassifications; these can create artificial swings unrelated to credit supply/demand.
- Inflation and nominal GDP regimes affect nominal credit growth. If you do not apply macro adjustments, static thresholds can misclassify high-inflation periods as “accelerating.”
- Fixed component weights and heuristic thresholds are simplifications; periodic recalibration and publication of component contributions improve robustness and transparency.