library(boe) not_on_cran <- identical(Sys.getenv("NOT_CRAN"), "true") knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4.5, eval = not_on_cran ) op <- options(boe.cache_dir = tempfile("boe_vignette_"))
The Bank of England publishes daily fitted yield curves at all maturities
using the Anderson and Sleath (2001) smoothing methodology. Five curves
are produced: nominal gilt, real (index-linked) gilt, implied inflation,
overnight index swap (OIS), and the commercial bank liability curve
(BLC). Each is available in spot and instantaneous-forward form, and in
two segments: the standard curve (half-year maturity steps out to 25 or
40 years) and the separately fitted short end (monthly steps from one
month to five years), selected with segment = "short".
The default behaviour of boe_curve() returns the latest published
month, matching what most analysts need when they reach for "today's
curve". Pass from, to, or frequency = "monthly" and the function
switches to the BoE historical archive, which extends back as far as
1979 for nominal gilts.
latest <- boe_curve(curve = "nominal", measure = "spot") range(latest$date) range(latest$maturity_years)
boe_curve() returns a long-format boe_tbl with one row per
(date, maturity) pair. Provenance is attached as an attribute:
attr(latest, "boe_query")$source attr(latest, "boe_query")$series_codes
For time-series work, boe_curve_panel() reshapes the long format into
a wide panel with one column per pillar maturity. End-of-month frequency
is plenty for multi-decade work and keeps the download small.
panel <- boe_curve_panel( curve = "nominal", measure = "spot", frequency = "monthly", from = "2000-01-01", maturities = c(2, 5, 10, 20) ) head(panel)
if (requireNamespace("ggplot2", quietly = TRUE)) { ggplot2::ggplot(panel, ggplot2::aes(date, m10)) + ggplot2::geom_line(colour = "#1f77b4") + ggplot2::labs( title = "UK 10-year nominal spot rate", subtitle = "End of month, Anderson-Sleath fitted", x = NULL, y = "Per cent" ) + ggplot2::theme_minimal() }
The 5y5y forward inflation rate (the average implied inflation rate over the second five-year horizon, five years from now) is a textbook medium-term inflation expectations measure. It comes straight off the implied-inflation forward curve.
inflation_fwd <- boe_curve_panel( curve = "inflation", measure = "forward", frequency = "monthly", from = "2010-01-01", maturities = c(5, 10) ) inflation_fwd$five_y_five_y <- (inflation_fwd$m10 * 10 - inflation_fwd$m5 * 5) / 5 head(inflation_fwd[, c("date", "m5", "m10", "five_y_five_y")])
if (requireNamespace("ggplot2", quietly = TRUE)) { ggplot2::ggplot(inflation_fwd, ggplot2::aes(date, five_y_five_y)) + ggplot2::geom_line(colour = "#d62728") + ggplot2::geom_hline(yintercept = 2.0, linetype = "dashed", colour = "grey40") + ggplot2::annotate("text", x = max(inflation_fwd$date), y = 2.0, label = "2% target", hjust = 1, vjust = -0.5, colour = "grey40", size = 3) + ggplot2::labs( title = "UK 5y5y forward implied inflation", subtitle = "End of month, derived from the BoE implied-inflation forward curve", x = NULL, y = "Per cent per annum" ) + ggplot2::theme_minimal() }
The OIS curve gives a market-implied path for Bank Rate. Comparing OIS spot pillars at MPC decision dates shows how expectations shifted through the 2022 to 2024 hiking cycle.
ois <- boe_curve_panel( curve = "ois", measure = "spot", frequency = "monthly", from = "2020-01-01", maturities = c(0.5, 1, 2, 5) ) mpc <- boe_mpc_decisions(from = "2020-01-01") mpc <- data.frame(date = mpc$date, bank_rate = mpc$new_rate_pct) merged <- merge(ois, mpc, by = "date", all.x = TRUE) merged$bank_rate <- as.numeric(merged$bank_rate) # carry the bank rate forward between MPC dates for (i in seq_along(merged$bank_rate)) { if (i > 1 && is.na(merged$bank_rate[i])) { merged$bank_rate[i] <- merged$bank_rate[i - 1] } } tail(merged)
if (requireNamespace("ggplot2", quietly = TRUE)) { long <- data.frame( date = rep(merged$date, 5), pillar = rep(c("Bank Rate", "6m OIS", "1y OIS", "2y OIS", "5y OIS"), each = nrow(merged)), rate = c(merged$bank_rate, merged$m0.5, merged$m1, merged$m2, merged$m5) ) long$pillar <- factor(long$pillar, levels = c("Bank Rate", "6m OIS", "1y OIS", "2y OIS", "5y OIS")) ggplot2::ggplot(long, ggplot2::aes(date, rate, colour = pillar)) + ggplot2::geom_line() + ggplot2::labs( title = "UK OIS spot pillars and Bank Rate, 2020 to present", subtitle = "Tightening cycle visible across all pillars", x = NULL, y = "Per cent", colour = NULL ) + ggplot2::theme_minimal() + ggplot2::theme(legend.position = "bottom") }
The standard curves step in half-years from 0.5 years out. For near-term
policy and money-market work the Bank fits a separate short end at
monthly maturities, from one month to five years. Pass
segment = "short" to boe_curve() or boe_curve_panel() to reach it.
short <- boe_curve(curve = "nominal", measure = "spot", segment = "short") range(short$maturity_years) # monthly grid, ~1/12 to 5 years
The short end of the OIS forward curve is the cleanest market-implied path for Bank Rate: the instantaneous forward rate at each horizon, at monthly resolution. Here it is on the most recent published date.
ois_short <- boe_curve(curve = "ois", measure = "forward", segment = "short") latest_day <- ois_short[ois_short$date == max(ois_short$date), ] head(latest_day)
if (requireNamespace("ggplot2", quietly = TRUE)) { ggplot2::ggplot(latest_day, ggplot2::aes(maturity_years, rate_pct)) + ggplot2::geom_line(colour = "#1f77b4") + ggplot2::geom_point(size = 0.8, colour = "#1f77b4") + ggplot2::labs( title = "UK OIS instantaneous forward curve, short end", subtitle = paste("Market-implied Bank Rate path on", format(max(ois_short$date), "%d %B %Y")), x = "Horizon (years)", y = "Per cent" ) + ggplot2::theme_minimal() }
Short-end history goes back as far as the Bank published it: to 1979 for nominal gilts, and from 2016 for OIS. Where a period has no short-end sheet (early OIS, for instance), those dates are simply absent from the result rather than causing an error.
| Question | Argument set |
|---|---|
| Today's curve | none (default) |
| Last few years, daily | from = "2020-01-01" |
| Multi-decade panel for econometrics | frequency = "monthly", from = "1990-01-01" |
| Near-term policy-rate path, monthly detail | segment = "short" |
| Commercial bank liability curve | curve = "blc" (always uses archive) |
Archive zips cache for 30 days by default; the latest-month zip caches
for 24 hours. Override with cache_ttl_h if you need to force a fresh
pull.
Anderson, N. and Sleath, J. (2001). New estimates of the UK real and nominal yield curves. Bank of England Working Paper No. 126. https://www.bankofengland.co.uk/working-paper/2001/new-estimates-of-the-uk-real-and-nominal-yield-curves
options(op)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.