Labor Market Tightness (JOLTS)

A reproducible signal summarising U.S. labor market tightness from JOLTS: quits, layoffs & discharges, and job openings. The headline combines a quits–layoffs differential with the openings rate using robust z‑scores.

Why: When quits outpace layoffs and openings remain elevated, firms face hiring frictions and wage pressure; the opposite signals cooling conditions.

Abstract

We construct a monthly signal from BLS JOLTS rates: quits (QUR), layoffs & discharges (LDR), and job openings (JOR). We compute the core differential Tightness_t = Quits_t − Layoffs_t, standardise it and the openings rate with robust rolling z‑scores, and blend them into a composite. We also provide a smoothed headline, momentum diagnostics, an intuitive 0–100 scale, and categorical regimes.

1. Data (BLS JOLTS Identifiers)

All inputs are monthly. We restrict to these three series (hard filter) before pivoting to a wide table to avoid stray IDs becoming all‑NaN columns.

2. Data Quality, Cleaning & Validation

  • Column sanity: assert presence of series_id, date, value.
  • Type coercion: force numeric value; parse date to monthly start.
  • Resampling: align to a monthly‑start grid via asfreq("MS").
  • Bounded forward‑fill: ffill(limit=2) to tame small gaps; larger gaps remain missing.
  • Fail‑fast: after pivot, raise if any of quits_rate, layoffs_rate, openings_rate is entirely missing or all NaN.

A simple data_quality log (optional) can track last observation date and ffill counts for monitoring.

3. Transform Definitions

Tightness_t = QuitsRate_t − LayoffsRate_t
Momentum^{(3m)}_t(x) = x_t − x_{t-3}

We compute Tightness and 3‑month differences for both Tightness and Openings as diagnostics. Momentum is not part of the composite by default.

4. Standardisation (Robust Rolling z‑scores)

Each target series is scaled with a rolling, history‑adaptive W (default 24 months, minimum 8–12 depending on availability) using median/MAD to mitigate outliers and base‑rate drift.

z_t(x) = \dfrac{x_t - \text{median}_W(x)}{1.4826\,\text{MAD}_W(x)}\ ,\quad W=\min(24,\max(12,\lfloor0.8\cdot N_{valid}\rfloor))

If the MAD is zero or non‑finite, we protect the denominator with a small \varepsilon to avoid division errors.

5. Weighting & Composite Construction

We combine the z‑scores of the core differential and the openings rate. Weights are configurable; defaults emphasise the quits–layoffs spread.

{
  "Labor_Tightness_z": 0.60,
  "Openings_z": 0.40
}
LMT_t = 0.60\,z_t(Tightness) + 0.40\,z_t(Openings)

Missing components are automatically dropped and weights re‑normalised if needed.

6. Smoothing, Scaling & Regimes

  • HOT (tightening risk): LMTz > +0.75
  • NEUTRAL: −0.75 ≤ LMTz ≤ +0.75
  • COOL (easing): LMTz < −0.75

7. Output Panel

The final panel includes the raw rates, transforms, diagnostics, and the composite:

[
  "quits_rate", "layoffs_rate", "openings_rate",
  "Labor_Tightness", "Labor_Tightness_z", "Openings_z",
  "Tightness_mom_3m", "Openings_mom_3m",
  "LMT_Composite_z", "LMT_Composite_0_100",
  "LMT_Signal_Smoothed", "LMT_Regime"
]

8. Implementation Notes (Python)

# Expect columns: series_id, date, value
subset = [
  "JTS000000000000000QUR",  # quits
  "JTS000000000000000LDR",  # layoffs & discharges
  "JTS000000000000000JOR",  # job openings
]
_lmt = long_df[long_df["series_id"].isin(subset)].copy()
_lmt["value"] = pd.to_numeric(_lmt["value"], errors="coerce")
_lmt["date"] = pd.to_datetime(_lmt["date"]).dt.to_period("M").dt.start_time

# Wide grid, bounded ffill
lmt_wide = (
  _lmt.pivot(index="date", columns="series_id", values="value")
      .sort_index().asfreq("MS").ffill(limit=2)
  .rename(columns={
    "JTS000000000000000QUR":"quits_rate",
    "JTS000000000000000LDR":"layoffs_rate",
    "JTS000000000000000JOR":"openings_rate",
  })
)

# Robust z, momentum, composite, smoothing, regime, 0–100 scale
# (as detailed above)

9. Interpretation & Use

HOT regimes align with tightening labor conditions and potential wage pressure; COOL regimes suggest easing frictions and lower inflationary impulse. Combine with inflation, liquidity, and growth signals for cross‑checking.

10. Governance & Change Control