---
title: "Real-time GDP nowcasting with monthly indicators"
author: "Charles Coverdale"
date: "`r format(Sys.Date(), '%d %B %Y')`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Real-time GDP nowcasting with monthly indicators}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
library(fred)
key_available <- nzchar(Sys.getenv("FRED_API_KEY"))
nowcast_available <- requireNamespace("nowcast", quietly = TRUE)
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 4.5,
  eval = key_available && nowcast_available
)
```

US GDP is published quarterly, with an advance release roughly four weeks
after quarter-end. Monthly indicators (retail sales, employment, industrial
production, financial conditions) are available much sooner, so analysts
build *bridge equations* that map monthly indicators onto quarterly GDP. The
challenge is doing this honestly: the data you have today has been revised
many times, so an in-sample fit overstates real-time forecast skill.

This vignette uses `fred` together with the
[`nowcast`](https://github.com/charlescoverdale/nowcast) package to:

1. Pull the standard monthly indicator panel from FRED.
2. Estimate a bridge equation for quarterly GDP growth.
3. Backtest in pseudo-real-time using `fred_as_of()` so each forecast only
   sees data that was actually available at the time.
4. Compare in-sample fit to honest pseudo-real-time error.

It needs both an API key and the `nowcast` package. Without them, the code
is shown but not executed.

## Setup

```{r}
library(fred)
library(nowcast)
```

## Step 1. The monthly indicator panel

Start with a small, defensible set of monthly indicators that are themselves
released early in the month for the previous month. Industrial production,
retail sales, employment, ISM-style activity, and financial conditions are
the standard choices.

```{r}
indicators <- c(
  "INDPRO",   # Industrial production (15th)
  "RSAFS",    # Retail sales advance (mid-month)
  "PAYEMS",   # Nonfarm payrolls (first Friday)
  "NFCI",     # Chicago Fed financial conditions (weekly)
  "UMCSENT"   # Michigan consumer sentiment (mid + late month)
)

monthly <- fred_series(indicators, from = "2000-01-01", format = "wide")
head(monthly)
```

GDP itself, transformed to quarter-on-quarter annualised growth (FRED's
`pca` or `transform = "annualised"`):

```{r}
gdp_growth <- fred_series(
  "GDPC1",
  from = "2000-01-01",
  transform = "annualised"
)
plot(gdp_growth, main = "Real GDP, QoQ annualised growth")
```

## Step 2. Bridge equation, latest vintage

The naive approach: regress GDP growth on aggregated monthly indicators
using the latest data. This is what most ad-hoc nowcasts use.

```{r}
# Aggregate monthlies to quarterly using fred_aggregate()
monthly_long <- fred_series(indicators, from = "2000-01-01")
quarterly <- fred_aggregate(monthly_long, fun = "mean", by = "quarter")
head(quarterly)
```

To estimate a bridge equation with `nowcast`, the inputs need to be a single
data frame with the target series and the indicators side by side. The
sketch below is illustrative; see `?nowcast::nc_bridge` for the actual
formula interface.

```{r, eval = FALSE}
# Pseudo-code: build a wide quarterly frame for nc_bridge(formula, data)
panel <- merge(
  fred_series("GDPC1", from = "2000-01-01", transform = "annualised"),
  fred_aggregate(
    fred_series(indicators, from = "2000-01-01", format = "wide"),
    fun = "mean", by = "quarter"
  ),
  by = "date"
)
bridge <- nowcast::nc_bridge(value ~ INDPRO + RSAFS + PAYEMS, data = panel)
summary(bridge)
```

The fit looks impressive because we are using *revised* indicator values
that were not available in real time.

## Step 3. Pseudo-real-time backtest

Replace each indicator series with its first-release vintage and rerun. The
discipline: at each forecast date, fetch only what was published as of that
date.

```{r, eval = FALSE}
forecast_dates <- seq(as.Date("2015-01-01"), as.Date("2024-12-01"),
                      by = "quarter")

backtest <- lapply(forecast_dates, function(d) {
  ind_rt <- fred_real_time_panel(indicators, vintages = d, from = "2000-01-01")
  gdp_rt <- fred_as_of("GDPC1", date = d, from = "2000-01-01",
                       units = "pca")
  list(date = d, ind = ind_rt, gdp = gdp_rt)
})
```

You can now run the same bridge equation per forecast date and compare the
real-time forecast to the eventual final-vintage GDP value. The `nowcast`
package has helpers for this; see `nowcast::nc_backtest()`.

## Step 4. Honest error

The honest pseudo-real-time RMSE is typically 30-100% larger than the
in-sample RMSE. This gap is the difference between "what your model would
have said at the time" and "what your model says now, with hindsight". For
publication-grade nowcasting, the pseudo-real-time number is the one to
report.

## Pinning the run for reproducibility

Save a manifest of every series your analysis used, with their hash and
vintage dates, alongside the paper code. Reviewers can re-run and verify
the data is unchanged.

```{r}
m <- fred_manifest(
  gdp = gdp_growth,
  monthly = monthly,
  quarterly = quarterly
)
print(m)
```

Cite each series in the paper itself:

```{r, eval = TRUE}
fred_cite_series("GDPC1", vintage_date = "2024-12-01", format = "text")
```

## Further reading

* `vignette("inflation-revisions")` for revision analysis on the inflation
  side.
* `vignette("multi-series-workflows")` for the basic fetch/transform/plot
  pattern.
* `nowcast::vignette("introduction")` for the bridge-equation methodology.
