The question
Banks, dealers and money funds lend each other cash overnight against U.S. Treasury securities. This is the repo market. The rate on that lending is called SOFR. The Federal Reserve also pays banks a rate on the money they keep with it, called IORB. Most days SOFR sits at or just below IORB. On some days spare cash runs short and SOFR jumps above it.
This project forecasts the gap between the two, SOFR minus IORB, for the next business day. The headline forecast is the chance that the gap is more than 5 and more than 10 basis points. A basis point is a hundredth of one percentage point. It uses public data only, and only what was public at 4 pm on the day before the forecast. The public data runs from 2018-04-03 to 2026-09-03.
Where this comes from: metadata/stress_thresholds.json, metadata/funding_panel_manifest.json, and the validation report.
How often it is right about pressure
Each day the model gives a probability that the gap will be above the line. A good probability forecast is neither too bold nor too timid. The usual measure is the Brier score: how far the forecast probability was from what happened, on average, where lower is better. Each result below is a paired difference: on every day, the benchmark's score minus the model's, averaged. A positive number means the model did better. The range after it is the 90% interval, found by resampling the days.
Two benchmarks keep the model honest. The calendar guess uses only how often pressure happens on each type of day (month-end, quarter-end, tax date, ordinary). The “tomorrow looks like today” model looks at today's gap and nothing else.
- More than +5 bp. This happened on 7.5% of the 1873 days scored (every day up to 2025-12-31). against the calendar guess the model was better (+0.0219, 90% interval +0.0158 to +0.0282); against the “tomorrow looks like today” model the model was better (+0.0068, 90% interval +0.0031 to +0.0107).
- More than +10 bp. This happened on 3.3% of the 1873 days scored (every day up to 2025-12-31). against the calendar guess the model was better (+0.0039, 90% interval +0.0015 to +0.0065); against the “tomorrow looks like today” model the model was not clearly different (+0.0007, 90% interval -0.0010 to +0.0024).
The gain is not the same everywhere. Against the “tomorrow looks like today” model at +5 bp, the model was better in 6 of 9 groups of days, not clearly different in 2, worse in 1, and 0 had too few days to say.
Show the numbers
| How far ahead | Above +5 bp, against the calendar guess | Above +5 bp, against the “tomorrow looks like today” model | Above +10 bp, against the calendar guess | Above +10 bp, against the “tomorrow looks like today” model |
|---|---|---|---|---|
| 1 business day ahead | +0.0219 (+0.0158 to +0.0282), better | +0.0068 (+0.0031 to +0.0107), better | +0.0039 (+0.0015 to +0.0065), better | +0.0007 (-0.0010 to +0.0024), not clearly different |
| 2 business days ahead | +0.0180 (+0.0120 to +0.0247), better | +0.0080 (+0.0037 to +0.0125), better | +0.0030 (+0.0004 to +0.0056), better | +0.0028 (+0.0006 to +0.0053), better |
| 3 business days ahead | +0.0166 (+0.0104 to +0.0235), better | +0.0103 (+0.0053 to +0.0153), better | +0.0024 (-0.0003 to +0.0053), not clearly different | +0.0018 (-0.0003 to +0.0040), not clearly different |
| 4 business days ahead | +0.0141 (+0.0082 to +0.0206), better | +0.0057 (+0.0013 to +0.0105), better | +0.0019 (-0.0008 to +0.0047), not clearly different | -0.0003 (-0.0022 to +0.0018), not clearly different |
| 5 business days ahead | +0.0136 (+0.0075 to +0.0204), better | +0.0060 (+0.0011 to +0.0114), better | +0.0017 (-0.0009 to +0.0043), not clearly different | -0.0003 (-0.0021 to +0.0015), not clearly different |
| Group of days | Days | Gain | Interval | Verdict |
|---|---|---|---|---|
| Market period: 2018-19 | 375 | +0.0292 | +0.0133 to +0.0463 | better |
| Market period: 2020 | 251 | +0.0093 | +0.0051 to +0.0146 | better |
| Market period: 2021-23 | 748 | -0.0003 | -0.0004 to -0.0002 | worse |
| Market period: 2024 | 250 | +0.0012 | +0.0000 to +0.0028 | better |
| Market period: 2025-26 | 249 | -0.0027 | -0.0136 to +0.0075 | not clearly different |
| Type of day: month end | 158 | +0.0115 | +0.0023 to +0.0226 | better |
| Type of day: ordinary | 1595 | +0.0052 | +0.0015 to +0.0093 | better |
| Type of day: quarter end | 31 | +0.0318 | +0.0028 to +0.0646 | better |
| Type of day: tax date | 89 | +0.0179 | -0.0004 to +0.0390 | not clearly different |
Where this comes from: pressure_model_v1_h1.json, pressure_model_v1_h2.json, pressure_model_v1_h3.json, pressure_model_v1_h4.json, pressure_model_v1_h5.json, the validation report.
The forecast range for tomorrow
The model also forecasts the whole range of where the gap could land, not just one number. This is the five-quantile score: it measures how far off the forecast range was, and lower is better. The benchmark is as-of persistence, which says tomorrow will look like the latest gap already public.
- Earlier years. From 2018-06-29 to 2025-12-31 (1873 forecasts) the model's score was 1.66 bp and persistence's was 2.09 bp. The gap is +0.43 bp, 90% interval +0.19 to +0.74 bp, so the model was better.
- The final test, January to September 2026. Over 169 scored days the model's score was 1.66 bp and persistence's was 1.83 bp. The gap's 90% interval, +0.03 to +0.36 bp, lies above zero, so the model was better. A few days drive the mean, and 2026 was a calm year.
The final test was set up before it was run and run once, on days the model had not been tuned on by name. Those days had appeared inside earlier pooled results, so it is called near-blind, not blind. The first fully blind confirmation will come from the live daily record.
Show the numbers
| Group of days | Days | Gain, bp | Interval, bp |
|---|---|---|---|
| Type of day: month end | 14 | -0.125 | -0.262 to +0.024 |
| Type of day: ordinary | 147 | +0.152 | -0.006 to +0.360 |
| Type of day: quarter end | 2 | none | |
| Type of day: tax date | 6 | none |
Where this comes from: compare_persistence_vs_gbm_conformal_pid_nested_funding_crps.json, final_test_near_blind.json, the final-test page, the validation report.
What a month-end does to the average
Month-end, quarter-end and year-end "turns" are the days when the rate tends to jump. Funds and lenders watch the average of the rate over a month, and one jump day counts for as many calendar days as it stays in force. The model therefore reports, for a scheduled pressure day, how much that day's forecast adds to the period average.
It is worked out as follows. The forecast mean is the mean of the piecewise-linear quantile function through the grid's points, held flat beyond the outer levels. That mean is multiplied by the calendar days the day carries and divided by the calendar days in the period: the day's calendar month, weighted by calendar day as SOFR averages are computed: a weekend or holiday (market holiday table) carries the previous business day's rate; carried days in the next month count in that month's average.
Status of this output: not yet calibrated (#243): computed from the uncalibrated interior quantiles. At two to five business days ahead, at h = 2 to 5 the q25, q50 and q75 are the one-step gbm served stale, identical across horizons; only the PID outer pair (q05, q95) differs.
Where this comes from: scripts/desk_outputs.py, docs/decisions/pressure-probability.md, the validation report.
How scarce cash is
Pressure is more likely when bank reserves, the cash banks keep at the Fed, are scarce. The model therefore shows a scarcity state beside each forecast: one of abundant, ample, tight, scarce. It is a label for what is happening now. It is not an input to the forecast, and it is not itself a forecast.
The label is set by two cut-points. Reserves count as ample or tight depending on where they stand as a share of all commercial-bank assets: 12% to 13% is the band where banks stop treating reserves as abundant. And the Fed's overnight reverse repo facility is a buffer only while it holds more than $100 billion; below that it no longer absorbs a drain on reserves. Both cut-points were chosen from the literature and from the same history they are checked on, so they describe the market and have not been proven in a separate test.
Where this comes from: src/repo_model/scarcity.py, scripts/desk_outputs.py, the validation report.
What the data show about the repo market
These are three things about the repo market itself, not about the forecasting model. The market lends cash overnight against Treasury securities. SOFR is the rate on that borrowing. IORB is the interest the Fed pays banks on the cash they hold with it. The gap is SOFR minus IORB, counted in basis points (a hundredth of a percentage point). Pressure is a gap more than 5 basis points above zero. This is development evidence: a description of what happened, not a forecast and not a verdict on any model.
1. Stress lives on the turn, not on month-end in general
The turn is the last business day of a month and the first business day of the next. In 2018-19 the gap averaged +11.5 basis points on the last business day and +4.0 on the first business day after it. On the second-last business day it averaged +0.3, the same as on an ordinary day in the middle of a month (+1.7). The days before the turn are ordinary; the turn carries the pressure. The latest period, 2025-26, has the same shape, smaller: +3.5 on the last business day, +2.1 on the first and -0.5 on the second-last.
| Market period | Last business day of the month | First business day of the next month | Second-last business day | Ordinary mid-month day |
|---|---|---|---|---|
| 2018-19 | +11.5 (14 days) | +4.0 (14 days) | +0.3 (14 days) | +1.7 (139 days) |
| 2020 | -1.6 (8 days) | -1.9 (8 days) | -2.9 (8 days) | -0.7 (77 days) |
| 2021-23 | -9.2 (24 days) | -8.8 (24 days) | -9.7 (24 days) | -9.7 (233 days) |
| 2024 | -5.5 (8 days) | -5.8 (8 days) | -8.0 (8 days) | -7.7 (78 days) |
| 2025-26 | +3.5 (14 days) | +2.1 (14 days) | -0.5 (14 days) | -3.8 (133 days) |
2. The calendar sets the date; reserve scarcity sets the size
The same month-end added about +5.8 basis points to the gap in 2018-19, +0.3 in 2021-23 and +4.3 in 2025-26. A coupon settlement, the day the Treasury is paid for newly auctioned notes and bonds, which draws cash out of the market, added +8.5, +0.5 and +3.8 in the same three periods. The calendar tells you which days to watch. How much a date adds follows how scarce reserves (the cash banks hold at the Fed) are. That second half is the project's reading of the pattern; the table shows the sizes, not the cause.
| Market period | Month-end | Coupon settlement |
|---|---|---|
| 2018-19 | +5.8 [+4.4, +7.2] | +8.5 [+7.2, +9.8] |
| 2020 | +2.2 [+1.3, +3.0] | +2.5 [+1.7, +3.4] |
| 2021-23 | +0.3 [+0.1, +0.5] | +0.5 [+0.3, +0.7] |
| 2024 | +1.8 [+1.3, +2.2] | +1.5 [+1.0, +2.0] |
| 2025-26 | +4.3 [+3.5, +5.0] | +3.8 [+2.8, +4.9] |
3. Stress episodes begin on known calendar dates
A stress episode starts on a day the gap is above 5 basis points after more than 10 business days without one. Since 2020-04-01 there have been 6. Of those, 5 began on or within a business day of a known calendar date: a month-end or quarter-end turn, a mid-month Treasury settlement or a tax date. For scale, 37% of all business days in that period sit on or next to such a date. The episodes all began in 2024 to 2026.
| Start | Gap, basis points | Known date on or next to it |
|---|---|---|
| 2024-09-30 | +6.0 | quarter-end |
| 2024-12-26 | +13.0 | none |
| 2025-09-15 | +11.0 | tax date, mid-month settlement |
| 2025-09-30 | +9.0 | quarter-end |
| 2026-02-17 | +6.0 | mid-month settlement |
| 2026-04-15 | +7.0 | tax date, mid-month settlement |
Where this comes from: docs/research/market-findings-1177/result.json, docs/research/state-calendar-1145/result.json, the study page, the validation report.
Where it falls short
This is a research forecast of next-day overnight borrowing costs, not a warning system or a tool for managing risk. It has been tested mostly in calm conditions, so it needs re-checking if the market changes sharply.
- Few severe days. Of the 169 days of the final test, 5 were above +5 bp and 0 above +10 bp. Such days are rare, so the evidence about them is thin.
- The test above +10 bp is weak. On the earlier years the model's gain over the “tomorrow looks like today” model at +10 bp has a 90% interval of -0.0010 to +0.0024, so it was not clearly different. Against the calendar guess it was better.
- Days that are locked. Some days are kept sealed so that no result can be tuned on them. A comparison scores only days before 2026-01-01. The older pooled distribution tables scored days through 2026-09-03 (the near-blind period); the results published since score only days before 2026-01-01.
The statement of record
A research forecast of the SOFR − IORB spread. It is not a stress-warning system and not a basis for VaR, limits, liquidity or capital, or desk sizing. Its central quantiles are not yet calibrated, its tail coverage is weaker on quarter-ends and turns, and it has little history in the current scarce-reserve regime. It needs revalidation after a material policy or regime change.
Where this comes from: pressure_model_v1_h1.json, final_test_near_blind.json, docs/use-limitation.md, metadata/lockbox.json, the lockbox rule, the validation report.
Where this sits among other work
To our knowledge, no public work forecasts the daily SOFR − IORB spread with strictly point-in-time public data and scores its exceedance probabilities with proper scoring rules against persistence baselines. Related efforts include Fed staff probability assessments for the fed funds − IOER spread (FOMC memo, 13 Sep 2019), a daily SOFR LSTM thesis scored by RMSE (Cornelissen, 2021), and futures-implied month-end premia, which tend to over-anticipate spikes (Gellert & Schlögl, 2021).
- FOMC memo, 13 September 2019 (Fed staff, the fed funds − IOER spread)
- Cornelissen (2021), the daily SOFR LSTM thesis
- Gellert and Schlögl (2021), futures-implied month-end premia
nicholasberoud/repo-market-model is a fork by Eleonora's collaborator, Nicholas Beroud. A reader who finds that repository with the same figures has found a copy of this project, not an independent replication.
Futures are left out, both as a benchmark and as an input. CME futures data needs a licence and cannot be redistributed with this repository, and futures-implied month-end premia are documented to over-anticipate spikes (Gellert and Schlögl, 2021; CME's March 2019 example).
Where this comes from: docs/model/external_sources.json, and the validation report.