--- title: "Trend Extraction Methods" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Trend Extraction Methods} %\VignetteEncoding{UTF-8} %\VignetteEngine{knitr::rmarkdown} editor_options: markdown: wrap: 80 --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4.5, message = FALSE, warning = FALSE ) ``` ```{r setup} library(trendseries) ``` This vignette is a catalogue of every trend-extraction method in `trendseries`: which family it belongs to, when to reach for it, and which parameters it accepts. For worked examples of specific families, see the companion [Moving Averages](moving-averages.html) and [Econometric Filters](econometric-filters.html) vignettes. To split a series into trend, seasonal, and remainder components instead of extracting a single smooth trend, see [Decomposing Series](decompose-series.html). # The two interfaces Every method is reachable through two functions that share the same engine and the same parameters: - `augment_trends()` — pipe-friendly. Takes a `data.frame`/`tibble`, adds `trend_{method}` columns, and supports grouped series via `group_cols`. - `extract_trends()` — takes a `ts`/`xts`/`zoo` object and returns `ts` objects (a single `ts` for one method, a named list for several). ```{r} # Data-frame interface: adds a trend_stl column head(augment_trends(ibcbr, value_col = "index", methods = "stl")) ``` ```{r} # Time-series interface: returns a ts object hp_trend <- extract_trends(AirPassengers, methods = "hp") class(hp_trend) ``` Pass several methods at once to compare them: ```{r} trends <- augment_trends( ibcbr, value_col = "index", methods = c("hp", "stl", "henderson") ) head(trends) ``` # The unified parameter system Rather than exposing every method's idiosyncratic arguments, `trendseries` routes a small set of *generic* parameters to whichever method-specific option they correspond to. Sensible, frequency-aware defaults mean you rarely need to set them. | Parameter | Applies to | Meaning | |-------------|------------|---------| | `window` | moving-average methods (`ma`, `wma`, `triangular`, `ewma`, `median`, `gaussian`, `stl`) | Number of observations in the smoothing window. | | `smoothing` | `hp`, `loess`, `spline`, `ewma`, `kernel`, `kalman` | Amount of smoothing (interpretation varies by method). | | `band` | bandpass filters (`bk`, `cf`) | `c(low, high)` cycle periods to keep. | | `align` | `ma`, `wma`, `triangular`, `gaussian` | `"center"` (default), `"right"` (causal), or `"left"`. | | `params` | all | A named list for any remaining method-specific options. | ```{r} # A wider HP smoothing and a 12-month moving average, in one call augment_trends( ibcbr, value_col = "index", methods = c("hp", "ma"), smoothing = 1600, window = 12 ) |> head() ``` Frequency-aware defaults adapt to the data: for monthly series the HP smoothing parameter defaults to `lambda = 14400` and the moving-average window to 12; for quarterly series, `lambda = 1600` and a window of 4 (Ravn & Uhlig, 2002). # Method catalogue `trendseries` ships 20 trend methods across four families. | Method | Category | Description | Typical use | |--------------|----------------|----------------------------------------|-------------| | `hp` | econometric | Hodrick-Prescott filter | General-purpose business-cycle trend | | `hamilton` | econometric | Hamilton regression filter | HP alternative without spurious cycles | | `bn` | econometric | Beveridge-Nelson decomposition | Permanent/transitory split | | `ucm` | econometric | Unobserved components model | Model-based, stochastic trend | | `bk` | bandpass | Baxter-King bandpass filter | Isolating a cycle frequency band | | `cf` | bandpass | Christiano-Fitzgerald bandpass filter | Asymmetric bandpass, uses endpoints | | `ma` | moving average | Simple moving average | Quick, intuitive smoothing | | `wma` | moving average | Weighted moving average | Smoothing with custom weights | | `ewma` | moving average | Exponentially weighted moving average | Recent-weighted, real-time smoothing | | `triangular` | moving average | Triangular moving average | Smoother than a simple MA | | `median` | moving average | Median filter | Robust to outliers/spikes | | `gaussian` | moving average | Gaussian-weighted moving average | Smooth, bell-weighted average | | `spencer` | moving average | Spencer's 15-term moving average | Classic actuarial graduation | | `henderson` | moving average | Henderson moving average | Trend term inside X-11 seasonal adj. | | `stl` | smoothing | Seasonal-trend decomposition via Loess | Trend from strongly seasonal data | | `loess` | smoothing | Local polynomial regression | Flexible non-parametric trend | | `spline` | smoothing | Smoothing splines | Smooth curve with automatic penalty | | `poly` | smoothing | Polynomial trends | Simple global trend shape | | `kernel` | smoothing | Kernel smoother | Non-parametric, bandwidth-controlled | | `kalman` | smoothing | Kalman filter/smoother | Adaptive trend for noisy series | ## Moving averages Moving-average methods replace each point with a (possibly weighted) average of its neighbours. They are fast, transparent, and a good default for exploratory work. Control the smoothing through `window` (and `align` for causal vs. centred variants). `ma`, `median`, and `henderson` also accept a *vector* of windows, returning one trend per window. ```{r} augment_trends( ibcbr, value_col = "index", methods = "henderson", window = c(13, 23) ) |> head() ``` See [Moving Averages](moving-averages.html) for the full treatment. ## Smoothing methods Smoothing methods fit a flexible curve to the data. `stl` and `loess` are locally adaptive; `spline` and `kernel` trade off fit against smoothness through a penalty/bandwidth; `poly` imposes a single global shape. The `smoothing` parameter tunes how aggressively they smooth. ```{r} loess_trend <- extract_trends(AirPassengers, methods = "loess", smoothing = 0.3) plot(AirPassengers, col = "grey60", ylab = "Air passengers") lines(loess_trend, col = "#C53030", lwd = 2) ``` ## Econometric filters These are the workhorses of applied macroeconomics. The Hodrick-Prescott filter (`hp`) is the most widely used; `hamilton` is a regression-based alternative that avoids HP's well-known spurious-cycle artefacts; `bn` and `ucm` are model-based decompositions into permanent and transitory parts. ```{r} augment_trends( gdp_construction, value_col = "index", methods = c("hp", "hamilton") ) |> head() ``` The HP filter has a one-sided (real-time) variant for nowcasting, where future observations must not influence the current estimate: ```{r} extract_trends( AirPassengers, methods = "hp", params = list(hp_onesided = TRUE) ) |> head() ``` See [Econometric Filters](econometric-filters.html) for details. ## Bandpass filters Bandpass filters (`bk`, `cf`) keep only the fluctuations whose periodicity falls inside a chosen band, removing both the long-run trend and high-frequency noise. Specify the band with `band = c(low, high)` in periods (quarters for quarterly data): ```{r} extract_trends( AirPassengers, methods = "cf", band = c(18, 96) ) |> head() ``` # Decomposition vs. trend extraction The methods above estimate a single smooth *trend*. When you instead want to split a series into **trend + seasonal + remainder**, use `decompose_series()`, which offers five methods of its own: | Method | Engine | Notes | |---------------|--------|-------| | `stl` | `stats::stl()` | Loess-based, robust option available. | | `regression` | OLS | Polynomial trend + seasonal dummies. | | `classic` | `stats::decompose()` | Classical moving-average; additive or multiplicative. | | `bsm` | `stats::StructTS()` | State-space model; components for every point. | | `seats` | X-13ARIMA-SEATS | Requires the optional **`seasonal`** package. | ```{r} decompose_series(gdp_construction, value_col = "index", methods = "stl") |> head() ``` The dedicated [Decomposing Series](decompose-series.html) vignette covers these in depth. # References Ravn, M. O., & Uhlig, H. (2002). On adjusting the Hodrick-Prescott filter for the frequency of observations. *The Review of Economics and Statistics*, 84(2), 371–376.