Title: | Forecast Reconciliation |
---|---|
Description: | Classical (bottom-up and top-down), optimal combination and heuristic point (Di Fonzo and Girolimetto, 2023 <doi:10.1016/j.ijforecast.2021.08.004>) and probabilistic (Girolimetto et al. 2023 <doi:10.1016/j.ijforecast.2023.10.003>) forecast reconciliation procedures for linearly constrained time series (e.g., hierarchical or grouped time series) in cross-sectional, temporal, or cross-temporal frameworks. |
Authors: | Daniele Girolimetto [aut, cre, fnd]
|
Maintainer: | Daniele Girolimetto <[email protected]> |
License: | GPL-3 |
Version: | 1.0.0.9012 |
Built: | 2025-03-08 05:31:54 UTC |
Source: | https://github.com/danigiro/foreco |
Classical (bottom-up and top-down), optimal combination and heuristic point (Di Fonzo and Girolimetto, 2023 doi:10.1016/j.ijforecast.2021.08.004) and probabilistic (Girolimetto et al. 2023 doi:10.1016/j.ijforecast.2023.10.003) forecast reconciliation procedures for linearly constrained time series (e.g., hierarchical or grouped time series) in cross-sectional, temporal, or cross-temporal frameworks.
Maintainer: Daniele Girolimetto [email protected] (ORCID) [funder]
Authors:
Tommaso Di Fonzo (ORCID) [funder]
Useful links:
Report bugs at https://github.com/daniGiro/FoReco/issues
Non-overlapping temporal aggregation of a time series according to a specific aggregation order.
aggts(y, agg_order, tew = "sum", align = "end", rm_na = FALSE)
aggts(y, agg_order, tew = "sum", align = "end", rm_na = FALSE)
y |
Univariate or multivariate time series: a vector/matrix or a |
agg_order |
A numeric vector with the aggregation orders to consider. |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
align |
A string or a vector specifying the alignment of |
rm_na |
If |
A list of vectors or ts
objects.
Utilities:
FoReco2matrix()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Monthly time series (input vector) y <- ts(rnorm(24), start = 2020, frequency = 12) # Quarterly time series x1 <- aggts(y, 3) # Monthly, quarterly and annual time series x2 <- aggts(y, c(1, 3, 12)) # All temporally aggregated time series x3 <- aggts(y) # Ragged data y2 <- ts(rnorm(11), start = c(2020, 3), frequency = 4) # Annual time series: start in 2021 x4 <- aggts(y2, 4, align = 3) # Semi-annual (start in 2nd semester of 2020) and annual (start in 2021) time series x5 <- aggts(y2, c(2, 4), align = c(1, 3))
# Monthly time series (input vector) y <- ts(rnorm(24), start = 2020, frequency = 12) # Quarterly time series x1 <- aggts(y, 3) # Monthly, quarterly and annual time series x2 <- aggts(y, c(1, 3, 12)) # All temporally aggregated time series x3 <- aggts(y) # Ragged data y2 <- ts(rnorm(11), start = c(2020, 3), frequency = 4) # Annual time series: start in 2021 x4 <- aggts(y2, 4, align = 3) # Semi-annual (start in 2nd semester of 2020) and annual (start in 2021) time series x5 <- aggts(y2, c(2, 4), align = c(1, 3))
A hierarchy with upper levels is said to be balanced if each variable at level
has at least one child at level
. When this doesn't hold, the hierarchy
is unbalanced. This function transforms an aggregation matrix of an unbalanced hierarchy
into an aggregation matrix of a balanced one. This function is used to reconcile forecasts
with cslcc, which operates exclusively with balanced hierarchies.
balance_hierarchy(agg_mat, nodes = "auto", sparse = TRUE)
balance_hierarchy(agg_mat, nodes = "auto", sparse = TRUE)
agg_mat |
A ( |
nodes |
A ( |
sparse |
Option to return sparse matrices (default is |
A list containing four elements:
bam |
The balanced aggregation matrix. |
agg_mat |
The input matrix. |
nodes |
A ( |
id |
The identification number of each variable in the balanced hierarchy. It may contains duplicated values. |
Utilities:
FoReco2matrix()
,
aggts()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Unbalanced -> Balanced # T T # |-------| |-------| # A | A B # |---| | |---| | # AA AB B AA AB BA A <- matrix(c(1, 1, 1, 1, 1, 0), 2, byrow = TRUE) obj <- balance_hierarchy(agg_mat = A, nodes = c(1, 1)) obj$bam
# Unbalanced -> Balanced # T T # |-------| |-------| # A | A B # |---| | |---| | # AA AB B AA AB BA A <- matrix(c(1, 1, 1, 1, 1, 0), 2, byrow = TRUE) obj <- balance_hierarchy(agg_mat = A, nodes = c(1, 1)) obj$bam
This function returns the ()
commutation matrix
such that
where
is a (
) matrix (Magnus and Neudecker, 2019).
commat(r, c)
commat(r, c)
r |
Number of rows of |
c |
Number of columns of |
A sparse () matrix,
.
Magnus, J.R. and Neudecker, H. (2019), Matrix Differential Calculus with Applications in Statistics and Econometrics, third edition, New York, Wiley, pp. 54-55.
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
Y <- matrix(rnorm(30), 5, 6) P <- commat(5, 6) P %*% as.vector(Y) == as.vector(t(Y)) # check
Y <- matrix(rnorm(30), 5, 6) P <- commat(5, 6) P %*% as.vector(Y) == as.vector(t(Y)) # check
Joint block bootstrap for generating probabilistic base forecasts that take into account the correlation between different time series (Panagiotelis et al. 2023).
csboot(model_list, boot_size, block_size, seed = NULL)
csboot(model_list, boot_size, block_size, seed = NULL)
model_list |
A list of all the |
boot_size |
The number of bootstrap replicates. |
block_size |
Block size of the bootstrap, which is typically equivalent to the forecast horizon. |
seed |
An integer seed. |
A list with two elements: the seed used to sample the errors and a 3-d array
().
Panagiotelis, A., Gamakumara, P., Athanasopoulos, G. and Hyndman, R.J. (2023), Probabilistic forecast reconciliation: Properties, evaluation and score optimisation, European Journal of Operational Research 306(2), 693–706. doi:10.1016/j.ejor.2022.07.040
Bootstrap samples:
ctboot()
,
teboot()
Cross-sectional framework:
csbu()
,
cscov()
,
cslcc()
,
csmo()
,
csrec()
,
cstd()
,
cstools()
This function computes the cross-sectional bottom-up reconciled forecasts
(Dunn et al., 1976) for all series by appropriate summation of the bottom
base forecasts :
where is the cross-sectional structural matrix.
csbu(base, agg_mat, sntz = FALSE)
csbu(base, agg_mat, sntz = FALSE)
base |
A ( |
agg_mat |
A ( |
sntz |
If |
A () numeric matrix of cross-sectional reconciled forecasts.
Dunn, D. M., Williams, W. H. and Dechaine, T. L. (1976), Aggregate versus subaggregate models in local area forecasting, Journal of the American Statistical Association 71(353), 68–71. doi:10.1080/01621459.1976.10481478
Bottom-up reconciliation:
ctbu()
,
tebu()
Cross-sectional framework:
csboot()
,
cscov()
,
cslcc()
,
csmo()
,
csrec()
,
cstd()
,
cstools()
set.seed(123) # (3 x 2) bottom base forecasts matrix (simulated), Z = X + Y bts <- matrix(rnorm(6, mean = c(10, 10)), 3, byrow = TRUE) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) reco <- csbu(base = bts, agg_mat = A) # Non negative reconciliation bts[2,2] <- -bts[2,2] # Making negative one of the base forecasts for variable Y nnreco <- csbu(base = bts, agg_mat = A, sntz = TRUE)
set.seed(123) # (3 x 2) bottom base forecasts matrix (simulated), Z = X + Y bts <- matrix(rnorm(6, mean = c(10, 10)), 3, byrow = TRUE) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) reco <- csbu(base = bts, agg_mat = A) # Non negative reconciliation bts[2,2] <- -bts[2,2] # Making negative one of the base forecasts for variable Y nnreco <- csbu(base = bts, agg_mat = A, sntz = TRUE)
This function provides an approximation of the cross-sectional base forecasts errors covariance matrix using different reconciliation methods (see Wickramasuriya et al., 2019 and Di Fonzo and Girolimetto, 2023).
cscov(comb = "ols", n = NULL, agg_mat = NULL, res, mse = TRUE, shrink_fun = shrink_estim, ...)
cscov(comb = "ols", n = NULL, agg_mat = NULL, res, mse = TRUE, shrink_fun = shrink_estim, ...)
comb |
A string specifying the reconciliation method.
|
n |
Number of variables ( |
agg_mat |
A ( |
res |
An ( |
mse |
If |
shrink_fun |
Shrinkage function of the covariance matrix, shrink_estim (default). |
... |
Not used. |
A () symmetric positive (semi-)definite matrix.
Ando, S., and Xiao, M. (2023), High-dimensional covariance matrix estimation: shrinkage toward a diagonal target. IMF Working Papers, 2023(257), A001. doi:10.5089/9798400260780.001.A001
Di Fonzo, T. and Girolimetto, D. (2023), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Wickramasuriya, S.L., Athanasopoulos, G. and Hyndman, R.J. (2019), Optimal forecast reconciliation for hierarchical and grouped time series through trace minimization, Journal of the American Statistical Association, 114, 526, 804-819. doi:10.1080/01621459.2018.1448825
Cross-sectional framework:
csboot()
,
csbu()
,
cslcc()
,
csmo()
,
csrec()
,
cstd()
,
cstools()
# Aggregation matrix for Z = X + Y A <- t(c(1,1)) # (10 x 3) in-sample residuals matrix (simulated) res <- t(matrix(rnorm(n = 30), nrow = 3)) cov1 <- cscov("ols", n = 3) # OLS methods cov2 <- cscov("str", agg_mat = A) # STR methods cov3 <- cscov("wls", res = res) # WLS methods cov4 <- cscov("shr", res = res) # SHR methods cov5 <- cscov("sam", res = res) # SAM methods # Custom covariance matrix cscov.ols2 <- function(comb, x) diag(x) cscov(comb = "ols2", x = 3) # == cscov("ols", n = 3)
# Aggregation matrix for Z = X + Y A <- t(c(1,1)) # (10 x 3) in-sample residuals matrix (simulated) res <- t(matrix(rnorm(n = 30), nrow = 3)) cov1 <- cscov("ols", n = 3) # OLS methods cov2 <- cscov("str", agg_mat = A) # STR methods cov3 <- cscov("wls", res = res) # WLS methods cov4 <- cscov("shr", res = res) # SHR methods cov5 <- cscov("sam", res = res) # SAM methods # Custom covariance matrix cscov.ols2 <- function(comb, x) diag(x) cscov(comb = "ols2", x = 3) # == cscov("ols", n = 3)
This function implements the cross-sectional forecast reconciliation procedure that extends the original proposal by Hollyman et al. (2021). Level conditional coherent reconciled forecasts are conditional on (i.e., constrained by) the base forecasts of a specific upper level in the hierarchy (exogenous constraints). It also allows handling the linear constraints linking the variables endogenously (Di Fonzo and Girolimetto, 2022). The function can calculate Combined Conditional Coherent (CCC) forecasts as simple averages of Level-Conditional Coherent (LCC) and bottom-up reconciled forecasts, with either endogenous or exogenous constraints.
cslcc(base, agg_mat, nodes = "auto", comb = "ols", res = NULL, CCC = TRUE, const = "exogenous", bts = NULL, approach = "proj", nn = NULL, settings = NULL, ...)
cslcc(base, agg_mat, nodes = "auto", comb = "ols", res = NULL, CCC = TRUE, const = "exogenous", bts = NULL, approach = "proj", nn = NULL, settings = NULL, ...)
base |
A ( |
agg_mat |
A ( |
nodes |
A ( |
comb |
A string specifying the reconciliation method. For a complete list, see cscov. |
res |
An ( |
CCC |
A logical value indicating whether the Combined Conditional Coherent reconciled
forecasts reconciliation should include bottom-up forecasts ( |
const |
A string specifying the reconciliation constraints:
|
bts |
A ( |
approach |
A string specifying the approach used to compute the reconciled forecasts. Options include: |
nn |
A string specifying the algorithm to compute non-negative forecasts:
|
settings |
A list of control parameters.
|
... |
Arguments passed on to
|
A () numeric matrix of cross-sectional reconciled forecasts.
Byron, R.P. (1978), The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 141, 3, 359-367. doi:10.2307/2344807
Byron, R.P. (1979), Corrigenda: The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 142(3), 405. doi:10.2307/2982515
Di Fonzo, T. and Girolimetto, D. (2024), Forecast combination-based forecast reconciliation: Insights and extensions, International Journal of Forecasting, 40(2), 490–514. doi:10.1016/j.ijforecast.2022.07.001
Di Fonzo, T. and Girolimetto, D. (2023b) Spatio-temporal reconciliation of solar forecasts. Solar Energy 251, 13–29. doi:10.1016/j.solener.2023.01.003
Hyndman, R.J., Ahmed, R.A., Athanasopoulos, G. and Shang, H.L. (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis, 55, 9, 2579-2589. doi:10.1016/j.csda.2011.03.006
Hollyman, R., Petropoulos, F. and Tipping, M.E. (2021), Understanding forecast reconciliation. European Journal of Operational Research, 294, 149–160. doi:10.1016/j.ejor.2021.01.017
Stellato, B., Banjac, G., Goulart, P., Bemporad, A. and Boyd, S. (2020), OSQP: An Operator Splitting solver for Quadratic Programs, Mathematical Programming Computation, 12, 4, 637-672. doi:10.1007/s12532-020-00179-2
Level conditional coherent reconciliation:
ctlcc()
,
telcc()
Cross-sectional framework:
csboot()
,
csbu()
,
cscov()
,
csmo()
,
csrec()
,
cstd()
,
cstools()
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (2 x 7) base forecasts matrix (simulated) base <- matrix(rnorm(7*2, mean = c(40, 20, 20, 10, 10, 10, 10)), 2, byrow = TRUE) # (10 x 7) in-sample residuals matrix (simulated) res <- matrix(rnorm(n = 7*10), ncol = 7) # (2 x 7) Naive bottom base forecasts matrix: all forecasts are set equal to 10 naive <- matrix(10, 2, 4) ## EXOGENOUS CONSTRAINTS (Hollyman et al., 2021) # Level Conditional Coherent (LCC) reconciled forecasts exo_LC <- cslcc(base = base, agg_mat = A, comb = "wls", bts = naive, res = res, nodes = "auto", CCC = FALSE) # Combined Conditional Coherent (CCC) reconciled forecasts exo_CCC <- cslcc(base = base, agg_mat = A, comb = "wls", bts = naive, res = res, nodes = "auto", CCC = TRUE) # Results detailed by level: # L-1: Level 1 immutable reconciled forecasts for the whole hierarchy # L-2: Middle-Out reconciled forecasts # L-3: Bottom-Up reconciled forecasts info_exo <- recoinfo(exo_CCC, verbose = FALSE) info_exo$lcc ## ENDOGENOUS CONSTRAINTS (Di Fonzo and Girolimetto, 2024) # Level Conditional Coherent (LCC) reconciled forecasts endo_LC <- cslcc(base = base, agg_mat = A, comb = "wls", res = res, nodes = "auto", CCC = FALSE, const = "endogenous") # Combined Conditional Coherent (CCC) reconciled forecasts endo_CCC <- cslcc(base = base, agg_mat = A, comb = "wls", res = res, nodes = "auto", CCC = TRUE, const = "endogenous") # Results detailed by level: # L-1: Level 1 reconciled forecasts for L1 + L3 (bottom level) # L-2: Level 2 reconciled forecasts for L2 + L3 (bottom level) # L-3: Bottom-Up reconciled forecasts info_endo <- recoinfo(endo_CCC, verbose = FALSE) info_endo$lcc
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (2 x 7) base forecasts matrix (simulated) base <- matrix(rnorm(7*2, mean = c(40, 20, 20, 10, 10, 10, 10)), 2, byrow = TRUE) # (10 x 7) in-sample residuals matrix (simulated) res <- matrix(rnorm(n = 7*10), ncol = 7) # (2 x 7) Naive bottom base forecasts matrix: all forecasts are set equal to 10 naive <- matrix(10, 2, 4) ## EXOGENOUS CONSTRAINTS (Hollyman et al., 2021) # Level Conditional Coherent (LCC) reconciled forecasts exo_LC <- cslcc(base = base, agg_mat = A, comb = "wls", bts = naive, res = res, nodes = "auto", CCC = FALSE) # Combined Conditional Coherent (CCC) reconciled forecasts exo_CCC <- cslcc(base = base, agg_mat = A, comb = "wls", bts = naive, res = res, nodes = "auto", CCC = TRUE) # Results detailed by level: # L-1: Level 1 immutable reconciled forecasts for the whole hierarchy # L-2: Middle-Out reconciled forecasts # L-3: Bottom-Up reconciled forecasts info_exo <- recoinfo(exo_CCC, verbose = FALSE) info_exo$lcc ## ENDOGENOUS CONSTRAINTS (Di Fonzo and Girolimetto, 2024) # Level Conditional Coherent (LCC) reconciled forecasts endo_LC <- cslcc(base = base, agg_mat = A, comb = "wls", res = res, nodes = "auto", CCC = FALSE, const = "endogenous") # Combined Conditional Coherent (CCC) reconciled forecasts endo_CCC <- cslcc(base = base, agg_mat = A, comb = "wls", res = res, nodes = "auto", CCC = TRUE, const = "endogenous") # Results detailed by level: # L-1: Level 1 reconciled forecasts for L1 + L3 (bottom level) # L-2: Level 2 reconciled forecasts for L2 + L3 (bottom level) # L-3: Bottom-Up reconciled forecasts info_endo <- recoinfo(endo_CCC, verbose = FALSE) info_endo$lcc
The middle-out forecast reconciliation (Athanasopoulos et al., 2009) combines
top-down (cstd) and bottom-up (csbu) for genuine hierarchical/grouped
time series. Given the base forecasts of variables at an intermediate
level , it performs
a top-down approach for the levels ;
a bottom-up approach for the levels .
csmo(base, agg_mat, id_rows = 1, weights, normalize = TRUE)
csmo(base, agg_mat, id_rows = 1, weights, normalize = TRUE)
base |
A ( |
agg_mat |
A ( |
id_rows |
A numeric vector indicating the |
weights |
A ( |
normalize |
If |
A () numeric matrix of cross-sectional reconciled forecasts.
Athanasopoulos, G., Ahmed, R. A. and Hyndman, R.J. (2009) Hierarchical forecasts for Australian domestic tourism. International Journal of Forecasting 25(1), 146–166. doi:10.1016/j.ijforecast.2008.07.004
Middle-out reconciliation:
ctmo()
,
temo()
Cross-sectional framework:
csboot()
,
csbu()
,
cscov()
,
cslcc()
,
csrec()
,
cstd()
,
cstools()
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (3 x 2) top base forecasts vector (simulated), forecast horizon = 3 baseL2 <- matrix(rnorm(2*3, 5), 3, 2) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- csmo(base = baseL2, agg_mat = A, id_rows = 2:3, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*3), 3, 4) recoh <- csmo(base = baseL2, agg_mat = A, id_rows = 2:3, weights = h_weights)
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (3 x 2) top base forecasts vector (simulated), forecast horizon = 3 baseL2 <- matrix(rnorm(2*3, 5), 3, 2) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- csmo(base = baseL2, agg_mat = A, id_rows = 2:3, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*3), 3, 4) recoh <- csmo(base = baseL2, agg_mat = A, id_rows = 2:3, weights = h_weights)
This function computes the projection or the mapping matrix
and
, respectively, such that
,
where
is the vector of the reconciled forecasts,
is the vector of the base forecasts,
is the cross-sectional structural matrix, and
.
For further information regarding on the structure of these matrices,
refer to Girolimetto et al. (2023).
csprojmat(agg_mat, cons_mat, comb = "ols", res = NULL, mat = "M", ...)
csprojmat(agg_mat, cons_mat, comb = "ols", res = NULL, mat = "M", ...)
agg_mat |
A ( |
cons_mat |
A ( |
comb |
A string specifying the reconciliation method. For a complete list, see cscov. |
res |
An ( |
mat |
A string specifying which matrix to return:
" |
... |
Arguments passed on to
|
The projection matrix (
mat = "M"
) or
the mapping matrix (
mat = "G"
).
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Cross-sectional framework A <- t(c(1,1)) # Aggregation matrix for Z = X + Y Mcs <- csprojmat(agg_mat = A, comb = "ols") Gcs <- csprojmat(agg_mat = A, comb = "ols", mat = "G")
# Cross-sectional framework A <- t(c(1,1)) # Aggregation matrix for Z = X + Y Mcs <- csprojmat(agg_mat = A, comb = "ols") Gcs <- csprojmat(agg_mat = A, comb = "ols", mat = "G")
This function performs optimal (in least squares sense) combination cross-sectional forecast reconciliation for a linearly constrained (e.g., hierarchical/grouped) multiple time series (Wickramasuriya et al., 2019, Panagiotelis et al., 2022, Girolimetto and Di Fonzo, 2023). The reconciled forecasts are calculated using either a projection approach (Byron, 1978, 1979) or the equivalent structural approach by Hyndman et al. (2011). Non-negative (Di Fonzo and Girolimetto, 2023) and immutable (including Zhang et al., 2023) reconciled forecasts can be considered.
csrec(base, agg_mat, cons_mat, comb = "ols", res = NULL, approach = "proj", nn = NULL, settings = NULL, bounds = NULL, immutable = NULL, ...)
csrec(base, agg_mat, cons_mat, comb = "ols", res = NULL, approach = "proj", nn = NULL, settings = NULL, bounds = NULL, immutable = NULL, ...)
base |
A ( |
agg_mat |
A ( |
cons_mat |
A ( |
comb |
A string specifying the reconciliation method. For a complete list, see cscov. |
res |
An ( |
approach |
A string specifying the approach used to compute the reconciled forecasts. Options include: |
nn |
A string specifying the algorithm to compute non-negative forecasts:
|
settings |
A list of control parameters.
|
bounds |
A matrix (see set_bounds) with 3 columns (
|
immutable |
A numeric vector containing the column indices of the base forecasts
( |
... |
Arguments passed on to
|
A () numeric matrix of cross-sectional reconciled forecasts.
Byron, R.P. (1978), The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 141, 3, 359-367. doi:10.2307/2344807
Byron, R.P. (1979), Corrigenda: The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 142(3), 405. doi:10.2307/2982515
Di Fonzo, T. and Girolimetto, D. (2023), Spatio-temporal reconciliation of solar forecasts, Solar Energy, 251, 13–29. doi:10.1016/j.solener.2023.01.003
Girolimetto, D. and Di Fonzo, T. (2023), Point and probabilistic forecast reconciliation for general linearly constrained multiple time series, Statistical Methods & Applications, 33, 581-607. doi:10.1007/s10260-023-00738-6.
Hyndman, R.J., Ahmed, R.A., Athanasopoulos, G. and Shang, H.L. (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis, 55, 9, 2579-2589. doi:10.1016/j.csda.2011.03.006
Panagiotelis, A., Athanasopoulos, G., Gamakumara, P. and Hyndman, R.J. (2021), Forecast reconciliation: A geometric view with new insights on bias correction, International Journal of Forecasting, 37, 1, 343–359. doi:10.1016/j.ijforecast.2020.06.004
Stellato, B., Banjac, G., Goulart, P., Bemporad, A. and Boyd, S. (2020), OSQP: An Operator Splitting solver for Quadratic Programs, Mathematical Programming Computation, 12, 4, 637-672. doi:10.1007/s12532-020-00179-2
Wickramasuriya, S.L., Athanasopoulos, G. and Hyndman, R.J. (2019), Optimal forecast reconciliation for hierarchical and grouped time series through trace minimization, Journal of the American Statistical Association, 114, 526, 804-819. doi:10.1080/01621459.2018.1448825
Zhang, B., Kang, Y., Panagiotelis, A. and Li, F. (2023), Optimal reconciliation with immutable forecasts, European Journal of Operational Research, 308(2), 650–660. doi:10.1016/j.ejor.2022.11.035
Regression-based reconciliation:
ctrec()
,
terec()
Cross-sectional framework:
csboot()
,
csbu()
,
cscov()
,
cslcc()
,
csmo()
,
cstd()
,
cstools()
set.seed(123) # (2 x 3) base forecasts matrix (simulated), Z = X + Y base <- matrix(rnorm(6, mean = c(20, 10, 10)), 2, byrow = TRUE) # (10 x 3) in-sample residuals matrix (simulated) res <- t(matrix(rnorm(n = 30), nrow = 3)) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) reco <- csrec(base = base, agg_mat = A, comb = "wls", res = res) # Zero constraints matrix for Z - X - Y = 0 C <- t(c(1, -1, -1)) reco <- csrec(base = base, cons_mat = C, comb = "wls", res = res) # same results # Non negative reconciliation base[1,3] <- -base[1,3] # Making negative one of the base forecasts for variable Y nnreco <- csrec(base = base, agg_mat = A, comb = "wls", res = res, nn = "osqp") recoinfo(nnreco, verbose = FALSE)$info
set.seed(123) # (2 x 3) base forecasts matrix (simulated), Z = X + Y base <- matrix(rnorm(6, mean = c(20, 10, 10)), 2, byrow = TRUE) # (10 x 3) in-sample residuals matrix (simulated) res <- t(matrix(rnorm(n = 30), nrow = 3)) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) reco <- csrec(base = base, agg_mat = A, comb = "wls", res = res) # Zero constraints matrix for Z - X - Y = 0 C <- t(c(1, -1, -1)) reco <- csrec(base = base, cons_mat = C, comb = "wls", res = res) # same results # Non negative reconciliation base[1,3] <- -base[1,3] # Making negative one of the base forecasts for variable Y nnreco <- csrec(base = base, agg_mat = A, comb = "wls", res = res, nn = "osqp") recoinfo(nnreco, verbose = FALSE)$info
Top-down forecast reconciliation for genuine hierarchical/grouped time series (Gross and Sohl, 1990), where the forecast of a ‘Total’ (top-level series, expected to be positive) is disaggregated according to a proportional scheme (weights). Besides fulfilling any aggregation constraint, the top-down reconciled forecasts should respect two main properties:
the top-level value remains unchanged;
all the bottom time series reconciled forecasts are non-negative.
cstd(base, agg_mat, weights, normalize = TRUE)
cstd(base, agg_mat, weights, normalize = TRUE)
base |
A ( |
agg_mat |
A ( |
weights |
A ( |
normalize |
If |
A () numeric matrix of cross-sectional reconciled forecasts.
Gross, C.W. and Sohl, J.E. (1990), Disaggregation methods to expedite product line forecasting. Journal of Forecasting 9(3), 233–254. doi:10.1002/for.3980090304
Top-down reconciliation:
cttd()
,
tetd()
Cross-sectional framework:
csboot()
,
csbu()
,
cscov()
,
cslcc()
,
csmo()
,
csrec()
,
cstools()
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (3 x 1) top base forecasts vector (simulated), forecast horizon = 3 topf <- rnorm(3, 10) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- cstd(base = topf, agg_mat = A, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*3), 3, 4) recoh <- cstd(base = topf, agg_mat = A, weights = h_weights)
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (3 x 1) top base forecasts vector (simulated), forecast horizon = 3 topf <- rnorm(3, 10) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- cstd(base = topf, agg_mat = A, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*3), 3, 4) recoh <- cstd(base = topf, agg_mat = A, weights = h_weights)
Some useful tools for the cross-sectional forecast reconciliation of a linearly constrained (e.g., hierarchical/grouped) multiple time series.
cstools(agg_mat, cons_mat, sparse = TRUE)
cstools(agg_mat, cons_mat, sparse = TRUE)
agg_mat |
A ( |
cons_mat |
A ( |
sparse |
Option to return sparse matrices (default is |
A list with four elements:
dim |
A vector containing information about the number of series for the complete
system ( |
agg_mat |
The cross-sectional aggregation matrix. |
strc_mat |
The cross-sectional structural matrix. |
cons_mat |
The cross-sectional zero constraints matrix. |
Cross-sectional framework:
csboot()
,
csbu()
,
cscov()
,
cslcc()
,
csmo()
,
csrec()
,
cstd()
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Cross-sectional framework # One level hierarchy A = [1 1] A <- matrix(1, 1, 2) obj <- cstools(agg_mat = A)
# Cross-sectional framework # One level hierarchy A = [1 1] A <- matrix(1, 1, 2) obj <- cstools(agg_mat = A)
Joint block bootstrap for generating probabilistic base forecasts that take into account the correlation between variables at different temporal aggregation orders (Girolimetto et al. 2023).
ctboot(model_list, boot_size, agg_order, block_size = 1, seed = NULL)
ctboot(model_list, boot_size, agg_order, block_size = 1, seed = NULL)
model_list |
A list of |
boot_size |
The number of bootstrap replicates. |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
block_size |
Block size of the bootstrap, which is typically equivalent to the forecast horizon for the most temporally aggregated series. |
seed |
An integer seed. |
A list with two elements: the seed used to sample the errors and
a () matrix.
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2023), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40(3), 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Bootstrap samples:
csboot()
,
teboot()
Cross-temporal framework:
ctbu()
,
ctcov()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttd()
,
cttools()
,
iterec()
,
tcsrec()
Cross-temporal bottom-up reconciled forecasts for all series at any temporal
aggregation level are computed by appropriate summation of the high-frequency
bottom base forecasts :
where and
are the cross-sectional and
temporal structural matrices, respectively.
ctbu(base, agg_mat, agg_order, tew = "sum", sntz = FALSE)
ctbu(base, agg_mat, agg_order, tew = "sum", sntz = FALSE)
base |
A ( |
agg_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
sntz |
If |
A () numeric matrix of cross-temporal reconciled forecasts.
Bottom-up reconciliation:
csbu()
,
tebu()
Cross-temporal framework:
ctboot()
,
ctcov()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttd()
,
cttools()
,
iterec()
,
tcsrec()
set.seed(123) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) # (2 x 4) high frequency bottom base forecasts matrix (simulated), # agg_order = 4 (annual-quarterly) hfbts <- matrix(rnorm(4*2, 2.5), 2, 4) reco <- ctbu(base = hfbts, agg_mat = A, agg_order = 4) # Non negative reconciliation hfbts[1,4] <- -hfbts[1,4] # Making negative one of the quarterly base forecasts for variable X nnreco <- ctbu(base = hfbts, agg_mat = A, agg_order = 4, sntz = TRUE)
set.seed(123) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) # (2 x 4) high frequency bottom base forecasts matrix (simulated), # agg_order = 4 (annual-quarterly) hfbts <- matrix(rnorm(4*2, 2.5), 2, 4) reco <- ctbu(base = hfbts, agg_mat = A, agg_order = 4) # Non negative reconciliation hfbts[1,4] <- -hfbts[1,4] # Making negative one of the quarterly base forecasts for variable X nnreco <- ctbu(base = hfbts, agg_mat = A, agg_order = 4, sntz = TRUE)
This function provides an approximation of the cross-temporal base forecasts errors covariance matrix using different reconciliation methods (Di Fonzo and Girolimetto, 2023, Girolimetto et al., 2023).
ctcov(comb = "ols", n = NULL, agg_mat = NULL, agg_order = NULL, res = NULL, tew = "sum", mse = TRUE, shrink_fun = shrink_estim, ...)
ctcov(comb = "ols", n = NULL, agg_mat = NULL, agg_order = NULL, res = NULL, tew = "sum", mse = TRUE, shrink_fun = shrink_estim, ...)
comb |
A string specifying the reconciliation method.
|
n |
Cross-sectional number of variables. |
agg_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
res |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
mse |
If |
shrink_fun |
Shrinkage function of the covariance matrix, shrink_estim (default). |
... |
Not used. |
A () symmetric matrix.
Di Fonzo, T. and Girolimetto, D. (2023), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttd()
,
cttools()
,
iterec()
,
tcsrec()
set.seed(123) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) # (3 x 70) in-sample residuals matrix (simulated), # agg_order = 4 (annual-quarterly) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) cov1 <- ctcov("ols", n = 3, agg_order = 4) # OLS methods cov2 <- ctcov("str", agg_mat = A, agg_order = 4) # STR methods cov3 <- ctcov("csstr", agg_mat = A, agg_order = 4) # CSSTR methods cov4 <- ctcov("testr", n = 3, agg_order = 4) # TESTR methods cov5 <- ctcov("wlsv", agg_order = 4, res = res) # WLSv methods cov6 <- ctcov("wlsh", agg_order = 4, res = res) # WLSh methods cov7 <- ctcov("shr", agg_order = 4, res = res) # SHR methods cov8 <- ctcov("sam", agg_order = 4, res = res) # SAM methods cov9 <- ctcov("acov", agg_order = 4, res = res) # ACOV methods cov10 <- ctcov("Sshr", agg_order = 4, res = res) # Sshr methods cov11 <- ctcov("Ssam", agg_order = 4, res = res) # Ssam methods cov12 <- ctcov("hshr", agg_order = 4, res = res) # Hshr methods cov13 <- ctcov("hsam", agg_order = 4, res = res) # Hsam methods cov14 <- ctcov("hbshr", agg_mat = A, agg_order = 4, res = res) # HBshr methods cov15 <- ctcov("hbsam", agg_mat = A, agg_order = 4, res = res) # HBsam methods cov16 <- ctcov("bshr", agg_mat = A, agg_order = 4, res = res) # Bshr methods cov17 <- ctcov("bsam", agg_mat = A, agg_order = 4, res = res) # Bsam methods cov18 <- ctcov("bdshr", agg_order = 4, res = res) # BDshr methods cov19 <- ctcov("bdsam", agg_order = 4, res = res) # BDsam methods # Custom covariance matrix ctcov.ols2 <- function(comb, x) diag(x) cov20 <- ctcov(comb = "ols2", x = 21) # == ctcov("ols", n = 3, agg_order = 4)
set.seed(123) # Aggregation matrix for Z = X + Y A <- t(c(1,1)) # (3 x 70) in-sample residuals matrix (simulated), # agg_order = 4 (annual-quarterly) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) cov1 <- ctcov("ols", n = 3, agg_order = 4) # OLS methods cov2 <- ctcov("str", agg_mat = A, agg_order = 4) # STR methods cov3 <- ctcov("csstr", agg_mat = A, agg_order = 4) # CSSTR methods cov4 <- ctcov("testr", n = 3, agg_order = 4) # TESTR methods cov5 <- ctcov("wlsv", agg_order = 4, res = res) # WLSv methods cov6 <- ctcov("wlsh", agg_order = 4, res = res) # WLSh methods cov7 <- ctcov("shr", agg_order = 4, res = res) # SHR methods cov8 <- ctcov("sam", agg_order = 4, res = res) # SAM methods cov9 <- ctcov("acov", agg_order = 4, res = res) # ACOV methods cov10 <- ctcov("Sshr", agg_order = 4, res = res) # Sshr methods cov11 <- ctcov("Ssam", agg_order = 4, res = res) # Ssam methods cov12 <- ctcov("hshr", agg_order = 4, res = res) # Hshr methods cov13 <- ctcov("hsam", agg_order = 4, res = res) # Hsam methods cov14 <- ctcov("hbshr", agg_mat = A, agg_order = 4, res = res) # HBshr methods cov15 <- ctcov("hbsam", agg_mat = A, agg_order = 4, res = res) # HBsam methods cov16 <- ctcov("bshr", agg_mat = A, agg_order = 4, res = res) # Bshr methods cov17 <- ctcov("bsam", agg_mat = A, agg_order = 4, res = res) # Bsam methods cov18 <- ctcov("bdshr", agg_order = 4, res = res) # BDshr methods cov19 <- ctcov("bdsam", agg_order = 4, res = res) # BDsam methods # Custom covariance matrix ctcov.ols2 <- function(comb, x) diag(x) cov20 <- ctcov(comb = "ols2", x = 21) # == ctcov("ols", n = 3, agg_order = 4)
This function implements a forecast reconciliation procedure inspired by the original proposal by Hollyman et al. (2021) for cross-temporal hierarchies. Level conditional coherent reconciled forecasts are conditional on (i.e., constrained by) the base forecasts of a specific upper level in the hierarchy (exogenous constraints). It also allows handling the linear constraints linking the variables endogenously (Di Fonzo and Girolimetto, 2022). The function can calculate Combined Conditional Coherent (CCC) forecasts as simple averages of Level-Conditional Coherent (LCC) and bottom-up reconciled forecasts, with either endogenous or exogenous constraints.
ctlcc(base, agg_mat, nodes = "auto", agg_order, comb = "ols", res = NULL, CCC = TRUE, const = "exogenous", hfbts = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, ...)
ctlcc(base, agg_mat, nodes = "auto", agg_order, comb = "ols", res = NULL, CCC = TRUE, const = "exogenous", hfbts = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, ...)
base |
A ( |
agg_mat |
A ( |
nodes |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
comb |
A string specifying the reconciliation method. For a complete list, see ctcov. |
res |
A ( |
CCC |
A logical value indicating whether the Combined Conditional Coherent reconciled
forecasts reconciliation should include bottom-up forecasts ( |
const |
A string specifying the reconciliation constraints:
|
hfbts |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
approach |
A string specifying the approach used to compute the reconciled forecasts. Options include: |
nn |
A string specifying the algorithm to compute non-negative forecasts:
|
settings |
A list of control parameters.
|
... |
Arguments passed on to
|
A () numeric matrix of cross-temporal reconciled forecasts.
Byron, R.P. (1978), The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 141, 3, 359-367. doi:10.2307/2344807
Byron, R.P. (1979), Corrigenda: The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 142(3), 405. doi:10.2307/2982515
Di Fonzo, T. and Girolimetto, D. (2024), Forecast combination-based forecast reconciliation: Insights and extensions, International Journal of Forecasting, 40(2), 490–514. doi:10.1016/j.ijforecast.2022.07.001
Di Fonzo, T. and Girolimetto, D. (2023b) Spatio-temporal reconciliation of solar forecasts. Solar Energy 251, 13–29. doi:10.1016/j.solener.2023.01.003
Hyndman, R.J., Ahmed, R.A., Athanasopoulos, G. and Shang, H.L. (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis, 55, 9, 2579-2589. doi:10.1016/j.csda.2011.03.006
Hollyman, R., Petropoulos, F. and Tipping, M.E. (2021), Understanding forecast reconciliation. European Journal of Operational Research, 294, 149–160. doi:10.1016/j.ejor.2021.01.017
Stellato, B., Banjac, G., Goulart, P., Bemporad, A. and Boyd, S. (2020), OSQP: An Operator Splitting solver for Quadratic Programs, Mathematical Programming Computation, 12, 4, 637-672. doi:10.1007/s12532-020-00179-2
Level conditional coherent reconciliation:
cslcc()
,
telcc()
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctmo()
,
ctrec()
,
cttd()
,
cttools()
,
iterec()
,
tcsrec()
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (7 x 7) base forecasts matrix (simulated), agg_order = 4 base <- rbind(rnorm(7, rep(c(40, 20, 10), c(1, 2, 4))), rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (7 x 70) in-sample residuals matrix (simulated) res <- matrix(rnorm(70*7), nrow = 7) # (4 x 4) Naive high frequency bottom base forecasts vector: # all forecasts are set equal to 2.5 naive <- matrix(2.5, 4, 4) ## EXOGENOUS CONSTRAINTS (Hollyman et al., 2021) # Level Conditional Coherent (LCC) reconciled forecasts exo_LC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", nn = "osqp", hfbts = naive, res = res, nodes = "auto", CCC = FALSE) # Combined Conditional Coherent (CCC) reconciled forecasts exo_CCC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", hfbts = naive, res = res, nodes = "auto", CCC = TRUE) # Results detailed by level: info_exo <- recoinfo(exo_CCC, verbose = FALSE) # info_exo$lcc ## ENDOGENOUS CONSTRAINTS (Di Fonzo and Girolimetto, 2024) # Level Conditional Coherent (LCC) reconciled forecasts endo_LC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = FALSE, const = "endogenous") # Combined Conditional Coherent (CCC) reconciled forecasts endo_CCC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = TRUE, const = "endogenous") # Results detailed by level: info_endo <- recoinfo(endo_CCC, verbose = FALSE) # info_endo$lcc
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (7 x 7) base forecasts matrix (simulated), agg_order = 4 base <- rbind(rnorm(7, rep(c(40, 20, 10), c(1, 2, 4))), rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (7 x 70) in-sample residuals matrix (simulated) res <- matrix(rnorm(70*7), nrow = 7) # (4 x 4) Naive high frequency bottom base forecasts vector: # all forecasts are set equal to 2.5 naive <- matrix(2.5, 4, 4) ## EXOGENOUS CONSTRAINTS (Hollyman et al., 2021) # Level Conditional Coherent (LCC) reconciled forecasts exo_LC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", nn = "osqp", hfbts = naive, res = res, nodes = "auto", CCC = FALSE) # Combined Conditional Coherent (CCC) reconciled forecasts exo_CCC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", hfbts = naive, res = res, nodes = "auto", CCC = TRUE) # Results detailed by level: info_exo <- recoinfo(exo_CCC, verbose = FALSE) # info_exo$lcc ## ENDOGENOUS CONSTRAINTS (Di Fonzo and Girolimetto, 2024) # Level Conditional Coherent (LCC) reconciled forecasts endo_LC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = FALSE, const = "endogenous") # Combined Conditional Coherent (CCC) reconciled forecasts endo_CCC <- ctlcc(base = base, agg_mat = A, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = TRUE, const = "endogenous") # Results detailed by level: info_endo <- recoinfo(endo_CCC, verbose = FALSE) # info_endo$lcc
The cross-temporal middle-out forecast reconciliation combines top-down
(cttd) and bottom-up (ctbu) methods in the cross-temporal framework for
genuine hierarchical/grouped time series. Given the base forecasts of an
intermediate cross-sectional level and aggregation order
,
it performs
a top-down approach for the aggregation orders and
cross-sectional levels
;
a bottom-up approach, otherwise.
ctmo(base, agg_mat, agg_order, id_rows = 1, order = max(agg_order), weights, tew = "sum", normalize = TRUE)
ctmo(base, agg_mat, agg_order, id_rows = 1, order = max(agg_order), weights, tew = "sum", normalize = TRUE)
base |
A ( |
agg_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
id_rows |
A numeric vector indicating the |
order |
The intermediate fixed aggregation order |
weights |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
normalize |
If |
A () numeric matrix of cross-temporal reconciled forecasts.
Middle-out reconciliation:
csmo()
,
temo()
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctlcc()
,
ctrec()
,
cttd()
,
cttools()
,
iterec()
,
tcsrec()
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (2 x 6) base forecasts matrix (simulated), forecast horizon = 3 # and intermediate aggregation order k = 2 (max agg order = 4) baseL2k2 <- rbind(rnorm(3*2, 5), rnorm(3*2, 5)) # Same weights for different forecast horizons, agg_order = 4 fix_weights <- matrix(runif(4*4), 4, 4) reco <- ctmo(base = baseL2k2, id_rows = 2:3, agg_mat = A, order = 2, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*4*3), 4, 3*4) recoh <- ctmo(base = baseL2k2, id_rows = 2:3, agg_mat = A, order = 2, agg_order = 4, weights = h_weights)
set.seed(123) # Aggregation matrix for Z = X + Y, X = XX + XY and Y = YX + YY A <- matrix(c(1,1,1,1,1,1,0,0,0,0,1,1), 3, byrow = TRUE) # (2 x 6) base forecasts matrix (simulated), forecast horizon = 3 # and intermediate aggregation order k = 2 (max agg order = 4) baseL2k2 <- rbind(rnorm(3*2, 5), rnorm(3*2, 5)) # Same weights for different forecast horizons, agg_order = 4 fix_weights <- matrix(runif(4*4), 4, 4) reco <- ctmo(base = baseL2k2, id_rows = 2:3, agg_mat = A, order = 2, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*4*3), 4, 3*4) recoh <- ctmo(base = baseL2k2, id_rows = 2:3, agg_mat = A, order = 2, agg_order = 4, weights = h_weights)
This function computes the projection or the mapping matrix
and
, respectively, such that
,
where
is the vector of the reconciled forecasts,
is the vector of the base forecasts,
is the cross-temporal structural matrix, and
.
For further information regarding on the structure of these matrices,
refer to Girolimetto et al. (2023).
ctprojmat(agg_mat, cons_mat, agg_order, comb = "ols", res = NULL, mat = "M", tew = "sum", ...)
ctprojmat(agg_mat, cons_mat, agg_order, comb = "ols", res = NULL, mat = "M", tew = "sum", ...)
agg_mat |
A ( |
cons_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
comb |
A string specifying the reconciliation method. For a complete list, see ctcov. |
res |
A ( |
mat |
A string specifying which matrix to return:
" |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
... |
Arguments passed on to
|
The projection matrix (
mat = "M"
) or
the mapping matrix (
mat = "G"
).
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Cross-temporal framework (Z = X + Y, annual-quarterly) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y Mct <- ctprojmat(agg_mat = A, agg_order = 4, comb = "ols") Gct <- ctprojmat(agg_mat = A, agg_order = 4, comb = "ols", mat = "G")
# Cross-temporal framework (Z = X + Y, annual-quarterly) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y Mct <- ctprojmat(agg_mat = A, agg_order = 4, comb = "ols") Gct <- ctprojmat(agg_mat = A, agg_order = 4, comb = "ols", mat = "G")
This function performs optimal (in least squares sense) combination cross-temporal forecast reconciliation (Di Fonzo and Girolimetto 2023a, Girolimetto et al. 2023). The reconciled forecasts are calculated using either a projection approach (Byron, 1978, 1979) or the equivalent structural approach by Hyndman et al. (2011). Non-negative (Di Fonzo and Girolimetto, 2023) and immutable reconciled forecasts can be considered.
ctrec(base, agg_mat, cons_mat, agg_order, comb = "ols", res = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, bounds = NULL, immutable = NULL, ...)
ctrec(base, agg_mat, cons_mat, agg_order, comb = "ols", res = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, bounds = NULL, immutable = NULL, ...)
base |
A ( |
agg_mat |
A ( |
cons_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
comb |
A string specifying the reconciliation method. For a complete list, see ctcov. |
res |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
approach |
A string specifying the approach used to compute the reconciled forecasts. Options include: |
nn |
A string specifying the algorithm to compute non-negative forecasts:
|
settings |
A list of control parameters.
|
bounds |
A matrix (see set_bounds) with 5 columns (
|
immutable |
A matrix with three columns (
For example, when working with a quarterly multivariate time series (
|
... |
Arguments passed on to
|
A () numeric matrix of cross-temporal reconciled forecasts.
Byron, R.P. (1978), The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 141, 3, 359-367. doi:10.2307/2344807
Byron, R.P. (1979), Corrigenda: The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 142(3), 405. doi:10.2307/2982515
Di Fonzo, T. and Girolimetto, D. (2023a), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Di Fonzo, T. and Girolimetto, D. (2023), Spatio-temporal reconciliation of solar forecasts, Solar Energy, 251, 13–29. doi:10.1016/j.solener.2023.01.003
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Hyndman, R.J., Ahmed, R.A., Athanasopoulos, G. and Shang, H.L. (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis, 55, 9, 2579-2589. doi:10.1016/j.csda.2011.03.006
Stellato, B., Banjac, G., Goulart, P., Bemporad, A. and Boyd, S. (2020), OSQP: An Operator Splitting solver for Quadratic Programs, Mathematical Programming Computation, 12, 4, 637-672. doi:10.1007/s12532-020-00179-2
Regression-based reconciliation:
csrec()
,
terec()
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctlcc()
,
ctmo()
,
cttd()
,
cttools()
,
iterec()
,
tcsrec()
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (3 x 70) in-sample residuals matrix (simulated) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation reco <- ctrec(base = base, agg_mat = A, agg_order = m, comb = "wlsv", res = res) C <- t(c(1, -1, -1)) # Zero constraints matrix for Z - X - Y = 0 reco <- ctrec(base = base, cons_mat = C, agg_order = m, comb = "wlsv", res = res) # Immutable reconciled forecasts # Fix all the quarterly forecasts of the second variable. imm_mat <- expand.grid(i = 2, k = 1, j = 1:4) immreco <- ctrec(base = base, cons_mat = C, agg_order = m, comb = "wlsv", res = res, immutable = imm_mat) # Non negative reconciliation base[2,7] <- -2*base[2,7] # Making negative one of the quarterly base forecasts for variable X nnreco <- ctrec(base = base, cons_mat = C, agg_order = m, comb = "wlsv", res = res, nn = "osqp") recoinfo(nnreco, verbose = FALSE)$info
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (3 x 70) in-sample residuals matrix (simulated) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation reco <- ctrec(base = base, agg_mat = A, agg_order = m, comb = "wlsv", res = res) C <- t(c(1, -1, -1)) # Zero constraints matrix for Z - X - Y = 0 reco <- ctrec(base = base, cons_mat = C, agg_order = m, comb = "wlsv", res = res) # Immutable reconciled forecasts # Fix all the quarterly forecasts of the second variable. imm_mat <- expand.grid(i = 2, k = 1, j = 1:4) immreco <- ctrec(base = base, cons_mat = C, agg_order = m, comb = "wlsv", res = res, immutable = imm_mat) # Non negative reconciliation base[2,7] <- -2*base[2,7] # Making negative one of the quarterly base forecasts for variable X nnreco <- ctrec(base = base, cons_mat = C, agg_order = m, comb = "wlsv", res = res, nn = "osqp") recoinfo(nnreco, verbose = FALSE)$info
Top-down forecast reconciliation for cross-temporal hierarchical/grouped time series, where the forecast of a ‘Total’ (top-level series, expected to be positive) is disaggregated according to a proportional scheme (weights). Besides fulfilling any aggregation constraint, the top-down reconciled forecasts should respect two main properties:
the top-level value remains unchanged;
all the bottom time series reconciled forecasts are non-negative.
cttd(base, agg_mat, agg_order, weights, tew = "sum", normalize = TRUE)
cttd(base, agg_mat, agg_order, weights, tew = "sum", normalize = TRUE)
base |
A ( |
agg_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
weights |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
normalize |
If |
A () numeric matrix of cross-temporal reconciled forecasts.
Top-down reconciliation:
cstd()
,
tetd()
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttools()
,
iterec()
,
tcsrec()
set.seed(123) # (3 x 1) top base forecasts vector (simulated), forecast horizon = 3 topf <- rnorm(3, 10) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y # Same weights for different forecast horizons, agg_order = 4 fix_weights <- matrix(runif(4*2), 2, 4) reco <- cttd(base = topf, agg_mat = A, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*2*3), 2, 3*4) recoh <- cttd(base = topf, agg_mat = A, agg_order = 4, weights = h_weights)
set.seed(123) # (3 x 1) top base forecasts vector (simulated), forecast horizon = 3 topf <- rnorm(3, 10) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y # Same weights for different forecast horizons, agg_order = 4 fix_weights <- matrix(runif(4*2), 2, 4) reco <- cttd(base = topf, agg_mat = A, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- matrix(runif(4*2*3), 2, 3*4) recoh <- cttd(base = topf, agg_mat = A, agg_order = 4, weights = h_weights)
Some useful tools for the cross-temporal forecast reconciliation of a linearly constrained (e.g., hierarchical/grouped) multiple time series.
cttools(agg_mat, cons_mat, agg_order, tew = "sum", fh = 1, sparse = TRUE)
cttools(agg_mat, cons_mat, agg_order, tew = "sum", fh = 1, sparse = TRUE)
agg_mat |
A ( |
cons_mat |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
fh |
Forecast horizon for the lowest frequency (most temporally aggregated)
time series (default is |
sparse |
Option to return sparse matrices (default is |
A list with four elements:
dim |
A vector containing information about the number of series for the
complete system ( |
set |
The vector of the temporal aggregation orders (in decreasing order). |
agg_mat |
The cross-temporal aggregation matrix. |
strc_mat |
The cross-temporal structural matrix. |
cons_mat |
The cross-temporal zero constraints matrix. |
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttd()
,
iterec()
,
tcsrec()
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Cross-temporal framework A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation cttools(agg_mat = A, agg_order = m)
# Cross-temporal framework A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation cttools(agg_mat = A, agg_order = m)
This function allows the user to easily build the ()
cross-sectional aggregation matrix starting from a data frame.
df2aggmat(formula, data, sep = "_", sparse = TRUE, top_label = "Total", verbose = TRUE)
df2aggmat(formula, data, sep = "_", sparse = TRUE, top_label = "Total", verbose = TRUE)
formula |
Specification of the hierarchical structure: grouped hierarchies are specified
using |
data |
A dataset in which each column contains the values of the variables in the formula and each row identifies a bottom level time series. |
sep |
Character to separate the names of the aggregated series, (default is " |
sparse |
Option to return sparse matrices (default is |
top_label |
Label of the top level variable (default is " |
verbose |
If |
A (na x nb
) matrix.
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
## Balanced hierarchy # T # |--------| # A B # |---| |--|--| # AA AB BA BB BC # Names of the bottom level variables data_bts <- data.frame(X1 = c("A", "A", "B", "B", "B"), X2 = c("A", "B", "A", "B", "C"), stringsAsFactors = FALSE) # Cross-sectional aggregation matrix agg_mat <- df2aggmat(~ X1 / X2, data_bts, sep = "", verbose = FALSE) ## Unbalanced hierarchy # T # |---------|---------| # A B C # |---| |---| |---| # AA AB BA BB CA CB # |----| |----| # AAA AAB BBA BBB # Names of the bottom level variables data_bts <- data.frame(X1 = c("A", "A", "A", "B", "B", "B", "C", "C"), X2 = c("A", "A", "B", "A", "B", "B", "A", "B"), X3 = c("A", "B", NA, NA, "A", "B", NA, NA), stringsAsFactors = FALSE) # Cross-sectional aggregation matrix agg_mat <- df2aggmat(~ X1 / X2 / X3, data_bts, sep = "", verbose = FALSE) ## Group of two hierarchies # T T T | A | B | C # |--|--| X |---| -> ---+----+----+---- # A B C M F M | AM | BM | CM # F | AF | BF | CF # Names of the bottom level variables data_bts <- data.frame(X1 = c("A", "A", "B", "B", "C", "C"), Y1 = c("M", "F", "M", "F", "M", "F"), stringsAsFactors = FALSE) # Cross-sectional aggregation matrix agg_mat <- df2aggmat(~ Y1 * X1, data_bts, sep = "", verbose = FALSE)
## Balanced hierarchy # T # |--------| # A B # |---| |--|--| # AA AB BA BB BC # Names of the bottom level variables data_bts <- data.frame(X1 = c("A", "A", "B", "B", "B"), X2 = c("A", "B", "A", "B", "C"), stringsAsFactors = FALSE) # Cross-sectional aggregation matrix agg_mat <- df2aggmat(~ X1 / X2, data_bts, sep = "", verbose = FALSE) ## Unbalanced hierarchy # T # |---------|---------| # A B C # |---| |---| |---| # AA AB BA BB CA CB # |----| |----| # AAA AAB BBA BBB # Names of the bottom level variables data_bts <- data.frame(X1 = c("A", "A", "A", "B", "B", "B", "C", "C"), X2 = c("A", "A", "B", "A", "B", "B", "A", "B"), X3 = c("A", "B", NA, NA, "A", "B", NA, NA), stringsAsFactors = FALSE) # Cross-sectional aggregation matrix agg_mat <- df2aggmat(~ X1 / X2 / X3, data_bts, sep = "", verbose = FALSE) ## Group of two hierarchies # T T T | A | B | C # |--|--| X |---| -> ---+----+----+---- # A B C M F M | AM | BM | CM # F | AF | BF | CF # Names of the bottom level variables data_bts <- data.frame(X1 = c("A", "A", "B", "B", "C", "C"), Y1 = c("M", "F", "M", "F", "M", "F"), stringsAsFactors = FALSE) # Cross-sectional aggregation matrix agg_mat <- df2aggmat(~ Y1 * X1, data_bts, sep = "", verbose = FALSE)
This function splits the temporal vectors and the cross-temporal matrices in a list according to the temporal aggregation order
FoReco2matrix(x, agg_order, keep_names = FALSE)
FoReco2matrix(x, agg_order, keep_names = FALSE)
x |
An output from any reconciliation function implemented by FoReco. |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
keep_names |
If |
A list of matrices or vectors distinct by temporal aggregation order.
Utilities:
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) reco <- ctrec(base = base, agg_mat = t(c(1,1)), agg_order = 4, comb = "ols") matrix_list <- FoReco2matrix(reco)
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) reco <- ctrec(base = base, agg_mat = t(c(1,1)), agg_order = 4, comb = "ols") matrix_list <- FoReco2matrix(reco)
A subset of the data used by Girolimetto et al. (2023) from the Italian Quarterly National Accounts (output, income and expenditure sides) spanning the period 2000:Q1-2019:Q4.
# 21 time series of the Italian Quarterly National Accounts itagdp # 'agg_mat' and 'cons_mat' for the output side outside # 'agg_mat' and 'cons_mat' for the expenditure side expside # 'agg_mat' and 'cons_mat' for the income side incside # zero constraints matrix encompassing output, expenditure and income sides gdpconsmat
# 21 time series of the Italian Quarterly National Accounts itagdp # 'agg_mat' and 'cons_mat' for the output side outside # 'agg_mat' and 'cons_mat' for the expenditure side expside # 'agg_mat' and 'cons_mat' for the income side incside # zero constraints matrix encompassing output, expenditure and income sides gdpconsmat
itagdp
is a
ts
object, corresponding to
21 time series of the Italian Quarterly National Accounts (2000:Q1-2019:Q4).
outside
, income
and expenditure
are lists with two elements:
agg_mat
contains the ,
, or
aggregation matrix according to output, income or expenditure side, respectively.
cons_mat
contains the ,
, or
zero constraints matrix according to output, income or expenditure side, respectively.
gdpconsmat
is the complete zero constraints matrix
encompassing output, expenditure and income sides.
https://ec.europa.eu/eurostat/web/national-accounts/
Girolimetto, D. and Di Fonzo, T. (2023), Point and probabilistic forecast reconciliation for general linearly constrained multiple time series, Statistical Methods & Applications, 33, 581-607. doi:10.1007/s10260-023-00738-6.
This function performs the iterative procedure described in Di Fonzo and Girolimetto (2023), which produces cross-temporally reconciled forecasts by alternating forecast reconciliation along one single dimension (either cross-sectional or temporal) at each iteration step.
iterec(base, cslist, telist, res = NULL, itmax = 100, tol = 1e-5, type = "tcs", norm = "inf", verbose = TRUE)
iterec(base, cslist, telist, res = NULL, itmax = 100, tol = 1e-5, type = "tcs", norm = "inf", verbose = TRUE)
base |
A ( |
cslist |
A list of elements for the cross-sectional reconciliation.
See csrec for a complete list (excluded |
telist |
A list of elements for the temporal reconciliation.
See terec for a complete list (excluded |
res |
A ( |
itmax |
Max number of iteration ( |
tol |
Convergence tolerance ( |
type |
A string specifying the uni-dimensional reconciliation order:
temporal and then cross-sectional (" |
norm |
Norm used to calculate the temporal and the cross-sectional
incoherence: infinity norm (" |
verbose |
If |
A () numeric matrix of cross-temporal reconciled forecasts.
Di Fonzo, T. and Girolimetto, D. (2023), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttd()
,
cttools()
,
tcsrec()
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (3 x 70) in-sample residuals matrix (simulated) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation rite <- iterec(base = base, cslist = list(agg_mat = A, comb = "shr"), telist = list(agg_order = m, comb = "wlsv"), res = res)
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (3 x 70) in-sample residuals matrix (simulated) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation rite <- iterec(base = base, cslist = list(agg_mat = A, comb = "shr"), telist = list(agg_order = m, comb = "wlsv"), res = res)
This function transforms a general (possibly redundant) zero constraints matrix into a
linear combination (aggregation) matrix .
When working with a general linearly constrained multiple (
-variate)
time series, getting a linear combination matrix
is a critical
step to obtain a structural-like representation such that
where is the full rank zero constraints matrix (Girolimetto and
Di Fonzo, 2023).
lcmat(cons_mat, method = "rref", tol = sqrt(.Machine$double.eps), verbose = FALSE, sparse = TRUE)
lcmat(cons_mat, method = "rref", tol = sqrt(.Machine$double.eps), verbose = FALSE, sparse = TRUE)
cons_mat |
A ( |
method |
Method to use: " |
tol |
Tolerance for the " |
verbose |
If |
sparse |
Option to return a sparse matrix (default is |
A list with two elements: (i) the linear combination (aggregation) matrix
(agg_mat
) and (ii) the vector of the column permutations (pivot
).
Girolimetto, D. and Di Fonzo, T. (2023), Point and probabilistic forecast reconciliation for general linearly constrained multiple time series, Statistical Methods & Applications, 33, 581-607. doi:10.1007/s10260-023-00738-6.
Strang, G. (2019), Linear algebra and learning from data, Wellesley, Cambridge Press.
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
## Two hierarchy sharing the same top-level variable, but not sharing the bottom variables # X X # |-------| |-------| # A B C D # |---| # A1 A2 # 1) X = C + D, # 2) X = A + B, # 3) A = A1 + A2. cons_mat <- matrix(c(1,-1,-1,0,0,0,0, 1,0,0,-1,-1,0,0, 0,0,0,1,0,-1,-1), nrow = 3, byrow = TRUE) obj <- lcmat(cons_mat = cons_mat, verbose = TRUE) agg_mat <- obj$agg_mat # linear combination matrix pivot <- obj$pivot # Pivot vector
## Two hierarchy sharing the same top-level variable, but not sharing the bottom variables # X X # |-------| |-------| # A B C D # |---| # A1 A2 # 1) X = C + D, # 2) X = A + B, # 3) A = A1 + A2. cons_mat <- matrix(c(1,-1,-1,0,0,0,0, 1,0,0,-1,-1,0,0, 0,0,0,1,0,-1,-1), nrow = 3, byrow = TRUE) obj <- lcmat(cons_mat = cons_mat, verbose = TRUE) agg_mat <- obj$agg_mat # linear combination matrix pivot <- obj$pivot # Pivot vector
This function extracts reconciliation information from the output of any reconciled function implemented by FoReco.
recoinfo(x, verbose = TRUE)
recoinfo(x, verbose = TRUE)
x |
An output from any reconciliation function implemented by FoReco. |
verbose |
If |
A list containing the following reconciliation process informations:
rfun |
the reconciliation function. |
cs_n |
the cross-sectional number of variables. |
te_set |
the set of temporal aggregation orders. |
forecast_horizon |
the forecast horizon (in temporal and cross-temporal frameworks, for the most temporally aggregated series). |
framework |
the reconciliation framework (cross-sectional, temporal or cross-temporal). |
info |
non-negative reconciled forecast convergence information. |
lcc |
list of level conditional reconciled forecasts (+ BU) for cslcc, telcc and ctlcc. |
nn |
if |
comb |
the covariance approximation. |
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
These functions can be used to arrange residuals to reconcile temporal or cross-temporal forecasts.
res2matrix takes as input a set of temporal and cross-temporal residuals and re-organizes them into a matrix where the rows correspond to different forecast horizons, capturing the temporal dimension. Meanwhile, the columns are ordered based on the specific arrangement as described in Di Fonzo and Girolimetto (2023).
arrange_hres takes as input a list of multi-step residuals and is designed to organize them in accordance with their time order (Girolimetto et al. 2023). When applied, this function ensures that the sequence of multi-step residuals aligns with the chronological order in which they occurred.
res2matrix(res, agg_order) arrange_hres(list_res)
res2matrix(res, agg_order) arrange_hres(list_res)
res |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
list_res |
A list of |
Let ,
, be a univariate time series. We can define the multi-step
residuals such us
where is the
-step fitted value, calculated as the
-step ahead
forecast condition to the information up to time
. Given the list of errors at different steps
arrange_hres returns a -vector with the residuals, organized in the following way:
A similar organisation can be apply to a multivariate time series.
res2matrix returns a () matrix, where
for the temporal framework.
arrange_hres returns a () vector (temporal framework)
or a (
) matrix (cross-temporal framework) of multi-step residuals.
Di Fonzo, T. and Girolimetto, D. (2023), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
This function defines the bounds matrix considering cross-sectional,
temporal, or cross-temporal frameworks. The output matrix can be used as
input for the bounds
parameter in functions such as csrec, terec,
or ctrec, to perform bounded reconciliations.
set_bounds(n, k, h, lb = -Inf, ub = Inf, approach = "osqp", bounds = NULL)
set_bounds(n, k, h, lb = -Inf, ub = Inf, approach = "osqp", bounds = NULL)
n |
A ( |
k |
A ( |
h |
A ( |
lb , ub
|
A ( |
approach |
A string specifying the algorithm to compute bounded reconciled forecasts:
|
bounds |
A matrix of previous bounds to be added. If not specified, new bounds will be computed. |
A numeric matrix representing the computed bounds, which can be:
Cross-sectional () matrix for cross-sectional reconciliation (csrec).
Temporal () matrix for temporal reconciliation (terec).
Cross-temporal () matrix for cross-temporal reconciliation (ctrec).
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
# Example 1 # Two cross-sectional series (i = 2,3), # with each series required to be between 0 and 1. n <- c(2, 3) lb <- c(0, 0) ub <- c(1,1) bounds_mat <- set_bounds(n = c(2, 3), lb = rep(0, 2), # or lb = 0 ub = rep(1, 2)) # or ub = 1 # Example 2 # All the monthly values are between 0 and 1. bounds_mat <- set_bounds(k = rep(1, 12), # or k = 1 h = 1:12, lb = rep(0, 12), # or lb = 0 ub = rep(1, 12)) # or ub = 1 # Example 3 # For two cross-sectional series (i = 2,3), # all the monthly values are between 0 and 1. bounds_mat <- set_bounds(n = rep(c(2, 3), each = 12), k = 1, h = rep(1:12, 2), lb = 0, # or lb = 0 ub = 1) # or ub = 1
# Example 1 # Two cross-sectional series (i = 2,3), # with each series required to be between 0 and 1. n <- c(2, 3) lb <- c(0, 0) ub <- c(1,1) bounds_mat <- set_bounds(n = c(2, 3), lb = rep(0, 2), # or lb = 0 ub = rep(1, 2)) # or ub = 1 # Example 2 # All the monthly values are between 0 and 1. bounds_mat <- set_bounds(k = rep(1, 12), # or k = 1 h = 1:12, lb = rep(0, 12), # or lb = 0 ub = rep(1, 12)) # or ub = 1 # Example 3 # For two cross-sectional series (i = 2,3), # all the monthly values are between 0 and 1. bounds_mat <- set_bounds(n = rep(c(2, 3), each = 12), k = 1, h = rep(1:12, 2), lb = 0, # or lb = 0 ub = 1) # or ub = 1
Shrinkage of the covariance matrix according to Schäfer and Strimmer (2005).
shrink_estim(x, mse = TRUE)
shrink_estim(x, mse = TRUE)
x |
A numeric matrix containing the in-sample residuals. |
mse |
If |
A shrunk covariance matrix.
Schäfer, J.L. and Strimmer, K. (2005), A shrinkage approach to large-scale covariance matrix estimation and implications for functional genomics, Statistical Applications in Genetics and Molecular Biology, 4, 1
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_oasd()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
Shrinkage of the covariance matrix according to the Oracle Approximating Shrinkage (OAS) of Chen et al. (2009) and Ando and Xiao (2023).
shrink_oasd(x, mse = TRUE)
shrink_oasd(x, mse = TRUE)
x |
A numeric matrix containing the in-sample residuals. |
mse |
If |
A shrunk covariance matrix.
Ando, S., and Xiao, M. (2023), High-dimensional covariance matrix estimation: shrinkage toward a diagonal target. IMF Working Papers, 2023(257), A001. doi:10.5089/9798400260780.001.A001
Chen, Y., Wiesel, A., and Hero, A. O. (2009), Shrinkage estimation of high dimensional covariance matrices, 2009 IEEE international conference on acoustics, speech and signal processing, 2937–2940. IEEE.
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
teprojmat()
,
tetools()
,
unbalance_hierarchy()
tcsrec replicates the procedure by Kourentzes and Athanasopoulos (2019): (i) for each time series the forecasts at any temporal aggregation order are reconciled using temporal hierarchies; (ii) time-by-time cross-sectional reconciliation is performed; and (iii) the projection matrices obtained at step (ii) are then averaged and used to cross-sectionally reconcile the forecasts obtained at step (i). In cstrec, the order of application of the two reconciliation steps (temporal first, then cross-sectional), is inverted compared to tcsrec (Di Fonzo and Girolimetto, 2023).
# First-temporal-then-cross-sectional forecast reconciliation tcsrec(base, cslist, telist, res = NULL, avg = "KA") # First-cross-sectional-then-temporal forecast reconciliation cstrec(base, cslist, telist, res = NULL)
# First-temporal-then-cross-sectional forecast reconciliation tcsrec(base, cslist, telist, res = NULL, avg = "KA") # First-cross-sectional-then-temporal forecast reconciliation cstrec(base, cslist, telist, res = NULL)
base |
A ( |
cslist |
A list of elements for the cross-sectional reconciliation.
See csrec for a complete list (excluded |
telist |
A list of elements for the temporal reconciliation.
See terec for a complete list (excluded |
res |
A ( |
avg |
If |
A () numeric matrix of cross-temporal reconciled forecasts.
The two-step heuristic reconciliation allows considering non negativity constraints only in the first step. This means that non-negativity is not guaranteed in the final reconciled values.
Di Fonzo, T. and Girolimetto, D. (2023), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Kourentzes, N. and Athanasopoulos, G. (2019), Cross-temporal coherent forecasts for Australian tourism, Annals of Tourism Research, 75, 393-409. doi:10.1016/j.annals.2019.02.001
Cross-temporal framework:
ctboot()
,
ctbu()
,
ctcov()
,
ctlcc()
,
ctmo()
,
ctrec()
,
cttd()
,
cttools()
,
iterec()
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (3 x 70) in-sample residuals matrix (simulated) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation rtcs <- tcsrec(base = base, cslist = list(agg_mat = A, comb = "shr"), telist = list(agg_order = m, comb = "wlsv"), res = res) rcst <- tcsrec(base = base, cslist = list(agg_mat = A, comb = "shr"), telist = list(agg_order = m, comb = "wlsv"), res = res)
set.seed(123) # (3 x 7) base forecasts matrix (simulated), Z = X + Y and m = 4 base <- rbind(rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4))), rnorm(7, rep(c(10, 5, 2.5), c(1, 2, 4)))) # (3 x 70) in-sample residuals matrix (simulated) res <- rbind(rnorm(70), rnorm(70), rnorm(70)) A <- t(c(1,1)) # Aggregation matrix for Z = X + Y m <- 4 # from quarterly to annual temporal aggregation rtcs <- tcsrec(base = base, cslist = list(agg_mat = A, comb = "shr"), telist = list(agg_order = m, comb = "wlsv"), res = res) rcst <- tcsrec(base = base, cslist = list(agg_mat = A, comb = "shr"), telist = list(agg_order = m, comb = "wlsv"), res = res)
Joint block bootstrap for generating probabilistic base forecasts that take into account the correlation between different temporal aggregation orders (Girolimetto et al. 2023).
teboot(model_list, boot_size, agg_order, block_size = 1, seed = NULL)
teboot(model_list, boot_size, agg_order, block_size = 1, seed = NULL)
model_list |
A list of all the |
boot_size |
The number of bootstrap replicates. |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
block_size |
Block size of the bootstrap, which is typically equivalent to the forecast horizon for the most temporally aggregated series. |
seed |
An integer seed. |
A list with two elements: the seed used to sample the errors and
a () matrix.
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2023), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40(3), 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Bootstrap samples:
csboot()
,
ctboot()
Temporal framework:
tebu()
,
tecov()
,
telcc()
,
temo()
,
terec()
,
tetd()
,
tetools()
Temporal bottom-up reconciled forecasts at any temporal aggregation level are computed by
appropriate aggregation of the high-frequency base forecasts, :
where is the temporal structural matrix.
tebu(base, agg_order, tew = "sum", sntz = FALSE)
tebu(base, agg_order, tew = "sum", sntz = FALSE)
base |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
sntz |
If |
A () numeric vector of temporal reconciled forecasts.
Bottom-up reconciliation:
csbu()
,
ctbu()
Temporal framework:
teboot()
,
tecov()
,
telcc()
,
temo()
,
terec()
,
tetd()
,
tetools()
set.seed(123) # (4 x 1) high frequency base forecasts vector (simulated), # agg_order = 4 (annual-quarterly) hfts <- rnorm(4, 5) reco <- tebu(base = hfts, agg_order = 4) # Non negative reconciliation hfts[4] <- -hfts[4] # Making negative one of the quarterly base forecasts nnreco <- tebu(base = hfts, agg_order = 4, sntz = TRUE)
set.seed(123) # (4 x 1) high frequency base forecasts vector (simulated), # agg_order = 4 (annual-quarterly) hfts <- rnorm(4, 5) reco <- tebu(base = hfts, agg_order = 4) # Non negative reconciliation hfts[4] <- -hfts[4] # Making negative one of the quarterly base forecasts nnreco <- tebu(base = hfts, agg_order = 4, sntz = TRUE)
This function provides an approximation of the temporal base forecasts errors covariance matrix using different reconciliation methods (see Di Fonzo and Girolimetto, 2023).
tecov(comb, agg_order = NULL, res = NULL, tew = "sum", mse = TRUE, shrink_fun = shrink_estim, ...)
tecov(comb, agg_order = NULL, res = NULL, tew = "sum", mse = TRUE, shrink_fun = shrink_estim, ...)
comb |
A string specifying the reconciliation method.
|
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
res |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
mse |
If |
shrink_fun |
Shrinkage function of the covariance matrix, shrink_estim (default) |
... |
Not used. |
A () symmetric matrix.
Di Fonzo, T. and Girolimetto, D. (2023), Cross-temporal forecast reconciliation: Optimal combination method and heuristic alternatives, International Journal of Forecasting, 39, 1, 39-57. doi:10.1016/j.ijforecast.2021.08.004
Temporal framework:
teboot()
,
tebu()
,
telcc()
,
temo()
,
terec()
,
tetd()
,
tetools()
# (7 x 70) in-sample residuals matrix (simulated), agg_order = 4 res <- rnorm(70) cov1 <- tecov("ols", agg_order = 4) # OLS methods cov2 <- tecov("str", agg_order = 4) # STRC methods cov3 <- tecov("wlsv", agg_order = 4, res = res) # WLSv methods cov4 <- tecov("wlsh", agg_order = 4, res = res) # WLSh methods cov5 <- tecov("acov", agg_order = 4, res = res) # ACOV methods cov6 <- tecov("strar1", agg_order = 4, res = res) # STRAR1 methods cov7 <- tecov("har1", agg_order = 4, res = res) # HAR1 methods cov8 <- tecov("sar1", agg_order = 4, res = res) # SAR1 methods cov9 <- tecov("shr", agg_order = 4, res = res) # SHR methods cov10 <- tecov("sam", agg_order = 4, res = res) # SAM methods # Custom covariance matrix tecov.ols2 <- function(comb, x) diag(x) tecov(comb = "ols2", x = 7) # == tecov("ols", agg_order = 4)
# (7 x 70) in-sample residuals matrix (simulated), agg_order = 4 res <- rnorm(70) cov1 <- tecov("ols", agg_order = 4) # OLS methods cov2 <- tecov("str", agg_order = 4) # STRC methods cov3 <- tecov("wlsv", agg_order = 4, res = res) # WLSv methods cov4 <- tecov("wlsh", agg_order = 4, res = res) # WLSh methods cov5 <- tecov("acov", agg_order = 4, res = res) # ACOV methods cov6 <- tecov("strar1", agg_order = 4, res = res) # STRAR1 methods cov7 <- tecov("har1", agg_order = 4, res = res) # HAR1 methods cov8 <- tecov("sar1", agg_order = 4, res = res) # SAR1 methods cov9 <- tecov("shr", agg_order = 4, res = res) # SHR methods cov10 <- tecov("sam", agg_order = 4, res = res) # SAM methods # Custom covariance matrix tecov.ols2 <- function(comb, x) diag(x) tecov(comb = "ols2", x = 7) # == tecov("ols", agg_order = 4)
This function implements a forecast reconciliation procedure inspired by the original proposal by Hollyman et al. (2021) for temporal hierarchies. Level conditional coherent reconciled forecasts are conditional on (i.e., constrained by) the base forecasts of a specific upper level in the hierarchy (exogenous constraints). It also allows handling the linear constraints linking the variables endogenously (Di Fonzo and Girolimetto, 2022). The function can calculate Combined Conditional Coherent (CCC) forecasts as simple averages of Level-Conditional Coherent (LCC) and bottom-up reconciled forecasts, with either endogenous or exogenous constraints.
telcc(base, agg_order, comb = "ols", res = NULL, CCC = TRUE, const = "exogenous", hfts = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, ...)
telcc(base, agg_order, comb = "ols", res = NULL, CCC = TRUE, const = "exogenous", hfts = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, ...)
base |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
comb |
A string specifying the reconciliation method. For a complete list, see tecov. |
res |
A ( |
CCC |
A logical value indicating whether the Combined Conditional Coherent reconciled
forecasts reconciliation should include bottom-up forecasts ( |
const |
A string specifying the reconciliation constraints:
|
hfts |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
approach |
A string specifying the approach used to compute the reconciled forecasts. Options include: |
nn |
A string specifying the algorithm to compute non-negative forecasts:
|
settings |
A list of control parameters.
|
... |
Arguments passed on to
|
A () numeric vector of temporal reconciled forecasts.
Byron, R.P. (1978), The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 141, 3, 359-367. doi:10.2307/2344807
Byron, R.P. (1979), Corrigenda: The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 142(3), 405. doi:10.2307/2982515
Di Fonzo, T. and Girolimetto, D. (2024), Forecast combination-based forecast reconciliation: Insights and extensions, International Journal of Forecasting, 40(2), 490–514. doi:10.1016/j.ijforecast.2022.07.001
Di Fonzo, T. and Girolimetto, D. (2023b) Spatio-temporal reconciliation of solar forecasts. Solar Energy 251, 13–29. doi:10.1016/j.solener.2023.01.003
Hyndman, R.J., Ahmed, R.A., Athanasopoulos, G. and Shang, H.L. (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis, 55, 9, 2579-2589. doi:10.1016/j.csda.2011.03.006
Hollyman, R., Petropoulos, F. and Tipping, M.E. (2021), Understanding forecast reconciliation. European Journal of Operational Research, 294, 149–160. doi:10.1016/j.ejor.2021.01.017
Stellato, B., Banjac, G., Goulart, P., Bemporad, A. and Boyd, S. (2020), OSQP: An Operator Splitting solver for Quadratic Programs, Mathematical Programming Computation, 12, 4, 637-672. doi:10.1007/s12532-020-00179-2
Level conditional coherent reconciliation:
cslcc()
,
ctlcc()
Temporal framework:
teboot()
,
tebu()
,
tecov()
,
temo()
,
terec()
,
tetd()
,
tetools()
set.seed(123) # (7 x 1) base forecasts vector (simulated), agg_order = 4 base <- rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))) # (70 x 1) in-sample residuals vector (simulated) res <- rnorm(70) # (4 x 1) Naive high frequency base forecasts vector: all forecasts are set equal to 2.5 naive <- rep(2.5, 4) ## EXOGENOUS CONSTRAINTS # Level Conditional Coherent (LCC) reconciled forecasts exo_LC <- telcc(base = base, agg_order = 4, comb = "wlsh", hfts = naive, res = res, nodes = "auto", CCC = FALSE) # Combined Conditional Coherent (CCC) reconciled forecasts exo_CCC <- telcc(base = base, agg_order = 4, comb = "wlsh", hfts = naive, res = res, nodes = "auto", CCC = TRUE) # Results detailed by level: info_exo <- recoinfo(exo_CCC, verbose = FALSE) # info_exo$lcc ## ENDOGENOUS CONSTRAINTS # Level Conditional Coherent (LCC) reconciled forecasts endo_LC <- telcc(base = base, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = FALSE, const = "endogenous") # Combined Conditional Coherent (CCC) reconciled forecasts endo_CCC <- telcc(base = base, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = TRUE, const = "endogenous") # Results detailed by level: info_endo <- recoinfo(endo_CCC, verbose = FALSE) # info_endo$lcc
set.seed(123) # (7 x 1) base forecasts vector (simulated), agg_order = 4 base <- rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))) # (70 x 1) in-sample residuals vector (simulated) res <- rnorm(70) # (4 x 1) Naive high frequency base forecasts vector: all forecasts are set equal to 2.5 naive <- rep(2.5, 4) ## EXOGENOUS CONSTRAINTS # Level Conditional Coherent (LCC) reconciled forecasts exo_LC <- telcc(base = base, agg_order = 4, comb = "wlsh", hfts = naive, res = res, nodes = "auto", CCC = FALSE) # Combined Conditional Coherent (CCC) reconciled forecasts exo_CCC <- telcc(base = base, agg_order = 4, comb = "wlsh", hfts = naive, res = res, nodes = "auto", CCC = TRUE) # Results detailed by level: info_exo <- recoinfo(exo_CCC, verbose = FALSE) # info_exo$lcc ## ENDOGENOUS CONSTRAINTS # Level Conditional Coherent (LCC) reconciled forecasts endo_LC <- telcc(base = base, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = FALSE, const = "endogenous") # Combined Conditional Coherent (CCC) reconciled forecasts endo_CCC <- telcc(base = base, agg_order = 4, comb = "wlsh", res = res, nodes = "auto", CCC = TRUE, const = "endogenous") # Results detailed by level: info_endo <- recoinfo(endo_CCC, verbose = FALSE) # info_endo$lcc
The middle-out forecast reconciliation for temporal hierarchies
combines top-down (tetd) and bottom-up (tebu) methods. Given
the base forecasts of an intermediate temporal aggregation order , it performs
a top-down approach for the aggregation orders ;
a bottom-up approach for the aggregation orders .
temo(base, agg_order, order = max(agg_order), weights, tew = "sum", normalize = TRUE)
temo(base, agg_order, order = max(agg_order), weights, tew = "sum", normalize = TRUE)
base |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
order |
The intermediate fixed aggregation order |
weights |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
normalize |
If |
A () numeric vector of temporal reconciled forecasts.
Middle-out reconciliation:
csmo()
,
ctmo()
Temporal framework:
teboot()
,
tebu()
,
tecov()
,
telcc()
,
terec()
,
tetd()
,
tetools()
set.seed(123) # (6 x 1) base forecasts vector (simulated), forecast horizon = 3 # and intermediate aggregation order k = 2 (max agg order = 4) basek2 <- rnorm(3*2, 5) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- temo(base = basek2, order = 2, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- runif(4*3) recoh <- temo(base = basek2, order = 2, agg_order = 4, weights = h_weights)
set.seed(123) # (6 x 1) base forecasts vector (simulated), forecast horizon = 3 # and intermediate aggregation order k = 2 (max agg order = 4) basek2 <- rnorm(3*2, 5) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- temo(base = basek2, order = 2, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- runif(4*3) recoh <- temo(base = basek2, order = 2, agg_order = 4, weights = h_weights)
This function computes the projection or the mapping matrix
and
, respectively, such that
,
where
is the vector of the reconciled forecasts,
is the vector of the base forecasts,
is the temporal structural matrix, and
.
For further information regarding on the structure of these matrices,
refer to Girolimetto et al. (2023).
teprojmat(agg_order, comb = "ols", res = NULL, mat = "M", tew = "sum", ...)
teprojmat(agg_order, comb = "ols", res = NULL, mat = "M", tew = "sum", ...)
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
comb |
A string specifying the reconciliation method. For a complete list, see tecov. |
res |
A ( |
mat |
A string specifying which matrix to return:
" |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
... |
Arguments passed on to
|
The projection matrix (
mat = "M"
) or
the mapping matrix (
mat = "G"
).
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
tetools()
,
unbalance_hierarchy()
# Temporal framework (annual-quarterly) Mte <- teprojmat(agg_order = 4, comb = "ols") Gte <- teprojmat(agg_order = 4, comb = "ols", mat = "G")
# Temporal framework (annual-quarterly) Mte <- teprojmat(agg_order = 4, comb = "ols") Gte <- teprojmat(agg_order = 4, comb = "ols", mat = "G")
This function performs forecast reconciliation for a single time series using temporal hierarchies (Athanasopoulos et al., 2017, Nystrup et al., 2020). The reconciled forecasts can be computed using either a projection approach (Byron, 1978, 1979) or the equivalent structural approach by Hyndman et al. (2011). Non-negative (Di Fonzo and Girolimetto, 2023) and immutable reconciled forecasts can be considered.
terec(base, agg_order, comb = "ols", res = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, bounds = NULL, immutable = NULL, ...)
terec(base, agg_order, comb = "ols", res = NULL, tew = "sum", approach = "proj", nn = NULL, settings = NULL, bounds = NULL, immutable = NULL, ...)
base |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
comb |
A string specifying the reconciliation method. For a complete list, see tecov. |
res |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
approach |
A string specifying the approach used to compute the reconciled forecasts. Options include: |
nn |
A string specifying the algorithm to compute non-negative forecasts:
|
settings |
A list of control parameters.
|
bounds |
A matrix (see set_bounds) with 4 columns (
|
immutable |
A matrix with 2 columns (
For example, when working with a quarterly time series:
|
... |
Arguments passed on to
|
A () numeric vector of temporal reconciled forecasts.
Athanasopoulos, G., Hyndman, R.J., Kourentzes, N. and Petropoulos, F. (2017), Forecasting with Temporal Hierarchies, European Journal of Operational Research, 262, 1, 60-74. doi:10.1016/j.ejor.2017.02.046
Byron, R.P. (1978), The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 141, 3, 359-367. doi:10.2307/2344807
Byron, R.P. (1979), Corrigenda: The estimation of large social account matrices, Journal of the Royal Statistical Society, Series A, 142(3), 405. doi:10.2307/2982515
Di Fonzo, T. and Girolimetto, D. (2023), Spatio-temporal reconciliation of solar forecasts, Solar Energy, 251, 13–29. doi:10.1016/j.solener.2023.01.003
Hyndman, R.J., Ahmed, R.A., Athanasopoulos, G. and Shang, H.L. (2011), Optimal combination forecasts for hierarchical time series, Computational Statistics & Data Analysis, 55, 9, 2579-2589. doi:10.1016/j.csda.2011.03.006
Nystrup, P., Lindström, E., Pinson, P. and Madsen, H. (2020), Temporal hierarchies with autocorrelation for load forecasting, European Journal of Operational Research, 280, 1, 876-888. doi:10.1016/j.ejor.2019.07.061
Stellato, B., Banjac, G., Goulart, P., Bemporad, A. and Boyd, S. (2020), OSQP: An Operator Splitting solver for Quadratic Programs, Mathematical Programming Computation, 12, 4, 637-672. doi:10.1007/s12532-020-00179-2
Regression-based reconciliation:
csrec()
,
ctrec()
Temporal framework:
teboot()
,
tebu()
,
tecov()
,
telcc()
,
temo()
,
tetd()
,
tetools()
set.seed(123) # (7 x 1) base forecasts vector (simulated), m = 4 base <- rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))) # (70 x 1) in-sample residuals vector (simulated) res <- rnorm(70) m <- 4 # from quarterly to annual temporal aggregation reco <- terec(base = base, agg_order = m, comb = "wlsv", res = res) # Immutable reconciled forecast # E.g. fix all the quarterly forecasts imm_q <- expand.grid(k = 1, j = 1:4) immreco <- terec(base = base, agg_order = m, comb = "wlsv", res = res, immutable = imm_q) # Non negative reconciliation base[7] <- -base[7] # Making negative one of the quarterly base forecasts nnreco <- terec(base = base, agg_order = m, comb = "wlsv", res = res, nn = "osqp") recoinfo(nnreco, verbose = FALSE)$info
set.seed(123) # (7 x 1) base forecasts vector (simulated), m = 4 base <- rnorm(7, rep(c(20, 10, 5), c(1, 2, 4))) # (70 x 1) in-sample residuals vector (simulated) res <- rnorm(70) m <- 4 # from quarterly to annual temporal aggregation reco <- terec(base = base, agg_order = m, comb = "wlsv", res = res) # Immutable reconciled forecast # E.g. fix all the quarterly forecasts imm_q <- expand.grid(k = 1, j = 1:4) immreco <- terec(base = base, agg_order = m, comb = "wlsv", res = res, immutable = imm_q) # Non negative reconciliation base[7] <- -base[7] # Making negative one of the quarterly base forecasts nnreco <- terec(base = base, agg_order = m, comb = "wlsv", res = res, nn = "osqp") recoinfo(nnreco, verbose = FALSE)$info
Top-down forecast reconciliation for a univariate time series, where the forecast of the most aggregated temporal level is disaggregated according to a proportional scheme (weights). Besides fulfilling any aggregation constraint, the top-down reconciled forecasts should respect two main properties:
the top-level value remains unchanged;
all the bottom time series reconciled forecasts are non-negative.
tetd(base, agg_order, weights, tew = "sum", normalize = TRUE)
tetd(base, agg_order, weights, tew = "sum", normalize = TRUE)
base |
A ( |
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
weights |
A ( |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
normalize |
If |
A () numeric vector of temporal reconciled forecasts.
Top-down reconciliation:
cstd()
,
cttd()
Temporal framework:
teboot()
,
tebu()
,
tecov()
,
telcc()
,
temo()
,
terec()
,
tetools()
set.seed(123) # (2 x 1) top base forecasts vector (simulated), forecast horizon = 2 topf <- rnorm(2, 10) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- tetd(base = topf, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- runif(4*2) recoh <- tetd(base = topf, agg_order = 4, weights = h_weights)
set.seed(123) # (2 x 1) top base forecasts vector (simulated), forecast horizon = 2 topf <- rnorm(2, 10) # Same weights for different forecast horizons fix_weights <- runif(4) reco <- tetd(base = topf, agg_order = 4, weights = fix_weights) # Different weights for different forecast horizons h_weights <- runif(4*2) recoh <- tetd(base = topf, agg_order = 4, weights = h_weights)
Some useful tools for forecast reconciliation through temporal hierarchies.
tetools(agg_order, fh = 1, tew = "sum", sparse = TRUE)
tetools(agg_order, fh = 1, tew = "sum", sparse = TRUE)
agg_order |
Highest available sampling frequency per seasonal cycle (max. order
of temporal aggregation, |
fh |
Forecast horizon for the lowest frequency (most temporally aggregated)
time series (default is |
tew |
A string specifying the type of temporal aggregation. Options include:
" |
sparse |
Option to return sparse matrices (default is |
A list with five elements:
dim |
A vector containing information about the maximum aggregation order
( |
set |
The vector of the temporal aggregation orders (in decreasing order). |
agg_mat |
The temporal linear combination or aggregation matrix. |
strc_mat |
The temporal structural matrix. |
cons_mat |
The temporal zero constraints matrix. |
Temporal framework:
teboot()
,
tebu()
,
tecov()
,
telcc()
,
temo()
,
terec()
,
tetd()
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
unbalance_hierarchy()
# Temporal framework (quarterly data) obj <- tetools(agg_order = 4, sparse = FALSE)
# Temporal framework (quarterly data) obj <- tetools(agg_order = 4, sparse = FALSE)
A hierarchy with upper levels is said to be balanced if each variable at level
has at least one child at level
. When this doesn't hold, the
hierarchy is unbalanced.
This function transforms an aggregation matrix of a balanced hierarchy
into an aggregation matrix of an unbalanced one, by removing possible duplicated series.
unbalance_hierarchy(agg_mat, more_info = FALSE, sparse = TRUE)
unbalance_hierarchy(agg_mat, more_info = FALSE, sparse = TRUE)
agg_mat |
A ( |
more_info |
If |
sparse |
Option to return sparse matrices (default is |
A list containing four
elements (more_info = TRUE
):
ubm |
The aggregation matrix of the unbalanced hierarchy. |
agg_mat |
The input matrix. |
idrm |
The identification number of the duplicated variables (row numbers of
the aggregation matrix |
id |
The identification number of each variable in the balanced hierarchy. It may contains duplicated values. |
Utilities:
FoReco2matrix()
,
aggts()
,
balance_hierarchy()
,
commat()
,
csprojmat()
,
cstools()
,
ctprojmat()
,
cttools()
,
df2aggmat()
,
lcmat()
,
recoinfo()
,
res2matrix()
,
set_bounds()
,
shrink_estim()
,
shrink_oasd()
,
teprojmat()
,
tetools()
# Balanced -> Unbalanced # T T # |-------| |-------| # A B A | # |---| | |---| | # AA AB BA AA AB BA A <- matrix(c(1, 1, 1, 1, 1, 0, 0, 0, 1), 3, byrow = TRUE) obj <- unbalance_hierarchy(agg_mat = A) obj
# Balanced -> Unbalanced # T T # |-------| |-------| # A B A | # |---| | |---| | # AA AB BA AA AB BA A <- matrix(c(1, 1, 1, 1, 1, 0, 0, 0, 1), 3, byrow = TRUE) obj <- unbalance_hierarchy(agg_mat = A) obj
The Australian Tourism Demand dataset (Wickramasuriya et al. 2019) measures the number of nights Australians spent away from home. It includes 228 monthly observations of Visitor Nights (VNs) from January 1998 to December 2016, and has a cross-sectional grouped structure based on a geographic hierarchy crossed by purpose of travel. The geographic hierarchy comprises 7 states, 27 zones, and 76 regions, for a total of 111 nested geographic divisions. Six of these zones are each formed by a single region, resulting in 105 unique nodes in the hierarchy. The purpose of travel comprises four categories: holiday, visiting friends and relatives, business, and other. To avoid redundancies (Girolimetto et al. 2023), 24 nodes (6 zones are formed by a single region) are not considered, resulting in an unbalanced hierarchy of 525 (304 bottom and 221 upper time series) unique nodes instead of the theoretical 555 with duplicated nodes.
# 525 time series of the Australian Tourism Demand dataset vndata # aggregation matrix vnaggmat
# 525 time series of the Australian Tourism Demand dataset vndata # aggregation matrix vnaggmat
vndata
is a
ts
object, corresponding to
525 time series of the Australian Tourism Demand dataset (1998:01-2016:12).
vnaggmat
is the aggregation matrix.
https://robjhyndman.com/publications/mint/
Girolimetto, D., Athanasopoulos, G., Di Fonzo, T. and Hyndman, R.J. (2024), Cross-temporal probabilistic forecast reconciliation: Methodological and practical issues. International Journal of Forecasting, 40, 3, 1134-1151. doi:10.1016/j.ijforecast.2023.10.003
Wickramasuriya, S.L., Athanasopoulos, G. and Hyndman, R.J. (2019), Optimal forecast reconciliation for hierarchical and grouped time series through trace minimization, Journal of the American Statistical Association, 114, 526, 804-819. doi:10.1080/01621459.2018.1448825