The Treasury Curve in H1 2026: a Twist, Not a Shift
Seven maturities, start of half against end: the front pinned, the belly up two-thirds of a point, the long end unmoved — a flattening without an inversion.
The Treasury curve spent the first half of 2026 twisting, not shifting. The very front end — the maturities that track policy most closely — barely moved; the two-year rose two-thirds of a percentage point; the thirty-year barely noticed. This page lays the whole curve out maturity by maturity, start of half against end, with the daily path underneath. Every number is a stored query result; expand any panel for the exact SQL.
The curve, maturity by maturity
The exact SQL behind every number
SELECT maturity, start_pct, end_pct, round((end_pct - start_pct) * 100, 0) AS change_bp FROM (
SELECT '1-month' AS maturity, (SELECT round(argMin(yield_1_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_month)) AS start_pct, (SELECT round(argMax(yield_1_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_month)) AS end_pct, 1 AS o
UNION ALL SELECT '3-month', (SELECT round(argMin(yield_3_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_3_month)), (SELECT round(argMax(yield_3_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_3_month)), 2
UNION ALL SELECT '1-year', (SELECT round(argMin(yield_1_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_year)), (SELECT round(argMax(yield_1_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_year)), 3
UNION ALL SELECT '2-year', (SELECT round(argMin(yield_2_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_2_year)), (SELECT round(argMax(yield_2_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_2_year)), 4
UNION ALL SELECT '5-year', (SELECT round(argMin(yield_5_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_5_year)), (SELECT round(argMax(yield_5_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_5_year)), 5
UNION ALL SELECT '10-year', (SELECT round(argMin(yield_10_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_10_year)), (SELECT round(argMax(yield_10_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_10_year)), 6
UNION ALL SELECT '30-year', (SELECT round(argMin(yield_30_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_30_year)), (SELECT round(argMax(yield_30_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_30_year)), 7
) ORDER BY oRead the change column top to bottom and the twist is unmistakable: the 1-month moved -2 basis points in six months while the 2-year rose 67 and the 30-year just 5. A parallel shift moves every maturity together; this half moved the middle of the curve and pinned both ends — short rates anchored near policy, long rates barely repriced.
What that did to the slope
The exact SQL behind every number
SELECT toString(date) AS d,
round((yield_10_year - yield_2_year) * 100, 0) AS spread_2s10s_bp
FROM global_markets.treasury_yields
WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30')
AND isNotNull(yield_10_year) AND isNotNull(yield_2_year)
ORDER BY dateThe exact SQL behind every number
SELECT
round((argMin(yield_10_year - yield_2_year, date)) * 100, 0) AS start_bp,
round((argMax(yield_10_year - yield_2_year, date)) * 100, 0) AS end_bp,
round(min((yield_10_year - yield_2_year)) * 100, 0) AS min_bp,
count() AS prints
FROM global_markets.treasury_yields
WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30')
AND isNotNull(yield_10_year) AND isNotNull(yield_2_year)The 2s10s spread ground down from 72 to 30 basis points across 124 prints — and its lowest print of the half was 27, so the curve flattened without ever inverting. Whether a flatter curve "means" anything about what comes next is a forecast, and this table doesn't make forecasts; past inversions and what followed them are covered in the explainer linked above.
A note on the missing maturities
Full data notes
- The yields table carries eleven maturity columns but only seven are populated in this window (6-month, 3-year, 7-year, and 20-year are null); the panel shows every populated one.
- The July 2 print had not been ingested at generation (a normal ~1-day lag); the half's window ends June 30, so nothing here is affected.
- Yields are Treasury par yields as published; changes are computed inside the queries shown, never by hand.
- The equity-market half these rates ran under is in the H1 recap; the macro releases behind the short end are in the macro picture.
Methodology
- Period: January 1 – June 30, 2026. Start/end values are the first and last print per maturity within the window (argMin/argMax by date), computed in-query.
- Generation runs through the gated read-only path; the public page never queries live. Warehouse state as of July 4, 2026.
Every panel is one stored object — chart, table, and SQL. Take the curve further on the Strasmore terminal.