“All models are wrong, but some are useful.” – George E. P. Box, statistician and Box-Jenkins time-series coauthor
“Be approximately right rather than exactly wrong.” – John W. Tukey, statistician and pioneer of exploratory data analysis
“The purpose of computing is insight, not numbers.” – Richard W. Hamming, numerical analyst and Turing Award winner
rollcast builds probabilistic forecasts for one numeric
time series by turning rolling statistics into forecast anchors,
learning which anchors are useful in the current state, and simulating
future paths from the resulting mixture.
Instead of asking one model to explain everything,
rollcast keeps a small bench of candidate locations:
Then a proper-score gate assigns state-dependent weights, optional conditional residual sampling adds local dispersion, and recursive simulation turns the one-step mixture into marginal and joint predictive distributions.
The rollcast package works this way:
error_scale > 0.Five anchors walk into a forecast. The gate checks the room, turns the lights up on the useful ones, and lets the simulation take it from there.
We will use a synthetic series with a gentle drift and enough noise to keep things honest. Scalar hyperparameters mean “use this value”; vectors mean “try these candidates with causal validation.”
library(rollcast)
set.seed(1)
y <- 100 + cumsum(rnorm(300, mean = 0.03, sd = 0.8))
fit <- rollcast(
y,
window = 60,
tau = 0.25,
lambda = 0.01,
conditional_k = 40,
state_bw = 1,
residual_bw = 0.35,
error_scale = 0.25,
residual_smoothing = 0.03,
rho_min = 0.05,
rho_max = 0.90,
rho_decay = 1
)
fitThe printed model shows the selected anchors, gate settings, adaptive persistence range, and current anchor probabilities. That last part is the quick read: which rolling summaries are currently getting the most probability.
The current probabilities live on the fitted object. A simple sort gives a small dashboard for the latest state.
The anchor names are deliberately plain. If
regression_forecast is high, the recent direction is doing
work. If median or inner quantiles dominate, the series is
behaving more like a stable level. If extremes get weight, the model is
seeing a state where boundary anchors helped historically.
predict() recursively simulates a predictive mixture.
The summary gives means, medians, standard deviations, and requested
quantiles by horizon.
Forecasts should come with distribution handles, so the prediction object also returns four small functions:
pred$dfun(100, h = 1)
pred$pfun(100, h = 1)
pred$qfun(c(0.05, 0.50, 0.95), h = 1)
pred$rfun(5, h = 1)Calling rfun() without h returns coherent
recursive paths rather than independent marginal draws:
That is the difference between “twenty separate one-step stories” and “one hundred possible futures that know their own history.”
The interface has one main rule:
scalar = fixed; vector = search.
For a fast fixed run, give scalar values throughout:
fixed <- rollcast(
y,
window = 60,
tau = 0.25,
lambda = 0.01,
conditional_k = 40,
state_bw = 1,
residual_bw = 0.35,
error_scale = 0.25,
residual_smoothing = 0.03,
rho_min = 0.05,
rho_max = 0.90,
rho_decay = 1
)To let the model choose among a few sensible options, pass vectors:
tuned <- rollcast(
y,
window = c(40, 60, 90),
tau = c(0.15, 0.25, 0.40),
lambda = c(0.001, 0.01, 0.05),
conditional_k = 40,
state_bw = 1,
residual_bw = c(0.20, 0.35, 0.55),
error_scale = c(0, 0.25, 0.50),
residual_smoothing = 0.03,
rho_min = 0.05,
rho_max = 0.90,
rho_decay = 1,
verbose = TRUE
)
tuned$hyperparameter_searchThe search is a cached coordinate search on common causal validation origins, not a full Cartesian grid. Translation: it tries to be useful without turning your check run into a long lunch.
Set error_scale = 0 for a pure weighted-anchor
forecast:
anchor_only <- rollcast(
y,
window = 60,
tau = 0.25,
lambda = 0.01,
conditional_k = 40,
state_bw = 1,
residual_bw = 0.35,
error_scale = 0,
residual_smoothing = 0.03,
rho_min = 0.05,
rho_max = 0.90,
rho_decay = 1
)Use error_scale between zero and one when the anchors
should keep their location role but local historical residuals should
add shape around them. Zero is crisp. One is full residual correction.
The middle is often where the forecast behaves like it has both a
steering wheel and suspension.
The default plot is a compact diagnostic dashboard:
Use the fan-only view when all you need is the forecast envelope:
The diagnostic view combines four checks:
The transition calculation fits the simple segmented shape
\[ W_h = a + b_1 h + \Delta b (h-h^*)_+, \]
where \(W_h\) is a predictive interval width and \(h^*\) is the horizon where the rate of uncertainty expansion changes.
rollcast is a small forecasting control room. Rolling
anchors suggest where the next value might land, the gate decides who
deserves attention, residuals add local texture when requested, and
recursive simulation turns the result into full predictive paths. Fit,
inspect, simulate, plot. Then let the distribution do the talking.
Enzoi!