---
title: "Pinning to a specific OBR publication"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Pinning to a specific OBR publication}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "#>"
)
NOT_CRAN <- identical(Sys.getenv("NOT_CRAN"), "true")
```

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

```{r}
library(obr)

efos <- obr_efo_vintages()
nrow(efos)
head(efos, 3)
tail(efos, 3)
```

`obr_efo_vintages()` is offline: the publication calendar is hardcoded into the package and refreshed at each release.

## Resolving an EFO by date

```{r}
obr_as_of("2024-12-15")
obr_as_of("2010-05-01") |> tryCatch(error = function(e) conditionMessage(e))
```

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

```{r}
obr_pin("October 2024")
obr_pinned()
obr_unpin()
obr_pinned()
```

When 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.

```{r, eval = FALSE}
# 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.

```{r, eval = FALSE}
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 object
```

The 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.

```{r, eval = FALSE}
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.
