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)
- JTS000000000000000QUR — Quits rate, total nonfarm (% of employment)
- JTS000000000000000LDR — Layoffs & discharges rate, total nonfarm (% of employment)
- JTS000000000000000JOR — Job openings rate, total nonfarm (% of employment)
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; parsedateto 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_rateis entirely missing or all NaN.
A simple data_quality log (optional) can track last observation date and ffill counts for monitoring.
3. Transform Definitions
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.
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
}
Missing components are automatically dropped and weights re‑normalised if needed.
6. Smoothing, Scaling & Regimes
- Headline smoothing: 3‑period EMA of the composite z‑score:
ewm(span=3). - Score (0–100): min–max scaled over the observed history; returns all‑NaN if the series is flat.
- Regime mapping: thresholds on the (unsmoothed) composite z‑score.
- 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
- Quarterly review of thresholds, lookback windows, and weights (0.60/0.40 baseline).
- Log code changes and backtest impacts; maintain semantic versioning.