< Back to Blog

April 2026 CPI: What the Cleveland Fed Nowcast Got Right (And Wrong)

TL;DR / Key Takeaways

  • The April 2026 CPI print came in at 2.3% YoY on May 13, below the 2.4% consensus and the lowest reading since early 2021.
  • The Cleveland Fed nowcast had been tracking 2.35% to 2.38% in the days before release, which put it directionally correct but slightly above the actual print.
  • The Econ Bot held positions across two strikes before settlement. One resolved correctly, one did not.
  • The post-mortem surfaces a real lesson about using nowcasts as probability anchors versus treating them as point forecasts.

The April 2026 CPI number dropped on May 13. Headline YoY came in at 2.3%. The market had priced 2.4% consensus. The Cleveland Fed nowcast, which is the primary signal the Econ Bot runs on, was sitting at approximately 2.36% in the 48 hours before release.

So: directionally correct that inflation was still running above 2.0%, but the nowcast was about 6 basis points hot versus the actual print. Not a catastrophic miss. But in a market where the difference between 2.3% and 2.4% determines whether a binary contract pays out, 6 basis points matters.

Let me walk through what the bot actually had on going into settlement.


What the Bot Was Holding

The Econ Bot scanned the available Kalshi CPI contracts about 72 hours before the release. At that point the Cleveland Fed nowcast was pointing to something in the 2.35% to 2.38% range. The FRED signals were mixed: oil was soft, the 10-year breakeven was flat around 2.20%, gas prices were down slightly. The BLS subcomponent data was showing services inflation still sticky, but goods continuing to deflate.

The homemade weighted nowcast came out to roughly 2.37% after combining all five signals.

The bot placed two positions:

Position 1: "No" on CPI above 2.4% (meaning I was betting the number would come in at 2.4% or below) Position 2: "Yes" on CPI above 2.2% (meaning I was betting inflation would not collapse below 2.2%)

Both of these were consistent with a 2.35% to 2.38% expectation. The strike-consistency enforcer confirmed there was no contradiction between them.


What Settled and How

The actual print: 2.3% YoY.

Position 1 resolved correctly. CPI did not exceed 2.4%, so "No on above 2.4%" paid out. The bot had bought that contract at around $0.56, and it settled at $1.00. Clean.

Position 2 also resolved correctly. CPI was 2.3%, which is above 2.2%, so "Yes on above 2.2%" paid out as well. Bought at around $0.82, settled at $1.00.

Two for two on direction. The nowcast being 6 basis points high did not cost me anything because both positions were structured around a range, not a pinpoint.

That said, let me be honest about where the signal was imprecise, because that matters.


Where the Nowcast Missed

The Cleveland Fed model was tracking 2.36% heading into release. The actual was 2.3%. That 6 basis point gap is worth understanding.

Looking at the BLS subcomponent breakdown after the fact, used car prices dropped more than expected. Shelter inflation ticked down slightly. Medical care services came in softer than the trailing 3-month average. These are the categories that are harder for any backward-looking model to anticipate because they're sensitive to one-time data revisions and seasonal adjustment quirks.

The Cleveland Fed nowcast is excellent at capturing the trend. It is not great at capturing the last-mile surprise from components that deviate from trend in the final month. That is not a knock on the model. It is just what it is.

What the bot's FRED signals did catch: oil was down about 4% in the two weeks before release. That is an early indicator for goods deflation. The gas price component of the FRED signal was nudging the composite nowcast slightly lower. Not enough to call a 2.3% print, but enough that the combined estimate was lower than the Cleveland Fed number alone would have been.

The homemade weighted nowcast at 2.37% was still above actual. But it was closer than the Cleveland Fed standalone at 2.36%.


The Regime Change Detector Did Not Fire

I want to explain this because it is relevant to how the bot handles surprises.

The regime change module watches for a 0.15 probability swing in the Cleveland Fed nowcast between cycles. If the nowcast moves that much, it closes positions that are suddenly on the wrong side.

In this case, the nowcast shifted from roughly 2.38% a week out to 2.36% two days out. That is a 2 basis point move. It did not trigger the 0.15 threshold, so no auto-close fired.

That was correct behavior. The bot should not be jittery about small movements. The positions I held were not made wrong by that small drift. If the nowcast had moved from 2.38% to 2.20%, the regime detector would have fired and I would have closed the "above 2.2%" long, which would have been the right call.

