Skip to content

Commit 17cd469

Browse files
Merge pull request #8 from Techtonique/dov070
Do version 0.7.0
2 parents e83209b + 9927a06 commit 17cd469

24 files changed

Lines changed: 1730 additions & 217 deletions

DESCRIPTION

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
Package: ahead
22
Type: Package
33
Title: Time Series Forecasting
4-
Version: 0.6.2
5-
Date: 2023-08-08
4+
Version: 0.7.0
5+
Date: 2023-08-23
66
Author: T. Moudiki
77
Maintainer: T. Moudiki <thierry.moudiki@gmail.com>
88
Description: Univariate and multivariate time series forecasting.
99
License: BSD_3_clause Clear + file LICENSE
10-
Imports: Rcpp (>= 1.0.6), forecast, vars, randtoolbox, fGarch
10+
Imports: Rcpp (>= 1.0.6)
11+
Depends: forecast, vars, randtoolbox, fGarch, VineCopula
1112
LinkingTo: Rcpp
1213
RoxygenNote: 7.2.2
1314
Encoding: UTF-8

NAMESPACE

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
useDynLib(ahead, .registration=TRUE)
22
S3method(plot, mtsforecast)
3+
S3method(plot, pairs)
34
S3method(predict, ridge)
45
importFrom(Rcpp, evalCpp)
5-
importFrom("stats", "as.ts", "complete.cases", "end", "frequency",
6-
"median", "predict", "predict.lm", "qnorm", "quantile",
7-
"residuals", "rnorm", "rt", "sd", "start", "ts", "tsp",
8-
"tsp<-")
6+
importFrom(VineCopula, C2RVine)
7+
importFrom(VineCopula, D2RVine)
8+
importFrom(VineCopula, RVineSim)
9+
importFrom(VineCopula, RVineStructureSelect)
10+
importFrom(forecast, ets)
11+
importFrom(forecast, auto.arima)
12+
importFrom(forecast, thetaf)
13+
importFrom(vars, VAR)
14+
importFrom(randtoolbox, sobol)
15+
importFrom(randtoolbox, halton)
16+
importFrom(fGarch, garchFit)
17+
importFrom("grDevices", "colorRampPalette")
18+
importFrom("graphics", "abline", "par", "points", "polygon")
19+
importFrom("stats", "t.test")
20+
importFrom("stats", "as.ts", "complete.cases", "ecdf", "end", "frequency",
21+
"lag", "median", "predict", "predict.lm", "qnorm", "quantile",
22+
"residuals", "rnorm", "rt", "sd", "setNames", "start",
23+
"ts", "tsp", "tsp<-")
924
importFrom("utils", "tail")
1025
importFrom("graphics", "lines")
26+
importFrom("graphics", "matplot")
1127
importFrom("stats", "is.ts", "runif", "time")
1228
export("armagarchf")
1329
export("basicf")
@@ -17,3 +33,5 @@ export("loessf")
1733
export("ridge2f")
1834
export("ridge")
1935
export("varf")
36+
export("getreturns")
37+
export("getsimulations")

NEWS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# version 0.7.0
2+
3+
- moving block bootstrap in `ridge2f`, `basicf` and `loessf`, in addition to circular block bootstrap from 0.6.2
4+
- adjust R-Vine copulas on residuals for `ridge2f` simulation
5+
- new plots for simulations see (new) vignettes
6+
- split conformal prediction intervals (**very very experimental** and basic right now, too conservative)
7+
- `Depends` and selective `Imports` (beneficial to Python and rpy2 for installation time?)
8+
- `getsimulations` extracts simulations from a given time series (from `ridge2f` and `basicf`)
9+
- `getreturns` extracts returns/log-returns from multivariate time series
10+
- `splitts` splits time series using a proportion of data
11+
112
# version 0.6.2
213

314
- Add Block Bootstrap to `ridge2f`

R/RcppExports.R

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ embedc <- function(x, lags) {
55
.Call(`_ahead_embedc`, x, lags)
66
}
77

8-
rcpp_hello_world <- function() {
9-
.Call(`_ahead_rcpp_hello_world`)
10-
}
11-
128
forecast_innovs_loop_cpp <- function(eps, rts, eps_prev, omega, alpha, beta, df, h) {
139
.Call(`_ahead_forecast_innovs_loop_cpp`, eps, rts, eps_prev, omega, alpha, beta, df, h)
1410
}

