Macro Regime Classification: Methodology and Data
eco3min · macro regime classification
Eco3min assigns a monthly macro regime to the US economy by combining public institutional indicators with a published threshold table. This page details the design, data sources, classification logic, and limitations.
What this classification computes
For any given month, the classification answers: what macro regime is the US economy in, based only on public data and a verifiable rule?
Every term is verifiable: the regime name follows from the growth × inflation grid (see Architecture), the financial conditions qualifier from the Chicago Fed’s NFCI, the global context from OECD CLIs and the ECB’s CISS.
What this classification is NOT
- A proprietary score (no opaque weighting)
- A trading signal or investment recommendation
- A forecast of future conditions
- An official cycle dating (≠ NBER)
- A portfolio timing or allocation system
Three independent axes
The classification uses three independent axes — real activity, inflation, financial conditions — rather than a flat list that conflates orthogonal dimensions. These three axes are the inputs of the calculation: what the engine measures to produce a verdict. They must not be confused with the three layers of the Atlas (see below), which describe the nature of the regime objects, at different horizons and evidentiary statuses. Two distinct reading grids: the axes are the ingredients, the layers are the dishes.
Axis 1 — Growth / real activity
Three states: acceleration (G+) / on-trend (G=) / contraction (G−). Primary input: Chicago Fed’s CFNAI (3-month moving average). A CFNAI value of 0 corresponds to the historical long-run trend.
Axis 2 — Inflation
Three states: acceleration (I+) / stable (I=) / disinflation (I−). Primary input: Dallas Fed’s Trimmed Mean PCE (12-month rate). This axis measures persistent underlying inflation. The Trimmed Mean PCE excludes, by construction, the most volatile price components — including energy. A transitory energy shock (a spike in gasoline or Brent) can therefore leave this axis at “stable” even as headline inflation climbs: this is intended behaviour, not a failure. In that case, the shock appears in the global context layer (commodity channel) and via the headline/underlying divergence flag — not in the regime name.
Axis 3 — Financial conditions (overlay-qualifier)
Four levels: accommodating / neutral / restrictive / acute stress. Primary input: Chicago Fed’s NFCI (composite of 105 variables, weekly since 1971). See our financial-conditions index series for the underlying data. This axis prefixes the regime name without creating a third nominal axis, and updates without hysteresis. The engine reads the NFCI and nothing else on this axis: no composite, no weighting, four thresholds. The Atlas also describes a named overlay, the Dollar Shortage, as a distinct configuration of global financial conditions — that page describes a mechanism; the classifier does not detect it and produces no named overlay in its output.
The 3×3 growth × inflation grid maps to seven named regimes plus a transition state.
A hierarchical world view, not an aggregated score
A single aggregated world score masks inter-zone divergence (e.g., 2022: US tightening vs China easing) — a misleading indicator. The architecture is hierarchical:
US core
Detailed growth × inflation classification + overlay, using the full set of US inputs. This is the primary verdict.
Global context layer
Qualifies the environment around the US core on two dimensions: synchronization (are other zones moving in the same direction? via OECD CLIs) and global transmission channels (broad dollar, commodities, market stress via VIX + ECB CISS eurozone).
A eurozone core on the same architecture (ECB and Eurostat inputs) is on the roadmap and is not part of v1.1.0, which calibrated the US core only. The euro area currently enters the classification through one channel: the ECB’s CISS, in the global context layer.
The seven regimes and the transition state
| Growth Inflation | I− (disinflation) | I= (stable) | I+ (acceleration) |
|---|---|---|---|
| G+ (above trend) | Disinflationary Expansion | Balanced Expansion | Overheating |
| G= (on trend) | Transition | Transition | Inflationary Pressure |
| G− (contracting) | Disinflationary Contraction | Slowdown | Stagflation |
Each regime below is followed by its verified occurrences in the published series (regime_history_v1.1.0.csv, 283 months, January 2003 → July 2026). These are the months the classifier actually assigns, not illustrative labels — every one can be checked by filtering the file. Episodes before 2003 fall outside the published window and are flagged as illustrative.
Disinflationary Expansion G+ I−
Above-trend activity with inflation decelerating or below target. Rare by construction: it requires the Trimmed Mean PCE below 1.50% — roughly the 4th percentile of its distribution — at the same time as above-trend growth.
Published series: 3 months — May to July 2010. Illustrative, pre-2003: 1995–1999 (New Economy)
Balanced Expansion G+ I=
Above-trend activity with inflation near target. The second most common state in the published series.
Published series: 65 months across 8 spans — longest Nov 2003 → Sep 2005 (23m), then Aug 2020 → Oct 2021 (15m) and Nov 2017 → Oct 2018 (12m)
Overheating G+ I+
Strong activity with accelerating inflation. Typically late-cycle. Note that the post-COVID reopening surge classifies as Balanced Expansion until November 2021: the Trimmed Mean PCE crosses 2.75% only in October, so the inflation axis turns later than headline commentary did at the time.
Published series: 7 months — Nov 2021 → May 2022. Illustrative, pre-2003: 1999–2000
Inflationary Pressure G= I+
On-trend or stalling activity with still-rising inflation. Often the phase that follows Overheating.
Published series: 37 months across 4 spans — longest Jun 2022 → Jun 2024 (25m), then Sep 2024 → Feb 2025 (6m). Illustrative, pre-2003: 1980 (rate shock)
Stagflation G− I+
Contracting activity with accelerating inflation. The most damaging configuration for real purchasing power. The two months in the published series are a documented residual, not a recession call: the real-time Sahm rule genuinely printed 0.53–0.57 and the gate fired, then the state exits on non-confirmation by activity data. It is retained rather than patched away.
Published series: 2 months — July and August 2024. Illustrative, pre-2003: 1973–1975, 1979–1982 (degraded mode only)
Slowdown G− I=
Contraction without inflationary pressure. This is the state the classifier assigns to both the global financial crisis and the COVID shock — see the note on Disinflationary Contraction below.
Published series: 21 months across 2 spans — Apr 2008 → Aug 2009 (17m, the GFC) and Apr 2020 → Jul 2020 (4m, COVID)
Disinflationary Contraction G− I−
Contraction with deflation risk. This regime never occurs in the published series — zero months out of 283. The result is counter-intuitive and it is retained rather than engineered away. The cell requires contraction and a Trimmed Mean PCE below 1.50% at the same time. Through the 2008–2009 recession the trimmed measure never left the 2.21–2.69% band on the current vintage, and the sustained sub-1.50% episode only arrives in December 2009, once activity had recovered. The GFC and COVID therefore classify as Slowdown. The cell would fire on a genuinely deflationary contraction; the published window contains none.
Published series: 0 months
Transition / Mixed signals G= neutral
Neutral states on both axes, or an unresolved hysteresis window. Not a stable regime — it marks ambiguity or a turning point. A classification that spends half its time saying “no clear regime” is doing what a threshold-based method should do when the data sits between states.
Published series: 148 months, 52.3% of the window — longest span Aug 2010 → Oct 2013 (39m)
The overlay prefixes the name: “Slowdown under acute financial stress” (the actual reading for October 2008 to April 2009), “Balanced Expansion under accommodating conditions” (2021).
Three axes in, three layers out
The previous section describes the seven regimes of the G × I grid: this is layer 1 of the Atlas, the one the engine computes in real time. But the Atlas of regimes contains two other kinds of objects, read at different time horizons and with different evidentiary status. To avoid confusion: the three axes above are the inputs of the calculation (growth, inflation, financial conditions); the three layers below are the nature of the regime objects. They are not two names for the same thing.
The growth × inflation state of the moment (the seven regimes above + transition), at a horizon of a few months. Produced by axes 1 and 2. This is the verdict the classification outputs. In the Atlas, these states group into two cyclical meta-regimes: inflationary (column I+) and disinflationary (column I−).
Derived from axis 3. Superimposes on any cyclical state, at a horizon of weeks to a few months, quickly reversible and without hysteresis. What the engine computes here is the qualifier that prefixes the regime name — accommodating, neutral, restrictive, acute stress. The Dollar Shortage belongs to the same layer conceptually, but it is an Atlas page rather than a computed output: see the dividing line below. No G/I code either way — this is not a state of the grid.
Background regimes that unfold over several years and deform the grid itself (a durably low natural rate r* changes what “G+” means). These are not real-time computed verdicts: they are interpretive frameworks, set by editorial judgment over the long run. Three pages: secular stagnation, financial repression, fiscal dominance.
Dividing line — why this distinction protects rigor
The criterion separating what is measured from what is judged is falsifiable: does the engine compute a signal for this object, yes or no? The financial-conditions qualifier is computed — classify_stress() reads the NFCI and returns one of four levels on every run. Secular stagnation, financial repression and fiscal dominance have no live signal: they are layer 3, long-run editorial judgment. The classification never presents as “measured” what is “judged” — that is the condition of its reproducibility.
Where Dollar Shortage stands today. The engine does not compute it. The broad dollar produces a descriptive qualifier in the global context layer when its 3-month move exceeds ±3%, and nothing more: there is no bundled trigger, no named overlay in the output, no overlay_name field in regime_current.json. The Atlas page describes the mechanism; the classifier does not detect it. Stating otherwise would be the exact failure this section exists to prevent.
US core and global context inputs
US Core
| Indicator | Series code | Source | Frequency | From |
|---|---|---|---|---|
| Chicago Fed NAI (MA3) | CFNAI | Chicago Fed / FRED | Monthly | 1967 |
| Sahm rule (real-time) | SAHMREALTIME | FRED | Monthly | 1960 |
| SOS indicator † | (Richmond Fed) | Richmond Fed | Weekly | 1971 |
| Trimmed Mean PCE (12m) | PCETRIM12M159SFRBDAL | Dallas Fed / FRED | Monthly | 1977 |
| 5Y5Y forward breakeven | T5YIFR | Federal Reserve / FRED | Daily → monthly | 2003 |
| NFCI | NFCI | Chicago Fed / FRED | Weekly | 1971 |
| Initial jobless claims | ICSA | FRED | Weekly | 1967 |
| HY OAS (optional)* | BAMLH0A0HYM2 | ICE / FRED | Daily → monthly | 1996 |
| Fed funds rate | FEDFUNDS | Federal Reserve / FRED | Monthly | 1954 |
| 10Y–2Y yield spread | T10Y2Y | Federal Reserve / FRED | Daily → monthly | 1976 |
* HY OAS: optional corroboration only. Since April 2026, FRED truncates ICE BofA series to 3 rolling years. Included only when a full pre-April 2026 historical fixture is available locally. Never written to the published output.
† SOS: specified as an early-warning gate on the growth axis, but the Richmond Fed series is not reliably retrievable programmatically. The column is empty on all 283 rows of the published series and the gate has never fired. Retained in the schema so the gap is documented rather than hidden.
Global context layer
| Indicator | Series code | Source | Role |
|---|---|---|---|
| US CLI (amplitude adj.) | USALOLITOAASTSAM | OECD / FRED | Synchronization — US baseline |
| G7 CLI (amplitude adj.) | G7LOLITOAASTSAM | OECD / FRED | Synchronization — G7 vs US |
| CISS euro area | SS_CIN | ECB Data Portal | European systemic stress |
| Broad dollar | DTWEXBGS | Federal Reserve / FRED | Global financial conditions channel |
| Brent crude | World Bank CMO | World Bank | Commodity channel |
| VIX | VIXCLS | CBOE / FRED | Global market stress |
The OECD CLIs, the Cboe VIX and the ICE BofA series are used as computation inputs but are never written to the published output — only the categorical labels derived from them survive, in global_sync and global_qualifiers. None of the global context inputs can change the regime name.
Several further inputs were named in the original design and are not implemented in v1.1.0: net liquidity (WALCL − WTREGEN − RRPONTSYD), the Wu-Xia shadow rate (Atlanta Fed updates suspended since April 2022), the copper/gold ratio, and EM high-yield spreads. None is fetched, computed or published. They are listed here so the gap between the design and the implementation is explicit rather than discoverable.
Fixed institutional thresholds
These thresholds are not Eco3min editorial choices — they are defined by the producing institutions:
Institutional thresholds (threshold table v1.1.0)
Calibrated thresholds
The remaining thresholds — CFNAI-MA3 levels, Trimmed Mean PCE bands, NFCI overlay levels — are calibrated by sweeping candidate values on a grid over the full 1968–2026 history and scoring each against a ground-truth matrix registered before any tuning: NBER recession dates, per-episode expectations, and pre-declared metrics for false positives, entry latency and stability. The percentile reported for each retained value is descriptive — it says where the value sits in the distribution — not the selection criterion.
The rejected candidates and the reason each was rejected are published alongside the retained values, in the changelog of thresholds.json. Any threshold change requires a version bump and a changelog entry: reproducing a given verdict depends on threshold immutability for that version.
Hysteresis: preventing regime oscillation
Without a hysteresis mechanism, an indicator oscillating around a threshold would produce unreadable regime changes month after month. The rule:
Hysteresis rule
A state change on the growth or inflation axes is confirmed only after two consecutive months beyond the threshold.
Exception — Sahm hard gate: when the Sahm real-time rule crosses 0.50 upward, the transition to G− is immediate with no confirmation delay. The crossing is the trigger, not a latch: persistence of G− is then governed by the normal two-month rule, and a return below 0.50 re-arms the gate for the next crossing. Under the earlier level-based rule the state stayed G− for as long as the Sahm reading remained elevated, which held Slowdown through April 2021 with the CFNAI-MA3 well above trend. The change cuts false-positive G− months from 55 to 4 across 1968–2026 while preserving all 8 NBER captures at identical entry latencies.
Stress overlay: updates without hysteresis. It reflects current financial conditions and can change every month.
Two resolution windows
Full resolution — from January 2003
All classification inputs available, including T5YIFR from 2003. This is the reference window for calibration and validation, and the range of the published series. Two caveats stated plainly: the SOS gate is specified but its source is not reliably retrievable, so the column is empty on all 283 published rows and the gate has never fired; and net liquidity, named in the original design, is not implemented in v1.1.0 — the financial-conditions qualifier rests on the NFCI alone.
Retroactive degraded extension — from 1977
Reduced input set: CFNAI (≥1967), NFCI (≥1971), Trimmed Mean PCE (≥1977), T10Y2Y (≥1976), Sahm (≥1960). T5YIFR absent. Clearly flagged in all exports (data_quality: "degraded"). The backtest runs over this extended window; the series published on GitHub starts at January 2003 and contains no degraded rows.
What this system cannot do
- Revisions: the current month’s regime may change after data source revisions (CFNAI is regularly revised). The NFCI in particular is re-estimated weekly over its entire history, which is enough to flip a label sitting on a boundary. The JSON timestamps the computation and flags lagged inputs.
- Publication lags: the CFNAI publishes with ~3-week lag. The classification uses the last known value and documents the pending input in the JSON.
- OECD CLI lag: ~6 weeks. The global context layer updates slower than the US core and may delay detection of inter-zone divergence.
- Not a forecast: the classification describes the currently measured state, not future conditions.
- Energy supply shocks: the Trimmed Mean PCE excludes volatile components. An oil spike can be invisible on the inflation axis while headline CPI surges. The
headline_underlying_divergenceflag in the JSON signals this case automatically. - SOS gate inert: the early-warning gate on the growth axis is specified but its source is not reliably retrievable. It has never fired, and no verdict in the published series depends on it.
- Structural regimes not computed: layer 3 regimes (secular stagnation, financial repression, fiscal dominance) are not produced by the engine. They are long-run editorial frameworks and must not be read as a measured monthly verdict.
Any third party can recalculate the regime
Any third party can recalculate the regime from primary institutional sources and the published threshold table, with no opaque component. The classification code, the threshold table and the full monthly output are published:
github.com/eco3min/macro-regime-classifier
| File | Contents |
|---|---|
scripts/regime_classifier.py | The classifier. Same logic as the one that runs in production. |
config/thresholds.json | Threshold table v1.1.0, semver versioned, with the calibration changelog |
docs/regime_history_v1.1.0.csv | Frozen output — 283 months, January 2003 → July 2026 |
docs/methodology.md, docs/backtest.md | Full methodology and the 1968–2026 validation record |
LICENSE, LICENSE-DATA | MIT for the code, CC-BY 4.0 for the thresholds and derived data |
Running it needs a free FRED API key and nothing else. No source series is redistributed in the repository: the code fetches them at runtime, and the three inputs under a restrictive licence — ICE BofA, Cboe, OECD — are excluded from every published file by design. Reproducing a past verdict exactly is not always possible, because the sources are revised: the NFCI in particular is re-estimated weekly over its entire history, which is enough to flip a label sitting on a boundary. That is why each threshold version ships a frozen snapshot rather than relying on a re-run.
Suggested citation format
“Eco3min Macro Regime Classification, based on the Chicago Fed NFCI and CFNAI and the Dallas Fed Trimmed Mean PCE. Threshold table v1.1.0. eco3min.fr/en/macro-regime-classification-methodology/”
Source indicator values
| Indicator | Value | Code |
|---|---|---|
| CFNAI-MA3 | -0.0533 | CFNAI |
| Sahm Rule | 0.07 | SAHMREALTIME |
| SOS indicator | — | Richmond Fed |
| Trimmed Mean PCE 12m | 2.23 % | PCETRIM12M159SFRBDAL |
| 5Y5Y breakeven | 2.31 % | T5YIFR |
| NFCI | -0.5385 | NFCI |
| HY OAS | — | BAMLH0A0HYM2 |
| Courbe 10Y–2Y | 0.45 % | T10Y2Y |
| Fed funds | 3.63 % | FEDFUNDS |
| Dollar broad (3m) | 0.87 % | DTWEXBGS |
| Brent YoY | 19.5409 % | World Bank CMO |
| VIX | — | VIXCLS |
Subject to revision on source updates.
NFCI), CFNAI (CFNAI) · Dallas Fed Trimmed Mean PCE (PCETRIM12M159SFRBDAL) · Federal Reserve FRED (SAHMREALTIME, T5YIFR, T10Y2Y, DTWEXBGS, VIXCLS, FEDFUNDS, ICSA) · Richmond Fed (SOS indicator) · OECD CLIs (USALOLITOAASTSAM, G7LOLITOAASTSAM) · ECB Data Portal (CISS, SS_CIN) · ICE BofA (BAMLH0A0HYM2) · World Bank CMO (Brent). Threshold table v1.1.0 · code and data: github.com/eco3min/macro-regime-classifier. Classification as of the 1st of the current month. Subject to revision.Disclaimer. The data, indicators and classifications presented on this page are provided for strictly informational and educational purposes. They are sourced from public institutional data and may be subject to delays, revisions or errors. They do not constitute investment advice, personalized recommendations, solicitation to buy or sell any financial instrument, or predictive analysis of the economic cycle. eco3min.fr is not a licensed financial institution and does not provide investment advisory services within the meaning of applicable regulations (MiFID II, French Monetary and Financial Code articles L.541-1 et seq.). Any investment decision is the sole responsibility of the investor, who is encouraged to consult a licensed professional. Past performance is not indicative of future results.
Last updated — 23 July 2026
Disclaimer – Financial Information: The analyses, commentary, and content published on eco3min.fr are provided for informational and educational purposes only. They do not constitute investment advice or a solicitation to buy or sell financial instruments. Past performance is not indicative of future results. All investment decisions involve risk and are the sole responsibility of the reader.
