07/04/2025The Bank Bill Swap Rate (BBSW) is Australia’s key short-term interest rate benchmark. It represents the mid-rate for Australian dollar-denominated bank bills (BABs/NCDs) traded in the interbank market.
BBSW is used to:
ASX calculates BBSW daily using a volume-weighted average price (VWAP) methodology based on market transactions observed between 08:30–10:00 AEST. Since January 2017, ASX has been the sole administrator (replacing AFMA).
| Item | Detail |
|---|---|
| Source | Reserve Bank of Australia — Statistical Table F1 |
| Title | Interest Rates and Yields – Money Market – Daily |
| URL | https://www.rba.gov.au/statistics/tables/#interest-rates |
| Direct download | https://www.rba.gov.au/statistics/tables/xls/f01d.xlsx |
| Tenors available | 1-month, 3-month, 6-month (EOD BABs/NCDs) |
| R package | readrba by Matt Cowgill — CRAN |
Note: The 2-month, 4-month, and 5-month tenors are not published by the RBA. These are only available via ASX paid subscription or Bloomberg terminal (tickers
BBSW1M–BBSW6M Index).
library(readrba)
library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)
f1 <- read_rba(table_no = "f1")
start_date <- as.Date("2025-01-01")
end_date <- Sys.Date()
bbsw <- f1 %>%
filter(
series %in% c(
"EOD 1-month BABs/NCDs",
"EOD 3-month BABs/NCDs",
"EOD 6-month BABs/NCDs"
),
date >= start_date,
date <= end_date
)
bbsw_wide <- bbsw %>%
select(date, series, value) %>%
pivot_wider(names_from = series, values_from = value) %>%
arrange(date) %>%
rename(
`1M_BBSW` = `EOD 1-month BABs/NCDs`,
`3M_BBSW` = `EOD 3-month BABs/NCDs`,
`6M_BBSW` = `EOD 6-month BABs/NCDs`
)
Period: 01 January 2025 to 07 April 2026 — 315 trading days
summary_stats <- bbsw_wide %>%
summarise(
across(
c(`1M_BBSW`, `3M_BBSW`, `6M_BBSW`),
list(
Min = ~ min(., na.rm = TRUE),
Max = ~ max(., na.rm = TRUE),
Mean = ~ round(mean(., na.rm = TRUE), 4),
Last = ~ last(na.omit(.))
),
.names = "{.fn}_{.col}"
)
)
stats_df <- data.frame(
Statistic = c("Min", "Max", "Mean", "Latest"),
`1M` = as.numeric(summary_stats[1, c(1, 4, 7, 10)]),
`3M` = as.numeric(summary_stats[1, c(2, 5, 8, 11)]),
`6M` = as.numeric(summary_stats[1, c(3, 6, 9, 12)])
)
names(stats_df) <- c("Statistic", "1-Month", "3-Month", "6-Month")
kable(stats_df, align = "lrrr", caption = "BBSW Summary Statistics (% p.a.)")
| Statistic | 1-Month | 3-Month | 6-Month |
|---|---|---|---|
| Min | 3.3803 | 4.3375 | 3.7953 |
| Max | 4.0809 | 3.4400 | 4.4075 |
| Mean | 3.8551 | 4.3204 | 3.6075 |
| Latest | 4.8108 | 4.0357 | 4.8108 |
kable(head(bbsw_wide, 10), caption = "Earliest 10 observations")
| date | 1M_BBSW | 3M_BBSW | 6M_BBSW |
|---|---|---|---|
| 2025-01-02 | 4.3325 | 4.4075 | 4.5097 |
| 2025-01-03 | 4.3225 | 4.3877 | 4.4782 |
| 2025-01-06 | 4.3375 | 4.4075 | 4.5103 |
| 2025-01-07 | 4.3158 | 4.3777 | 4.4772 |
| 2025-01-08 | 4.2698 | 4.3281 | 4.4356 |
| 2025-01-09 | 4.3114 | 4.3369 | 4.4434 |
| 2025-01-10 | 4.3315 | 4.3628 | 4.4393 |
| 2025-01-13 | 4.3368 | 4.3597 | 4.4585 |
| 2025-01-14 | 4.3150 | 4.3411 | 4.4453 |
| 2025-01-15 | 4.3099 | 4.3484 | 4.4400 |
kable(tail(bbsw_wide, 10), caption = "Most recent 10 observations")
| date | 1M_BBSW | 3M_BBSW | 6M_BBSW |
|---|---|---|---|
| 2026-03-20 | 4.0812 | 4.3075 | 4.7825 |
| 2026-03-23 | 3.9900 | 4.2530 | 4.7355 |
| 2026-03-24 | 4.0500 | 4.2837 | 4.7106 |
| 2026-03-25 | 4.0400 | 4.2810 | 4.7231 |
| 2026-03-26 | 4.0707 | 4.3093 | 4.7589 |
| 2026-03-27 | 4.0785 | 4.3233 | 4.7987 |
| 2026-03-30 | 4.0349 | 4.2952 | 4.7841 |
| 2026-03-31 | 4.0450 | 4.3000 | 4.7750 |
| 2026-04-01 | 4.0100 | 4.2683 | 4.7472 |
| 2026-04-02 | 4.0809 | 4.3204 | 4.8108 |
bbsw_long <- bbsw_wide %>%
pivot_longer(
cols = c(`1M_BBSW`, `3M_BBSW`, `6M_BBSW`),
names_to = "Tenor",
values_to = "Rate"
) %>%
mutate(Tenor = factor(Tenor,
levels = c("1M_BBSW", "3M_BBSW", "6M_BBSW"),
labels = c("1 Month", "3 Month", "6 Month")
))
ggplot(bbsw_long, aes(x = date, y = Rate, colour = Tenor)) +
geom_line(linewidth = 0.7) +
labs(
title = "Australian Bank Bill Swap Rates (BBSW)",
subtitle = paste("Daily EOD rates |", format(min(bbsw_wide$date), "%d %b %Y"),
"–", format(max(bbsw_wide$date), "%d %b %Y")),
x = NULL, y = "Rate (% p.a.)", colour = "Tenor",
caption = "Source: RBA Statistical Table F1 via readrba"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "top", plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()) +
scale_colour_manual(values = c("1 Month" = "#1b9e77", "3 Month" = "#d95f02", "6 Month" = "#7570b3"))
A positive spread indicates a normal upward-sloping yield curve. A negative spread suggests the market is pricing in future rate cuts.
spread_df <- bbsw_wide %>%
mutate(Spread_6M_1M = `6M_BBSW` - `1M_BBSW`) %>%
filter(!is.na(Spread_6M_1M))
ggplot(spread_df, aes(x = date, y = Spread_6M_1M)) +
geom_line(colour = "#d95f02", linewidth = 0.7) +
geom_hline(yintercept = 0, linetype = "dashed", colour = "grey40") +
labs(
title = "BBSW Term Spread (6M minus 1M)",
subtitle = "Positive = normal curve | Negative = inverted",
x = NULL, y = "Spread (percentage points)",
caption = "Source: RBA Statistical Table F1 via readrba"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold"), panel.grid.minor = element_blank())
Comparing today’s short-end curve against 3 months ago.
latest_date <- max(bbsw_wide$date, na.rm = TRUE)
compare_date <- bbsw_wide %>%
filter(date <= latest_date - 90) %>%
pull(date) %>%
max()
curve_data <- bbsw_wide %>%
filter(date %in% c(latest_date, compare_date)) %>%
pivot_longer(
cols = c(`1M_BBSW`, `3M_BBSW`, `6M_BBSW`),
names_to = "Tenor", values_to = "Rate"
) %>%
mutate(
Months = case_when(
Tenor == "1M_BBSW" ~ 1,
Tenor == "3M_BBSW" ~ 3,
Tenor == "6M_BBSW" ~ 6
),
Label = format(date, "%d %b %Y")
)
ggplot(curve_data, aes(x = Months, y = Rate, colour = Label)) +
geom_line(linewidth = 1) +
geom_point(size = 3) +
scale_x_continuous(breaks = c(1, 3, 6), labels = c("1M", "3M", "6M")) +
labs(
title = "BBSW Yield Curve Snapshot",
subtitle = paste("Comparing", format(compare_date, "%d %b %Y"),
"vs", format(latest_date, "%d %b %Y")),
x = "Tenor", y = "Rate (% p.a.)", colour = NULL,
caption = "Source: RBA Statistical Table F1 via readrba"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "top", plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()) +
scale_colour_manual(values = c("#7570b3", "#d95f02"))
library(writexl)
output_file <- "BBSW_2025_to_Today.xlsx"
write_xlsx(bbsw_wide, output_file)
Data exported to BBSW_2025_to_Today.xlsx — 315 rows.
Report generated on 07 April 2026 at 19:25 AEST using R 4.5.1 and readrba.