R/basic.R

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
#' @param h Forecasting horizon
77
#' @param level Confidence level for prediction intervals
88
#' @param method forecasting method, either "mean", "median", or random walk ("rw")
9-
#' @param type_pi type of prediction interval currently, "gaussian" or "bootstrap"
10-
#' @param block_length length of block for circular block bootstrap (\code{type_pi == 'blockbootstrap'})
9+
#' @param type_pi type of prediction interval currently, "gaussian", "bootstrap",
10+
#' "blockbootstrap" or "movingblockbootstrap"
11+
#' @param block_length length of block for (circular) "blockbootstrap" or "movingblockbootstrap"
1112
#' @param seed reproducibility seed for \code{type_pi == 'bootstrap'}
1213
#' @param B Number of bootstrap replications for \code{type_pi == 'bootstrap'}
1314
#'
@@ -52,11 +53,24 @@
5253
#' plot(res5, "Quotes")
5354
#' plot(res5, "TV.advert")
5455
#'
56+
#'
57+
#' # moving block bootstrap
58+
#' res6 <- ahead::basicf(fpp::insurance, h=10,
59+
#' type_pi = "movingblockbootstrap", B=10,
60+
#' block_length = 4, method = "rw")
61+
#'
62+
#' par(mfrow=c(1, 2))
63+
#' plot(res6, "Quotes")
64+
#' plot(res6, "TV.advert")
65+
#'
5566
basicf <- function(y,
5667
h = 5,
5768
level = 95,
5869
method = c("mean", "median", "rw"),
59-
type_pi = c("gaussian", "bootstrap", "blockbootstrap"),
70+
type_pi = c("gaussian",
71+
"bootstrap",
72+
"blockbootstrap",
73+
"movingblockbootstrap"),
6074
block_length = NULL,
6175
seed = 1,
6276
B = 100)
@@ -90,6 +104,7 @@ basicf <- function(y,
90104
fits <- ts(t(replicate(n = n_inputs, expr = point_forecast)),
91105
start = start_x, frequency = freq_x)
92106
resids <- y - fits
107+
colnames(resids) <- colnames(y)
93108

94109
# out-of-sample
95110
fcast <- ts(t(replicate(n = h, expr = point_forecast)),
@@ -117,24 +132,45 @@ basicf <- function(y,
117132
return(structure(out, class = "mtsforecast"))
118133
}
119134

120-
if (type_pi %in% c("bootstrap", "blockbootstrap"))
135+
if(type_pi %in% c("blockbootstrap", "movingblockbootstrap"))
136+
{
137+
if (nrow(y) <= 2 * freq_x)
138+
freq_x <- 1L
139+
140+
if (is.null(block_length)) {
141+
block_length <- ifelse(freq_x > 1, 2 * freq_x, min(8, floor(nrow(y) / 2)))
142+
}
143+
}
144+
145+
if (type_pi %in% c("bootstrap", "blockbootstrap", "movingblockbootstrap"))
121146
{
122147
sims <- vector("list", length = B)
123148
for (i in 1:B)
124149
{
125150
# sampling from the residuals
126151
set.seed(seed + i*100 + nchar(method))
127152

128-
idx <- switch(type_pi,
129-
bootstrap = sample.int(n = nrow(resids),
130-
size = h, replace = TRUE),
131-
blockbootstrap = mbb(
132-
r = resids,
133-
n = h,
134-
b = block_length,
135-
return_indices = TRUE,
136-
seed = seed + i*100 + nchar(method)
137-
)
153+
idx <- switch(
154+
type_pi,
155+
bootstrap = sample.int(
156+
n = nrow(resids),
157+
size = h,
158+
replace = TRUE
159+
),
160+
blockbootstrap = mbb(
161+
r = resids,
162+
n = h,
163+
b = block_length,
164+
return_indices = TRUE,
165+
seed = seed + i * 100 + nchar(method)
166+
),
167+
movingblockbootstrap = mbb2(
168+
r = resids,
169+
n = h,
170+
b = block_length,
171+
return_indices = TRUE,
172+
seed = seed + i * 100 + nchar(method)
173+
)
138174
)
139175

140176
sims[[i]] <- ts(as.matrix(fcast) + as.matrix(resids[idx, ]),

R/getreturns.R

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#' Calculate returns or log-returns for multivariate time series
2+
#'
3+
#' @param x Multivariate time series
4+
#' @param type Type of return: basic return ("basic") or log-return ("log")
5+
#'
6+
#' @return The returns
7+
#' @export
8+
#'
9+
#' @examples
10+
#'
11+
#' returns <- getreturns(EuStockMarkets)
12+
#' log_returns <- getreturns(EuStockMarkets,
13+
#' type = "log")
14+
#'
15+
#' par(mfrow=c(1, 3))
16+
#' matplot(EuStockMarkets, type = 'l', main = "Closing Prices of \n European stocks (1991-1998)",
17+
#' xlab = "time")
18+
#' matplot(returns, type = 'l', main = "Returns", xlab = "time")
19+
#' matplot(log_returns, type = 'l', main = "Log-returns", xlab = "time")
20+
#'
21+
getreturns <- function(x, type = c("basic", "log"))
22+
{
23+
# ?rlang::abort #?
24+
stopifnot(is.ts(x))
25+
names_x <- colnames(x)
26+
type <- match.arg(type)
27+
28+
if (identical(type, "basic"))
29+
{
30+
res <- diff(x)/lag(x)
31+
colnames(res) <- names_x
32+
return (res)
33+
}
34+
res <- diff(log(x))
35+
colnames(res) <- names_x
36+
return (res)
37+
}

R/getsimulations.R

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#' Obtain simulations (when relevant) from a selected time series
2+
#'
3+
#' @param obj result from ridge2f (multivariate time series forecast with simulations)
4+
#' @param selected_series name of the time series selected
5+
#' @param transpose return a transposed time series
6+
#'
7+
#' @export
8+
#'
9+
#' @examples
10+
#'
11+
#' require(fpp)
12+
#'
13+
#' obj <- ahead::ridge2f(fpp::insurance, h = 7,
14+
#' type_pi = "bootstrap", B = 5)
15+
#' print(getsimulations(obj, selected_series = "TV.advert"))
16+
#' print(getsimulations(obj, selected_series = "Quotes"))
17+
#' print(getsimulations(obj, selected_series = "TV.advert", transpose = TRUE))
18+
#' print(getsimulations(obj, selected_series = "Quotes", transpose = TRUE))
19+
#'
20+
getsimulations <- function(obj, selected_series, transpose = FALSE)
21+
{
22+
n_sims <- length(obj$sims)
23+
start_preds <- stats::start(obj$mean)
24+
frequency_preds <- stats::frequency(obj$mean)
25+
selected_series_sims <- sapply(1:n_sims,
26+
FUN = function(i) obj$sims[[i]][, selected_series])
27+
28+
temp <- ts(selected_series_sims,
29+
start = start_preds,
30+
frequency = frequency_preds)
31+
32+
if (transpose)
33+
{
34+
temp <- t(temp)
35+
colnames(temp) <- paste0("date", 1:nrow(obj$mean))
36+
return(list(series = temp,
37+
name = selected_series))
38+
} else {
39+
return(list(series = temp,
40+
name = selected_series))
41+
}
42+
}

R/loess.R

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#' @param level Confidence level for prediction intervals
88
#' @param span the parameter which controls the degree of smoothing
99
#' @param degree the degree of the polynomials to be used, normally 1 or 2. (Degree 0 is also allowed, but see \code{stats::loess})
10-
#' @param type_pi Type of prediction interval currently (independent) "bootstrap" or (circular) "blockbootstrap"
10+
#' @param type_pi Type of prediction interval currently (independent) "bootstrap", (circular) "blockbootstrap", or "movingblockbootstrap"
1111
#' @param b block length for circular block bootstrap
1212
#' @param B number of bootstrap replications
1313
#' @param type_aggregation Type of aggregation, ONLY for bootstrapping; either "mean" or "median"
@@ -28,20 +28,29 @@
2828
#'
2929
#' @examples
3030
#'
31+
#' par(mfrow = c(3, 1))
32+
#'
3133
#' plot(loessf(Nile, h=20, level=95, B=10))
3234
#'
35+
#' plot(loessf(Nile, h=20, level=95, B=10,
36+
#' type_pi = "blockbootstrap"))
37+
#'
38+
#' plot(loessf(Nile, h=20, level=95, B=10,
39+
#' type_pi = "movingblockbootstrap"))
40+
#'
3341
loessf <- function(y,
3442
h = 5,
3543
level = 95,
3644
span = 0.75,
3745
degree = 2,
38-
type_pi = c("bootstrap", "blockbootstrap"),
46+
type_pi = c("bootstrap",
47+
"blockbootstrap",
48+
"movingblockbootstrap"),
3949
b = NULL,
4050
B = 250,
4151
type_aggregation = c("mean", "median"),
4252
seed = 123)
4353
{
44-
# adapted from forecast:::bld.mbb.bootstrap ---
4554
freq_y <- frequency(y)
4655
if (length(y) <= 2 * freq_y)
4756
freq_y <- 1L
@@ -100,6 +109,7 @@ loessf <- function(y,
100109
idx <- sample.int(n = length(resids),
101110
size = h,
102111
replace = TRUE)
112+
103113
bootstrapped_residuals <- ts(switch(
104114
type_pi,
105115
bootstrap = matrix(resids, ncol = 1L)[idx,],
@@ -111,9 +121,17 @@ loessf <- function(y,
111121
seed = 100 * i + 3,
112122
return_indices =
113123
FALSE
114-
)
115-
)
116-
),
124+
)),
125+
movingblockbootstrap = drop(
126+
mbb2(
127+
r = matrix(resids, ncol = 1L),
128+
n = h,
129+
b = b,
130+
seed = 100 * i + 3,
131+
return_indices =
132+
FALSE
133+
))
134+
),
117135
start = start_preds,
118136
frequency = freq_y)
119137

0 commit comments

Comments
 (0)