The detector is not designed to react to noise. It is designed to react to genuine signal reversals.


A Note on the "Above 2.4%" Contract Pricing

One thing I track alongside the bot's own edge calculation is how the Kalshi market priced these contracts relative to the nowcast.

The "above 2.4%" No contract was trading around $0.56 when the bot bought it. That implies the market was pricing roughly a 44% chance CPI would exceed 2.4%. The Cleveland Fed nowcast at 2.36% implied something closer to a 28% to 32% chance of exceeding 2.4%, depending on how you model the distribution width.

That gap between 44% market probability and 30% model probability is the edge. The bot found it. The trade paid out.

This is the whole thesis. The market was pricing more uncertainty around the upside than the models justified. When the models converge below a threshold and the market is still pricing meaningful probability of exceeding it, you sell that probability.


One Position the Bot Did Not Take (And Should Have)

There was a "below 2.3%" contract available. The market was pricing it at about $0.15, implying 15% odds the print would be at or below 2.3%.

The bot did not take that trade. The homemade nowcast at 2.37% said the probability of printing at or below 2.3% was roughly 18% to 22%. That is edge, but it was inside the dollar-edge check threshold at the contract size the bot was willing to hold. The minimum dollar edge filter blocked it.

In hindsight, the print was exactly 2.3%. That contract would have paid out.

I am not going to second-guess the filter. It is doing what it is supposed to do: prevent the bot from chasing tiny-dollar edges that do not survive fees and slippage at small position sizes. One correct outcome does not validate overriding a risk filter.


Code: How the Composite Nowcast Gets Built

Here is a simplified version of what homemade_nowcast.py does with the individual signals:

def compute_composite_nowcast(
    cleveland_fed_prob: float,
    fred_signals: dict,
    bls_signal_adjustment: float,
    bea_signal_adjustment: float,
    weights: dict = None
) -> float:
    """
    Combine Cleveland Fed base probability with ancillary signal adjustments.
    Returns a composite probability estimate for the CPI strike in question.
    """
    if weights is None:
        weights = {
            "cleveland_fed": 0.50,
            "fred":          0.20,
            "bls":           0.15,
            "bea":           0.15,
        }

    # FRED signals arrive as a dict of individual nudges
    fred_adjustment = sum(fred_signals.values())

    composite = (
        cleveland_fed_prob * weights["cleveland_fed"]
        + (cleveland_fed_prob + fred_adjustment) * weights["fred"]
        + (cleveland_fed_prob + bls_signal_adjustment) * weights["bls"]
        + (cleveland_fed_prob + bea_signal_adjustment) * weights["bea"]
    )

    # Clamp to valid probability range
    return max(0.01, min(0.99, composite))

The Cleveland Fed number anchors 50% of the weight. The FRED, BLS, and BEA signals each adjust around that anchor. No single ancillary source can overwhelm the base. That is intentional. The Cleveland Fed model is the most methodologically rigorous of the five inputs. The others are nudges, not overrides.

For the April print, fred_adjustment came out to roughly -0.009 (oil and gas were slightly deflationary), bls_signal_adjustment was close to neutral, and bea_signal_adjustment was -0.006. The composite landed at 2.37% where the Cleveland Fed alone would have said 2.38%.

Small difference. But over many trades, small differences in probability estimates compound.


What I Would Tune After This Release

The main thing I am watching is the goods deflation sensitivity. Used cars, apparel, and consumer electronics can swing in the final month and the model does not catch it. Adding a used car auction index as a FRED proxy signal is on my list. Manheim publishes a used vehicle index that leads the BLS component by about 4 to 6 weeks.

That is not a v1 fix. It is a v2 Econ Bot enhancement. But I am logging it now while the miss is fresh.


Honest Summary

The Cleveland Fed nowcast was 6 basis points above the actual April print. The Econ Bot's composite was 7 basis points above. Both signals were directionally correct and within a range that kept the bot's positions profitable. Two positions entered, two resolved correctly.

The miss on the exact number was real. The architecture handled it because the positions were built around a range, not a point. That is why the probability framework matters more than chasing a precise forecast.

The model will miss again. The goal is not perfection. The goal is being right more than the market priced, often enough to stay profitable over time.