The OBR revises every forecast at every Budget and Statement. A number that is correct in March can be wrong in October. For research, audit, and reproducibility, you need a way to say “this analysis used the October 2024 forecast” and have the package reliably return the same numbers six months later.
obr calls this the vintage layer. This
vignette walks through the four ways to use it. The chunks that do not
require a network connection are run inline; the chunks that download
from the OBR are shown as code only.
The vintage table
library(obr)
efos <- obr_efo_vintages()
nrow(efos)
#> [1] 33
head(efos, 3)
#> publication vintage date
#> 1 EFO June 2010 2010-06-22
#> 2 EFO November 2010 2010-11-29
#> 3 EFO March 2011 2011-03-23
#> slug
#> 1 june-2010-economic-and-fiscal-outlook
#> 2 november-2010-economic-and-fiscal-outlook
#> 3 march-2011-economic-and-fiscal-outlook
tail(efos, 3)
#> publication vintage date
#> 31 EFO March 2025 2025-03-26
#> 32 EFO November 2025 2025-11-26
#> 33 EFO March 2026 2026-03-26
#> slug
#> 31 march-2025-economic-and-fiscal-outlook
#> 32 november-2025-economic-and-fiscal-outlook
#> 33 march-2026-economic-and-fiscal-outlookobr_efo_vintages() is offline: the publication calendar
is hardcoded into the package and refreshed at each release.
Resolving an EFO by date
obr_as_of("2024-12-15")
#> [1] "October 2024"
obr_as_of("2010-05-01") |> tryCatch(error = function(e) conditionMessage(e))
#> [1] "\033[1m\033[22mNo EFO had been published on or before 2010-05-01.\n\033[36mℹ\033[39m The OBR was established in June 2010; the first EFO was published 22 June\n 2010."The first call returns the most recent EFO published on or before 15 December 2024. The second errors because no EFO existed before June 2010.
Pinning a session-wide vintage
obr_pin("October 2024")
#> ✔ Pinned EFO to "October 2024".
obr_pinned()
#> [1] "October 2024"
obr_unpin()
#> ✔ Unpinned EFO (was "October 2024").
obr_pinned()
#> NULLWhen pinned, the EFO functions default to that vintage.
obr_unpin() clears the pin and returns to the dynamic
resolver.
Downloading a specific vintage
These chunks require a network connection and are shown as code only.
# Pull two vintages of the same fiscal table to compare forecast revisions
oct24 <- get_efo_fiscal(vintage = "October 2024")
mar26 <- get_efo_fiscal(vintage = "March 2026")
# Net borrowing forecast for 2027-28 from each vintage. v0.4.0 schema
# uses `period` for the time column (with `period_type = "fiscal_year"`).
oct24[oct24$series == "Net borrowing" & oct24$period == "2027-28", ]
mar26[mar26$series == "Net borrowing" & mar26$period == "2027-28", ]Cached files are vintage-tagged, so different vintages do not
overwrite each other in the cache. The vintage = ...
argument always overrides any pin set with obr_pin().
What’s recorded as provenance
Every obr_tbl carries enough metadata for an OBR analyst
to audit which publication produced any number.
obr_provenance(get_efo_fiscal(vintage = "October 2024"))
# $publication: "EFO"
# $vintage: "October 2024"
# $source_url: https://obr.uk/download/october-2024-economic-and-fiscal-outlook-...
# $retrieved: timestamp of download
# $file_md5: MD5 fingerprint of the underlying spreadsheet
# $package_version: obr version that produced the objectThe MD5 fingerprint lets two analyses verify they ran against an identical underlying file, even if downloaded weeks apart.
How vintage interacts with get_forecasts()
The Historical Forecasts Database is a single workbook covering every
OBR vintage in one file, so it does not take a vintage =
argument. To filter to a specific forecast date, subset the long-format
result.
fc <- get_forecasts("PSNB")
fc[fc$forecast_date == "October 2024", ]For reproducibility, the HFD itself is itself versioned: the OBR
releases a new HFD at each fiscal event, so the underlying file MD5
changes over time even if the older forecasts within it do not.
obr_provenance() records the HFD vintage on every
result.