├── .Rbuildignore ├── .github └── FUNDING.yml ├── .gitignore ├── CONTRIBUTING.md ├── DESCRIPTION ├── LICENSE ├── Makefile ├── NAMESPACE ├── NAMESPACE_backup ├── NEWS.md ├── R ├── RcppExports.R ├── VAR.R ├── armagarch.R ├── auto_arima.R ├── basic.R ├── caretfitpredict.R ├── comb_GLMNET.R ├── comb_OLS.R ├── comb_Ridge.R ├── compute_attention.R ├── conformalize.R ├── dynrm.R ├── eat.R ├── fitforecast.R ├── genforecast.R ├── getreturns.R ├── getsimulations.R ├── glmtheta.R ├── krrf.R ├── loess.R ├── loocvridge2.R ├── ml.R ├── mlarch.R ├── plot.R ├── plot.foreccomb_res.R ├── predict.foreccomb_res.R ├── ridge.R ├── ridge2.R ├── sampling.R ├── splitts.R ├── summary.foreccomb_res.R ├── utils.R ├── utils_benchmarks.R └── zzz.R ├── README.md ├── biblio.bib ├── man ├── .DS_Store ├── armagarchf.Rd ├── basicf.Rd ├── comb_GLMNET.Rd ├── comb_OLS.Rd ├── comb_Ridge.Rd ├── computeattention.Rd ├── conformalize.Rd ├── createtrendseason.Rd ├── direct_sampling.Rd ├── dynrmf.Rd ├── eatf.Rd ├── fit_func.Rd ├── fitforecast.Rd ├── genericforecast.Rd ├── get_error.Rd ├── getreturns.Rd ├── getsimulations.Rd ├── glmthetaf.Rd ├── loessf.Rd ├── loocvridge2f.Rd ├── mlarchf.Rd ├── mlf.Rd ├── plot.foreccomb_res.Rd ├── plot.mtsforecast.Rd ├── predict.foreccomb_res.Rd ├── predict_func.Rd ├── ridge2f.Rd ├── rmultivariate.Rd ├── splitts.Rd ├── summary.foreccomb_res.Rd └── varf.Rd ├── src ├── RcppExports.cpp ├── RcppExports.o ├── ahead.so ├── compute_attention.cpp ├── compute_attention.o ├── embedc.cpp ├── embedc.o ├── ml_forecast.cpp ├── ml_forecast.o ├── utils_armagarch.cpp ├── utils_armagarch.o ├── utils_matrix.cpp └── utils_matrix.o ├── tests ├── testthat.R └── testthat │ ├── Rplots.pdf │ ├── test_armagarchf.R │ ├── test_basicf.R │ ├── test_dynrmf.R │ ├── test_eat.R │ ├── test_loessf.R │ ├── test_ml.R │ ├── test_ridge2f.R │ └── test_varf.R └── vignettes ├── .gitignore ├── ahead-loess-forecasting.Rmd ├── ahead-neutralize.Rmd ├── ahead-plotting-functions.Rmd ├── ahead-ridge2-conformal.Rmd ├── ahead-ridge2-prediction-intervals.Rmd ├── ahead-univariate-season.Rmd ├── ahead-vignette.Rmd ├── caretfitpredict.Rmd ├── comb_OLS.Rmd ├── comb_OLS2.Rmd ├── conformal-ml.Rmd ├── fitforecastbench.Rmd ├── generic-conformal.Rmd ├── glmthetaf-attention-conformal.Rmd ├── glmthetaf-attention.Rmd ├── glmthetaf-ridge-attention.Rmd ├── glmthetaf.Rmd └── mlarch.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: Techtonique -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # History files 2 | .Rhistory 3 | .Rapp.history 4 | 5 | # Session Data files 6 | .RData 7 | .RDataTmp 8 | 9 | # User-specific files 10 | .Ruserdata 11 | 12 | # Example code in package build process 13 | *-Ex.R 14 | 15 | # Output files from R CMD build 16 | /*.tar.gz 17 | 18 | # Output files from R CMD check 19 | /*.Rcheck/ 20 | 21 | # RStudio files 22 | .Rproj.user/ 23 | 24 | # produced vignettes 25 | vignettes/*.html 26 | vignettes/*.pdf 27 | 28 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 29 | .httr-oauth 30 | 31 | # knitr and R markdown default cache directories 32 | *_cache/ 33 | /cache/ 34 | 35 | # Temporary files created by R markdown 36 | *.utf8.md 37 | *.knit.md 38 | 39 | # R Environment Variables 40 | .Renviron 41 | 42 | # pkgdown site 43 | docs/ 44 | 45 | # translation temp files 46 | po/*~ 47 | 48 | # RStudio Connect folder 49 | rsconnect/ 50 | 51 | .DS_Store -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # `ahead` Code of Conduct 2 | 3 | ## 1. Purpose 4 | 5 | A primary goal of this project is to be __inclusive__ to the largest number of contributors, and most importantly __with the most varied and diverse backgrounds possible__. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion, or lack of religion thereof. 6 | 7 | This code of conduct outlines our expectations for all those who participate to the project, as well as the consequences for unacceptable behavior. 8 | 9 | We invite all those who participate in, to help us create safe and positive experiences for everyone. 10 | 11 | ## 2. Open [Source/Culture/Tech] Citizenship 12 | 13 | A supplemental goal of this Code of Conduct is to encourage participants to recognize and strengthen the relationships between our actions and their effects on other participants. 14 | 15 | Communities mirror the societies in which they exist, and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. 16 | 17 | ## 3. Expected Behavior 18 | 19 | The following behaviors are expected and requested of all contributors: 20 | 21 | * __Attempt collaboration before conflict__. 22 | * Participate in an __authentic__ and active way. In doing so, you contribute to the health and longevity of this project. 23 | * Exercise consideration and respect in your speech and actions. 24 | * Refrain from demeaning, discriminatory, or harassing behavior and speech. 25 | * Be mindful of your surroundings and of your fellow participants. 26 | 27 | ## 4. Unacceptable Behavior 28 | 29 | The following behaviors are considered harassment and are unacceptable: 30 | 31 | * Violence, threats of violence or violent language directed against another person. 32 | * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. 33 | * Posting or displaying sexually explicit or violent material. 34 | * Posting or threatening to post other people's personally identifying information ("doxing"). 35 | * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. 36 | * Inappropriate photography or recording. 37 | * Unwelcome sexual attention. This includes, sexualized comments or jokes. 38 | * Deliberate intimidation, stalking or following (online or in person). 39 | * Advocating for, or encouraging, any of the above behavior. 40 | 41 | ## 5. Consequences of Unacceptable Behavior 42 | 43 | Unacceptable behavior from any contributor will not be tolerated. 44 | 45 | Anyone asked to stop unacceptable behavior is expected to comply immediately. 46 | 47 | If a contributor engages in unacceptable behavior, appropriate action will be taken, up to and including a temporary ban or permanent expulsion without warning. 48 | 49 | ## 6. Scope 50 | 51 | We expect all contributors to abide by this Code of Conduct in all venues, online and in-person. 52 | 53 | ## 7. Contact info 54 | 55 | thierry.moudiki AT gmail.com 56 | 57 | ## 8. License and attribution 58 | 59 | Portions of text derived from the [Citizen Code of Conduct](http://citizencodeofconduct.org/). 60 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ahead 2 | Type: Package 3 | Title: Time Series Forecasting with uncertainty quantification 4 | Version: 0.19.1 5 | Date: 2025-06-03 6 | Author: T. Moudiki 7 | Maintainer: T. Moudiki 8 | Description: Univariate and multivariate time series forecasting with uncertainty quantification. 9 | License: BSD_3_clause Clear + file LICENSE 10 | Imports: 11 | Rcpp (>= 1.0.6), 12 | misc, 13 | foreach, 14 | snow, 15 | forecast (>= 8.0), 16 | ggplot2 (>= 3.0.0), 17 | tseries, 18 | randtoolbox (>= 1.17) 19 | Depends: R (>= 3.5.0) 20 | Suggests: 21 | caret, 22 | dfoptim, 23 | doSNOW, 24 | knitr, 25 | rmarkdown, 26 | testthat, 27 | ForecastComb, 28 | fpp, 29 | glmnet, 30 | e1071, 31 | gam, 32 | quantreg, 33 | randomForest, 34 | vars, 35 | roxygen2 36 | LinkingTo: Rcpp 37 | RoxygenNote: 7.3.2 38 | Encoding: UTF-8 39 | Roxygen: list(markdown = TRUE) 40 | VignetteBuilder: knitr 41 | Remotes: thierrymoudiki/misc 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Clear BSD License 2 | 3 | Copyright (c) [2021] [Thierry Moudiki] 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted (subject to the limitations in the disclaimer 8 | below) provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from this 19 | software without specific prior written permission. 20 | 21 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY 22 | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 23 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 30 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build buildsite check clean cleanvars coverage docs getwd initialize install installcranpkg installgithubpkg installedpkgs load removepkg render setwd start test usegit 2 | .DEFAULT_GOAL := help 3 | 4 | # The directory where R files are stored 5 | R_DIR = ./R 6 | 7 | define BROWSER_PYSCRIPT 8 | import os, webbrowser, sys 9 | from urllib.request import pathname2url 10 | 11 | # The input is expected to be the full HTML filename 12 | filename = sys.argv[1] 13 | filepath = os.path.abspath(os.path.join("./vignettes/", filename)) 14 | webbrowser.open("file://" + pathname2url(filepath)) 15 | endef 16 | export BROWSER_PYSCRIPT 17 | 18 | define PRINT_HELP_PYSCRIPT 19 | import re, sys 20 | 21 | for line in sys.stdin: 22 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 23 | if match: 24 | target, help = match.groups() 25 | print("%-20s %s" % (target, help)) 26 | endef 27 | export PRINT_HELP_PYSCRIPT 28 | 29 | BROWSER := python3 -c "$$BROWSER_PYSCRIPT" 30 | 31 | build: setwd ## build package 32 | Rscript -e "devtools::build('.')" 33 | 34 | buildsite: setwd ## create a website for the package 35 | Rscript -e "pkgdown::build_site('.')" 36 | cp -rf docs/* ~/Documents/Pro_Website/Techtonique.github.io/ahead/ 37 | 38 | check: clean setwd ## check package 39 | @read -p "Enter options (e.g: --no-tests --no-examples) or leave empty: " pckgcheckoptions; \ 40 | if [ -z "$$pckgcheckoptions" ]; then \ 41 | Rscript -e "try(devtools::check('.'), silent=TRUE)" && exit 0; \ 42 | fi; \ 43 | Rscript -e "try(devtools::check('.', args=base::strsplit('$$pckgcheckoptions', ' ')[[1]]), silent=TRUE)"; 44 | 45 | clean: ## remove all build, and artifacts 46 | rm -f .Rhistory 47 | rm -f *.RData 48 | rm -f *.Rproj 49 | rm -rf .Rproj.user 50 | rm -f src/*.o 51 | rm -f src/*.so 52 | rm -f vignettes/*.html 53 | 54 | cleanvars: setwd ## remove all local variables 55 | @read -p "Do you want to remove all local variables in R? (1-yes, 2-no): " choice; \ 56 | if [ $$choice -eq 1 ]; then \ 57 | echo "Removing all local variables..."; \ 58 | Rscript -e "rm(list=ls())"; \ 59 | else \ 60 | echo "Keeping the variables."; \ 61 | fi 62 | 63 | coverage: ## get test coverage 64 | Rscript -e "devtools::test_coverage('.')" 65 | 66 | create: setwd ## create a new package in current directory 67 | Rscript -e "usethis::create_package(path = getwd(), rstudio = FALSE)" 68 | rm -f .here 69 | 70 | docs: clean setwd ## generate docs 71 | Rscript -e "devtools::document('.')" 72 | 73 | getwd: ## get current directory 74 | Rscript -e "getwd()" 75 | 76 | install: clean setwd docs ## install current package 77 | Rscript -e "try(devtools::install('.'), silent = FALSE)" 78 | @read -p "Start R session? (y/n): " choice; \ 79 | if [ "$$choice" = "y" ]; then \ 80 | $(MAKE) start; \ 81 | fi 82 | 83 | installcranpkg: setwd ## install a package 84 | @read -p "Enter the name of package to be installed: " pckg; \ 85 | if [ -z "$$pckg" ]; then \ 86 | echo "Package name cannot be empty."; \ 87 | exit 1; \ 88 | fi; \ 89 | Rscript -e "utils::install.packages('$$pckg', repos='https://cloud.r-project.org')"; 90 | 91 | installgithubpkg: setwd ## install a package from GitHub ('repository/pkgname') 92 | @read -p "Enter the name of package to be installed ('repository/pkgname'): " pckg; \ 93 | if [ -z "$$pckg" ]; then \ 94 | echo "Package name cannot be empty."; \ 95 | exit 1; \ 96 | fi; \ 97 | Rscript -e "devtools::install_github('$$pckg')"; 98 | 99 | installedpkgs: ## list of installed packages 100 | Rscript -e "utils::installed.packages()[,c(10, 16)]" 101 | 102 | initialize: setwd ## initialize: install packages devtools, usethis, pkgdown and rmarkdown 103 | Rscript -e "utils::install.packages(c('devtools', 'remotes', 'roxygen2', 'usethis', 'pkgdown', 'rmarkdown'), repos='https://cloud.r-project.org')" 104 | 105 | help: ## print menu with all options 106 | @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 107 | 108 | load: clean setwd docs ## load all and restart (when developing the package) 109 | Rscript -e "devtools::load_all('.')" 110 | @read -p "Start R session? (y/n): " choice; \ 111 | if [ "$$choice" = "y" ]; then \ 112 | $(MAKE) start; \ 113 | fi 114 | 115 | removepkg: ## remove package 116 | @read -p "Enter the name of package to be removed: " pckg; \ 117 | if [ -z "$$pckg" ]; then \ 118 | echo "Package name cannot be empty."; \ 119 | exit 1; \ 120 | fi; \ 121 | Rscript -e "utils::remove.packages('$$pckg')"; \ 122 | Rscript -e "base::unlink(paste0(.libPaths()[1], '/$$pckg'), recursive = TRUE, force = TRUE)" 123 | 124 | render: ## run R markdown file in /vignettes, open rendered HTML 125 | @files=$$(ls -1 ./vignettes/*.Rmd | sort); \ 126 | i=0; \ 127 | echo "Available Rmd files:"; \ 128 | for file in $$files; do \ 129 | echo "$$i: $$(basename $$file .Rmd)"; \ 130 | i=$$((i+1)); \ 131 | done; \ 132 | read -p "Enter the number of the Rmd file to render: " filenum; \ 133 | filename=$$(echo $$files | cut -d' ' -f$$((filenum+1))); \ 134 | filename=$$(basename $$filename .Rmd); \ 135 | Rscript -e "rmarkdown::render(paste0('./vignettes/', '$$filename', '.Rmd'))"; \ 136 | python3 -c "$$BROWSER_PYSCRIPT" "$$filename.html" 137 | 138 | setwd: ## set working directory to current directory 139 | Rscript -e "setwd('.')" 140 | 141 | start: ## start or restart R session 142 | Rscript -e "system('R')" 143 | 144 | test: ## runs package tests 145 | Rscript -e "devtools::test('.')" 146 | 147 | usegit: ## initialize Git repo and initial commit 148 | @read -p "Enter the first commit message: " message; \ 149 | if [ -z "$$message" ]; then \ 150 | echo "Commit message cannot be empty."; \ 151 | exit 1; \ 152 | fi; \ 153 | Rscript -e "usethis::use_git('$$message')"; \ 154 | git add .; \ 155 | git commit -m "$$message" -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | useDynLib(ahead, .registration=TRUE) 2 | S3method(predict, comb_GLMNET) 3 | S3method(predict, comb_OLS) 4 | S3method(predict, comb_Ridge) 5 | S3method(plot, mtsforecast) 6 | S3method(predict, ridge) 7 | S3method(plot, foreccomb_res) 8 | S3method(predict, foreccomb_res) 9 | S3method(print, foreccomb_res_summary) 10 | S3method(summary, foreccomb_res) 11 | importFrom(tseries, surrogate) 12 | importFrom(tseries, tsbootstrap) 13 | 14 | importFrom(Rcpp, evalCpp) 15 | importFrom("grDevices", "colorRampPalette") 16 | importFrom("graphics", "abline", "par", "points", "polygon") 17 | importFrom("graphics", "lines") 18 | importFrom("graphics", "matplot") 19 | importFrom("graphics", "matlines") 20 | importFrom("graphics", "barplot") 21 | importFrom("foreach", "foreach") 22 | importFrom("snow", "stopCluster") 23 | importFrom("stats", "is.ts", "runif", "time") 24 | importFrom("stats", "t.test") 25 | importFrom("stats", "as.ts", "complete.cases", "ecdf", "end", "frequency", 26 | "lag", "median", "predict", "predict.lm", "qnorm", "quantile", 27 | "residuals", "rnorm", "rt", "sd", "setNames", "start", 28 | "ts", "tsp", "tsp<-") 29 | importFrom("utils", "tail") 30 | importFrom("utils", "install.packages", "installed.packages") 31 | importFrom("stats", "approx", "coef", "density", "fitted") 32 | import(forecast) 33 | import(ggplot2) 34 | export("armagarchf") 35 | export("basicf") 36 | export("eatf") 37 | export("dynrmf") 38 | export("fitforecast") 39 | export("loessf") 40 | export("loocvridge2f") 41 | export("ridge2f") 42 | export("ridge") 43 | export("varf") 44 | export("createtrendseason") 45 | export("getreturns") 46 | export("getsimulations") 47 | export("removenas") 48 | export("fit_func") 49 | export("predict_func") 50 | export("comb_OLS") 51 | export("comb_Ridge") 52 | export("comb_GLMNET") 53 | export(fitdistr_ahead) 54 | export(quantile_scp) 55 | export(genericforecast) 56 | export(conformalize) 57 | export(mlf) 58 | export(glmthetaf) 59 | export(computeattention) 60 | export(ml_forecast) 61 | export(ml_forecast2) 62 | export(ml_forecast3) 63 | export(mlarchf) -------------------------------------------------------------------------------- /NAMESPACE_backup: -------------------------------------------------------------------------------- 1 | useDynLib(ahead, .registration=TRUE) 2 | S3method(predict, comb_GLMNET) 3 | S3method(predict, comb_OLS) 4 | S3method(predict, comb_Ridge) 5 | S3method(plot, mtsforecast) 6 | S3method(predict, ridge) 7 | importFrom(Rcpp, evalCpp) 8 | importFrom("grDevices", "colorRampPalette") 9 | importFrom("graphics", "abline", "par", "points", "polygon") 10 | importFrom("graphics", "lines") 11 | importFrom("graphics", "matplot") 12 | importFrom("foreach", "foreach") 13 | importFrom("snow", "stopCluster") 14 | importFrom("stats", "is.ts", "runif", "time") 15 | importFrom("stats", "t.test") 16 | importFrom("stats", "as.ts", "complete.cases", "ecdf", "end", "frequency", 17 | "lag", "median", "predict", "predict.lm", "qnorm", "quantile", 18 | "residuals", "rnorm", "rt", "sd", "setNames", "start", 19 | "ts", "tsp", "tsp<-") 20 | importFrom("utils", "tail") 21 | importFrom("utils", "install.packages", "installed.packages") 22 | importFrom("graphics", "matlines") 23 | importFrom("stats", "approx", "coef", "density", "fitted") 24 | export("armagarchf") 25 | export("basicf") 26 | export("eatf") 27 | export("dynrmf") 28 | export("fitforecast") 29 | export("loessf") 30 | export("loocvridge2f") 31 | export("ridge2f") 32 | export("ridge") 33 | export("varf") 34 | export("createtrendseason") 35 | export("getreturns") 36 | export("getsimulations") 37 | export("removenas") 38 | export("fit_func") 39 | export("predict_func") 40 | export("comb_OLS") 41 | export("comb_Ridge") 42 | export("comb_GLMNET") 43 | 44 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # version 0.18.0 2 | 3 | - Add ML-ARCH model, see vignettes for more examples 4 | 5 | # version 0.17.0 6 | 7 | - Add conformal prediction to `ridge2f` (with KDE, bootstrap, block bootstrap and sequential split conformal prediction) 8 | - Faster install, less imports 9 | 10 | # version 0.14.0 11 | 12 | - Add `fit_func` and `predict_func` for custom fitting and prediction functions of `ahead::dynrmf` (using `caret` Machine Learning). 13 | - Add forecasting combinations based on ForecastComb, adding Ridge and Elastic Net to the mix. 14 | 15 | # version 0.11.0 16 | 17 | - Include tests (90% coverage). After cloning, run: 18 | 19 | ```R 20 | install.packages("covr") 21 | covr::report() 22 | ``` 23 | 24 | # version 0.10.0 25 | 26 | - Univariate forecasting for `ridge2f`. 27 | See https://thierrymoudiki.github.io/blog/2024/02/26/python/r/julia/ahead-v0100. 28 | - Fast calibration for `ridge2f` (univariate and multivariate case). 29 | See https://thierrymoudiki.github.io/blog/2024/02/26/python/r/julia/ahead-v0100. 30 | 31 | # version 0.9.0 32 | 33 | - progress bars for bootstrap (independent, circular block, moving block) 34 | 35 | # version 0.8.0 36 | 37 | - empirical marginals for R-Vine copula simulation 38 | - risk-neutralize simulations 39 | 40 | # version 0.7.0 41 | 42 | - moving block bootstrap in `ridge2f`, `basicf` and `loessf`, in addition to circular block bootstrap from 0.6.2 43 | - adjust R-Vine copulas on residuals for `ridge2f` simulation 44 | - new plots for simulations see (new) vignettes 45 | - split conformal prediction intervals (**very very experimental** and basic right now, too conservative) 46 | - `Depends` and selective `Imports` (beneficial to Python and rpy2 for installation time?) 47 | - `getsimulations` extracts simulations from a given time series (from `ridge2f` and `basicf`) 48 | - `getreturns` extracts returns/log-returns from multivariate time series 49 | - `splitts` splits time series using a proportion of data 50 | 51 | # version 0.6.2 52 | 53 | - Add Block Bootstrap to `ridge2f` 54 | - Add external regressors to `ridge2f` 55 | - Add clustering to `ridge2f` 56 | - Add Block Bootstrap to `loessf` 57 | - Create new vignettes for `ridge2f` and `loessf` 58 | 59 | # version 0.6.1 60 | 61 | - Align version with Python's 62 | - Temporarily remove dependency with `cclust` 63 | 64 | # version 0.6.0 65 | 66 | - Include basic methods: mean forecast, median forecast, random walk forecast 67 | 68 | # version 0.5.0 69 | 70 | - add dropout regularization to `ridge2f` 71 | - parallel execution for `type_pi == bootstrap` in `ridge2f` (done in R /!\, experimental) 72 | - preallocate matrices for `type_forecast == recursive` in `ridge2f` 73 | 74 | 75 | # version 0.4.2 76 | 77 | - new attributes mean, lower bound, upper bound forecast as numpy arrays 78 | 79 | 80 | # version 0.4.1 81 | 82 | - use `get_frequency` to get series frequency as a number 83 | - create a function `get_tscv_indices` for getting time series cross-validation indices 84 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | compute_attention_cpp <- function(series) { 5 | .Call(`_ahead_compute_attention_cpp`, series) 6 | } 7 | 8 | compute_context_vectors_cpp <- function(series, attention_weights) { 9 | .Call(`_ahead_compute_context_vectors_cpp`, series, attention_weights) 10 | } 11 | 12 | exact_rf_forecast <- function(embed_mat, h, lags, predict_func, model) { 13 | .Call(`_ahead_exact_rf_forecast`, embed_mat, h, lags, predict_func, model) 14 | } 15 | 16 | forecast_innovs_loop_cpp <- function(eps, rts, eps_prev, omega, alpha, beta, df, h) { 17 | .Call(`_ahead_forecast_innovs_loop_cpp`, eps, rts, eps_prev, omega, alpha, beta, df, h) 18 | } 19 | 20 | forecast_innovs_loop_cpp2 <- function(eps, rn, eps_prev, omega, alpha, beta, df, h) { 21 | .Call(`_ahead_forecast_innovs_loop_cpp2`, eps, rn, eps_prev, omega, alpha, beta, df, h) 22 | } 23 | 24 | create_lags_cpp <- function(x, k) { 25 | .Call(`_ahead_create_lags_cpp`, x, k) 26 | } 27 | 28 | create_train_inputs_cpp <- function(x, k) { 29 | .Call(`_ahead_create_train_inputs_cpp`, x, k) 30 | } 31 | 32 | reformat_cpp <- function(x, n_k) { 33 | .Call(`_ahead_reformat_cpp`, x, n_k) 34 | } 35 | 36 | rev_matrix_cpp <- function(x) { 37 | .Call(`_ahead_rev_matrix_cpp`, x) 38 | } 39 | 40 | rbind_vecmat_cpp <- function(y, x) { 41 | .Call(`_ahead_rbind_vecmat_cpp`, y, x) 42 | } 43 | 44 | -------------------------------------------------------------------------------- /R/VAR.R: -------------------------------------------------------------------------------- 1 | #' Vector Autoregressive model (adapted from vars::VAR) 2 | #' 3 | #' Vector Autoregressive model adapted from vars::VAR (only for benchmarking) 4 | #' 5 | #' @param y A multivariate time series of class \code{ts} 6 | #' @param h Forecasting horizon 7 | #' @param level Confidence level for prediction intervals 8 | #' @param lags Number of lags 9 | #' @param type_VAR Type of deterministic regressors to include. 10 | #' @param ... Additional parameters to be passed to vars::VAR. 11 | #' 12 | #' @return An object of class "mtsforecast"; a list containing the following elements: 13 | #' 14 | #' \item{method}{The name of the forecasting method as a character string} 15 | #' \item{mean}{Point forecasts for the time series} 16 | #' \item{lower}{Lower bound for prediction interval} 17 | #' \item{upper}{Upper bound for prediction interval} 18 | #' \item{x}{The original time series} 19 | #' \item{residuals}{Residuals from the fitted model} 20 | #' 21 | #' @author T. Moudiki 22 | #' 23 | #' @references 24 | #' 25 | #' Bernhard Pfaff (2008). VAR, SVAR and SVEC Models: Implementation 26 | #' Within R Package vars. Journal of Statistical Software 27(4). URL 27 | #' http://www.jstatsoft.org/v27/i04/. \cr 28 | #' 29 | #' Pfaff, B. (2008) Analysis of Integrated and Cointegrated Time Series 30 | #' with R. Second Edition. Springer, New York. ISBN 0-387-27960-1 31 | #' 32 | #' @export 33 | #' 34 | #' @examples 35 | #' 36 | #' require(fpp) 37 | #' 38 | #' print(varf(fpp::insurance, lags=2, h=10)) 39 | #' 40 | #' res <- varf(fpp::usconsumption, h=20, lags=2) 41 | #' 42 | #' par(mfrow=c(1, 2)) 43 | #' plot(res, "consumption") 44 | #' plot(res, "income") 45 | #' 46 | varf <- function(y, h = 5, 47 | level = 95, 48 | lags = 1, 49 | type_VAR = c("const", "trend", 50 | "both", "none"), 51 | ...) 52 | { 53 | # if(is_package_available("vars") == FALSE) 54 | # install.packages("vars", 55 | # repos = c(CRAN = "https://cloud.r-project.org")) 56 | 57 | if (!is.ts(y)) 58 | { 59 | y <- ts(y) 60 | } 61 | freq_y <- frequency(y) 62 | start_y <- start(y) 63 | start_preds <- tsp(y)[2] + 1/freq_y 64 | 65 | type_VAR <- match.arg(type_VAR) 66 | 67 | # Fitting a VAR model to multiple time series 68 | fit_obj <- fit_var_mts(y, lags = lags, 69 | type_VAR = type_VAR, 70 | ...) 71 | 72 | # Forecast from fit_obj 73 | preds <- fcast_var_mts(fit_obj$fit_obj, 74 | h = h, level = level) 75 | 76 | out <- list(mean = ts(sapply(preds$fcst, function(x) x[,"fcst"]), 77 | start = start_preds, frequency = freq_y), 78 | lower = ts(sapply(preds$fcst, function(x) x[,"lower"]), 79 | start = start_preds, frequency = freq_y), 80 | upper = ts(sapply(preds$fcst, function(x) x[,"upper"]), 81 | start = start_preds, frequency = freq_y), 82 | x = y, 83 | level = level, 84 | method = "VAR", 85 | residuals = residuals(fit_obj$fit_obj)) 86 | 87 | # cat("Point Forecast", "\n") 88 | # print(out$mean) 89 | # cat("\n") 90 | # 91 | # cat("Lo", level, "\n") 92 | # print(out$lower) 93 | # cat("\n") 94 | # 95 | # cat("Hi", level, "\n") 96 | # print(out$upper) 97 | # cat("\n") 98 | 99 | return(structure(out, class = "mtsforecast")) 100 | } 101 | varf <- compiler::cmpfun(varf) 102 | 103 | 104 | # Fitting a VAR model to multiple time series 105 | fit_var_mts <- function(x, 106 | lags = 1, 107 | type_VAR = c("const", "trend", 108 | "both", "none"), 109 | ...) 110 | # for penalization == "none" only 111 | { 112 | series_names <- colnames(x) 113 | 114 | # unrestricted VAR algo from package 'vars' 115 | type_VAR <- match.arg(type_VAR) 116 | fit_obj <- vars::VAR(y = x, p = lags, type = type_VAR, 117 | ...) 118 | 119 | return( 120 | list( 121 | fit_obj = fit_obj, 122 | series_names = series_names, 123 | class_res = "VAR" 124 | ) 125 | ) 126 | } 127 | 128 | 129 | # Forecasting a VAR model 130 | fcast_var_mts <- function(fit_obj, 131 | h = 5, 132 | level = 95) 133 | { 134 | return(predict(fit_obj, n.ahead = h, 135 | ci = level / 100)) 136 | } 137 | -------------------------------------------------------------------------------- /R/armagarch.R: -------------------------------------------------------------------------------- 1 | #' ARMA(1, 1)-GARCH(1, 1) forecasting (with simulation) 2 | #' 3 | #' @param y a univariate time series 4 | #' @param h number of periods for forecasting 5 | #' @param level confidence level for prediction intervals 6 | #' @param B number of simulations for `arima.sim` 7 | #' @param cl an integer; the number of clusters for parallel execution 8 | #' @param dist distribution of innovations ("student" or "gaussian") 9 | #' @param seed reproducibility seed 10 | #' 11 | #' @return An object of class "forecast"; a list containing the following elements: 12 | #' 13 | #' \item{model}{A list containing information about the fitted model} 14 | #' \item{method}{The name of the forecasting method as a character string} 15 | #' \item{mean}{Point forecasts for the time series} 16 | #' \item{lower}{Lower bound for prediction interval} 17 | #' \item{upper}{Upper bound for prediction interval} 18 | #' \item{x}{The original time series} 19 | #' \item{sims}{Simulations of ARMA(1, 1)-GARCH(1, 1)} 20 | #' 21 | #' @author T. Moudiki 22 | #' 23 | #' @export 24 | #' 25 | #' @examples 26 | #' 27 | #' y <- datasets::EuStockMarkets[ , "DAX"] 28 | #' log_returns <- ts(log(y[-1]/y[-length(y)])) 29 | #' 30 | #' # require(forecast) 31 | #' # z <- ahead::armagarchf(y=log_returns, h=200) 32 | #' # plot(z) 33 | #' 34 | #' 35 | armagarchf <- function(y, 36 | h = 5, 37 | level = 95, 38 | B = 250, 39 | cl = 1L, 40 | dist = c("student", "gaussian"), 41 | seed = 123) { 42 | 43 | # if(is_package_available("forecast") == FALSE) 44 | # utils::install.packages("forecast", 45 | # repos = c(CRAN = "https://cloud.r-project.org"), 46 | # dependencies = TRUE) 47 | 48 | # if(is_package_available("fBasics") == FALSE) 49 | # utils::install.packages("fBasics", 50 | # repos = c(CRAN = "https://cloud.r-project.org"), 51 | # dependencies = TRUE) 52 | 53 | # if(is_package_available("fGarch") == FALSE) 54 | # utils::install.packages("fGarch", 55 | # repos = c(CRAN = "https://cloud.r-project.org"), 56 | # dependencies = TRUE) 57 | 58 | dist <- match.arg(dist) 59 | 60 | # Fit ARIMA to original series 61 | obj_arma <- stats::arima(x = y, order = c(1L, 0L, 1L)) 62 | 63 | # In sample residuals 64 | eps <- stats::residuals(obj_arma) 65 | 66 | eps_prev <- eps[length(eps)] 67 | 68 | # Fit GARCH to residuals 69 | base::suppressWarnings( 70 | obj_garch <- fGarch::garchFit( 71 | formula = ~ garch(1, 1), 72 | data = eps, 73 | include.mean = FALSE, 74 | trace = FALSE 75 | ) 76 | ) 77 | omega <- obj_garch@fit$coef["omega"] 78 | alpha <- obj_garch@fit$coef["alpha1"] 79 | beta <- obj_garch@fit$coef["beta1"] 80 | 81 | 82 | # Forecasting using simulation 83 | if (cl <= 1L) 84 | { 85 | res <- 86 | sapply(1:B, function(x) 87 | stats::arima.sim( 88 | model = list(ar = obj_arma$coef["ar1"], 89 | ma = obj_arma$coef["ma1"]), 90 | n = h, 91 | start.innov = eps, 92 | innov = forecast_innovs( 93 | eps_prev = eps_prev, 94 | h = 95 | h, 96 | omega = omega, 97 | alpha = 98 | alpha, 99 | beta = beta, 100 | seed = 101 | x + 10 * seed, 102 | dist = dist 103 | ) 104 | )) 105 | } else { 106 | stopifnot(is.numeric(cl)) 107 | cluster <- parallel::makeCluster(getOption("cl.cores", cl)) 108 | res <- 109 | parallel::parSapply( 110 | cl = cluster, 111 | X = 1:B, 112 | FUN = function(x) 113 | stats::arima.sim( 114 | model = list(ar = obj_arma$coef["ar1"], 115 | ma = obj_arma$coef["ma1"]), 116 | n = h, 117 | start.innov = eps, 118 | innov = forecast_innovs( 119 | eps_prev = eps_prev, 120 | h = 121 | h, 122 | omega = omega, 123 | alpha = 124 | alpha, 125 | beta = beta, 126 | seed = 127 | x + 10 * seed, 128 | dist = dist 129 | ) 130 | ) 131 | ) 132 | parallel::stopCluster(cluster) 133 | } 134 | 135 | 136 | # return 137 | tspx <- tsp(y) 138 | start_preds <- tspx[2] + 1 / tspx[3] 139 | freq_y <- tspx[3] 140 | ans <- list() 141 | ans$x <- y 142 | 143 | ans$mean <- ts(apply(res, 1, median), 144 | start = start_preds, 145 | frequency = freq_y) 146 | 147 | ans$level <- level 148 | level_100 <- level / 100 149 | qts <- 150 | apply(res, 1, function(x) 151 | quantile(x, probs = c((1 - level_100) / 2, 152 | 1 - (1 - level_100) / 153 | 2))) 154 | ans$lower <- ts(qts[1,], start = start_preds, frequency = freq_y) 155 | ans$upper <- ts(qts[2,], start = start_preds, frequency = freq_y) 156 | 157 | ans$method <- "ARMA(1, 1) - GARCH(1, 1)" 158 | ans$model <- list( 159 | h = h, 160 | level = level, 161 | B = B, 162 | seed = seed 163 | ) 164 | ans$sims <- res 165 | 166 | return(structure(ans, class = "forecast")) 167 | } 168 | armagarchf <- compiler::cmpfun(armagarchf) 169 | 170 | 171 | # Utils function for armagarchf 172 | forecast_innovs <- function(eps_prev, 173 | omega, 174 | alpha, 175 | beta, 176 | df = 3, 177 | h = 5, 178 | seed = 123, 179 | dist = c("student", "gaussian")) 180 | { 181 | sigma_prev <- omega / (1 - alpha - beta) 182 | 183 | eps <- rep(NA, h) 184 | 185 | set.seed(seed) 186 | 187 | dist <- match.arg(dist) 188 | 189 | if (dist == "student") 190 | { 191 | rts <- rt(n = h, df = df) 192 | 193 | eps <- forecast_innovs_loop_cpp(eps, rts, 194 | eps_prev, 195 | omega, alpha, beta, 196 | df, h) 197 | } else { 198 | rn <- rnorm(n = h) 199 | 200 | eps <- forecast_innovs_loop_cpp2(eps, rn, 201 | eps_prev, 202 | omega, alpha, beta, 203 | df, h) 204 | } 205 | 206 | 207 | 208 | return(drop(eps)) 209 | } 210 | -------------------------------------------------------------------------------- /R/auto_arima.R: -------------------------------------------------------------------------------- 1 | auto_arima <- function(y, h=5L, n_starts=10L, ...) 2 | { 3 | penalty <- 1e6 4 | ndims <- 6 5 | objective <- function(xx) 6 | { 7 | model <- try(forecast::Arima(y=y, 8 | order = c(floor(xx[1]), 9 | floor(xx[2]), 10 | floor(xx[3])), 11 | seasonal = c(floor(xx[4]), 12 | floor(xx[5]), 13 | floor(xx[6])), 14 | method = "ML"), 15 | silent = TRUE) 16 | if (inherits(model, "try-error")) 17 | { 18 | return(.Machine$double.xmax) 19 | } 20 | ans <- try(model$aicc + penalty*(suppressWarnings(tseries::kpss.test(model$residuals))$p.value < 0.05), 21 | silent = TRUE) 22 | cond <- inherits(ans, "try-error") 23 | return(ans*(!cond)+.Machine$double.xmax*cond) 24 | } 25 | objective <- memoise::memoise(objective) 26 | 27 | res <- vector("list", length = n_starts) 28 | lower_bounds <- rep(0, ndims) 29 | upper_bounds <- rep(5, ndims) 30 | upper_bounds[2] <- 2 31 | upper_bounds[4] <- 2 32 | upper_bounds[6] <- 12 33 | pb <- utils::txtProgressBar(min=1, max=n_starts, style=3L) 34 | for (i in seq_len(n_starts)) 35 | { 36 | set.seed(123 + i * 100) 37 | res[[i]] <- stats::nlminb(start = floor(3*runif(ndims)), 38 | objective = objective, 39 | lower = lower_bounds, 40 | upper = upper_bounds) 41 | if (i >= 2) 42 | { 43 | if (res[[i]]$objective <= res[[i-1]]$objective) 44 | { 45 | ans <- res[[i]] 46 | } 47 | } 48 | utils::setTxtProgressBar(pb, i) 49 | } 50 | close(pb) 51 | return(forecast::Arima(y=y, 52 | order = c(floor(ans$par[1]), 53 | floor(ans$par[2]), 54 | floor(ans$par[3])), 55 | seasonal = c(floor(ans$par[4]), 56 | floor(ans$par[5]), 57 | floor(ans$par[6])), 58 | method = "ML")) 59 | } 60 | 61 | -------------------------------------------------------------------------------- /R/caretfitpredict.R: -------------------------------------------------------------------------------- 1 | 2 | #' Fit univariate time series using caret ML model (for use with \code{dynrmf}) 3 | #' 4 | #' @param x A matrix of predictors 5 | #' @param y A vector of responses 6 | #' @param method The caret method to use for fitting the model 7 | #' @param initial_window The initial window size 8 | #' @param horizon The forecast horizon 9 | #' @param fixed_window Whether to use a fixed window size 10 | #' @param tune_length Length of the tuning grid 11 | #' @param verbose Whether to print the model summary 12 | #' @return A model object 13 | #' @export 14 | fit_func <- function(x, y, method="ranger", 15 | initial_window = 10L, horizon = 10L, fixed_window = FALSE, 16 | tune_length = 5, summary_function = NULL, 17 | verbose=TRUE) 18 | { 19 | df <- data.frame(y=y, x) 20 | if (is.null(summary_function)) 21 | { 22 | summary_function <- caret::defaultSummary 23 | } 24 | res <- caret::train(y ~ ., data=df, 25 | method = method, 26 | trControl = caret::trainControl( 27 | method = "timeslice", 28 | initialWindow = initial_window, 29 | horizon = horizon, 30 | fixedWindow = fixed_window, 31 | skip = 0, 32 | summaryFunction = summary_function 33 | ), 34 | verboseIter = FALSE, 35 | savePredictions = "final", 36 | tuneLength = tune_length) 37 | if (verbose) 38 | { 39 | print(res) 40 | } 41 | return(res) 42 | } 43 | 44 | 45 | #' Predict univariate time series using caret ML model(for use with \code{dynrmf}) 46 | #' 47 | #' @param x A matrix of predictors 48 | #' @param y A vector of responses 49 | #' @param method The caret method to use for fitting the model 50 | #' @param verbose Whether to print the model summary 51 | #' @return A model object 52 | #' @export 53 | predict_func <- function(obj, newx) 54 | { 55 | colnames(newx) <- paste0("X", seq_len(ncol(newx))) 56 | as.numeric(caret::predict.train(object=obj, 57 | newdata=newx, 58 | type = "raw")) 59 | } 60 | 61 | -------------------------------------------------------------------------------- /R/comb_GLMNET.R: -------------------------------------------------------------------------------- 1 | #' @title GLMNET Regression Forecast Combination 2 | #' 3 | #' @description Computes forecast combination weights using GLMNET Regression (OLS) regression. 4 | #' 5 | #' @details 6 | #' The function integrates the GLMNET Regression forecast combination implementation of the 7 | #' \emph{ForecastCombinations} package into ForecastComb. 8 | #' 9 | #' The results are stored in an object of class 'ForecastComb::foreccomb_res', for which separate plot and summary functions are provided. 10 | #' 11 | #' @param x An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set. 12 | #' 13 | #' @return Returns an object of class \code{ForecastComb::foreccomb_res} with the following components: 14 | #' \item{Method}{Returns the best-fit forecast combination method.} 15 | #' \item{Models}{Returns the individual input models that were used for the forecast combinations.} 16 | #' \item{Weights}{Returns the combination weights obtained by applying the combination method to the training set.} 17 | #' \item{Intercept}{Returns the intercept of the linear regression.} 18 | #' \item{Fitted}{Returns the fitted values of the combination method for the training set.} 19 | #' \item{Accuracy_Train}{Returns range of summary measures of the forecast accuracy for the training set.} 20 | #' \item{Forecasts_Test}{Returns forecasts produced by the combination method for the test set. Only returned if input included a forecast matrix for the test set.} 21 | #' \item{Accuracy_Test}{Returns range of summary measures of the forecast accuracy for the test set. Only returned if input included a forecast matrix and a vector of actual values for the test set.} 22 | #' \item{Input_Data}{Returns the data forwarded to the method.} 23 | #' 24 | #' @examples 25 | #' 26 | #' library(ForecastComb) 27 | #' 28 | #' data(electricity) 29 | #' 30 | #' print(head(electricity)) 31 | #' 32 | #' forecasting_methods <- colnames(electricity)[1:5] 33 | #' 34 | #' train_obs <- electricity[1:84, "Actual"] 35 | #' train_pred <- electricity[1:84, forecasting_methods] 36 | #' test_obs <- electricity[85:123, "Actual"] 37 | #' test_pred <- electricity[85:123, forecasting_methods] 38 | #' data <- ForecastComb::foreccomb(train_obs, train_pred, test_obs, test_pred) 39 | #' 40 | #' # obj <- ahead::comb_GLMNET(data)) 41 | #' 42 | #' @seealso 43 | #' \code{\link[ForecastCombinations]{Forecast_comb}}, 44 | #' \code{\link{foreccomb}}, 45 | #' \code{\link{plot.ForecastComb::foreccomb_res}}, 46 | #' \code{\link{summary.ForecastComb::foreccomb_res}}, 47 | #' \code{\link[forecast]{accuracy}} 48 | #' 49 | #' @keywords models 50 | #' 51 | #' @import forecast 52 | #' 53 | #' @export 54 | comb_GLMNET <- function(x, custom_error = NULL) { 55 | if (!inherits(x, "foreccomb")) 56 | stop("Data must be class 'foreccomb'. See ?foreccomb, to bring data in correct format.", call. = FALSE) 57 | observed_vector <- x$Actual_Train 58 | prediction_matrix <- x$Forecasts_Train 59 | modelnames <- x$modelnames 60 | 61 | lin_model <- glmnet::cv.glmnet(x = as.matrix(prediction_matrix), y = as.numeric(observed_vector)) 62 | weights <- as.numeric(drop(coef(lin_model, s = "lambda.min"))) 63 | intercept <- weights[1] 64 | fitted <- drop(predict(lin_model, prediction_matrix, s = "lambda.min")) 65 | accuracy_insample <- forecast::accuracy(observed_vector, as.numeric(fitted)) 66 | if (!is.null(custom_error)) { 67 | accuracy_insample <- cbind(accuracy_insample, custom_error(as.numeric(observed_vector), as.numeric(fitted))) 68 | colnames(accuracy_insample)[length(accuracy_insample)] <- "Custom Error" 69 | } 70 | 71 | if (is.null(x$Forecasts_Test) && is.null(x$Actual_Test)) { 72 | result <- ForecastComb::foreccomb_res(method = "GLMNET Regression Regression", modelnames = modelnames, weights = weights[-1], intercept = intercept, fitted = fitted, accuracy_insample = accuracy_insample, 73 | input_data = list(Actual_Train = x$Actual_Train, Forecasts_Train = x$Forecasts_Train), 74 | predict = predict.comb_GLMNET) 75 | } 76 | 77 | if (is.null(x$Forecasts_Test) == FALSE) { 78 | newpred_matrix <- x$Forecasts_Test 79 | pred <- drop(predict(lin_model, newpred_matrix, s = "lambda.min")) 80 | if (is.null(x$Actual_Test) == TRUE) { 81 | result <- ForecastComb::foreccomb_res(method = "GLMNET Regression Regression", modelnames = modelnames, weights = weights[-1], intercept = intercept, fitted = fitted, accuracy_insample = accuracy_insample, 82 | pred = pred, input_data = list(Actual_Train = x$Actual_Train, Forecasts_Train = x$Forecasts_Train, Forecasts_Test = x$Forecasts_Test), 83 | predict = predict.comb_GLMNET) 84 | } else { 85 | newobs_vector <- x$Actual_Test 86 | accuracy_outsample <- forecast::accuracy(newobs_vector, as.numeric(pred)) 87 | if (!is.null(custom_error)) { 88 | accuracy_outsample <- cbind(accuracy_outsample, custom_error(as.numeric(newobs_vector), as.numeric(pred))) 89 | colnames(accuracy_outsample)[length(accuracy_outsample)] <- "Custom Error" 90 | } 91 | result <- ForecastComb::foreccomb_res(method = "GLMNET Regression Regression", modelnames = modelnames, weights = weights[-1], intercept = intercept, fitted = fitted, accuracy_insample = accuracy_insample, 92 | pred = pred, accuracy_outsample = accuracy_outsample, input_data = list(Actual_Train = x$Actual_Train, Forecasts_Train = x$Forecasts_Train, Actual_Test = x$Actual_Test, 93 | Forecasts_Test = x$Forecasts_Test), 94 | predict = predict.comb_GLMNET) 95 | result$lin_model <- lin_model 96 | } 97 | } 98 | class(result) <- c("foreccomb_res", "comb_GLMNET") 99 | return(result) 100 | } 101 | 102 | #' @export 103 | predict.comb_GLMNET <- function(object, newpreds) { 104 | return(drop(predict(object$lin_model, newpreds, s = "lambda.min"))) 105 | } 106 | -------------------------------------------------------------------------------- /R/comb_Ridge.R: -------------------------------------------------------------------------------- 1 | #' @title Ridge Regression Forecast Combination 2 | #' 3 | #' @description Computes forecast combination weights using Ridge Regression (OLS) regression. 4 | #' 5 | #' @details 6 | #' The function integrates the Ridge Regression forecast combination implementation of the 7 | #' \emph{ForecastCombinations} package into ForecastComb. 8 | #' 9 | #' The results are stored in an object of class 'ForecastComb::foreccomb_res', for which separate plot and summary functions are provided. 10 | #' 11 | #' @param x An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set. 12 | #' 13 | #' @return Returns an object of class \code{ForecastComb::foreccomb_res} with the following components: 14 | #' \item{Method}{Returns the best-fit forecast combination method.} 15 | #' \item{Models}{Returns the individual input models that were used for the forecast combinations.} 16 | #' \item{Weights}{Returns the combination weights obtained by applying the combination method to the training set.} 17 | #' \item{Intercept}{Returns the intercept of the linear regression.} 18 | #' \item{Fitted}{Returns the fitted values of the combination method for the training set.} 19 | #' \item{Accuracy_Train}{Returns range of summary measures of the forecast accuracy for the training set.} 20 | #' \item{Forecasts_Test}{Returns forecasts produced by the combination method for the test set. Only returned if input included a forecast matrix for the test set.} 21 | #' \item{Accuracy_Test}{Returns range of summary measures of the forecast accuracy for the test set. Only returned if input included a forecast matrix and a vector of actual values for the test set.} 22 | #' \item{Input_Data}{Returns the data forwarded to the method.} 23 | #' 24 | #' @examples 25 | #' obs <- rnorm(100) 26 | #' preds <- matrix(rnorm(1000, 1), 100, 10) 27 | #' train_o<-obs[1:80] 28 | #' train_p<-preds[1:80,] 29 | #' test_o<-obs[81:100] 30 | #' test_p<-preds[81:100,] 31 | #' 32 | #' data<-ForecastComb::foreccomb(train_o, train_p, test_o, test_p) 33 | #' ahead::comb_Ridge(data) 34 | #' 35 | #' @seealso 36 | #' \code{\link[ForecastCombinations]{Forecast_comb}}, 37 | #' \code{\link{foreccomb}}, 38 | #' \code{\link{plot.ForecastComb::foreccomb_res}}, 39 | #' \code{\link{summary.ForecastComb::foreccomb_res}}, 40 | #' \code{\link[forecast]{accuracy}} 41 | #' 42 | #' @keywords models 43 | #' 44 | #' @import forecast 45 | #' 46 | #' @export 47 | comb_Ridge <- function(x, custom_error = NULL) { 48 | if (!inherits(x, "foreccomb")) 49 | stop("Data must be class 'foreccomb'. See ?foreccomb, to bring data in correct format.", call. = FALSE) 50 | observed_vector <- x$Actual_Train 51 | prediction_matrix <- x$Forecasts_Train 52 | modelnames <- x$modelnames 53 | 54 | lin_model <- ridge(x = prediction_matrix, y = observed_vector) 55 | weights <- unname(lin_model$coef[,which.min(lin_model$GCV)] ) 56 | intercept <- lin_model$ym 57 | fitted <- predict(lin_model, prediction_matrix) 58 | 59 | accuracy_insample <- forecast::accuracy(fitted, observed_vector) 60 | if (!is.null(custom_error)) { 61 | accuracy_insample <- cbind(accuracy_insample, custom_error(as.numeric(observed_vector), as.numeric(fitted))) 62 | colnames(accuracy_insample)[length(accuracy_insample)] <- "Custom Error" 63 | } 64 | 65 | if (is.null(x$Forecasts_Test) && is.null(x$Actual_Test)) { 66 | result <- ForecastComb::foreccomb_res(method = "Ridge Regression Regression", modelnames = modelnames, weights = weights, intercept = intercept, fitted = fitted, accuracy_insample = accuracy_insample, 67 | input_data = list(Actual_Train = x$Actual_Train, Forecasts_Train = x$Forecasts_Train), 68 | predict = predict.comb_Ridge) 69 | } 70 | 71 | if (is.null(x$Forecasts_Test) == FALSE) { 72 | newpred_matrix <- x$Forecasts_Test 73 | pred <- predict(lin_model, newpred_matrix) 74 | if (is.null(x$Actual_Test) == TRUE) { 75 | result <- ForecastComb::foreccomb_res(method = "Ridge Regression Regression", modelnames = modelnames, weights = weights, intercept = intercept, fitted = fitted, accuracy_insample = accuracy_insample, 76 | pred = pred, input_data = list(Actual_Train = x$Actual_Train, Forecasts_Train = x$Forecasts_Train, Forecasts_Test = x$Forecasts_Test), 77 | predict = predict.comb_Ridge) 78 | } else { 79 | newobs_vector <- x$Actual_Test 80 | accuracy_outsample <- forecast::accuracy(pred, newobs_vector) 81 | if (!is.null(custom_error)) { 82 | accuracy_outsample <- cbind(accuracy_outsample, custom_error(as.numeric(newobs_vector), as.numeric(pred))) 83 | colnames(accuracy_outsample)[length(accuracy_outsample)] <- "Custom Error" 84 | } 85 | result <- ForecastComb::foreccomb_res(method = "Ridge Regression Regression", modelnames = modelnames, weights = weights, intercept = intercept, fitted = fitted, accuracy_insample = accuracy_insample, 86 | pred = pred, accuracy_outsample = accuracy_outsample, input_data = list(Actual_Train = x$Actual_Train, Forecasts_Train = x$Forecasts_Train, Actual_Test = x$Actual_Test, 87 | Forecasts_Test = x$Forecasts_Test), 88 | predict = predict.comb_Ridge) 89 | result$lin_model <- lin_model 90 | } 91 | } 92 | class(result) <- c("foreccomb_res", "comb_Ridge") 93 | return(result) 94 | } 95 | 96 | #' @export 97 | predict.comb_Ridge <- function(object, newpreds) { 98 | return(predict(object$lin_model, newpreds)) 99 | } -------------------------------------------------------------------------------- /R/compute_attention.R: -------------------------------------------------------------------------------- 1 | #' Compute global attention weights and context vectors for time series 2 | #' 3 | #' @param series Numeric vector containing the time series of length n 4 | #' @return List containing: 5 | #' \item{attention_weights}{n × n matrix where entry (i,j) represents the attention 6 | #' weight of time j on time i. Only entries j <= i are non-zero (causal attention).} 7 | #' \item{context_vectors}{Vector of length n where each entry i is the weighted sum 8 | #' of all values up to time i, using the attention weights.} 9 | #' @examples 10 | #' # For a series of length 5 11 | #' series <- c(1, 2, 3, 4, 5) 12 | #' result <- computeattention(series) 13 | #' 14 | #' # attention_weights will be 5x5 matrix 15 | #' # context_vectors will be length 5 16 | #' dim(result$attention_weights) # [1] 5 5 17 | #' length(result$context_vectors) # [1] 5 18 | #' @export 19 | computeattention <- function(series) { 20 | # Input validation 21 | if (!is.numeric(series)) stop("series must be numeric") 22 | 23 | # Compute attention weights using Rcpp function 24 | attention_weights <- compute_attention_cpp(series) 25 | 26 | # Compute context vectors using Rcpp function 27 | context_vectors <- compute_context_vectors_cpp(series, attention_weights) 28 | 29 | # Add dimension names for clarity 30 | n <- length(series) 31 | dimnames(attention_weights) <- list( 32 | paste0("t", 1:n), 33 | paste0("t", 1:n) 34 | ) 35 | names(context_vectors) <- paste0("t", 1:n) 36 | 37 | return(list( 38 | attention_weights = attention_weights, 39 | context_vectors = context_vectors 40 | )) 41 | } -------------------------------------------------------------------------------- /R/conformalize.R: -------------------------------------------------------------------------------- 1 | #' Conformalize a forecasting function 2 | #' 3 | #' @description 4 | #' 5 | #' This function allows to conformalize any forecasting function. 6 | #' 7 | #' @param FUN A forecasting function. 8 | #' @param y A time series (\code{ts} object or vector). 9 | #' @param h Forecasting horizon. 10 | #' @param level Confidence level. 11 | #' @param method Method to be used for conformalization (simulation of calibrated residuals). 12 | #' @param nsim Number of simulations. 13 | #' @param block_size Block size for block-bootstrap. 14 | #' @param seed Seed for reproducibility. 15 | #' @param ... Additional arguments to be passed to the forecasting function. 16 | #' 17 | #' @return An object of class \code{forecast}. 18 | #' 19 | #' @examples 20 | #' 21 | #' y <- fdeaths 22 | #' h <- 25L 23 | #' obj <- conformalize(FUN=forecast::ets, y, h); plot(obj) 24 | #' obj <- conformalize(FUN=HoltWinters, y=y, h=h, seasonal = "mult"); plot(obj) 25 | #' 26 | conformalize <- function(FUN, y, h, level=95, 27 | method = c("block-bootstrap", "surrogate", 28 | "kde", "bootstrap", "fitdistr"), 29 | nsim = 100L, 30 | block_size = 5, 31 | seed = 123L, 32 | ...) 33 | { 34 | method <- match.arg(method) 35 | n <- length(y) 36 | freq_x <- frequency(y) 37 | half_n <- ceiling(n/2) 38 | idx_train <- seq_len(half_n) 39 | idx_calib <- setdiff(seq_len(n), idx_train) 40 | splitted_y <- misc::splitts(y) 41 | y_train <- splitted_y$training 42 | y_calib <- splitted_y$testing 43 | n_calib <- length(idx_calib) 44 | 45 | calib_resids <- ahead::genericforecast(y=y_train, h=n_calib, 46 | level=level, FUN=FUN, 47 | ...)$mean - y_calib 48 | scaled_calib_resids <- base::scale(calib_resids) 49 | xm <- attr(scaled_calib_resids, "scaled:center") 50 | xsd <- attr(scaled_calib_resids, "scaled:scale") 51 | obj_fcast <- ahead::genericforecast(y=y_calib, h=h, 52 | level=level, FUN=FUN, 53 | ...) # train on calibration set 54 | 55 | if (method == "fitdistr") 56 | { 57 | simulate_function <- misc::fit_param_dist(as.numeric(scaled_calib_resids), 58 | verbose = FALSE) 59 | sims <- matrix(simulate_function(nsim*h), ncol=nsim, nrow=h) 60 | preds <- as.numeric(obj_fcast$mean) + sims*xsd 61 | 62 | res <- list() 63 | res$level <- level 64 | res$x <- y_calib 65 | res$method <- paste0("conformalized ", obj_fcast$method) 66 | start_preds <- start(obj_fcast$mean) 67 | res$mean <- ts(rowMeans(preds), 68 | start = start_preds, 69 | frequency = freq_x) 70 | res$upper <- ts(apply(preds, 1, function(x) 71 | stats::quantile(x, probs = 1 - (1 - level / 100) / 2)), 72 | start = start_preds, 73 | frequency = freq_x) 74 | res$lower <- ts(apply(preds, 1, function(x) 75 | stats::quantile(x, probs = (1 - level / 100) / 2)), 76 | start = start_preds, 77 | frequency = freq_x) 78 | res$sims <- ts(preds, start = start_preds, 79 | frequency = freq_x) 80 | class(res) <- "forecast" 81 | return(res) 82 | } 83 | 84 | if (method == "block-bootstrap") 85 | { 86 | start_preds <- start(obj_fcast$mean) 87 | sims <- ts(sapply(1:nsim, function(i) mbb(matrix(scaled_calib_resids, 88 | ncol = 1), 89 | n=h, 90 | b=block_size, 91 | seed=i+seed*100)), 92 | start = start_preds, 93 | frequency = freq_x) 94 | preds <- as.numeric(obj_fcast$mean) + sims*xsd 95 | 96 | res <- list() 97 | res$level <- level 98 | res$x <- y_calib 99 | res$method <- paste0("conformalized ", obj_fcast$method) 100 | res$mean <- ts(rowMeans(preds), 101 | start = start_preds, 102 | frequency = freq_x) 103 | res$upper <- ts(apply(preds, 1, function(x) 104 | stats::quantile(x, probs = 1 - (1 - level / 100) / 2)), 105 | start = start_preds, 106 | frequency = freq_x) 107 | res$lower <- ts(apply(preds, 1, function(x) 108 | stats::quantile(x, probs = (1 - level / 100) / 2)), 109 | start = start_preds, 110 | frequency = freq_x) 111 | res$sims <- ts(preds, start = start_preds, 112 | frequency = freq_x) 113 | class(res) <- "forecast" 114 | return(res) 115 | } 116 | 117 | if (method %in% c("kde", "surrogate", "bootstrap")) 118 | { 119 | start_preds <- start(obj_fcast$mean) 120 | sims <- ts(matrix(direct_sampling(scaled_calib_resids, 121 | n = nsim*h, method=method), 122 | nrow = h, ncol = nsim), start = start_preds, 123 | frequency = freq_x) 124 | preds <- as.numeric(obj_fcast$mean) + sims*xsd 125 | 126 | res <- list() 127 | res$level <- level 128 | res$x <- y_calib 129 | res$method <- paste0("conformalized ", obj_fcast$method) 130 | res$mean <- ts(rowMeans(preds), 131 | start = start_preds, 132 | frequency = freq_x) 133 | res$upper <- ts(apply(preds, 1, function(x) 134 | stats::quantile(x, probs = 1 - (1 - level / 100) / 2)), 135 | start = start_preds, 136 | frequency = freq_x) 137 | res$lower <- ts(apply(preds, 1, function(x) 138 | stats::quantile(x, probs = (1 - level / 100) / 2)), 139 | start = start_preds, 140 | frequency = freq_x) 141 | res$sims <- ts(preds, start = start_preds, 142 | frequency = freq_x) 143 | class(res) <- "forecast" 144 | return(res) 145 | } 146 | } -------------------------------------------------------------------------------- /R/genforecast.R: -------------------------------------------------------------------------------- 1 | #' 2 | #' @title Generic Forecasting Function (Unified interface) 3 | #' 4 | #' @description 5 | #' 6 | #' This function allows to call any function "of class \code{forecast}" in a unified way. 7 | #' 8 | #' @param FUN A forecasting function. 9 | #' @param y A time series (\code{ts} object or vector). 10 | #' @param h Forecasting horizon. 11 | #' @param level The confidence level. 12 | #' @param ... Additional arguments to be passed to the forecasting function. 13 | #' 14 | #' @return An object of class \code{forecast}. 15 | #' 16 | #' @examples 17 | #' 18 | #' y <- fdeaths 19 | #' h <- 25L 20 | #' plot(genericforecast(FUN=forecast::thetaf, y, h)) 21 | #' plot(genericforecast(FUN=ahead::dynrmf, y, h)) 22 | #' plot(genericforecast(FUN=forecast::tbats, y=y, h=h, use.box.cox = TRUE, use.trend=FALSE)) 23 | #' 24 | #' @export 25 | #' 26 | genericforecast <- function(FUN, y, h, level=95, ...) 27 | { 28 | obj <- try(do.call(what=FUN, args=list(y = y, ...)), 29 | silent = TRUE) # forecast:: e.g 30 | if (inherits(obj, "try-error")) 31 | { 32 | obj <- try(do.call(what=FUN, args=list(x = y, ...)), 33 | silent = TRUE) # Holtwinters e.g 34 | } 35 | res <- try(forecast::forecast(obj, h=h, level=level, ...), 36 | silent = TRUE) 37 | if (inherits(res, "try-error")) 38 | { 39 | res <- do.call(what = FUN, 40 | args = list(y=y, h=h, ...)) 41 | } 42 | return(res) 43 | } -------------------------------------------------------------------------------- /R/getreturns.R: -------------------------------------------------------------------------------- 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 | } 38 | -------------------------------------------------------------------------------- /R/getsimulations.R: -------------------------------------------------------------------------------- 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 | } 43 | -------------------------------------------------------------------------------- /R/krrf.R: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/R/krrf.R -------------------------------------------------------------------------------- /R/loess.R: -------------------------------------------------------------------------------- 1 | 2 | 3 | #' Loess forecasting 4 | #' 5 | #' @param y A numeric vector or time series of class \code{ts} 6 | #' @param h Forecasting horizon 7 | #' @param level Confidence level for prediction intervals 8 | #' @param span the parameter which controls the degree of smoothing 9 | #' @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", (circular) "blockbootstrap", or "movingblockbootstrap" 11 | #' @param b block length for circular block bootstrap 12 | #' @param B number of bootstrap replications 13 | #' @param type_aggregation Type of aggregation, ONLY for bootstrapping; either "mean" or "median" 14 | #' @param seed reproducibility seed 15 | #' 16 | #' @return An object of class "forecast"; a list containing the following elements: 17 | #' 18 | #' \item{model}{A list containing information about the fitted model} 19 | #' \item{method}{The name of the forecasting method as a character string} 20 | #' \item{mean}{Point forecasts for the time series} 21 | #' \item{lower}{Lower bound for prediction interval} 22 | #' \item{upper}{Upper bound for prediction interval} 23 | #' \item{x}{The original time series} 24 | #' \item{residuals}{Residuals from the fitted model} 25 | #' \item{sims}{Model simulations for bootstrapping} 26 | #' 27 | #' @export 28 | #' 29 | #' @examples 30 | #' 31 | #' par(mfrow = c(3, 1)) 32 | #' 33 | #' plot(loessf(Nile, h=20, level=95, B=10)) 34 | #' 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 | #' 41 | loessf <- function(y, 42 | h = 5, 43 | level = 95, 44 | span = 0.75, 45 | degree = 2, 46 | type_pi = c("bootstrap", 47 | "blockbootstrap", 48 | "movingblockbootstrap"), 49 | b = NULL, 50 | B = 250, 51 | type_aggregation = c("mean", "median"), 52 | seed = 123) 53 | { 54 | freq_y <- frequency(y) 55 | if (length(y) <= 2 * freq_y) 56 | freq_y <- 1L 57 | 58 | if (is.null(b)) { 59 | b <- ifelse(freq_y > 1, 2 * freq_y, min(8, floor(length(y) / 2))) 60 | } 61 | 62 | type_pi <- match.arg(type_pi) 63 | type_aggregation <- match.arg(type_aggregation) 64 | 65 | # start and frequency for returned result 66 | tspy <- tsp(as.ts(y)) 67 | start_preds <- tspy[2] + 1 / tspy[3] 68 | 69 | # Adjust 70 | input_times <- stats::time(y) 71 | fit_loess <- stats::loess( 72 | value ~ time, 73 | data = cbind.data.frame(time = input_times, 74 | value = y), 75 | span = span, 76 | degree = degree, 77 | control = stats::loess.control(surface = "direct") 78 | ) 79 | resids <- ts(stats::residuals(fit_loess), 80 | start = start(y), 81 | frequency = freq_y) 82 | fitted_values <- ts(stats::fitted(fit_loess), 83 | start = start(y), 84 | frequency = freq_y) 85 | 86 | # point forecast 87 | 88 | time_y <- time(y) 89 | 90 | diff_time_y <- diff(time_y)[1] 91 | 92 | time_oos <- seq(time_y[length(time_y)] + diff_time_y, 93 | by = diff_time_y, 94 | length.out = h) 95 | 96 | fcast <- ts(as.numeric(predict(fit_loess, 97 | data.frame(time = time_oos))), 98 | start = start_preds, 99 | frequency = freq_y) 100 | 101 | simulations <- ts(matrix(NA, nrow = h, ncol = B), 102 | start = start_preds, 103 | frequency = freq_y) 104 | 105 | for (i in 1:B) 106 | { 107 | set.seed(100 * i + 3) 108 | # sampling from the residuals 109 | idx <- sample.int(n = length(resids), 110 | size = h, 111 | replace = TRUE) 112 | 113 | bootstrapped_residuals <- ts(switch( 114 | type_pi, 115 | bootstrap = matrix(resids, ncol = 1L)[idx,], 116 | blockbootstrap = drop( 117 | mbb( 118 | r = matrix(resids, ncol = 1L), 119 | n = h, 120 | b = b, 121 | seed = 100 * i + 3, 122 | return_indices = 123 | FALSE 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 | ), 135 | start = start_preds, 136 | frequency = freq_y) 137 | 138 | simulations[, i] <- ts(fcast + bootstrapped_residuals, 139 | start = start_preds, 140 | frequency = freq_y) 141 | } 142 | 143 | preds_upper <- preds_lower <- rep(0, h) 144 | 145 | preds_mean <- ts(switch(type_aggregation, 146 | mean = rowMeans(simulations), 147 | median = apply(simulations, 1, median)), 148 | start = start_preds, 149 | frequency = freq_y) 150 | 151 | preds_upper <- 152 | ts( 153 | apply(simulations, 1, function(x) 154 | quantile(x, probs = 1 - (1 - level / 100) / 2)), 155 | start = start_preds, 156 | frequency = freq_y 157 | ) 158 | 159 | preds_lower <- 160 | ts( 161 | apply(simulations, 1, function(x) 162 | quantile(x, probs = (1 - level / 100) / 2)), 163 | start = start_preds, 164 | frequency = freq_y 165 | ) 166 | 167 | out <- list( 168 | mean = preds_mean, 169 | lower = preds_lower, 170 | upper = preds_upper, 171 | level = level, 172 | fitted = fitted_values, 173 | residuals = resids, 174 | model = fit_loess, 175 | method = "loessf", 176 | sims = simulations, 177 | x = y 178 | ) 179 | 180 | # 'forecast' must be in the environment 181 | return(structure(out, class = "forecast")) 182 | } 183 | -------------------------------------------------------------------------------- /R/mlarch.R: -------------------------------------------------------------------------------- 1 | #' Conformalized Forecasting using Machine Learning models with ARCH effects 2 | #' 3 | #' @param y A numeric vector or time series of class \code{ts} 4 | #' @param h Forecasting horizon 5 | #' @param mean_model Function to fit the mean model (default: \code{forecast::auto.arima}) 6 | #' @param model_residuals Function to model the residuals (default: \code{forecast::thetaf}) 7 | #' @param fit_func Fitting function for the variance model (default: \code{ahead::ridge}) 8 | #' @param predict_func Prediction function for the variance model (default: \code{predict}) 9 | #' @param type_pi Type of prediction interval ("kde", "surrogate", or "bootstrap") for volatility modeling 10 | #' @param type_sim_conformalize Type of simulation for conformalization of standardized residuals ("block-bootstrap", "surrogate", "kde", "bootstrap", or "fitdistr") 11 | #' @param ml_method Machine learning method to use (if NULL, uses default methods) 12 | #' @param level Confidence level for prediction intervals 13 | #' @param B Number of bootstrap replications or simulations 14 | #' 15 | #' @return A forecast object containing predictions and prediction intervals 16 | #' @export 17 | #' 18 | #' @examples 19 | #' # Example usage will be added 20 | mlarchf <- function(y, h=10L, 21 | mean_model=forecast::auto.arima, 22 | model_residuals=forecast::thetaf, 23 | fit_func=ahead::ridge, 24 | predict_func=predict, 25 | type_pi = c("kde", "surrogate", "bootstrap"), 26 | type_sim_conformalize = c("block-bootstrap", "surrogate", "kde", "bootstrap", "fitdistr"), 27 | ml_method=NULL, 28 | level=95, 29 | B=250L) 30 | { 31 | if (!is.ts(y)) 32 | { 33 | y <- ts(y) 34 | } 35 | x <- y 36 | last_price <- as.numeric(tail(y, 1)) 37 | freq_x <- frequency(y) 38 | start_preds <- tsp(y)[2] + 1/freq_x 39 | type_pi <- match.arg(type_pi) 40 | type_sim_conformalize <- match.arg(type_sim_conformalize) 41 | fit_mean <- ahead::genericforecast(mean_model, y=y, h=h) 42 | 43 | if (!is.null(ml_method)) 44 | { 45 | fit_func <- function(x, y, method = ml_method, ...) 46 | { 47 | df <- data.frame(y=y, as.matrix(x)) 48 | colnames(df) <- c("y", paste0("X", 1:ncol(x))) 49 | caret::train(y ~ ., data=df, 50 | method = ml_method, 51 | trControl=caret::trainControl(method = "none")) 52 | } 53 | 54 | predict_func <- function(obj, newx) 55 | { 56 | colnames(newx) <- paste0("X", 1:ncol(newx)) 57 | predict(obj, newx) 58 | } 59 | } 60 | 61 | resids <- residuals(fit_mean) 62 | fit_sigma <- ahead::mlf(log(resids^2), 63 | lags = 2L, 64 | fit_func=fit_func, 65 | predict_func=predict_func, 66 | type_pi=type_pi, 67 | h=h, 68 | B = B) 69 | z <- resids/sqrt(exp(fitted(fit_sigma))) 70 | fit_z <- ahead::conformalize(FUN=model_residuals, 71 | method=type_sim_conformalize, 72 | nsim=B, 73 | y=z, h=h) 74 | #f <- as.numeric(fit_mean$mean) + matrix(fit_z$sims, ncol=B)*sqrt(pmax(matrix(fit_sigma$sims, ncol=B), 0)) # think about this clipping 75 | f <- as.numeric(fit_mean$mean) + matrix(fit_z$sims, ncol=B)*sqrt(matrix(exp(fit_sigma$sims), ncol=B)) 76 | mean_f <- rowMeans(f) 77 | alpha <- 1 - level/100 78 | lower_bound <- apply(f, 1, function(x) quantile(x, probs=alpha/2)) 79 | upper_bound <- apply(f, 1, function(x) quantile(x, probs=1-alpha/2)) 80 | out <- list() 81 | out$x <- x 82 | out$level <- level 83 | out$resids_t_test <- t.test(resids, conf.level = level/100) 84 | out$resids_kpss_test <- suppressWarnings(tseries::kpss.test(resids)) 85 | out$sims <- ts(f, start = start_preds, 86 | frequency = freq_x) 87 | if (!is.null(ml_method)) 88 | { 89 | out$method <- paste0(ml_method, "ARCH") 90 | } else { 91 | out$method <- "ML-ARCH" 92 | } 93 | out$model <- list(fit_mean, fit_sigma, fit_z) 94 | out$mean <- ts(mean_f, 95 | start = start_preds, 96 | frequency = freq_x) 97 | out$lower <- ts(lower_bound, 98 | start = start_preds, 99 | frequency = freq_x) 100 | out$upper <- ts(upper_bound, 101 | start = start_preds, 102 | frequency = freq_x) 103 | return(structure(out, class = "forecast")) 104 | } -------------------------------------------------------------------------------- /R/predict.foreccomb_res.R: -------------------------------------------------------------------------------- 1 | #' @name predict.foreccomb_res 2 | #' @title Prediction function for Forecast Combinations 3 | #' @description \code{prediction} method for class \sQuote{foreccomb_res}. Uses the previously created forecast combination 4 | #' result to predict the combination for a newly provided prediction dataset. 5 | #' 6 | #' @param object An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set. 7 | #' @param newobs A vector or univariate time series; contains \sQuote{actual values} if a test set is used (optional). 8 | #' @param newpreds A matrix or multivariate time series; contains individual model forecasts if a test set is used (optional). Does not 9 | #' require specification of \code{newobs} -- in the case in which a forecaster only wants to train the forecast combination method 10 | #' with a training set and apply it to future individual model forecasts, only \code{newpreds} is required, not \code{newobs}. 11 | #' @param simplify logical. The default (\code{TRUE}) returns the predictions separately. If set to (\code{FALSE}) the predictions are incorporated 12 | #' into the foreccomb_res object, that is, the object is equal to the one that would have been obtained, if the new prediction set would have 13 | #' been provided when the forecast combination method was trained originally. 14 | #' @param byrow logical. The default (\code{FALSE}) assumes that each column of the forecast matrices (\code{prediction_matrix} and -- if 15 | #' specified -- \code{newpreds}) contains forecasts from one forecast model; if each row of the matrices contains forecasts from 16 | #' one forecast model, set to \code{TRUE}. 17 | #' @param ... potential further arguments (require by generic) 18 | #' 19 | #' @seealso 20 | #' \code{\link[ForecastComb]{foreccomb}}, 21 | #' 22 | #' @author Adapted from Christoph E. Weiss and Gernot R. Roetzer (ForecastComb) 23 | #' 24 | #' @import forecast 25 | #' 26 | #' @rdname predict.foreccomb_res 27 | #' @method predict foreccomb_res 28 | #' @export 29 | predict.foreccomb_res <- function(object, newpreds, newobs = NULL, simplify=TRUE, byrow=FALSE, ...) { 30 | 31 | if (!is.null(newpreds)) { 32 | if (byrow==TRUE){ 33 | newpreds <- t(as.matrix(newpreds)) 34 | } 35 | 36 | if (ncol(object$Input_Data$Forecasts_Train) != ncol(newpreds)) 37 | stop("Test set predictions and training set predictions must contain same individual forecasts. Number of forecasts differ.", call. = FALSE) 38 | } 39 | 40 | if (sum(is.na(newpreds)) > 0) { 41 | stop("Calling predict with newpreds containing NAs is not yet supported. Please use the classical foreccomb object approach.", call. = FALSE) 42 | } 43 | 44 | if(!is.null(newobs) & sum(is.null(newobs)) > 0) { 45 | stop("New observations for the test set cannot contain NAs.") 46 | } 47 | 48 | if (!is.ts(newpreds)) { 49 | newpreds <- stats::ts(newpreds) 50 | } 51 | 52 | colnames(newpreds) <- colnames(object$Input_Data$Forecasts_Train) 53 | 54 | if (is.null(object$Predict)) { 55 | pred <- stats::ts(as.vector(newpreds %*% object$Weights)) 56 | } else { 57 | pred <- object$Predict(object, newpreds) 58 | } 59 | 60 | attributes(pred)$tsp <- attributes(newpreds)$tsp 61 | 62 | if (simplify) { 63 | result <- pred 64 | } else { 65 | object[['Forecasts_Test']] <- pred 66 | object$Input_Data[['Forecasts_Test']] <- newpreds 67 | 68 | if (!is.null(newobs)) { 69 | accuracy_outsample <- accuracy(pred, newobs) 70 | object[['Accuracy_Test']] <- accuracy_outsample 71 | rownames(result$Accuracy_Test) <- "Test Set" 72 | } 73 | 74 | result <- object 75 | } 76 | 77 | return(result) 78 | } -------------------------------------------------------------------------------- /R/ridge.R: -------------------------------------------------------------------------------- 1 | #' #' Forecasts from ridge regression models 2 | #' #' 3 | #' #' @param y A multivariate (for now) time series of class \code{ts} (preferred) or a \code{matrix} 4 | #' #' @param h Forecasting horizon 5 | #' #' @param level Confidence level for prediction intervals 6 | #' #' @param lags Number of lags to include in the model 7 | #' #' @param nb_hidden Number of hidden units in the neural network 8 | #' #' @param fit_method Method to fit the model. Either \code{ridge} for elastic net or \code{mgaussian} for multivariate Gaussian elastic net 9 | #' #' @param nodes_sim Method to generate the nodes for the simulation of the multivariate . Either \code{sobol}, \code{halton} or \code{unif} 10 | #' #' @param activ Activation function for the hidden layer. Either \code{relu}, \code{sigmoid}, \code{tanh}, \code{leakyrelu}, \code{elu} or \code{linear} 11 | #' #' @param hidden_layer_bias Whether to include a bias term in the hidden layer 12 | #' #' @param a Hyperparameter for activation function "leakyrelu", "elu" 13 | #' #' @param lambda Hyperparameter for elastic net (regularization parameter) 14 | #' #' @param alpha Hyperparameter for elastic net (compromise between ridge and lasso) 15 | #' #' @param seed Seed for reproducibility 16 | #' #' @param type_ci Type of confidence interval. Either \code{none}, \code{parametric} or \code{nonparametric} 17 | #' #' @param type_forecast Type of forecast. Either \code{recursive} or \code{direct} 18 | #' #' 19 | #' #' @return an object of class \code{mforecast}; a list containing the following elements: 20 | #' #' \item{mean}{Point forecasts for the time series} \item{resid}{Residuals from the fitted model} 21 | #' #' \item{model}{A list containing information about the fitted model} 22 | #' #' \item{method}{The name of the forecasting method as a character string} 23 | #' #' \item{x}{The original time series} 24 | #' #' 25 | #' #' @export 26 | #' #' 27 | #' #' @examples 28 | #' #' 29 | #' #' 30 | #' ridgef <- function(y, h = 5, 31 | #' level = 95, 32 | #' lags = 1, 33 | #' nb_hidden = 5, 34 | #' fit_method = c("ridge", "mgaussian"), 35 | #' nodes_sim = c("sobol", "halton", "unif"), 36 | #' activ = c("relu", "sigmoid", "tanh", 37 | #' "leakyrelu", "elu", "linear"), 38 | #' hidden_layer_bias = FALSE, 39 | #' a = 0.01, 40 | #' lambda = 0.1, 41 | #' alpha = 0.5, 42 | #' seed = 1, 43 | #' type_pi = "none", 44 | #' type_forecast = c("recursive", "direct")) 45 | #' { 46 | #' if (!is.ts(y)) 47 | #' { 48 | #' x <- ts(y) 49 | #' } else { 50 | #' x <- y 51 | #' } 52 | #' 53 | #' freq_x <- frequency(x) 54 | #' start_fits <- start(x) 55 | #' start_preds <- tsp(x)[2] + 1/freq_x 56 | #' n_series <- ncol(x) 57 | #' 58 | #' fit_method <- match.arg(fit_method) 59 | #' nodes_sim <- match.arg(nodes_sim) 60 | #' activ <- match.arg(activ) 61 | #' type_forecast <- match.arg(type_forecast) 62 | #' 63 | #' # Fitting a regularized regression model to multiple time series 64 | #' fit_obj <- fit_ridge_mts( 65 | #' x, 66 | #' lags = lags, 67 | #' nb_hidden = nb_hidden, 68 | #' fit_method = fit_method, 69 | #' nodes_sim = nodes_sim, 70 | #' activ = activ, 71 | #' hidden_layer_bias = hidden_layer_bias, 72 | #' a = a, 73 | #' lambda = lambda, 74 | #' alpha = alpha, 75 | #' seed = seed 76 | #' ) 77 | #' 78 | #' # Forecast from fit_obj 79 | #' 80 | #' preds <- ts(data = fcast_obj_mts(fit_obj, 81 | #' h = h, 82 | #' type_pi = type_pi, 83 | #' type_forecast = type_forecast, 84 | #' level = level), 85 | #' start = start_preds, frequency = freq_x) 86 | #' 87 | #' resids <- ts(data = fit_obj$resid, 88 | #' start = start_preds, frequency = freq_x) 89 | #' 90 | #' # Forecast from fit_obj 91 | #' forecasts <- lapply(1:n_series, 92 | #' FUN = function (i) {structure(ts(preds[,i], 93 | #' start = start_preds, 94 | #' frequency = freq_x), class = "forecast")}) 95 | #' 96 | #' names(forecasts) <- colnames(x) 97 | #' 98 | #' out <- list(mean = preds, 99 | #' residuals = resids, 100 | #' method = fit_method, 101 | #' model = fit_obj, 102 | #' x = x, 103 | #' forecast = forecasts) 104 | #' 105 | #' return(structure(out, class = "mforecast")) 106 | #' } 107 | #' ridgef <- compiler::cmpfun(ridgef) 108 | -------------------------------------------------------------------------------- /R/sampling.R: -------------------------------------------------------------------------------- 1 | 2 | #' Direct sampling 3 | #' 4 | #' @param data A numeric vector or matrix. 5 | #' @param n The number of samples to draw. 6 | #' @param method The method to use for sampling. 7 | #' @param kde The kernel density estimate to use for sampling. 8 | #' @param seed The seed to use for sampling. 9 | #' @param ... Additional arguments to pass to the density function. 10 | #' 11 | #' @export 12 | #' 13 | direct_sampling <- function(data = NULL, n = 100L, 14 | method = c("kde", 15 | "surrogate", 16 | "bootstrap"), 17 | kde = NULL, 18 | seed = NULL, 19 | ...) { 20 | method <- match.arg(method) 21 | if (!is.null(seed)) 22 | { 23 | set.seed(seed) 24 | } 25 | if (identical(method, "kde")) 26 | { 27 | if (is.null(kde)) { 28 | stopifnot(!is.null(data)) 29 | kde <- density(data, bw = "SJ", ...) 30 | } else if (is.null(data)) 31 | { 32 | stopifnot(!is.null(kde)) 33 | } 34 | prob <- kde$y / sum(kde$y) 35 | return(sample(kde$x, size = n, replace = TRUE, prob = prob)) 36 | } 37 | 38 | if (identical(method, "surrogate")) 39 | { 40 | return(sample(tseries::surrogate(data, ns = 1, ...), 41 | size = n, 42 | replace = TRUE)) 43 | } 44 | 45 | if (identical(method, "bootstrap")) 46 | { 47 | return(sample(tseries::tsbootstrap(data, nb = 1, type = "block", b = 1, ...), 48 | size = n, 49 | replace = TRUE)) 50 | } 51 | } 52 | 53 | 54 | # Simulate multivariate data ----- 55 | 56 | #' Simulate multivariate data 57 | #' 58 | #' @param data A numeric vector or matrix. 59 | #' @param method The method to use for sampling. 60 | #' @param n The number of samples to draw. 61 | #' @param block_size The size of the blocks to use for the block bootstrap. 62 | #' @param ... Additional arguments to pass to the density function. 63 | #' 64 | #' @export 65 | #' 66 | rmultivariate <- function(data, method = c("bootstrap", "block-bootstrap"), 67 | n = 100L, block_size = 5) { 68 | method <- match.arg(method) 69 | 70 | # Ensure data is a matrix 71 | if (!is.matrix(data)) data <- as.matrix(data) 72 | n_rows <- nrow(data) 73 | 74 | if (method == "bootstrap") { 75 | # Simple resampling with replacement 76 | return(data[sample(seq_len(n_rows), size = n, replace = TRUE), ]) 77 | } 78 | 79 | if (method == "block-bootstrap") { 80 | # Moving block bootstrap (for time series) 81 | blocks <- split(1:n_rows, ceiling(seq_along(1:n_rows) / block_size)) 82 | sampled_blocks <- sample(blocks, size = ceiling(n / block_size), replace = TRUE) 83 | sampled_indices <- unlist(sampled_blocks)[1:n] # Trim excess if necessary 84 | return(data[sampled_indices, ]) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /R/splitts.R: -------------------------------------------------------------------------------- 1 | #' Partition a time series object 2 | #' 3 | #' @param y A time series object 4 | #' @param split_prob Splitting ratio 5 | #' @param return_indices if TRUE, returns series' indices, otherwise, time series objects 6 | #' 7 | #' @export 8 | #' @examples 9 | #' 10 | #' misc::splitts(ts(1:10)) 11 | #' 12 | splitts <- 13 | function(y, 14 | split_prob = 0.5, 15 | return_indices = FALSE) 16 | { 17 | n_y <- base::ifelse(test = is.null(dim(y)), 18 | yes = length(y), 19 | no = dim(y)[1]) 20 | 21 | index_train <- 1:floor(split_prob * n_y) 22 | if (return_indices) 23 | return(index_train) 24 | 25 | start_y <- stats::start(y) 26 | frequency_y <- stats::frequency(y) 27 | 28 | if (is.null(ncol(y))) 29 | # univariate case 30 | { 31 | training <- ts(y[index_train], 32 | start = start_y, 33 | frequency = frequency_y) 34 | start_testing <- tsp(training)[2] + 1 / frequency_y 35 | return(list( 36 | training = training, 37 | testing = ts(y[-index_train], 38 | start = start_testing, 39 | frequency = frequency_y) 40 | )) 41 | } else { 42 | # multivariate case 43 | training <- ts(y[index_train, ], 44 | start = start_y, 45 | frequency = frequency_y) 46 | start_testing <- tsp(training)[2] + 1 / frequency_y 47 | return(list( 48 | training = training, 49 | testing = ts(y[-index_train, ], 50 | start = start_testing, 51 | frequency = frequency_y) 52 | )) 53 | } 54 | } -------------------------------------------------------------------------------- /R/summary.foreccomb_res.R: -------------------------------------------------------------------------------- 1 | #' @name summary.foreccomb_res 2 | #' @aliases print.foreccomb_res_summary 3 | 4 | #' @title Summary of Forecast Combination 5 | #' @description \code{summary} method for class \sQuote{foreccomb_res}. Includes information about combination method, 6 | #' combination weights assigned to the individual forecast models, as well as an accuracy evaluation of the combined 7 | #' forecast. 8 | #' 9 | #' @param object An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set. 10 | #' @param x An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set. 11 | #' @param ... potential further arguments (require by generic) 12 | #' 13 | #' 14 | #' @seealso 15 | #' \code{\link[ForecastComb]{foreccomb}}, 16 | #' \code{\link[ForecastComb]{plot.foreccomb_res}}, 17 | #' 18 | #' @author Christoph E. Weiss and Gernot R. Roetzer 19 | #' 20 | #' @import forecast 21 | #' 22 | #' @rdname summary.foreccomb_res 23 | #' @method summary foreccomb_res 24 | #' @export 25 | summary.foreccomb_res <- function(object, ...) { 26 | if (!inherits(object, "foreccomb_res")) 27 | stop("Data must be class 'foreccomb'. See ?foreccomb, to bring data in correct format.", call. = FALSE) 28 | 29 | ans <- list() 30 | 31 | ans$Method <- object$Method 32 | 33 | if (!is.character(object$Weights)) { 34 | if(is.null(dim(object$Weights))){ 35 | ans$weight <- matrix(object$Weights, ncol = 1) 36 | colnames(ans$weight) <- "Combination Weight" 37 | rownames(ans$weight) <- object$Models 38 | } 39 | else{ 40 | ans$weight <- matrix(object$Weights[dim(object$Weights)[1],], ncol = 1) 41 | colnames(ans$weight) <- "Combination Weight (End of Test Set)" 42 | rownames(ans$weight) <- object$Models 43 | } 44 | } else { 45 | ans$weight <- "Weights of the individual forecasts differ over time with trimmed mean" 46 | } 47 | 48 | ans$Intercept <- object$Intercept 49 | if(!is.null(ans$Intercept) & length(ans$Intercept)>1) 50 | ans$Intercept <- ans$Intercept[length(ans$Intercept)] 51 | 52 | ans$accuracy <- as.data.frame(rbind(object$Accuracy_Train[1:5], object$Accuracy_Test)) 53 | rownames(ans$accuracy)[1] <- "Training Set" 54 | colnames(ans$accuracy) <- c("ME", "RMSE", "MAE", "MPE", "MAPE") 55 | 56 | ans$data <- deparse(substitute(object)) 57 | 58 | ans <- append(ans, subset(object, !(names(object) %in% c("Method", "Weights", "Intercept", "Accuracy_Train", "Accuracy_Test")))) 59 | 60 | class(ans) <- c("foreccomb_res_summary") 61 | 62 | return(ans) 63 | } 64 | 65 | #' @rdname summary.foreccomb_res 66 | #' @method print foreccomb_res_summary 67 | #' @export 68 | print.foreccomb_res_summary <- function(x, ...) { 69 | if (inherits(x, "foreccomb_res_summary")) 70 | stop("Data must be class 'foreccomb_res_summary'", call. = FALSE) 71 | 72 | cat("\n") 73 | cat("Summary of Forecast Combination \n") 74 | cat("------------------------------- \n") 75 | cat("\n") 76 | cat("Method: ", x$Method, "\n") 77 | cat("\n") 78 | cat("Individual Forecasts & Combination Weights: \n") 79 | if (!is.character(x$weight)) { 80 | cat("\n") 81 | print(x$weight) 82 | } else { 83 | cat(x$weight) 84 | cat("\n") 85 | } 86 | cat("\n") 87 | if (!is.null(x$Intercept)) { 88 | cat("Intercept (Bias-Correction): ", x$Intercept, "\n") 89 | cat("\n") 90 | } 91 | cat("Accuracy of Combined Forecast: \n") 92 | cat("\n") 93 | print(x$accuracy) 94 | cat("\n") 95 | cat("Additional information can be extracted from the combination object: \n") 96 | cat("For fitted values (training set): ", paste0(x$data, "$Fitted"), "\n") 97 | if (!is.null(x$Forecasts_Test)) { 98 | cat("For forecasts (test set): ", paste0(x$data, "$Forecasts_Test"), "\n") 99 | } 100 | cat("See ", paste0("str(", x$data, ")"), " for full list.") 101 | } -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/R/zzz.R -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # ahead 3 | 4 | Univariate and multivariate time series forecasting, with uncertainty quantification. 5 | 6 | [![Documentation](https://img.shields.io/badge/documentation-is_here-green)](https://techtonique.github.io/ahead/index.html) 7 | 8 | 9 | ### Installation 10 | 11 | - __1st method__, released version: from [Techtonique's R package's repository](https://r-packages.techtonique.net) 12 | 13 | In R console: 14 | 15 | ```R 16 | options(repos = c( 17 | techtonique = "https://r-packages.techtonique.net", 18 | CRAN = "https://cloud.r-project.org" 19 | )) 20 | 21 | install.packages("ahead") 22 | ``` 23 | 24 | - __2nd method__: from Github 25 | 26 | In R console: 27 | 28 | ```R 29 | devtools::install_github("Techtonique/ahead") 30 | ``` 31 | 32 | ### Demo 33 | 34 | For univariate and multivariate time series. 35 | 36 | #### 1 - Univariate time series 37 | 38 | ##### 1 - 1 Example 1: with `dynrmf` (type `?dynrmf` in R console for more details) and Random Forest 39 | 40 | ```R 41 | require(fpp) 42 | 43 | par(mfrow=c(3, 2)) 44 | plot(dynrmf(USAccDeaths, h=20, level=95, fit_func = randomForest::randomForest, 45 | fit_params = list(ntree = 50), predict_func = predict)) 46 | plot(dynrmf(AirPassengers, h=20, level=95, fit_func = randomForest::randomForest, 47 | fit_params = list(ntree = 50), predict_func = predict)) 48 | plot(dynrmf(lynx, h=20, level=95, fit_func = randomForest::randomForest, 49 | fit_params = list(ntree = 50), predict_func = predict)) 50 | plot(dynrmf(WWWusage, h=20, level=95, fit_func = randomForest::randomForest, 51 | fit_params = list(ntree = 50), predict_func = predict)) 52 | plot(dynrmf(Nile, h=20, level=95, fit_func = randomForest::randomForest, 53 | fit_params = list(ntree = 50), predict_func = predict)) 54 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = randomForest::randomForest, 55 | fit_params = list(ntree = 50), predict_func = predict)) 56 | ``` 57 | 58 | 59 | ##### 1 - 2 Example 2: with `dynrmf` and Support Vector Machines 60 | 61 | ```R 62 | require(e1071) 63 | 64 | par(mfrow=c(2, 2)) 65 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 66 | fit_params = list(kernel = "linear"), predict_func = predict)) 67 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 68 | fit_params = list(kernel = "polynomial"), predict_func = predict)) 69 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 70 | fit_params = list(kernel = "radial"), predict_func = predict)) 71 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 72 | fit_params = list(kernel = "sigmoid"), predict_func = predict)) 73 | ``` 74 | 75 | For more examples on `dynrmf`, you can read this [blog post](https://thierrymoudiki.github.io/blog/2021/12/20/r/forecasting/ahead-more-examples). 76 | 77 | #### 2 - Multivariate time series 78 | 79 | With `ridge2f` (type `?ridge2f` in R console for more details), the model from : 80 | 81 | Moudiki, T., Planchet, F., & Cousin, A. (2018). 82 | Multiple time series forecasting using quasi-randomized 83 | functional link neural networks. Risks, 6(1), 22. 84 | 85 | ```R 86 | require(fpp) 87 | 88 | print(ahead::ridge2f(fpp::insurance)$mean) 89 | print(ahead::ridge2f(fpp::usconsumption)$lower) 90 | 91 | res <- ahead::ridge2f(fpp::insurance, lags=2) 92 | par(mfrow=c(1, 2)) 93 | plot(res, "Quotes") 94 | plot(res, "TV.advert") 95 | ``` 96 | 97 | ### Contributing 98 | 99 | Your contributions are welcome. Please, make sure to __read__ the [Code of Conduct](CONTRIBUTING.md) first. 100 | 101 | ### Note to self 102 | 103 | ```bash 104 | git remote set-url origin https://username:your_generated_token@github.com/xxx/repo.git 105 | ``` 106 | 107 | ```bash 108 | git remote set-url origin https://MY_GITHUB_TOKEN@github.com/Techtonique/ahead.git 109 | ``` 110 | 111 | ### License 112 | 113 | [BSD 3-Clause](LICENSE) © Thierry Moudiki, 2019. 114 | 115 | -------------------------------------------------------------------------------- /man/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/man/.DS_Store -------------------------------------------------------------------------------- /man/armagarchf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/armagarch.R 3 | \name{armagarchf} 4 | \alias{armagarchf} 5 | \title{ARMA(1, 1)-GARCH(1, 1) forecasting (with simulation)} 6 | \usage{ 7 | armagarchf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | B = 250, 12 | cl = 1L, 13 | dist = c("student", "gaussian"), 14 | seed = 123 15 | ) 16 | } 17 | \arguments{ 18 | \item{y}{a univariate time series} 19 | 20 | \item{h}{number of periods for forecasting} 21 | 22 | \item{level}{confidence level for prediction intervals} 23 | 24 | \item{B}{number of simulations for \code{arima.sim}} 25 | 26 | \item{cl}{an integer; the number of clusters for parallel execution} 27 | 28 | \item{dist}{distribution of innovations ("student" or "gaussian")} 29 | 30 | \item{seed}{reproducibility seed} 31 | } 32 | \value{ 33 | An object of class "forecast"; a list containing the following elements: 34 | 35 | \item{model}{A list containing information about the fitted model} 36 | \item{method}{The name of the forecasting method as a character string} 37 | \item{mean}{Point forecasts for the time series} 38 | \item{lower}{Lower bound for prediction interval} 39 | \item{upper}{Upper bound for prediction interval} 40 | \item{x}{The original time series} 41 | \item{sims}{Simulations of ARMA(1, 1)-GARCH(1, 1)} 42 | } 43 | \description{ 44 | ARMA(1, 1)-GARCH(1, 1) forecasting (with simulation) 45 | } 46 | \examples{ 47 | 48 | y <- datasets::EuStockMarkets[ , "DAX"] 49 | log_returns <- ts(log(y[-1]/y[-length(y)])) 50 | 51 | # require(forecast) 52 | # z <- ahead::armagarchf(y=log_returns, h=200) 53 | # plot(z) 54 | 55 | 56 | } 57 | \author{ 58 | T. Moudiki 59 | } 60 | -------------------------------------------------------------------------------- /man/basicf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/basic.R 3 | \name{basicf} 4 | \alias{basicf} 5 | \title{Basic forecasting (mean, median, random walk)} 6 | \usage{ 7 | basicf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | method = c("mean", "median", "rw"), 12 | type_pi = c("gaussian", "bootstrap", "blockbootstrap", "movingblockbootstrap"), 13 | block_length = NULL, 14 | seed = 1, 15 | B = 100, 16 | show_progress = TRUE 17 | ) 18 | } 19 | \arguments{ 20 | \item{y}{A multivariate time series of class \code{ts} or a matrix} 21 | 22 | \item{h}{Forecasting horizon} 23 | 24 | \item{level}{Confidence level for prediction intervals} 25 | 26 | \item{method}{forecasting method, either "mean", "median", or random walk ("rw")} 27 | 28 | \item{type_pi}{type of prediction interval currently, "gaussian", "bootstrap", 29 | "blockbootstrap" or "movingblockbootstrap"} 30 | 31 | \item{block_length}{length of block for (circular) "blockbootstrap" or 32 | "movingblockbootstrap"} 33 | 34 | \item{seed}{reproducibility seed for \code{type_pi == 'bootstrap'}} 35 | 36 | \item{B}{Number of bootstrap replications for \code{type_pi == 'bootstrap'}} 37 | 38 | \item{show_progress}{A boolean; show progress bar for bootstrapping? Default is TRUE.} 39 | } 40 | \value{ 41 | An object of class "mtsforecast"; a list containing the following elements: 42 | 43 | \item{method}{The name of the forecasting method as a character string} 44 | \item{mean}{Point forecasts for the time series} 45 | \item{lower}{Lower bound for prediction interval} 46 | \item{upper}{Upper bound for prediction interval} 47 | \item{sims}{Model simulations for bootstrapping (basic, or block)} 48 | \item{x}{The original time series} 49 | \item{residuals}{Residuals from the fitted model} 50 | \item{coefficients}{Regression coefficients for \code{type_pi == 'gaussian'} for now} 51 | } 52 | \description{ 53 | Basic forecasting functions for multivariate time series 54 | } 55 | \examples{ 56 | 57 | require(fpp) 58 | 59 | res <- ahead::basicf(fpp::insurance, h=10) 60 | par(mfrow=c(1, 2)) 61 | plot(res, "TV.advert") 62 | plot(res, "Quotes") 63 | 64 | 65 | res <- ahead::basicf(fpp::insurance, method="rw", h=10) 66 | par(mfrow=c(1, 2)) 67 | plot(res, "TV.advert") 68 | plot(res, "Quotes") 69 | 70 | 71 | # block bootstrap 72 | res3 <- ahead::basicf(fpp::insurance, h=10, type_pi = "bootstrap", B=10) 73 | res5 <- ahead::basicf(fpp::insurance, h=10, type_pi = "blockbootstrap", B=10, 74 | block_length = 4) 75 | 76 | print(res3$sims[[2]]) 77 | print(res5$sims[[2]]) 78 | 79 | par(mfrow=c(2, 2)) 80 | plot(res3, "Quotes") 81 | plot(res3, "TV.advert") 82 | plot(res5, "Quotes") 83 | plot(res5, "TV.advert") 84 | 85 | 86 | # moving block bootstrap 87 | res6 <- ahead::basicf(fpp::insurance, h=10, 88 | type_pi = "movingblockbootstrap", B=10, 89 | block_length = 4, method = "rw") 90 | 91 | par(mfrow=c(1, 2)) 92 | plot(res6, "Quotes") 93 | plot(res6, "TV.advert") 94 | 95 | } 96 | -------------------------------------------------------------------------------- /man/comb_GLMNET.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/comb_GLMNET.R 3 | \name{comb_GLMNET} 4 | \alias{comb_GLMNET} 5 | \title{GLMNET Regression Forecast Combination} 6 | \usage{ 7 | comb_GLMNET(x, custom_error = NULL) 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set.} 11 | } 12 | \value{ 13 | Returns an object of class \code{ForecastComb::foreccomb_res} with the following components: 14 | \item{Method}{Returns the best-fit forecast combination method.} 15 | \item{Models}{Returns the individual input models that were used for the forecast combinations.} 16 | \item{Weights}{Returns the combination weights obtained by applying the combination method to the training set.} 17 | \item{Intercept}{Returns the intercept of the linear regression.} 18 | \item{Fitted}{Returns the fitted values of the combination method for the training set.} 19 | \item{Accuracy_Train}{Returns range of summary measures of the forecast accuracy for the training set.} 20 | \item{Forecasts_Test}{Returns forecasts produced by the combination method for the test set. Only returned if input included a forecast matrix for the test set.} 21 | \item{Accuracy_Test}{Returns range of summary measures of the forecast accuracy for the test set. Only returned if input included a forecast matrix and a vector of actual values for the test set.} 22 | \item{Input_Data}{Returns the data forwarded to the method.} 23 | } 24 | \description{ 25 | Computes forecast combination weights using GLMNET Regression (OLS) regression. 26 | } 27 | \details{ 28 | The function integrates the GLMNET Regression forecast combination implementation of the 29 | \emph{ForecastCombinations} package into ForecastComb. 30 | 31 | The results are stored in an object of class 'ForecastComb::foreccomb_res', for which separate plot and summary functions are provided. 32 | } 33 | \examples{ 34 | 35 | library(ForecastComb) 36 | 37 | data(electricity) 38 | 39 | print(head(electricity)) 40 | 41 | forecasting_methods <- colnames(electricity)[1:5] 42 | 43 | train_obs <- electricity[1:84, "Actual"] 44 | train_pred <- electricity[1:84, forecasting_methods] 45 | test_obs <- electricity[85:123, "Actual"] 46 | test_pred <- electricity[85:123, forecasting_methods] 47 | data <- ForecastComb::foreccomb(train_obs, train_pred, test_obs, test_pred) 48 | 49 | # obj <- ahead::comb_GLMNET(data)) 50 | 51 | } 52 | \seealso{ 53 | \code{\link[ForecastCombinations]{Forecast_comb}}, 54 | \code{\link{foreccomb}}, 55 | \code{\link{plot.ForecastComb::foreccomb_res}}, 56 | \code{\link{summary.ForecastComb::foreccomb_res}}, 57 | \code{\link[forecast]{accuracy}} 58 | } 59 | \keyword{models} 60 | -------------------------------------------------------------------------------- /man/comb_OLS.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/comb_OLS.R 3 | \name{comb_OLS} 4 | \alias{comb_OLS} 5 | \title{Ordinary Least Squares Forecast Combination} 6 | \usage{ 7 | comb_OLS(x, custom_error = NULL) 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set.} 11 | } 12 | \value{ 13 | Returns an object of class \code{ForecastComb::foreccomb_res} with the following components: 14 | \item{Method}{Returns the best-fit forecast combination method.} 15 | \item{Models}{Returns the individual input models that were used for the forecast combinations.} 16 | \item{Weights}{Returns the combination weights obtained by applying the combination method to the training set.} 17 | \item{Intercept}{Returns the intercept of the linear regression.} 18 | \item{Fitted}{Returns the fitted values of the combination method for the training set.} 19 | \item{Accuracy_Train}{Returns range of summary measures of the forecast accuracy for the training set.} 20 | \item{Forecasts_Test}{Returns forecasts produced by the combination method for the test set. Only returned if input included a forecast matrix for the test set.} 21 | \item{Accuracy_Test}{Returns range of summary measures of the forecast accuracy for the test set. Only returned if input included a forecast matrix and a vector of actual values for the test set.} 22 | \item{Input_Data}{Returns the data forwarded to the method.} 23 | } 24 | \description{ 25 | Computes forecast combination weights using ordinary least squares (OLS) regression. 26 | } 27 | \details{ 28 | The function integrates the ordinary least squares (OLS) forecast combination implementation of the 29 | \emph{ForecastCombinations} package into ForecastComb. 30 | 31 | The OLS combination method (Granger and Ramanathan (1984)) uses ordinary least squares to 32 | estimate the weights, \eqn{\mathbf{w}^{OLS} = (w_1, \ldots, w_N)'}, as well as an intercept, \eqn{b}, for the combination of 33 | the forecasts. 34 | 35 | Suppose that there are \eqn{N} not perfectly collinear predictors \eqn{\mathbf{f}_t = (f_{1t}, \ldots, f_{Nt})'}, 36 | then the forecast combination for one data point can be represented as: 37 | \deqn{y_t = b + \sum_{i=1}^{N} w_i f_{it}} 38 | 39 | An appealing feature of the method is its bias correction through the intercept -- even if one or more of the individual 40 | predictors are biased, the resulting combined forecast is unbiased. A disadvantage of the method is that it places no 41 | restriction on the combination weights (i.e., they do not add up to 1 and can be negative), which can make interpretation 42 | hard. Another issue, documented in Nowotarski et al. (2014), is the method's unstable behavior 43 | when predictors are highly correlated (which is the norm in forecast combination): Minor fluctuations in the sample 44 | can cause major shifts of the coefficient vector (\sQuote{bouncing betas}) -- often causing poor out-of-sample performance. 45 | This issue is addressed by the \code{\link{comb_LAD}} method that is more robust to outliers. 46 | 47 | The results are stored in an object of class 'ForecastComb::foreccomb_res', for which separate plot and summary functions are provided. 48 | } 49 | \examples{ 50 | obs <- rnorm(100) 51 | preds <- matrix(rnorm(1000, 1), 100, 10) 52 | train_o<-obs[1:80] 53 | train_p<-preds[1:80,] 54 | test_o<-obs[81:100] 55 | test_p<-preds[81:100,] 56 | 57 | data<-ForecastComb::foreccomb(train_o, train_p, test_o, test_p) 58 | ahead::comb_OLS(data) 59 | 60 | } 61 | \seealso{ 62 | \code{\link[ForecastCombinations]{Forecast_comb}}, 63 | \code{\link{foreccomb}}, 64 | \code{\link{plot.ForecastComb::foreccomb_res}}, 65 | \code{\link{summary.ForecastComb::foreccomb_res}}, 66 | \code{\link[forecast]{accuracy}} 67 | } 68 | \keyword{models} 69 | -------------------------------------------------------------------------------- /man/comb_Ridge.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/comb_Ridge.R 3 | \name{comb_Ridge} 4 | \alias{comb_Ridge} 5 | \title{Ridge Regression Forecast Combination} 6 | \usage{ 7 | comb_Ridge(x, custom_error = NULL) 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set.} 11 | } 12 | \value{ 13 | Returns an object of class \code{ForecastComb::foreccomb_res} with the following components: 14 | \item{Method}{Returns the best-fit forecast combination method.} 15 | \item{Models}{Returns the individual input models that were used for the forecast combinations.} 16 | \item{Weights}{Returns the combination weights obtained by applying the combination method to the training set.} 17 | \item{Intercept}{Returns the intercept of the linear regression.} 18 | \item{Fitted}{Returns the fitted values of the combination method for the training set.} 19 | \item{Accuracy_Train}{Returns range of summary measures of the forecast accuracy for the training set.} 20 | \item{Forecasts_Test}{Returns forecasts produced by the combination method for the test set. Only returned if input included a forecast matrix for the test set.} 21 | \item{Accuracy_Test}{Returns range of summary measures of the forecast accuracy for the test set. Only returned if input included a forecast matrix and a vector of actual values for the test set.} 22 | \item{Input_Data}{Returns the data forwarded to the method.} 23 | } 24 | \description{ 25 | Computes forecast combination weights using Ridge Regression (OLS) regression. 26 | } 27 | \details{ 28 | The function integrates the Ridge Regression forecast combination implementation of the 29 | \emph{ForecastCombinations} package into ForecastComb. 30 | 31 | The results are stored in an object of class 'ForecastComb::foreccomb_res', for which separate plot and summary functions are provided. 32 | } 33 | \examples{ 34 | obs <- rnorm(100) 35 | preds <- matrix(rnorm(1000, 1), 100, 10) 36 | train_o<-obs[1:80] 37 | train_p<-preds[1:80,] 38 | test_o<-obs[81:100] 39 | test_p<-preds[81:100,] 40 | 41 | data<-ForecastComb::foreccomb(train_o, train_p, test_o, test_p) 42 | ahead::comb_Ridge(data) 43 | 44 | } 45 | \seealso{ 46 | \code{\link[ForecastCombinations]{Forecast_comb}}, 47 | \code{\link{foreccomb}}, 48 | \code{\link{plot.ForecastComb::foreccomb_res}}, 49 | \code{\link{summary.ForecastComb::foreccomb_res}}, 50 | \code{\link[forecast]{accuracy}} 51 | } 52 | \keyword{models} 53 | -------------------------------------------------------------------------------- /man/computeattention.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compute_attention.R 3 | \name{computeattention} 4 | \alias{computeattention} 5 | \title{Compute global attention weights and context vectors for time series} 6 | \usage{ 7 | computeattention(series) 8 | } 9 | \arguments{ 10 | \item{series}{Numeric vector containing the time series of length n} 11 | } 12 | \value{ 13 | List containing: 14 | \item{attention_weights}{n × n matrix where entry (i,j) represents the attention 15 | weight of time j on time i. Only entries j <= i are non-zero (causal attention).} 16 | \item{context_vectors}{Vector of length n where each entry i is the weighted sum 17 | of all values up to time i, using the attention weights.} 18 | } 19 | \description{ 20 | Compute global attention weights and context vectors for time series 21 | } 22 | \examples{ 23 | # For a series of length 5 24 | series <- c(1, 2, 3, 4, 5) 25 | result <- computeattention(series) 26 | 27 | # attention_weights will be 5x5 matrix 28 | # context_vectors will be length 5 29 | dim(result$attention_weights) # [1] 5 5 30 | length(result$context_vectors) # [1] 5 31 | } 32 | -------------------------------------------------------------------------------- /man/conformalize.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/conformalize.R 3 | \name{conformalize} 4 | \alias{conformalize} 5 | \title{Conformalize a forecasting function} 6 | \usage{ 7 | conformalize( 8 | FUN, 9 | y, 10 | h, 11 | level = 95, 12 | method = c("block-bootstrap", "surrogate", "kde", "bootstrap", "fitdistr"), 13 | nsim = 100L, 14 | block_size = 5, 15 | seed = 123L, 16 | ... 17 | ) 18 | } 19 | \arguments{ 20 | \item{FUN}{A forecasting function.} 21 | 22 | \item{y}{A time series (\code{ts} object or vector).} 23 | 24 | \item{h}{Forecasting horizon.} 25 | 26 | \item{level}{Confidence level.} 27 | 28 | \item{method}{Method to be used for conformalization (simulation of calibrated residuals).} 29 | 30 | \item{nsim}{Number of simulations.} 31 | 32 | \item{block_size}{Block size for block-bootstrap.} 33 | 34 | \item{seed}{Seed for reproducibility.} 35 | 36 | \item{...}{Additional arguments to be passed to the forecasting function.} 37 | } 38 | \value{ 39 | An object of class \code{forecast}. 40 | } 41 | \description{ 42 | This function allows to conformalize any forecasting function. 43 | } 44 | \examples{ 45 | 46 | y <- fdeaths 47 | h <- 25L 48 | obj <- conformalize(FUN=forecast::ets, y, h); plot(obj) 49 | obj <- conformalize(FUN=HoltWinters, y=y, h=h, seasonal = "mult"); plot(obj) 50 | 51 | } 52 | -------------------------------------------------------------------------------- /man/createtrendseason.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{createtrendseason} 4 | \alias{createtrendseason} 5 | \title{Create trend and seasonality features for univariate time series} 6 | \usage{ 7 | createtrendseason(y) 8 | } 9 | \arguments{ 10 | \item{y}{a univariate time series} 11 | } 12 | \value{ 13 | a vector or matrix of features 14 | } 15 | \description{ 16 | Create trend and seasonality features for univariate time series 17 | } 18 | \examples{ 19 | 20 | y <- ts(rnorm(100), start = 1, frequency = 12) 21 | createtrendseason(y) 22 | 23 | createtrendseason(USAccDeaths) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /man/direct_sampling.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sampling.R 3 | \name{direct_sampling} 4 | \alias{direct_sampling} 5 | \title{Direct sampling} 6 | \usage{ 7 | direct_sampling( 8 | data = NULL, 9 | n = 100L, 10 | method = c("kde", "surrogate", "bootstrap"), 11 | kde = NULL, 12 | seed = NULL, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{data}{A numeric vector or matrix.} 18 | 19 | \item{n}{The number of samples to draw.} 20 | 21 | \item{method}{The method to use for sampling.} 22 | 23 | \item{kde}{The kernel density estimate to use for sampling.} 24 | 25 | \item{seed}{The seed to use for sampling.} 26 | 27 | \item{...}{Additional arguments to pass to the density function.} 28 | } 29 | \description{ 30 | Direct sampling 31 | } 32 | -------------------------------------------------------------------------------- /man/dynrmf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/dynrm.R 3 | \name{dynrmf} 4 | \alias{dynrmf} 5 | \title{Dynamic regression model} 6 | \usage{ 7 | dynrmf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | fit_func = ahead::ridge, 12 | predict_func = predict, 13 | fit_params = NULL, 14 | type_pi = c("gaussian", "E", "A", "T"), 15 | xreg_fit = NULL, 16 | xreg_predict = NULL, 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{y}{A numeric vector or time series of class \code{ts}} 22 | 23 | \item{h}{Forecasting horizon} 24 | 25 | \item{level}{Confidence level for prediction intervals} 26 | 27 | \item{fit_func}{Fitting function (Statistical/ML model). Default is Ridge regression.} 28 | 29 | \item{predict_func}{Prediction function (Statistical/ML model)} 30 | 31 | \item{fit_params}{a list of additional parameters for the fitting function \code{fit_func} (see examples)} 32 | 33 | \item{type_pi}{Type of prediction interval (currently "gaussian", ETS: "E", Arima: "A" or Theta: "T")} 34 | 35 | \item{xreg_fit}{Optionally, a vector or matrix of external regressors, which 36 | must have the same number of rows as y. Must be numeric.} 37 | 38 | \item{xreg_predict}{Future values of external regressor variables.} 39 | 40 | \item{...}{additional parameters} 41 | } 42 | \value{ 43 | a list; an object of class \code{forecast}. 44 | 45 | The function \code{summary} is used to obtain and print a summary of the 46 | results. 47 | 48 | The generic accessor functions \code{fitted.values} and \code{residuals} 49 | extract useful features. 50 | } 51 | \description{ 52 | Adapted from forecast::nnetar, with alternative fitting functions (see examples) 53 | } 54 | \examples{ 55 | 56 | # Example 0: with Ridge regression 57 | 58 | par(mfrow=c(3, 2)) 59 | plot(dynrmf(USAccDeaths, h=20, level=95)) 60 | plot(dynrmf(AirPassengers, h=20, level=95)) 61 | plot(dynrmf(lynx, h=20, level=95)) 62 | plot(dynrmf(WWWusage, h=20, level=95)) 63 | plot(dynrmf(Nile, h=20, level=95)) 64 | plot(dynrmf(fdeaths, h=20, level=95)) 65 | 66 | 67 | # Example 1: with Random Forest 68 | 69 | \dontrun{ 70 | 71 | require(randomForest) 72 | 73 | par(mfrow=c(3, 2)) 74 | plot(dynrmf(USAccDeaths, h=20, level=95, fit_func = randomForest::randomForest, 75 | fit_params = list(ntree = 50), predict_func = predict)) 76 | plot(dynrmf(AirPassengers, h=20, level=95, fit_func = randomForest::randomForest, 77 | fit_params = list(ntree = 50), predict_func = predict)) 78 | plot(dynrmf(lynx, h=20, level=95, fit_func = randomForest::randomForest, 79 | fit_params = list(ntree = 50), predict_func = predict)) 80 | plot(dynrmf(WWWusage, h=20, level=95, fit_func = randomForest::randomForest, 81 | fit_params = list(ntree = 50), predict_func = predict)) 82 | plot(dynrmf(Nile, h=20, level=95, fit_func = randomForest::randomForest, 83 | fit_params = list(ntree = 50), predict_func = predict)) 84 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = randomForest::randomForest, 85 | fit_params = list(ntree = 50), predict_func = predict)) 86 | } 87 | 88 | # Example 2: with SVM 89 | 90 | \dontrun{ 91 | 92 | require(e1071) 93 | 94 | par(mfrow=c(2, 2)) 95 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 96 | fit_params = list(kernel = "linear"), predict_func = predict)) 97 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 98 | fit_params = list(kernel = "polynomial"), predict_func = predict)) 99 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 100 | fit_params = list(kernel = "radial"), predict_func = predict)) 101 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 102 | fit_params = list(kernel = "sigmoid"), predict_func = predict)) 103 | 104 | } 105 | 106 | 107 | } 108 | \references{ 109 | Hyndman, R. J., & Athanasopoulos, G. (2018). Forecasting: 110 | principles and practice. OTexts. 111 | 112 | Hyndman R, Athanasopoulos G, Bergmeir C, Caceres G, Chhay L, 113 | O'Hara-Wild M, Petropoulos F, Razbash S, Wang E, Yasmeen F (2021). 114 | forecast: Forecasting functions for time series and linear models. R 115 | package version 8.14, . \cr 116 | } 117 | \author{ 118 | T. Moudiki 119 | } 120 | -------------------------------------------------------------------------------- /man/eatf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/eat.R 3 | \name{eatf} 4 | \alias{eatf} 5 | \title{Combined ets-arima-theta forecasts} 6 | \usage{ 7 | eatf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | method = c("EAT", "E", "A", "T"), 12 | weights = rep(1/3, 3), 13 | type_pi = c("gaussian", "E", "A", "T"), 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{y}{a univariate time series} 19 | 20 | \item{h}{number of periods for forecasting} 21 | 22 | \item{level}{confidence level for prediction intervals} 23 | 24 | \item{method}{forecasting method: "E" for \code{forecast::ets}; 25 | "A"for \code{forecast::auto.arima}; "T" for \code{forecast::thetaf}; 26 | or "EAT" for the combination of the three (default, with \code{weights})} 27 | 28 | \item{weights}{weights for each method, in method \code{EAT}. Must add up to 1.} 29 | 30 | \item{type_pi}{type of prediction interval: currently ETS: "E", Auto.Arima: "A" or Theta: "T"} 31 | 32 | \item{...}{additional parameters to be passed to \code{forecast::ets}, 33 | \code{forecast::auto.arima}, \code{forecast::thetaf} and 34 | \code{forecast::forecast}} 35 | } 36 | \value{ 37 | An object of class "forecast"; a list containing the following elements: 38 | 39 | \item{model}{A list containing information about the fitted model} 40 | \item{method}{The name of the forecasting method as a character string} 41 | \item{mean}{Point forecasts for the time series} 42 | \item{lower}{Lower bound for prediction interval} 43 | \item{upper}{Upper bound for prediction interval} 44 | \item{x}{The original time series} 45 | \item{residuals}{Residuals from the fitted model} 46 | } 47 | \description{ 48 | Combined ets, arima, and theta (eat) forecasting (uses \code{forecast::ets}, 49 | \code{forecast::auto.arima}, \code{forecast::thetaf}) 50 | } 51 | \details{ 52 | ensemble forecasts obtained from \code{forecast::ets}, 53 | \code{forecast::auto.arima} and \code{forecast::theta} (with weights) 54 | } 55 | \examples{ 56 | 57 | require(forecast) 58 | 59 | \dontrun{ 60 | 61 | print(ahead::eatf(WWWusage, method = "EAT", 62 | weights = c(0.5, 0, 0.5))) 63 | 64 | print(ahead::eatf(WWWusage, method = "EAT")) 65 | 66 | 67 | obj <- ahead::eatf(WWWusage, method = "EAT", 68 | weights = c(0, 0.5, 0.5), h=10, 69 | type_pi = "T") 70 | plot(obj) 71 | 72 | 73 | obj <- ahead::eatf(WWWusage, method = "EAT", 74 | weights = c(0, 0.5, 0.5), h=10, type_pi="A") 75 | plot(obj) 76 | } 77 | 78 | 79 | par(mfrow=c(3, 2)) 80 | plot(ahead::eatf(USAccDeaths, h=10, level=95)) 81 | plot(ahead::eatf(AirPassengers, h=10, level=95, type_pi = "T")) 82 | plot(ahead::eatf(lynx, h=10, level=95, type_pi = "A")) 83 | plot(ahead::eatf(WWWusage, h=10, level=95, type_pi = "E")) 84 | plot(ahead::eatf(Nile, h=10, level=95)) 85 | plot(ahead::eatf(fdeaths, h=10, level=95)) 86 | 87 | 88 | } 89 | \references{ 90 | Hyndman R, Athanasopoulos G, Bergmeir C, Caceres G, Chhay L, 91 | O'Hara-Wild M, Petropoulos F, Razbash S, Wang E, Yasmeen F (2021). 92 | forecast: Forecasting functions for time series and linear models. R 93 | package version 8.14, . \cr 94 | 95 | Hyndman RJ, Khandakar Y (2008). 'Automatic time series forecasting: the 96 | forecast package for R.' Journal of Statistical Software, 26 (3), 97 | 1-22. . 98 | 99 | Assimakopoulos, V. and Nikolopoulos, K. (2000). The theta model: a 100 | decomposition approach to forecasting. International Journal of 101 | Forecasting 16, 521-530. 102 | 103 | Hyndman, R.J., and Billah, B. (2003) Unmasking the Theta method. 104 | International J. Forecasting, 19, 287-290. 105 | } 106 | \author{ 107 | T. Moudiki 108 | } 109 | -------------------------------------------------------------------------------- /man/fit_func.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/caretfitpredict.R 3 | \name{fit_func} 4 | \alias{fit_func} 5 | \title{Fit univariate time series using caret ML model (for use with \code{dynrmf})} 6 | \usage{ 7 | fit_func( 8 | x, 9 | y, 10 | method = "ranger", 11 | initial_window = 10L, 12 | horizon = 10L, 13 | fixed_window = FALSE, 14 | tune_length = 5, 15 | summary_function = NULL, 16 | verbose = TRUE 17 | ) 18 | } 19 | \arguments{ 20 | \item{x}{A matrix of predictors} 21 | 22 | \item{y}{A vector of responses} 23 | 24 | \item{method}{The caret method to use for fitting the model} 25 | 26 | \item{initial_window}{The initial window size} 27 | 28 | \item{horizon}{The forecast horizon} 29 | 30 | \item{fixed_window}{Whether to use a fixed window size} 31 | 32 | \item{tune_length}{Length of the tuning grid} 33 | 34 | \item{verbose}{Whether to print the model summary} 35 | } 36 | \value{ 37 | A model object 38 | } 39 | \description{ 40 | Fit univariate time series using caret ML model (for use with \code{dynrmf}) 41 | } 42 | -------------------------------------------------------------------------------- /man/fitforecast.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fitforecast.R 3 | \name{fitforecast} 4 | \alias{fitforecast} 5 | \title{Fit and forecast for benchmarking purposes} 6 | \usage{ 7 | fitforecast( 8 | y, 9 | h = NULL, 10 | pct_train = 0.9, 11 | pct_calibration = 0.5, 12 | method = c("thetaf", "arima", "ets", "te", "tbats", "tslm", "dynrmf", "ridge2f", 13 | "naive", "snaive"), 14 | level = 95, 15 | B = 1000L, 16 | seed = 17223L, 17 | graph = TRUE, 18 | conformalize = FALSE, 19 | type_calibration = c("splitconformal", "cv1", "loocv"), 20 | gap = 3L, 21 | agg = c("mean", "median"), 22 | vol = c("constant", "garch"), 23 | type_sim = c("kde", "surrogate", "bootstrap"), 24 | ... 25 | ) 26 | } 27 | \arguments{ 28 | \item{y}{A univariate time series of class \code{ts}} 29 | 30 | \item{h}{Forecasting horizon (default is \code{NULL}, in that case, \code{pct_train} 31 | and \code{pct_calibration} are used)} 32 | 33 | \item{pct_train}{Percentage of data in the training set, when \code{h} is \code{NULL}} 34 | 35 | \item{pct_calibration}{Percentage of data in the calibration set for conformal prediction} 36 | 37 | \item{method}{For now "thetaf" (default), "arima", "ets", "tbats", "tslm", "dynrmf" (from ahead), 38 | "ridge2f" (from ahead), "naive", "snaive"} 39 | 40 | \item{level}{Confidence level for prediction intervals in \%, default is 95} 41 | 42 | \item{B}{Number of bootstrap replications or number of simulations 43 | (yes, 'B' is unfortunate)} 44 | 45 | \item{seed}{Reproducibility seed} 46 | 47 | \item{graph}{Plot or not?} 48 | 49 | \item{conformalize}{Calibrate or not?} 50 | 51 | \item{type_calibration}{"splitconformal" (default conformal method), "cv1" (do not use), 52 | "loocv" (do not use)} 53 | 54 | \item{gap}{length of training set for loocv conformal (do not use)} 55 | 56 | \item{agg}{"mean" or "median" (aggregation method)} 57 | 58 | \item{vol}{"constant" or "garch" (type of volatility modeling for calibrated residuals)} 59 | 60 | \item{type_sim}{"kde", "surrogate", "bootstrap" (type of simulation for calibrated residuals)} 61 | 62 | \item{...}{additional parameters} 63 | } 64 | \value{ 65 | an object of class 'forecast' with additional information 66 | } 67 | \description{ 68 | Fit and forecast for benchmarking purposes 69 | } 70 | \examples{ 71 | 72 | par(mfrow=c(2, 2)) 73 | obj1 <- ahead::fitforecast(AirPassengers) 74 | obj2 <- ahead::fitforecast(AirPassengers, conformalize = TRUE) 75 | plot(AirPassengers) 76 | plot(obj1) 77 | obj2$plot() 78 | obj2$plot("simulations") 79 | 80 | } 81 | -------------------------------------------------------------------------------- /man/genericforecast.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/genforecast.R 3 | \name{genericforecast} 4 | \alias{genericforecast} 5 | \title{Generic Forecasting Function (Unified interface)} 6 | \usage{ 7 | genericforecast(FUN, y, h, level = 95, ...) 8 | } 9 | \arguments{ 10 | \item{FUN}{A forecasting function.} 11 | 12 | \item{y}{A time series (\code{ts} object or vector).} 13 | 14 | \item{h}{Forecasting horizon.} 15 | 16 | \item{level}{The confidence level.} 17 | 18 | \item{...}{Additional arguments to be passed to the forecasting function.} 19 | } 20 | \value{ 21 | An object of class \code{forecast}. 22 | } 23 | \description{ 24 | This function allows to call any function "of class \code{forecast}" in a unified way. 25 | } 26 | \examples{ 27 | 28 | y <- fdeaths 29 | h <- 25L 30 | plot(genericforecast(FUN=forecast::thetaf, y, h)) 31 | plot(genericforecast(FUN=ahead::dynrmf, y, h)) 32 | plot(genericforecast(FUN=forecast::tbats, y=y, h=h, use.box.cox = TRUE, use.trend=FALSE)) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /man/get_error.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils_benchmarks.R 3 | \name{get_error} 4 | \alias{get_error} 5 | \title{Get error metrics} 6 | \usage{ 7 | get_error(obj, actual, level = 95) 8 | } 9 | \arguments{ 10 | \item{obj}{A prediction object containing mean predictions and intervals.} 11 | 12 | \item{actual}{A numeric vector of actual values.} 13 | 14 | \item{level}{The confidence level for the prediction intervals.} 15 | } 16 | \value{ 17 | A numeric vector containing the error metrics. 18 | } 19 | \description{ 20 | This function calculates various error metrics for a given prediction object. 21 | } 22 | \examples{ 23 | 24 | obj <- list(mean = 10, lower = 8, upper = 12) 25 | actual <- 11 26 | get_error(obj, actual) 27 | 28 | } 29 | -------------------------------------------------------------------------------- /man/getreturns.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getreturns.R 3 | \name{getreturns} 4 | \alias{getreturns} 5 | \title{Calculate returns or log-returns for multivariate time series} 6 | \usage{ 7 | getreturns(x, type = c("basic", "log")) 8 | } 9 | \arguments{ 10 | \item{x}{Multivariate time series} 11 | 12 | \item{type}{Type of return: basic return ("basic") or log-return ("log")} 13 | } 14 | \value{ 15 | The returns 16 | } 17 | \description{ 18 | Calculate returns or log-returns for multivariate time series 19 | } 20 | \examples{ 21 | 22 | returns <- getreturns(EuStockMarkets) 23 | log_returns <- getreturns(EuStockMarkets, 24 | type = "log") 25 | 26 | par(mfrow=c(1, 3)) 27 | matplot(EuStockMarkets, type = 'l', main = "Closing Prices of \n European stocks (1991-1998)", 28 | xlab = "time") 29 | matplot(returns, type = 'l', main = "Returns", xlab = "time") 30 | matplot(log_returns, type = 'l', main = "Log-returns", xlab = "time") 31 | 32 | } 33 | -------------------------------------------------------------------------------- /man/getsimulations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getsimulations.R 3 | \name{getsimulations} 4 | \alias{getsimulations} 5 | \title{Obtain simulations (when relevant) from a selected time series} 6 | \usage{ 7 | getsimulations(obj, selected_series, transpose = FALSE) 8 | } 9 | \arguments{ 10 | \item{obj}{result from ridge2f (multivariate time series forecast with simulations)} 11 | 12 | \item{selected_series}{name of the time series selected} 13 | 14 | \item{transpose}{return a transposed time series} 15 | } 16 | \description{ 17 | Obtain simulations (when relevant) from a selected time series 18 | } 19 | \examples{ 20 | 21 | require(fpp) 22 | 23 | obj <- ahead::ridge2f(fpp::insurance, h = 7, 24 | type_pi = "bootstrap", B = 5) 25 | print(getsimulations(obj, selected_series = "TV.advert")) 26 | print(getsimulations(obj, selected_series = "Quotes")) 27 | print(getsimulations(obj, selected_series = "TV.advert", transpose = TRUE)) 28 | print(getsimulations(obj, selected_series = "Quotes", transpose = TRUE)) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /man/glmthetaf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/glmtheta.R 3 | \name{glmthetaf} 4 | \alias{glmthetaf} 5 | \title{Generalized Linear Model Theta Forecast} 6 | \usage{ 7 | glmthetaf( 8 | y, 9 | h = ifelse(frequency(y) > 1, 2 * frequency(y), 10), 10 | level = 95L, 11 | fit_func = stats::glm, 12 | fan = FALSE, 13 | x = y, 14 | type_pi = c("conformal-split", "conformal-surrogate", "conformal-kde", 15 | "conformal-bootstrap", "conformal-block-bootstrap", "conformal-fitdistr", "gaussian"), 16 | attention = TRUE, 17 | scale_ctxt = 1, 18 | B = 250L, 19 | nsim = B, 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{y}{The time series data} 25 | 26 | \item{h}{The number of periods to forecast} 27 | 28 | \item{level}{The confidence level for the forecast intervals} 29 | 30 | \item{fit_func}{The function to use for fitting the GLM} 31 | 32 | \item{fan}{Logical flag for fan plot} 33 | 34 | \item{x}{The time series data} 35 | 36 | \item{attention}{Logical flag for using attention mechanism} 37 | 38 | \item{scale_ctxt}{Scaling coefficient for context vector} 39 | 40 | \item{B}{Number of bootstrap replications or number of simulations (yes, 'B' is unfortunate)} 41 | 42 | \item{nsim}{Alias for B} 43 | 44 | \item{...}{Additional arguments to pass to the fit_func} 45 | } 46 | \value{ 47 | A forecast object 48 | } 49 | \description{ 50 | This function implements the Theta method using a Generalized Linear Model (GLM) 51 | } 52 | -------------------------------------------------------------------------------- /man/loessf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/loess.R 3 | \name{loessf} 4 | \alias{loessf} 5 | \title{Loess forecasting} 6 | \usage{ 7 | loessf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | span = 0.75, 12 | degree = 2, 13 | type_pi = c("bootstrap", "blockbootstrap", "movingblockbootstrap"), 14 | b = NULL, 15 | B = 250, 16 | type_aggregation = c("mean", "median"), 17 | seed = 123 18 | ) 19 | } 20 | \arguments{ 21 | \item{y}{A numeric vector or time series of class \code{ts}} 22 | 23 | \item{h}{Forecasting horizon} 24 | 25 | \item{level}{Confidence level for prediction intervals} 26 | 27 | \item{span}{the parameter which controls the degree of smoothing} 28 | 29 | \item{degree}{the degree of the polynomials to be used, normally 1 or 2. (Degree 0 is also allowed, but see \code{stats::loess})} 30 | 31 | \item{type_pi}{Type of prediction interval currently (independent) "bootstrap", (circular) "blockbootstrap", or "movingblockbootstrap"} 32 | 33 | \item{b}{block length for circular block bootstrap} 34 | 35 | \item{B}{number of bootstrap replications} 36 | 37 | \item{type_aggregation}{Type of aggregation, ONLY for bootstrapping; either "mean" or "median"} 38 | 39 | \item{seed}{reproducibility seed} 40 | } 41 | \value{ 42 | An object of class "forecast"; a list containing the following elements: 43 | 44 | \item{model}{A list containing information about the fitted model} 45 | \item{method}{The name of the forecasting method as a character string} 46 | \item{mean}{Point forecasts for the time series} 47 | \item{lower}{Lower bound for prediction interval} 48 | \item{upper}{Upper bound for prediction interval} 49 | \item{x}{The original time series} 50 | \item{residuals}{Residuals from the fitted model} 51 | \item{sims}{Model simulations for bootstrapping} 52 | } 53 | \description{ 54 | Loess forecasting 55 | } 56 | \examples{ 57 | 58 | par(mfrow = c(3, 1)) 59 | 60 | plot(loessf(Nile, h=20, level=95, B=10)) 61 | 62 | plot(loessf(Nile, h=20, level=95, B=10, 63 | type_pi = "blockbootstrap")) 64 | 65 | plot(loessf(Nile, h=20, level=95, B=10, 66 | type_pi = "movingblockbootstrap")) 67 | 68 | } 69 | -------------------------------------------------------------------------------- /man/loocvridge2f.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/loocvridge2.R 3 | \name{loocvridge2f} 4 | \alias{loocvridge2f} 5 | \title{LOOCV for Ridge2 model} 6 | \usage{ 7 | loocvridge2f( 8 | y, 9 | xreg = NULL, 10 | h = 5, 11 | level = 95, 12 | lags = 1, 13 | nb_hidden = 5, 14 | nodes_sim = c("sobol", "halton", "unif"), 15 | activ = c("relu", "sigmoid", "tanh", "leakyrelu", "elu", "linear"), 16 | a = 0.01, 17 | lambda_1 = 0.1, 18 | lambda_2 = 0.1, 19 | dropout = 0, 20 | type_forecast = c("recursive", "direct"), 21 | type_pi = c("gaussian", "bootstrap", "blockbootstrap", "movingblockbootstrap", 22 | "rvinecopula", "splitconformal"), 23 | block_length = NULL, 24 | margins = c("gaussian", "empirical", "student"), 25 | seed = 1, 26 | B = 100L, 27 | type_aggregation = c("mean", "median"), 28 | centers = NULL, 29 | type_clustering = c("kmeans", "hclust"), 30 | ym = NULL, 31 | cl = 1L, 32 | show_progress = TRUE, 33 | ... 34 | ) 35 | } 36 | \arguments{ 37 | \item{y}{A multivariate time series of class \code{ts} (preferred) or a \code{matrix}} 38 | 39 | \item{xreg}{External regressors. A data.frame (preferred) or a \code{matrix}} 40 | 41 | \item{h}{Forecasting horizon} 42 | 43 | \item{level}{Confidence level for prediction intervals} 44 | 45 | \item{lags}{Number of lags} 46 | 47 | \item{nb_hidden}{Number of nodes in hidden layer} 48 | 49 | \item{nodes_sim}{Type of simulation for nodes in the hidden layer} 50 | 51 | \item{activ}{Activation function} 52 | 53 | \item{a}{Hyperparameter for activation function "leakyrelu", "elu"} 54 | 55 | \item{lambda_1}{Regularization parameter for original predictors} 56 | 57 | \item{lambda_2}{Regularization parameter for transformed predictors} 58 | 59 | \item{dropout}{dropout regularization parameter (dropping nodes in hidden layer)} 60 | 61 | \item{type_forecast}{Recursive or direct forecast} 62 | 63 | \item{type_pi}{Type of prediction interval currently "gaussian", "bootstrap", 64 | "blockbootstrap", "movingblockbootstrap", "splitconformal" (very experimental right now), 65 | "rvinecopula" (with Gaussian margins for now, Student-t coming soon)} 66 | 67 | \item{block_length}{Length of block for circular or moving block bootstrap} 68 | 69 | \item{margins}{Distribution of margins: "gaussian", "empirical", "student" (postponed or 70 | never) for \code{type_pi == "rvinecopula"}} 71 | 72 | \item{seed}{Reproducibility seed for random stuff} 73 | 74 | \item{B}{Number of bootstrap replications or number of simulations (yes, 'B' is unfortunate)} 75 | 76 | \item{type_aggregation}{Type of aggregation, ONLY for bootstrapping; either "mean" or "median"} 77 | 78 | \item{centers}{Number of clusters for \code{type_clustering}} 79 | 80 | \item{type_clustering}{"kmeans" (K-Means clustering) or "hclust" (Hierarchical clustering)} 81 | 82 | \item{ym}{Univariate time series (\code{stats::ts}) of yield to maturities with 83 | \code{frequency = frequency(y)} and \code{start = tsp(y)[2] + 1 / frequency(y)}. 84 | Default is \code{NULL}.} 85 | 86 | \item{cl}{An integer; the number of clusters for parallel execution, for bootstrap} 87 | 88 | \item{show_progress}{A boolean; show progress bar for bootstrapping? Default is TRUE.} 89 | 90 | \item{...}{Additional parameters to be passed to \code{\link{kmeans}} or \code{\link{hclust}}} 91 | } 92 | \value{ 93 | An object of class "mtsforecast"; a list containing the following elements: 94 | 95 | \item{method}{The name of the forecasting method as a character string} 96 | \item{mean}{Point forecasts for the time series} 97 | \item{lower}{Lower bound for prediction interval} 98 | \item{upper}{Upper bound for prediction interval} 99 | \item{sims}{Model simulations for bootstrapping (basic, or block)} 100 | \item{x}{The original time series} 101 | \item{residuals}{Residuals from the fitted model} 102 | \item{coefficients}{Regression coefficients for \code{type_pi == 'gaussian'} for now} 103 | } 104 | \description{ 105 | LOOCV for Random Vector functional link network model with 2 regularization parameters 106 | } 107 | \examples{ 108 | 109 | require(fpp) 110 | 111 | print(ahead::loocvridge2f(fpp::insurance)) 112 | print(ahead::loocvridge2f(fpp::usconsumption)) 113 | 114 | #foo <- function(xx) ahead::loocvridge2f(fpp::insurance, lambda_1=10^xx[1], lambda_2=10^xx[2]) 115 | #(opt <- stats::nlminb(objective=foo, lower=c(-10,-10), upper=c(10,10), start=c(0, 0))) 116 | #print(ahead::loocvridge2f(fpp::insurance, lambda_1=10^opt$par[1], lambda_2=10^opt$par[2])) 117 | 118 | } 119 | \references{ 120 | Moudiki, T., Planchet, F., & Cousin, A. (2018). 121 | Multiple time series forecasting using quasi-randomized 122 | functional link neural networks. Risks, 6(1), 22. \cr 123 | } 124 | \author{ 125 | T. Moudiki 126 | } 127 | -------------------------------------------------------------------------------- /man/mlarchf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mlarch.R 3 | \name{mlarchf} 4 | \alias{mlarchf} 5 | \title{Conformalized Forecasting using Machine Learning models with ARCH effects} 6 | \usage{ 7 | mlarchf( 8 | y, 9 | h = 10L, 10 | mean_model = forecast::auto.arima, 11 | model_residuals = forecast::thetaf, 12 | fit_func = ahead::ridge, 13 | predict_func = predict, 14 | type_pi = c("kde", "surrogate", "bootstrap"), 15 | type_sim_conformalize = c("block-bootstrap", "surrogate", "kde", "bootstrap", 16 | "fitdistr"), 17 | ml_method = NULL, 18 | level = 95, 19 | B = 250L 20 | ) 21 | } 22 | \arguments{ 23 | \item{y}{A numeric vector or time series of class \code{ts}} 24 | 25 | \item{h}{Forecasting horizon} 26 | 27 | \item{mean_model}{Function to fit the mean model (default: \code{forecast::auto.arima})} 28 | 29 | \item{model_residuals}{Function to model the residuals (default: \code{forecast::thetaf})} 30 | 31 | \item{fit_func}{Fitting function for the variance model (default: \code{ahead::ridge})} 32 | 33 | \item{predict_func}{Prediction function for the variance model (default: \code{predict})} 34 | 35 | \item{type_pi}{Type of prediction interval ("kde", "surrogate", or "bootstrap") for volatility modeling} 36 | 37 | \item{type_sim_conformalize}{Type of simulation for conformalization of standardized residuals ("block-bootstrap", "surrogate", "kde", "bootstrap", or "fitdistr")} 38 | 39 | \item{ml_method}{Machine learning method to use (if NULL, uses default methods)} 40 | 41 | \item{level}{Confidence level for prediction intervals} 42 | 43 | \item{B}{Number of bootstrap replications or simulations} 44 | } 45 | \value{ 46 | A forecast object containing predictions and prediction intervals 47 | } 48 | \description{ 49 | Conformalized Forecasting using Machine Learning models with ARCH effects 50 | } 51 | \examples{ 52 | # Example usage will be added 53 | } 54 | -------------------------------------------------------------------------------- /man/mlf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ml.R 3 | \name{mlf} 4 | \alias{mlf} 5 | \title{Conformalized Forecasting using Machine Leaning models} 6 | \usage{ 7 | mlf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | lags = 15L, 12 | fit_func = ahead::ridge, 13 | predict_func = predict, 14 | coeffs = NULL, 15 | type_pi = c("kde", "surrogate", "bootstrap"), 16 | B = 250L, 17 | agg = c("mean", "median"), 18 | seed = 123, 19 | ... 20 | ) 21 | } 22 | \arguments{ 23 | \item{y}{A numeric vector or time series of class \code{ts}} 24 | 25 | \item{h}{Forecasting horizon} 26 | 27 | \item{level}{Confidence level for prediction intervals} 28 | 29 | \item{lags}{Number of lags of the input time series considered in the regression} 30 | 31 | \item{fit_func}{Fitting function (Statistical/ML model). Default is Ridge regression.} 32 | 33 | \item{predict_func}{Prediction function (Statistical/ML model)} 34 | 35 | \item{coeffs}{Coefficients of the fitted model. If provided, a linear combination with the coefficients is used to compute the prediction.} 36 | 37 | \item{type_pi}{Type of prediction interval} 38 | 39 | \item{B}{Number of bootstrap replications or number of simulations} 40 | 41 | \item{agg}{"mean" or "median" (aggregation method)} 42 | 43 | \item{...}{additional parameters passed to the fitting function \code{fit_func}} 44 | } 45 | \description{ 46 | Conformalized Forecasting using Machine Leaning models 47 | } 48 | \examples{ 49 | 50 | plot(ahead::mlf(AirPassengers, h=20L)) 51 | 52 | res <- ahead::mlf(USAccDeaths, h=15L, lags=15L, type_pi="surrogate", B=250L) 53 | plot(res) 54 | 55 | res <- ahead::mlf(USAccDeaths, fit_func = glmnet::cv.glmnet, h=15L, lags=15L, 56 | type_pi="kde", B=250L) 57 | plot(res) 58 | 59 | (res <- ahead::mlf(USAccDeaths, fit_func = e1071::svm, h=15L, lags=15L, 60 | type_pi="kde", B=250L)) 61 | plot(res) 62 | 63 | res <- ahead::mlf(mdeaths, h=15L, lags=15L, type_pi="surrogate", B=250L) 64 | plot(res) 65 | 66 | res <- ahead::mlf(fdeaths, fit_func = glmnet::cv.glmnet, h=15L, lags=25L, 67 | type_pi="kde", B=250L) 68 | plot(res) 69 | 70 | res <- ahead::mlf(fdeaths, fit_func = randomForest::randomForest, h=15L, lags=15L, 71 | type_pi="kde", B=250L) 72 | plot(res) 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /man/plot.foreccomb_res.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot.foreccomb_res.R 3 | \name{plot.foreccomb_res} 4 | \alias{plot.foreccomb_res} 5 | \title{Plot results from forecast combination model} 6 | \usage{ 7 | \method{plot}{foreccomb_res}(x, which = 1, ...) 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'foreccomb_res'.} 11 | 12 | \item{which}{Type of plot: 1 = actual vs. fitted, 2 = combination weights.} 13 | 14 | \item{...}{Other arguments passing to \code{\link[graphics]{plot.default}}.} 15 | } 16 | \value{ 17 | A plot for the foreccomb_res class. 18 | } 19 | \description{ 20 | Produces plots for the results of a forecast combination method. Either 21 | an actual vs. fitted plot (\code{which = 1}) or a barplot of the combination weights 22 | (\code{which = 2}). 23 | } 24 | \seealso{ 25 | \code{\link[ForecastComb]{foreccomb}}, 26 | \code{\link[ForecastComb]{summary.foreccomb_res}} 27 | } 28 | \author{ 29 | adapted from Christoph E. Weiss and Gernot R. Roetzer (ForecastComb) 30 | } 31 | -------------------------------------------------------------------------------- /man/plot.mtsforecast.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot.R 3 | \name{plot.mtsforecast} 4 | \alias{plot.mtsforecast} 5 | \title{Plot multivariate time series forecast or residuals} 6 | \usage{ 7 | \method{plot}{mtsforecast}(x, selected_series, type = c("pi", "dist", "sims"), level = 95, ...) 8 | } 9 | \arguments{ 10 | \item{x}{result from \code{basicf}, \code{ridge2f} or \code{varf} (multivariate time series forecast)} 11 | 12 | \item{selected_series}{name of the time series selected for plotting} 13 | 14 | \item{type}{"pi": basic prediction intervals; 15 | "dist": a distribution of predictions; "sims": the simulations} 16 | 17 | \item{level}{confidence levels for prediction intervals} 18 | 19 | \item{...}{additional parameters to be passed to \code{plot} or \code{matplot}} 20 | } 21 | \description{ 22 | Plot multivariate time series forecast or residuals 23 | } 24 | \examples{ 25 | 26 | require(fpp) 27 | 28 | fit_obj_VAR <- ahead::varf(fpp::insurance, lags = 2, 29 | h = 10, level = 95) 30 | 31 | fit_obj_ridge2 <- ahead::ridge2f(fpp::insurance, lags = 2, 32 | h = 10, level = 95) 33 | 34 | par(mfrow=c(2, 2)) 35 | plot(fit_obj_VAR, "Quotes") 36 | plot(fit_obj_VAR, "TV.advert") 37 | plot(fit_obj_ridge2, "Quotes") 38 | plot(fit_obj_ridge2, "TV.advert") 39 | 40 | obj <- ahead::ridge2f(fpp::insurance, h = 10, type_pi = "blockbootstrap", 41 | block_length=5, B = 10) 42 | par(mfrow=c(1, 2)) 43 | plot(obj, selected_series = "Quotes", type = "sims", 44 | main = "Predictive simulation for Quotes") 45 | plot(obj, selected_series = "TV.advert", type = "sims", 46 | main = "Predictive simulation for TV.advert") 47 | 48 | 49 | par(mfrow=c(1, 2)) 50 | plot(obj, selected_series = "Quotes", type = "dist", 51 | main = "Predictive simulation for Quotes") 52 | plot(obj, selected_series = "TV.advert", type = "dist", 53 | main = "Predictive simulation for TV.advert") 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /man/predict.foreccomb_res.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/predict.foreccomb_res.R 3 | \name{predict.foreccomb_res} 4 | \alias{predict.foreccomb_res} 5 | \title{Prediction function for Forecast Combinations} 6 | \usage{ 7 | \method{predict}{foreccomb_res}(object, newpreds, newobs = NULL, simplify = TRUE, byrow = FALSE, ...) 8 | } 9 | \arguments{ 10 | \item{object}{An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set.} 11 | 12 | \item{newpreds}{A matrix or multivariate time series; contains individual model forecasts if a test set is used (optional). Does not 13 | require specification of \code{newobs} -- in the case in which a forecaster only wants to train the forecast combination method 14 | with a training set and apply it to future individual model forecasts, only \code{newpreds} is required, not \code{newobs}.} 15 | 16 | \item{newobs}{A vector or univariate time series; contains \sQuote{actual values} if a test set is used (optional).} 17 | 18 | \item{simplify}{logical. The default (\code{TRUE}) returns the predictions separately. If set to (\code{FALSE}) the predictions are incorporated 19 | into the foreccomb_res object, that is, the object is equal to the one that would have been obtained, if the new prediction set would have 20 | been provided when the forecast combination method was trained originally.} 21 | 22 | \item{byrow}{logical. The default (\code{FALSE}) assumes that each column of the forecast matrices (\code{prediction_matrix} and -- if 23 | specified -- \code{newpreds}) contains forecasts from one forecast model; if each row of the matrices contains forecasts from 24 | one forecast model, set to \code{TRUE}.} 25 | 26 | \item{...}{potential further arguments (require by generic)} 27 | } 28 | \description{ 29 | \code{prediction} method for class \sQuote{foreccomb_res}. Uses the previously created forecast combination 30 | result to predict the combination for a newly provided prediction dataset. 31 | } 32 | \seealso{ 33 | \code{\link[ForecastComb]{foreccomb}}, 34 | } 35 | \author{ 36 | Adapted from Christoph E. Weiss and Gernot R. Roetzer (ForecastComb) 37 | } 38 | -------------------------------------------------------------------------------- /man/predict_func.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/caretfitpredict.R 3 | \name{predict_func} 4 | \alias{predict_func} 5 | \title{Predict univariate time series using caret ML model(for use with \code{dynrmf})} 6 | \usage{ 7 | predict_func(obj, newx) 8 | } 9 | \arguments{ 10 | \item{x}{A matrix of predictors} 11 | 12 | \item{y}{A vector of responses} 13 | 14 | \item{method}{The caret method to use for fitting the model} 15 | 16 | \item{verbose}{Whether to print the model summary} 17 | } 18 | \value{ 19 | A model object 20 | } 21 | \description{ 22 | Predict univariate time series using caret ML model(for use with \code{dynrmf}) 23 | } 24 | -------------------------------------------------------------------------------- /man/ridge2f.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ridge2.R 3 | \name{ridge2f} 4 | \alias{ridge2f} 5 | \title{Ridge2 model} 6 | \usage{ 7 | ridge2f( 8 | y, 9 | h = 5, 10 | level = 95, 11 | xreg = NULL, 12 | lags = 1, 13 | nb_hidden = 5, 14 | nodes_sim = c("sobol", "halton", "unif"), 15 | activ = c("relu", "sigmoid", "tanh", "leakyrelu", "elu", "linear"), 16 | a = 0.01, 17 | lambda_1 = 0.1, 18 | lambda_2 = 0.1, 19 | dropout = 0, 20 | type_forecast = c("recursive", "direct"), 21 | type_pi = c("gaussian", "bootstrap", "blockbootstrap", "movingblockbootstrap", 22 | "rvinecopula", "conformal-split", "conformal-bootstrap", "conformal-block-bootstrap"), 23 | block_length = NULL, 24 | margins = c("gaussian", "empirical"), 25 | seed = 1, 26 | B = 100L, 27 | type_aggregation = c("mean", "median"), 28 | centers = NULL, 29 | type_clustering = c("kmeans", "hclust"), 30 | ym = NULL, 31 | cl = 1L, 32 | show_progress = TRUE, 33 | ... 34 | ) 35 | } 36 | \arguments{ 37 | \item{y}{A univariate of multivariate time series of class \code{ts} (preferred) or a \code{matrix}} 38 | 39 | \item{h}{Forecasting horizon} 40 | 41 | \item{level}{Confidence level for prediction intervals} 42 | 43 | \item{xreg}{External regressors. A data.frame (preferred) or a \code{matrix}} 44 | 45 | \item{lags}{Number of lags} 46 | 47 | \item{nb_hidden}{Number of nodes in hidden layer} 48 | 49 | \item{nodes_sim}{Type of simulation for nodes in the hidden layer} 50 | 51 | \item{activ}{Activation function} 52 | 53 | \item{a}{Hyperparameter for activation function "leakyrelu", "elu"} 54 | 55 | \item{lambda_1}{Regularization parameter for original predictors} 56 | 57 | \item{lambda_2}{Regularization parameter for transformed predictors} 58 | 59 | \item{dropout}{dropout regularization parameter (dropping nodes in hidden layer)} 60 | 61 | \item{type_forecast}{Recursive or direct forecast} 62 | 63 | \item{type_pi}{Type of prediction interval currently "gaussian", "bootstrap", 64 | "blockbootstrap", "movingblockbootstrap", "rvinecopula" (with Gaussian and empirical margins for now) 65 | "conformal-split", "conformal-bootstrap", "conformal-block-bootstrap"} 66 | 67 | \item{block_length}{Length of block for circular or moving block bootstrap} 68 | 69 | \item{margins}{Distribution of margins: "gaussian", "empirical" for \code{type_pi == "rvinecopula"}} 70 | 71 | \item{seed}{Reproducibility seed for random stuff} 72 | 73 | \item{B}{Number of bootstrap replications or number of simulations (yes, 'B' is unfortunate)} 74 | 75 | \item{type_aggregation}{Type of aggregation, ONLY for bootstrapping; either "mean" or "median"} 76 | 77 | \item{centers}{Number of clusters for \code{type_clustering}} 78 | 79 | \item{type_clustering}{"kmeans" (K-Means clustering) or "hclust" (Hierarchical clustering)} 80 | 81 | \item{ym}{Univariate time series (\code{stats::ts}) of yield to maturities with 82 | \code{frequency = frequency(y)} and \code{start = tsp(y)[2] + 1 / frequency(y)}. 83 | Default is \code{NULL}.} 84 | 85 | \item{cl}{An integer; the number of clusters for parallel execution, for bootstrap} 86 | 87 | \item{show_progress}{A boolean; show progress bar for bootstrapping? Default is TRUE.} 88 | 89 | \item{...}{Additional parameters to be passed to \code{\link{kmeans}} or \code{\link{hclust}}} 90 | } 91 | \value{ 92 | An object of class "mtsforecast"; a list containing the following elements: 93 | 94 | \item{method}{The name of the forecasting method as a character string} 95 | \item{mean}{Point forecasts for the time series} 96 | \item{lower}{Lower bound for prediction interval} 97 | \item{upper}{Upper bound for prediction interval} 98 | \item{sims}{Model simulations for bootstrapping (basic, or block)} 99 | \item{x}{The original time series} 100 | \item{residuals}{Residuals from the fitted model} 101 | \item{coefficients}{Regression coefficients for \code{type_pi == 'gaussian'} for now} 102 | } 103 | \description{ 104 | Random Vector functional link network model with 2 regularization parameters 105 | } 106 | \examples{ 107 | 108 | require(fpp) 109 | 110 | print(ahead::ridge2f(fpp::insurance)$mean) 111 | print(ahead::ridge2f(fpp::usconsumption)$lower) 112 | 113 | res <- ahead::ridge2f(fpp::insurance, h=10, lags=2) 114 | par(mfrow=c(1, 2)) 115 | plot(res, "Quotes") 116 | plot(res, "TV.advert") 117 | 118 | # include a trend (just for the example) 119 | xreg <- as.numeric(time(fpp::insurance)) 120 | res2 <- ahead::ridge2f(fpp::insurance, xreg=xreg, 121 | h=10, lags=2) 122 | par(mfrow=c(1, 2)) 123 | plot(res2, "Quotes") 124 | plot(res2, "TV.advert") 125 | 126 | # block bootstrap 127 | xreg <- as.numeric(time(fpp::insurance)) 128 | res3 <- ahead::ridge2f(fpp::insurance, xreg=xreg, 129 | h=10, lags=1L, type_pi = "bootstrap", B=10) 130 | res5 <- ahead::ridge2f(fpp::insurance, xreg=xreg, 131 | h=10, lags=1L, type_pi = "blockbootstrap", B=10, 132 | block_length = 4) 133 | 134 | print(res3$sims[[2]]) 135 | print(res5$sims[[2]]) 136 | 137 | par(mfrow=c(2, 2)) 138 | plot(res3, "Quotes") 139 | plot(res3, "TV.advert") 140 | plot(res5, "Quotes") 141 | plot(res5, "TV.advert") 142 | 143 | 144 | res4 <- ahead::ridge2f(fpp::usconsumption, h=20, lags=2L, 145 | lambda_2=1) 146 | par(mfrow=c(1, 2)) 147 | plot(res4, "income") 148 | plot(res4, "consumption") 149 | 150 | 151 | # moving block bootstrap 152 | xreg <- as.numeric(time(fpp::insurance)) 153 | res6 <- ahead::ridge2f(fpp::insurance, xreg=xreg, 154 | h=10, lags=1L, 155 | type_pi = "movingblockbootstrap", B=10, 156 | block_length = 4) 157 | 158 | print(res6$sims[[2]]) 159 | 160 | par(mfrow=c(1, 2)) 161 | plot(res6, "Quotes") 162 | plot(res6, "TV.advert") 163 | 164 | 165 | } 166 | \references{ 167 | Moudiki, T., Planchet, F., & Cousin, A. (2018). 168 | Multiple time series forecasting using quasi-randomized 169 | functional link neural networks. Risks, 6(1), 22. \cr 170 | } 171 | \author{ 172 | T. Moudiki 173 | } 174 | -------------------------------------------------------------------------------- /man/rmultivariate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sampling.R 3 | \name{rmultivariate} 4 | \alias{rmultivariate} 5 | \title{Simulate multivariate data} 6 | \usage{ 7 | rmultivariate( 8 | data, 9 | method = c("bootstrap", "block-bootstrap"), 10 | n = 100L, 11 | block_size = 5 12 | ) 13 | } 14 | \arguments{ 15 | \item{data}{A numeric vector or matrix.} 16 | 17 | \item{method}{The method to use for sampling.} 18 | 19 | \item{n}{The number of samples to draw.} 20 | 21 | \item{block_size}{The size of the blocks to use for the block bootstrap.} 22 | 23 | \item{...}{Additional arguments to pass to the density function.} 24 | } 25 | \description{ 26 | Simulate multivariate data 27 | } 28 | -------------------------------------------------------------------------------- /man/splitts.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/splitts.R 3 | \name{splitts} 4 | \alias{splitts} 5 | \title{Partition a time series object} 6 | \usage{ 7 | splitts(y, split_prob = 0.5, return_indices = FALSE, ...) 8 | } 9 | \arguments{ 10 | \item{y}{A time series object} 11 | 12 | \item{split_prob}{Splitting ratio} 13 | 14 | \item{return_indices}{if TRUE, returns series' indices, otherwise, time series objects} 15 | } 16 | \description{ 17 | Partition a time series object 18 | } 19 | \examples{ 20 | 21 | misc::splitts(ts(1:10)) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /man/summary.foreccomb_res.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/summary.foreccomb_res.R 3 | \name{summary.foreccomb_res} 4 | \alias{summary.foreccomb_res} 5 | \alias{print.foreccomb_res_summary} 6 | \title{Summary of Forecast Combination} 7 | \usage{ 8 | \method{summary}{foreccomb_res}(object, ...) 9 | 10 | \method{print}{foreccomb_res_summary}(x, ...) 11 | } 12 | \arguments{ 13 | \item{object}{An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set.} 14 | 15 | \item{...}{potential further arguments (require by generic)} 16 | 17 | \item{x}{An object of class 'foreccomb'. Contains training set (actual values + matrix of model forecasts) and optionally a test set.} 18 | } 19 | \description{ 20 | \code{summary} method for class \sQuote{foreccomb_res}. Includes information about combination method, 21 | combination weights assigned to the individual forecast models, as well as an accuracy evaluation of the combined 22 | forecast. 23 | } 24 | \seealso{ 25 | \code{\link[ForecastComb]{foreccomb}}, 26 | \code{\link[ForecastComb]{plot.foreccomb_res}}, 27 | } 28 | \author{ 29 | Christoph E. Weiss and Gernot R. Roetzer 30 | } 31 | -------------------------------------------------------------------------------- /man/varf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/VAR.R 3 | \name{varf} 4 | \alias{varf} 5 | \title{Vector Autoregressive model (adapted from vars::VAR)} 6 | \usage{ 7 | varf( 8 | y, 9 | h = 5, 10 | level = 95, 11 | lags = 1, 12 | type_VAR = c("const", "trend", "both", "none"), 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{y}{A multivariate time series of class \code{ts}} 18 | 19 | \item{h}{Forecasting horizon} 20 | 21 | \item{level}{Confidence level for prediction intervals} 22 | 23 | \item{lags}{Number of lags} 24 | 25 | \item{type_VAR}{Type of deterministic regressors to include.} 26 | 27 | \item{...}{Additional parameters to be passed to vars::VAR.} 28 | } 29 | \value{ 30 | An object of class "mtsforecast"; a list containing the following elements: 31 | 32 | \item{method}{The name of the forecasting method as a character string} 33 | \item{mean}{Point forecasts for the time series} 34 | \item{lower}{Lower bound for prediction interval} 35 | \item{upper}{Upper bound for prediction interval} 36 | \item{x}{The original time series} 37 | \item{residuals}{Residuals from the fitted model} 38 | } 39 | \description{ 40 | Vector Autoregressive model adapted from vars::VAR (only for benchmarking) 41 | } 42 | \examples{ 43 | 44 | require(fpp) 45 | 46 | print(varf(fpp::insurance, lags=2, h=10)) 47 | 48 | res <- varf(fpp::usconsumption, h=20, lags=2) 49 | 50 | par(mfrow=c(1, 2)) 51 | plot(res, "consumption") 52 | plot(res, "income") 53 | 54 | } 55 | \references{ 56 | Bernhard Pfaff (2008). VAR, SVAR and SVEC Models: Implementation 57 | Within R Package vars. Journal of Statistical Software 27(4). URL 58 | http://www.jstatsoft.org/v27/i04/. \cr 59 | 60 | Pfaff, B. (2008) Analysis of Integrated and Cointegrated Time Series 61 | with R. Second Edition. Springer, New York. ISBN 0-387-27960-1 62 | } 63 | \author{ 64 | T. Moudiki 65 | } 66 | -------------------------------------------------------------------------------- /src/RcppExports.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/RcppExports.o -------------------------------------------------------------------------------- /src/ahead.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/ahead.so -------------------------------------------------------------------------------- /src/compute_attention.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace Rcpp; 3 | 4 | // [[Rcpp::export]] 5 | NumericMatrix compute_attention_cpp(NumericVector series) { 6 | int n = series.length(); 7 | NumericMatrix attention_matrix(n, n); 8 | 9 | // Pre-compute series norm once since we'll use the full series 10 | double series_norm = 0.0; 11 | for (int i = 0; i < n; i++) { 12 | series_norm += series[i] * series[i]; 13 | } 14 | series_norm = sqrt(series_norm); 15 | 16 | // For each time point t, compute attention weights for all points j <= t 17 | for (int t = 0; t < n; t++) { 18 | for (int j = 0; j <= t; j++) { 19 | double dot_product = 0.0; 20 | double past_norm = 0.0; 21 | 22 | // Only consider values up to point j 23 | for (int k = 0; k <= j; k++) { 24 | dot_product += series[k] * series[k]; 25 | past_norm += series[k] * series[k]; 26 | } 27 | past_norm = sqrt(past_norm); 28 | 29 | // Calculate similarity 30 | double similarity = 0.0; 31 | if (past_norm > 0.0) { 32 | similarity = dot_product / (series_norm * past_norm); 33 | } 34 | 35 | attention_matrix(t, j) = similarity; 36 | } 37 | 38 | // Normalize weights for current time point 39 | double sum_weights = 0.0; 40 | for (int j = 0; j <= t; j++) { 41 | sum_weights += attention_matrix(t, j); 42 | } 43 | 44 | if (sum_weights > 0.0) { 45 | for (int j = 0; j <= t; j++) { 46 | attention_matrix(t, j) /= sum_weights; 47 | } 48 | } 49 | } 50 | 51 | return attention_matrix; 52 | } 53 | 54 | // [[Rcpp::export]] 55 | NumericVector compute_context_vectors_cpp(NumericVector series, 56 | NumericMatrix attention_weights) { 57 | int n = series.length(); 58 | NumericVector context_vectors(n); 59 | 60 | // For each time point t, compute weighted sum of past values 61 | for (int t = 0; t < n; t++) { 62 | double weighted_sum = 0.0; 63 | // Only use information up to time t (causal attention) 64 | for (int j = 0; j <= t; j++) { 65 | weighted_sum += attention_weights(t, j) * series[j]; 66 | } 67 | context_vectors[t] = weighted_sum; 68 | } 69 | 70 | return context_vectors; 71 | } -------------------------------------------------------------------------------- /src/compute_attention.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/compute_attention.o -------------------------------------------------------------------------------- /src/embedc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace Rcpp; 3 | 4 | NumericMatrix embedc(NumericVector x, 5 | unsigned int lags) { 6 | unsigned long int n = x.size(); 7 | unsigned long int i = 0; 8 | unsigned long int j = 0; 9 | lags -= 1; 10 | unsigned long int n_lags = n-lags; 11 | unsigned int lag_plus = lags + 1; 12 | NumericMatrix res(n_lags, lag_plus); 13 | 14 | for (j = 0; j < lag_plus; j++) 15 | { 16 | for (i = 0; i < n_lags; i++) 17 | { 18 | res(i, j) = x(lags + i - j); 19 | } 20 | } 21 | 22 | return (res); 23 | } 24 | 25 | 26 | // You can include R code blocks in C++ files processed with sourceCpp 27 | // (useful for testing and development). The R code will be automatically 28 | // run after the compilation. 29 | // 30 | 31 | // /*** R 32 | // (y <- rnorm(10)) 33 | // embedc(y, 1) 34 | // embedc(y, 2) 35 | // */ 36 | -------------------------------------------------------------------------------- /src/embedc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/embedc.o -------------------------------------------------------------------------------- /src/ml_forecast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace Rcpp; 3 | 4 | // [[Rcpp::export]] 5 | NumericVector exact_rf_forecast(NumericMatrix embed_mat, int h, int lags, 6 | Function predict_func, List model) { 7 | int n = embed_mat.nrow(); 8 | NumericVector forecasts(h); 9 | 10 | // Create full working matrix (matches R's growing approach) 11 | NumericMatrix working_mat(h + n, lags + 1); 12 | for (int i = 0; i < n; i++) { 13 | for (int j = 0; j <= lags; j++) { 14 | working_mat(h + i, j) = embed_mat(i, j); 15 | } 16 | } 17 | 18 | // Create lag names identical to R 19 | CharacterVector lag_names(lags); 20 | for (int j = 0; j < lags; j++) { 21 | lag_names[j] = "lag" + std::to_string(lags - j); 22 | } 23 | 24 | for (int i = 0; i < h; i++) { 25 | // Create prediction data frame (exact match to R) 26 | List newdata(lags); 27 | for (int j = 0; j < lags; j++) { 28 | newdata[j] = NumericVector::create(working_mat(h - i, j)); 29 | } 30 | newdata.attr("names") = lag_names; 31 | newdata.attr("class") = "data.frame"; 32 | newdata.attr("row.names") = 1; 33 | 34 | // Make prediction 35 | forecasts[i] = as(predict_func(model, newdata)); 36 | 37 | // Update working matrix (EXACT match to R's behavior) 38 | // 1. Create new row with shifted lags 39 | for (int j = lags; j > 1; j--) { 40 | working_mat(h - i - 1, j - 1) = working_mat(h - i, j - 2); 41 | } 42 | // 2. Insert forecast as first lag 43 | working_mat(h - i - 1, 0) = forecasts[i]; 44 | // 3. Set y value 45 | working_mat(h - i - 1, lags) = forecasts[i]; 46 | } 47 | 48 | // Return forecasts in reverse order to match R 49 | std::reverse(forecasts.begin(), forecasts.end()); 50 | return forecasts; 51 | } -------------------------------------------------------------------------------- /src/ml_forecast.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/ml_forecast.o -------------------------------------------------------------------------------- /src/utils_armagarch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace Rcpp; 3 | 4 | 5 | // Forecasting innovations - core loop 6 | 7 | // [[Rcpp::export]] 8 | NumericVector forecast_innovs_loop_cpp(NumericVector eps, 9 | NumericVector rts, 10 | double eps_prev, 11 | double omega, double alpha, double beta, 12 | unsigned int df, unsigned int h) 13 | { 14 | double sigma_prev, sigma_new; 15 | double eps_new; 16 | 17 | sigma_prev = omega/(1 - alpha - beta); 18 | sigma_new = 0; 19 | eps_new = 0; 20 | 21 | for(unsigned int i = 0; i < h; i++) 22 | { 23 | sigma_new = sqrt(omega + alpha*pow(eps_prev, 2) + beta*pow(sigma_prev, 2)); 24 | eps_new = rts(i)*sigma_new/sqrt(df/(df-2)); 25 | 26 | eps(i) = eps_new; 27 | 28 | eps_prev = eps_new; 29 | sigma_prev = sigma_new; 30 | } 31 | 32 | return(eps); 33 | } 34 | 35 | 36 | // [[Rcpp::export]] 37 | NumericVector forecast_innovs_loop_cpp2(NumericVector eps, 38 | NumericVector rn, 39 | double eps_prev, 40 | double omega, double alpha, double beta, 41 | unsigned int df, unsigned int h) 42 | { 43 | double sigma_prev, sigma_new; 44 | double eps_new; 45 | 46 | sigma_prev = omega/(1 - alpha - beta); 47 | sigma_new = 0; 48 | eps_new = 0; 49 | 50 | for(unsigned int i = 0; i < h; i++) 51 | { 52 | sigma_new = sqrt(omega + alpha*pow(eps_prev, 2) + beta*pow(sigma_prev, 2)); 53 | eps_new = rn(i)*sigma_new; 54 | 55 | eps(i) = eps_new; 56 | 57 | eps_prev = eps_new; 58 | sigma_prev = sigma_new; 59 | } 60 | 61 | return(eps); 62 | } 63 | 64 | // You can include R code blocks in C++ files processed with sourceCpp 65 | // (useful for testing and development). The R code will be automatically 66 | // run after the compilation. 67 | // 68 | 69 | /*** R 70 | timesTwo(42) 71 | */ 72 | -------------------------------------------------------------------------------- /src/utils_armagarch.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/utils_armagarch.o -------------------------------------------------------------------------------- /src/utils_matrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace Rcpp; 3 | 4 | // [[Rcpp::export]] 5 | NumericMatrix create_lags_cpp(NumericVector x, int k) 6 | { 7 | unsigned long int n = x.size(); 8 | unsigned long int n_k = n-k; 9 | 10 | int ncol = k + 1; 11 | NumericMatrix res(n_k, ncol); 12 | 13 | for(int i = 0; i < ncol; i++) { 14 | for(int p = 0; p < n_k; p++) 15 | { 16 | res(p, i) = x(p + i); 17 | } 18 | } 19 | return res; 20 | } 21 | 22 | // [[Rcpp::export]] 23 | List create_train_inputs_cpp(NumericMatrix x, int k) 24 | { 25 | unsigned long int n = x.nrow(); 26 | unsigned long int p = x.ncol(); 27 | unsigned long int n_k = n-k; 28 | 29 | unsigned long int j, l; 30 | 31 | NumericMatrix y(n_k, p); 32 | NumericMatrix regressors(n_k, k*p); 33 | NumericMatrix Y_x(n_k, k); 34 | 35 | for(j = 0; j < p; j++) { 36 | Y_x = create_lags_cpp(x(_, j), k); 37 | y(_, j) = Y_x(_, 0); 38 | for(l = 1; l < k; l++) { 39 | regressors(_, j*k + (l-1)) = Y_x(_, l); 40 | } 41 | regressors(_, j*k + (k-1)) = Y_x(_, l); 42 | } 43 | 44 | return Rcpp::List::create(Rcpp::Named("y") = y, 45 | Rcpp::Named("regressors") = regressors); 46 | 47 | } 48 | 49 | // [[Rcpp::export]] 50 | NumericMatrix reformat_cpp(NumericMatrix x, unsigned long int n_k) 51 | { 52 | unsigned long int n = x.nrow(); 53 | unsigned long int p = x.ncol(); 54 | NumericMatrix res(1, n_k*p); 55 | 56 | if (n_k >= n) { 57 | ::Rf_error("you must have n_k < x.nrow()"); 58 | } 59 | 60 | for(int j = 0; j < p; j++) { 61 | for(int i = 0; i < n_k; i++) { 62 | res(0, j*n_k + i) = x(i, j); 63 | } 64 | } 65 | return res; 66 | } 67 | 68 | // [[Rcpp::export]] 69 | NumericMatrix rev_matrix_cpp(NumericMatrix x) 70 | { 71 | unsigned long int n = x.nrow(); 72 | unsigned long int p = x.ncol(); 73 | NumericMatrix res(n, p); 74 | 75 | int j; 76 | for(int k = 0; k < p; k++) { 77 | j = 0; 78 | for(int i = (n-1); i >= 0; i--) { 79 | res(j , k) = x(i , k); 80 | j++; 81 | } 82 | } 83 | return res; 84 | } 85 | 86 | // [[Rcpp::export]] 87 | NumericMatrix rbind_vecmat_cpp(NumericVector y, NumericMatrix x) 88 | { 89 | unsigned long int x_nrow = x.nrow(); 90 | unsigned long int x_ncol = x.ncol(); 91 | unsigned long int y_ncol = y.size(); 92 | if (x_ncol != y_ncol) { 93 | ::Rf_error("you must have x.ncol() == y.size()"); 94 | } 95 | unsigned long int res_nrow = x_nrow + 1; 96 | NumericMatrix res(res_nrow, x_ncol); 97 | 98 | for(int i = 0; i < x_nrow; i++) { 99 | res(i + 1 , _) = x(i , _); 100 | } 101 | 102 | for(int j = 0; j < x_ncol; j++) { 103 | res(0, j) = y(j); 104 | } 105 | 106 | return res; 107 | } 108 | -------------------------------------------------------------------------------- /src/utils_matrix.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/src/utils_matrix.o -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ahead) 3 | 4 | test_check("ahead") 5 | -------------------------------------------------------------------------------- /tests/testthat/Rplots.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Techtonique/ahead/91bfb814dc24b79fdd170ba6749dfd6c4d9edb6c/tests/testthat/Rplots.pdf -------------------------------------------------------------------------------- /tests/testthat/test_armagarchf.R: -------------------------------------------------------------------------------- 1 | context("Tests on `ridge2f`") 2 | 3 | # 1 - Code ---- 4 | 5 | library(testthat) 6 | library(ahead) 7 | 8 | set.seed(123L) 9 | x <- ts(rnorm(100L)) 10 | 11 | res1 <- ahead::armagarchf(x, h = 5, 12 | level = 95, 13 | B = 10L, 14 | cl = 1L, 15 | dist = "student", 16 | seed = 1231) 17 | res2 <- ahead::armagarchf(x, h = 6, 18 | level = 80, 19 | B = 10L, 20 | cl = 1L, 21 | dist = "gaussian", 22 | seed = 1232) 23 | res3 <- ahead::armagarchf(x, h = 7, 24 | level = 95, 25 | B = 10L, 26 | cl = 1L, 27 | dist = "student", 28 | seed = 1233) 29 | res4 <- ahead::armagarchf(x, h = 8, 30 | level = 80, 31 | B = 10L, 32 | cl = 1L, 33 | dist = "gaussian", 34 | seed = 1234) 35 | res5 <- ahead::armagarchf(x, h = 9, 36 | level = 95, 37 | B = 10L, 38 | cl = 1L, 39 | dist = "student", 40 | seed = 1235) 41 | res6 <- ahead::armagarchf(x, h = 5, 42 | level = 95, 43 | B = 10L, 44 | cl = 2L, 45 | dist = "student", 46 | seed = 1231) 47 | 48 | # 2 - tests ----- 49 | 50 | testthat::test_that("1 - tests on types of residuals' simulations", { 51 | expect_equal(as.numeric(round(res1$mean[5], 2)), -0.24) 52 | expect_equal(as.numeric(round(res2$mean[5], 2)), 0.95) 53 | expect_equal(as.numeric(round(res3$lower[5])), -1) 54 | expect_equal(as.numeric(round(res4$lower[5], 2)), -0.72) 55 | expect_equal(as.numeric(round(res5$mean[5], 2)), -0.18) 56 | expect_equal(as.numeric(round(res6$mean[5], 2)), -0.24) 57 | }) 58 | 59 | -------------------------------------------------------------------------------- /tests/testthat/test_basicf.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ahead) 3 | 4 | set.seed(123) 5 | x <- ts(matrix(rnorm(100), ncol=2)) 6 | z <- matrix(rnorm(100), ncol=2) 7 | 8 | res1 <- ahead::basicf(x) 9 | res2 <- ahead::basicf(x, type_pi = "bootstrap", B=10) 10 | res3 <- ahead::basicf(x, type_pi = "blockbootstrap", B=10, 11 | block_length = 4, show_progress = FALSE) 12 | res4 <- ahead::basicf(z) 13 | res5 <- ahead::basicf(x, 14 | type_pi = "blockbootstrap", 15 | B=10, 16 | show_progress = FALSE) 17 | res6 <- ahead::basicf(x, 18 | type_pi = "movingblockbootstrap", 19 | B=10, 20 | show_progress = FALSE) 21 | 22 | 23 | testthat::test_that("1 - tests on basicf", { 24 | print("running tests on basicf") 25 | expect_equal(as.numeric(round(res1$mean[1, 1], 2)), 0.03) 26 | expect_equal(as.numeric(round(res2$mean[1, 1], 2)), 0.03) 27 | expect_equal(as.numeric(round(res3$mean[1, 1], 2)), 0.03) 28 | expect_equal(as.numeric(round(res4$mean[1, 1], 2)), -0.25) 29 | expect_equal(as.numeric(round(res5$mean[1, 1], 2)), 0.03) 30 | expect_equal(as.numeric(round(res6$mean[1, 1], 2)), 0.03) 31 | }) 32 | -------------------------------------------------------------------------------- /tests/testthat/test_dynrmf.R: -------------------------------------------------------------------------------- 1 | context("Tests on `dynrmf`") 2 | 3 | # 1 - Code ---- 4 | 5 | library(testthat) 6 | library(ahead) 7 | require(e1071) 8 | 9 | set.seed(123) 10 | x <- ts(rnorm(100)) 11 | 12 | # fit_func = ahead::ridge, 13 | # predict_func = predict, 14 | # fit_params = NULL, 15 | # type_pi = c("gaussian", "E", "A", "T"), 16 | # xreg_fit = NULL, 17 | # xreg_predict = NULL, 18 | res1 <- ahead::dynrmf(x) 19 | res2 <- ahead::dynrmf(x, type_pi ="E") 20 | res3 <- ahead::dynrmf(x, type_pi ="A") 21 | res4 <- ahead::dynrmf(x, type_pi ="T") 22 | res5 <- ahead::dynrmf(x, fit_func = e1071::svm, 23 | fit_params = list(kernel = "linear"), 24 | predict_func = predict) 25 | res7 <- ahead::dynrmf(x, xreg_fit = 1:length(x), 26 | xreg_predict = (length(x)+1):(length(x)+5)) 27 | x <- AirPassengers 28 | res6 <- ahead::dynrmf(x, xreg_fit = 1:length(x), 29 | xreg_predict = (length(x)+1):(length(x)+5)) 30 | res8 <- ahead::dynrmf(abs(x), lambda="auto") 31 | 32 | testthat::test_that("1 - tests on dynrm", { 33 | print("running tests on dynrm") 34 | expect_equal(as.numeric(round(res1$mean[1], 2)), 0.1) 35 | expect_equal(as.numeric(round(res2$mean[1], 2)), 0.1) 36 | expect_equal(as.numeric(round(res3$mean[1], 2)), 0.1) 37 | expect_equal(as.numeric(round(res4$mean[1], 2)), 0.2) 38 | expect_equal(as.numeric(round(res5$mean[1], 2)), 0.08) 39 | expect_equal(as.numeric(round(res6$mean[1], 2)), 455.82) 40 | expect_equal(as.numeric(round(res7$mean[1], 2)), 0.1) 41 | expect_equal(as.numeric(round(res8$mean[1], 2)), 454.44) 42 | }) 43 | -------------------------------------------------------------------------------- /tests/testthat/test_eat.R: -------------------------------------------------------------------------------- 1 | context("Tests on `eatf`") 2 | 3 | # 1 - Code ---- 4 | 5 | library(testthat) 6 | library(ahead) 7 | 8 | set.seed(123) 9 | x <- ts(rnorm(100)) 10 | 11 | # method = c("EAT", "E", "A", "T"), 12 | # weights = rep(1/3, 3), 13 | # type_pi = c("gaussian", "E", "A", "T") 14 | res1 <- ahead::eatf(x) 15 | res2 <- ahead::eatf(x, method = "E") 16 | res3 <- ahead::eatf(x, method = "A") 17 | res4 <- ahead::eatf(x, method = "T") 18 | res5 <- ahead::eatf(x, method = "EAT") 19 | res6 <- ahead::eatf(x, weights = c(0, 0.5, 0.5)) 20 | res7 <- ahead::eatf(x, weights = c(0.5, 0, 0.5)) 21 | res8 <- ahead::eatf(x, weights = c(0.5, 0.5, 0)) 22 | res9 <- ahead::eatf(x, type_pi = "E") 23 | res10 <- ahead::eatf(x, type_pi = "A") 24 | res11 <- ahead::eatf(x, type_pi = "T") 25 | 26 | testthat::test_that("1 - tests on eat", { 27 | print("running tests on eat") 28 | expect_equal(as.numeric(round(res1$mean[1], 2)), 0.1) 29 | expect_equal(as.numeric(round(res2$mean[1], 2)), 0.1) 30 | expect_equal(as.numeric(round(res3$mean[1], 2)), 0) 31 | expect_equal(as.numeric(round(res4$mean[1], 2)), 0.22) 32 | expect_equal(as.numeric(round(res5$mean[1], 2)), 0.1) 33 | expect_equal(as.numeric(round(res6$mean[1], 2)), 0.11) 34 | expect_equal(as.numeric(round(res7$mean[1], 2)), 0.16) 35 | expect_equal(as.numeric(round(res8$mean[1], 2)), 0.05) 36 | expect_equal(as.numeric(round(res9$mean[1], 2)), 0.14) 37 | expect_equal(as.numeric(round(res10$mean[1], 2)), 0.1) 38 | expect_equal(as.numeric(round(res11$mean[1], 2)), 0.26) 39 | }) 40 | -------------------------------------------------------------------------------- /tests/testthat/test_loessf.R: -------------------------------------------------------------------------------- 1 | context("Tests on `loessf`") 2 | 3 | # 1 - Code ---- 4 | 5 | library(testthat) 6 | library(ahead) 7 | require(e1071) 8 | 9 | set.seed(123) 10 | x <- ts(rnorm(50)) 11 | 12 | res1 <- ahead::loessf(x) 13 | res2 <- ahead::loessf(x, type_aggregation = "mean") 14 | res3 <- ahead::loessf(x, type_aggregation = "median") 15 | res4 <- ahead::loessf(x, type_aggregation = "median", 16 | type_pi = "bootstrap") 17 | res5 <- ahead::loessf(x, type_aggregation = "median", 18 | b = 3, type_pi = "blockbootstrap") 19 | res6 <- ahead::loessf(x, type_aggregation = "median", 20 | type_pi = "movingblockbootstrap") 21 | 22 | 23 | testthat::test_that("1 - tests on dynrm", { 24 | print("running tests on dynrm") 25 | expect_equal(as.numeric(round(res1$mean[1], 2)), -0.24) 26 | expect_equal(as.numeric(round(res2$mean[1], 2)), -0.24) 27 | expect_equal(as.numeric(round(res3$mean[1], 2)), -0.35) 28 | expect_equal(as.numeric(round(res4$mean[1], 2)), -0.35) 29 | expect_equal(as.numeric(round(res5$mean[1], 2)), -0.25) 30 | expect_equal(as.numeric(round(res6$mean[1], 2)), -0.42) 31 | }) 32 | -------------------------------------------------------------------------------- /tests/testthat/test_ml.R: -------------------------------------------------------------------------------- 1 | # context("Tests on `mlf`") 2 | # 3 | # # 1 - Code ---- 4 | # 5 | # library(testthat) 6 | # library(ahead) 7 | # 8 | # set.seed(123) 9 | # x <- ts(rnorm(10)) 10 | # res <- ahead::embedc(x, 1) 11 | # 12 | # testthat::test_that("1 - tests on mlf", { 13 | # print("running tests on mlf") 14 | # expect_equal(res, embed(x, 1)) 15 | # }) 16 | -------------------------------------------------------------------------------- /tests/testthat/test_varf.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ahead) 3 | 4 | set.seed(123) 5 | z <- matrix(rnorm(100), ncol=2) 6 | x <- ts(z) 7 | 8 | res1 <- ahead::varf(x) 9 | res2 <- ahead::varf(z) 10 | 11 | testthat::test_that("1 - tests on varf", { 12 | print("running tests on varf") 13 | expect_equal(as.numeric(round(res1$mean[1, 1], 2)), 0.04) 14 | expect_equal(as.numeric(round(res2$mean[1, 1], 2)), 0.04) 15 | }) 16 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/ahead-loess-forecasting.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Prediction intervals for Loess forecasting (simulation-based)" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Prediction intervals for Loess forecasting (simulation-based)} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | `ahead` is a package for **univariate** and **multivariate time series forecasting**, with uncertainty quantification (R and [Python](https://techtonique.github.io/ahead_python/)). 11 | 12 | The model used in this demo is `stats::loess` (Local Polynomial Regression Fitting), 13 | **adapted to univariate forecasting** in `ahead::loessf`. 14 | 15 | Currently for this model (as of 2023-08-28), for **uncertainty quantification**, options are: 16 | 17 | - Independent **bootstrap** of the residuals 18 | - Multivariate circular **block bootstrap** of the residuals 19 | - Multivariate moving block bootstrap of the residuals 20 | - Adjustment of a copula to the residuals 21 | - **More options to come** in the future. 22 | 23 | Please remember that _in real life_, this model's hyperparameters will have to be tuned. 24 | 25 | ```{r, include = FALSE} 26 | knitr::opts_chunk$set( 27 | collapse = TRUE, 28 | comment = "#>" 29 | ) 30 | ``` 31 | 32 | # Install `ahead` 33 | 34 | Here's how to install the R version of the package: 35 | 36 | - **1st method**: from [R-universe](https://r-packages.techtonique.net) 37 | 38 | In R console: 39 | 40 | ``` r 41 | options(repos = c( 42 | techtonique = 'https://r-packages.techtonique.net', 43 | CRAN = 'https://cloud.r-project.org')) 44 | 45 | install.packages("ahead") 46 | ``` 47 | 48 | - **2nd method**: from [Github](https://github.com/Techtonique/ahead) 49 | 50 | In R console: 51 | 52 | ``` r 53 | devtools::install_github("Techtonique/ahead") 54 | ``` 55 | 56 | Or 57 | 58 | ``` r 59 | remotes::install_github("Techtonique/ahead") 60 | ``` 61 | 62 | And here are the packages that will be used in this vignette: 63 | 64 | ```{r include=FALSE} 65 | library(ahead) 66 | library(fpp) 67 | library(datasets) 68 | library(randomForest) 69 | library(e1071) 70 | ``` 71 | 72 | ``` r 73 | library(ahead) 74 | library(datasets) 75 | ``` 76 | 77 | # `ahead::loessf` on Nile dataset 78 | 79 | ```{r "bootstrap-mean", fig.width=7.2} 80 | plot(loessf(Nile, h=20, 81 | type_pi = "bootstrap", 82 | type_aggregation = "mean", 83 | level=95, B=10)) 84 | ``` 85 | 86 | ```{r "bootstrap-median", fig.width=7.2} 87 | plot(loessf(Nile, h=20, 88 | type_pi = "bootstrap", 89 | type_aggregation = "median", 90 | level=95, B=10)) 91 | ``` 92 | 93 | ```{r "blockbootstrap-mean", fig.width=7.2} 94 | plot(loessf(Nile, h=20, 95 | type_pi = "blockbootstrap", 96 | type_aggregation = "mean", 97 | level=95, B=10)) 98 | ``` 99 | 100 | ```{r "blockbootstrap-median", fig.width=7.2} 101 | plot(loessf(Nile, h=20, 102 | type_pi = "blockbootstrap", 103 | type_aggregation = "median", 104 | level=95, B=10)) 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /vignettes/ahead-neutralize.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Risk-neutralize simulations" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Risk-neutralize simulations} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r setup, include=FALSE} 11 | knitr::opts_chunk$set(echo = TRUE) 12 | ``` 13 | 14 | **Contents:** 15 | 16 | - 0 - Install `ahead` 17 | 18 | - 1 - Get and transform data 19 | 20 | - 2 - Risk-neutralize simulations 21 | 22 | - 3 - Visualization 23 | 24 | # 0 - Install `ahead` 25 | 26 | `ahead` is released under the BSD Clear license. Here's how to install the R version of the package: 27 | 28 | - **1st method**: from [R-universe](https://r-packages.techtonique.net) 29 | 30 | In R console: 31 | 32 | ``` r 33 | options(repos = c( 34 | techtonique = 'https://r-packages.techtonique.net', 35 | CRAN = 'https://cloud.r-project.org')) 36 | 37 | install.packages("ahead") 38 | ``` 39 | 40 | - **2nd method**: from [Github](https://github.com/Techtonique/ahead) 41 | 42 | In R console: 43 | 44 | ``` r 45 | devtools::install_github("Techtonique/ahead") 46 | ``` 47 | 48 | Or 49 | 50 | ``` r 51 | remotes::install_github("Techtonique/ahead") 52 | ``` 53 | 54 | Using `ahead`: 55 | 56 | ```{r include=FALSE} 57 | library(ahead) 58 | ``` 59 | 60 | ```R 61 | library(ahead) 62 | library(fpp) 63 | ``` 64 | 65 | # 1 - Get and transform data 66 | 67 | ```{r} 68 | data(EuStockMarkets) 69 | 70 | EuStocks <- ts(EuStockMarkets[1:100, ], 71 | start = start(EuStockMarkets), 72 | frequency = frequency(EuStockMarkets)) 73 | 74 | EuStocksLogReturns <- ahead::getreturns(EuStocks, type = "log") 75 | 76 | print(head(EuStocksLogReturns)) 77 | ``` 78 | 79 | # 2 - Risk-neutralize simulations 80 | 81 | ## 2 - 1 Yield to maturities (fake *risk-free* rates) 82 | 83 | ```{r} 84 | ym <- c(0.03013425, 0.03026776, 0.03040053, 0.03053258, 0.03066390, 0.03079450, 0.03092437) 85 | 86 | freq <- frequency(EuStocksLogReturns) 87 | (start_preds <- tsp(EuStocksLogReturns)[2] + 1 / freq) 88 | (ym <- stats::ts(ym, 89 | start = start_preds, 90 | frequency = frequency(EuStocksLogReturns))) 91 | ``` 92 | 93 | ## 2 - 2 Risk-neutralized simulations 94 | 95 | ```{r echo=TRUE, eval=FALSE} 96 | obj <- ahead::ridge2f(EuStocksLogReturns, h = 7L, 97 | type_pi = 'bootstrap', 98 | B = 10L, ym = ym) 99 | ``` 100 | 101 | ```{r echo=TRUE, eval=FALSE} 102 | rowMeans(obj$neutralized_sims$CAC) 103 | ``` 104 | 105 | ```{r echo=TRUE, eval=FALSE} 106 | print(ym) 107 | ``` 108 | 109 | ```{r echo=TRUE, eval=FALSE} 110 | rowMeans(obj$neutralized_sims$DAX) 111 | ``` 112 | 113 | ```{r echo=TRUE, eval=FALSE} 114 | print(ym) 115 | ``` 116 | 117 | # 3 - Visualization 118 | 119 | ```{r echo=TRUE, fig.width=7.2, eval=FALSE} 120 | 121 | #par(mfrow = c(2, 2)) 122 | 123 | matplot(EuStocksLogReturns, type = 'l', 124 | main = "Historical log-Returns", xlab = "time") 125 | 126 | plot(ym, main = "fake spot curve", 127 | xlab = "time to maturity", 128 | ylab = "yield", 129 | ylim = c(0.02, 0.04)) 130 | 131 | matplot(obj$neutralized_sims$DAX, type = 'l', 132 | main = "simulations of \n predicted DAX log-returns ('risk-neutral')", 133 | ylim = c(0.02, 0.04), 134 | ylab = "log-returns") 135 | 136 | ci <- apply(obj$neutralized_sims$DAX, 1, function(x) t.test(x)$conf.int) 137 | plot(rowMeans(obj$neutralized_sims$DAX), type = 'l', main = "average predicted \n DAX log-returns ('risk-neutral')", col = "blue", 138 | ylim = c(0.02, 0.04), 139 | ylab = "log-returns") 140 | lines(ci[1, ], col = "red") 141 | lines(ci[2, ], col = "red") 142 | ``` 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /vignettes/ahead-plotting-functions.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Plotting functions" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Plotting functions} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | `ahead` is a package for **univariate** and **multivariate time series forecasting**, with uncertainty quantification (R and [Python](https://techtonique.github.io/ahead_python/)). 11 | 12 | The model used in this demo is `stats::ridge2f`. 13 | 14 | Please remember that _in real life_, this model's hyperparameters will have to be tuned. 15 | 16 | ```{r, include = FALSE} 17 | knitr::opts_chunk$set( 18 | collapse = TRUE, 19 | comment = "#>" 20 | ) 21 | ``` 22 | 23 | # Install `ahead` 24 | 25 | Here's how to install the R version of the package: 26 | 27 | - **1st method**: from [R-universe](https://r-packages.techtonique.net) 28 | 29 | In R console: 30 | 31 | ``` r 32 | options(repos = c( 33 | techtonique = 'https://r-packages.techtonique.net', 34 | CRAN = 'https://cloud.r-project.org')) 35 | 36 | install.packages("ahead") 37 | ``` 38 | 39 | - **2nd method**: from [Github](https://github.com/Techtonique/ahead) 40 | 41 | In R console: 42 | 43 | ``` r 44 | devtools::install_github("Techtonique/ahead") 45 | ``` 46 | 47 | Or 48 | 49 | ``` r 50 | remotes::install_github("Techtonique/ahead") 51 | ``` 52 | 53 | And here are the packages that will be used in this vignette: 54 | 55 | ``` r 56 | library(ahead) 57 | library(fpp) 58 | ``` 59 | 60 | ```{r include=FALSE} 61 | library(ahead) 62 | library(fpp) 63 | ``` 64 | 65 | # Forecasting and plot predictions 66 | 67 | ```{r , eval=FALSE} 68 | obj <- ahead::ridge2f(fpp::insurance, h = 7, type_pi = "blockbootstrap", B = 10, 69 | block_length = 5) 70 | ``` 71 | 72 | ```{r fig.width=7.2, eval=FALSE} 73 | plot(obj, selected_series = "Quotes", type = "sims", 74 | main = "Predictive simulations \n for Quotes") 75 | plot(obj, selected_series = "Quotes", type = "dist", 76 | main = "Predictive simulation \n for Quotes") 77 | ``` 78 | 79 | ```{r fig.width=7.2, eval=FALSE} 80 | plot(obj, selected_series = "TV.advert", type = "sims", 81 | main = "Predictive simulation \n for TV.advert") 82 | plot(obj, selected_series = "TV.advert", type = "dist", 83 | main = "Predictive simulation \n for TV.advert") 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /vignettes/ahead-ridge2-conformal.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Conformal Prediction using Ridge2" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Conformal Prediction using Ridge2} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | **Ridge2** is a uni/multivariate nonlinear probabilistic time series model originally presented in [Multiple Time Series Forecasting Using Quasi-Randomized Functional Link Neural Networks](https://www.mdpi.com/2227-9091/6/1/22). 11 | 12 | ```{r} 13 | library(ahead) 14 | ``` 15 | 16 | # Univariate 17 | 18 | ## AirPassengers 19 | 20 | ```{r, fig.width=5} 21 | plot(ahead::ridge2f(AirPassengers, h=30L, lags=20L, type_pi="conformal-split")) 22 | ``` 23 | 24 | ```{r, fig.width=5} 25 | plot(ahead::ridge2f(AirPassengers, h=30L, lags=20L, type_pi="conformal-block-bootstrap")) 26 | ``` 27 | 28 | ```{r, fig.width=5} 29 | plot(ahead::ridge2f(AirPassengers, h=30L, lags=20L, type_pi="conformal-bootstrap")) 30 | ``` 31 | 32 | ## USAccDeaths 33 | 34 | ```{r, fig.width=5} 35 | plot(ahead::ridge2f(USAccDeaths, h=20L, lags=10L, type_pi="conformal-split")) 36 | ``` 37 | 38 | ```{r, fig.width=5} 39 | plot(ahead::ridge2f(USAccDeaths, h=20L, lags=10L, type_pi="conformal-block-bootstrap")) 40 | ``` 41 | 42 | ```{r, fig.width=5} 43 | plot(ahead::ridge2f(USAccDeaths, h=20L, lags=10L, type_pi="conformal-bootstrap")) 44 | ``` 45 | 46 | 47 | # Multivariate 48 | 49 | ```{r, fig.width=5} 50 | obj <- ahead::ridge2f(fpp::insurance, 51 | h=10L, lags=2L, 52 | type_pi = "conformal-split") 53 | 54 | 55 | plot(obj, "Quotes") 56 | plot(obj, "TV.advert") 57 | ``` 58 | 59 | 60 | ```{r, fig.width=7.5} 61 | obj <- ahead::ridge2f(fpp::insurance, 62 | n_hidden_features = 0L, 63 | h=10L, lags=1L, 64 | type_pi = "conformal-block-bootstrap") 65 | 66 | 67 | plot(obj, "Quotes") 68 | plot(obj, "TV.advert") 69 | ``` 70 | 71 | ```{r, fig.width=7.5} 72 | obj <- ahead::ridge2f(fpp::insurance, 73 | h=10L, lags=2L, 74 | type_pi = "conformal-bootstrap") 75 | 76 | 77 | plot(obj, "Quotes") 78 | plot(obj, "TV.advert") 79 | ``` 80 | 81 | ```{r, fig.width=7.2} 82 | plot(obj, "Quotes", type = "dist") 83 | plot(obj, "TV.advert", type = "sims") 84 | ``` 85 | -------------------------------------------------------------------------------- /vignettes/ahead-univariate-season.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Univariate forecasting with `ridge2f` in `ahead`" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Univariate forecasting with `ridge2f` in `ahead`} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | 11 | ```{r} 12 | library(ahead) 13 | library(forecast) 14 | ``` 15 | 16 | 17 | ```{r fig.width=6.5} 18 | x <- fdeaths 19 | xreg <- ahead::createtrendseason(x) 20 | (z <- ahead::ridge2f(x, xreg = xreg, h=20)) 21 | autoplot(z) 22 | ``` 23 | 24 | ```{r fig.width=6.5} 25 | x <- USAccDeaths 26 | xreg <- ahead::createtrendseason(x) 27 | (z <- ahead::ridge2f(x, xreg = xreg, h=20)) 28 | autoplot(z) 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /vignettes/ahead-vignette.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to R package `ahead`" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Introduction to R package `ahead`} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | `ahead` is a package for __univariate__ and __multivariate time series forecasting__. Five forecasting methods are implemented so far, as of October 13th, 2021. 11 | 12 | - `armagarchf`: **univariate** time series forecasting method using simulation of an ARMA(1, 1) - GARCH(1, 1) 13 | - `dynrmf`: **univariate** time series forecasting method adapted from [`forecast::nnetar`](https://otexts.com/fpp2/nnetar.html#neural-network-autoregression) to support any 14 | Statistical/Machine learning model (such as Ridge Regression, Random Forest, Support Vector Machines, etc) 15 | - `eatf`: **univariate** time series forecasting method based on combinations of `forecast::ets`, `forecast::auto.arima`, and `forecast::thetaf` 16 | - `ridge2f`: **multivariate** time series forecasting method, based on __quasi-randomized networks__ and presented in [this paper](https://www.mdpi.com/2227-9091/6/1/22) 17 | - `varf`: **multivariate** time series forecasting method using Vector AutoRegressive model (VAR, mostly here for benchmarking purpose) 18 | 19 | 20 | 21 | ```{r, include = FALSE} 22 | knitr::opts_chunk$set( 23 | collapse = TRUE, 24 | comment = "#>" 25 | ) 26 | ``` 27 | 28 | Here's how to install the package: 29 | 30 | - __1st method__: from [R-universe](https://ropensci.org/r-universe/) 31 | 32 | In R console: 33 | 34 | ```R 35 | options(repos = c( 36 | techtonique = 'https://r-packages.techtonique.net', 37 | CRAN = 'https://cloud.r-project.org')) 38 | 39 | install.packages("ahead") 40 | ``` 41 | 42 | - __2nd method__: from Github 43 | 44 | In R console: 45 | 46 | ```R 47 | devtools::install_github("Techtonique/ahead") 48 | ``` 49 | 50 | Or 51 | 52 | ```R 53 | remotes::install_github("Techtonique/ahead") 54 | ``` 55 | 56 | And here are the packages that will be used in this vignette: 57 | 58 | ```{r include=FALSE} 59 | library(ahead) 60 | library(fpp) 61 | library(datasets) 62 | library(randomForest) 63 | library(e1071) 64 | ``` 65 | 66 | ```R 67 | library(ahead) 68 | library(fpp) 69 | library(datasets) 70 | library(randomForest) 71 | library(e1071) 72 | ``` 73 | 74 | # Univariate time series 75 | 76 | In this section, we illustrate `dynrmf` forecasting, with Random Forest and SVM. Do not hesitate to type `?dynrmf`, 77 | `?armagarchf` or `?eatf` in R console for more details and examples. 78 | 79 | ```{r fig.width=6.5} 80 | 81 | # Plotting forecasts 82 | # With a Random Forest regressor, an horizon of 20, 83 | # and a 95% prediction interval 84 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = randomForest::randomForest, 85 | fit_params = list(ntree = 50), predict_func = predict)) 86 | 87 | # With a Support Vector Machine regressor, an horizon of 20, 88 | # and a 95% prediction interval 89 | plot(dynrmf(fdeaths, h=20, level=95, fit_func = e1071::svm, 90 | fit_params = list(kernel = "linear"), predict_func = predict)) 91 | 92 | plot(dynrmf(Nile, h=20, level=95, fit_func = randomForest::randomForest, 93 | fit_params = list(ntree = 50), predict_func = predict)) 94 | 95 | plot(dynrmf(Nile, h=20, level=95, fit_func = e1071::svm, 96 | fit_params = list(kernel = "linear"), predict_func = predict)) 97 | 98 | ``` 99 | 100 | 101 | For more advanced examples on `dynrmf`, you can read this [blog post](https://thierrymoudiki.github.io/blog/2021/12/20/r/forecasting/ahead-more-examples). 102 | 103 | # Multivariate time series 104 | 105 | In this section, we illustrate `ridge2f` and `varf` forecasting. Do not hesitate 106 | to type `?ridge2f` or `?varf` in R console for more details on both functions. 107 | 108 | 109 | ```{r fig.width=6.5} 110 | # Forecast using ridge2 111 | # With 2 time series lags, an horizon of 10, 112 | # and a 95% prediction interval 113 | fit_obj_ridge2 <- ahead::ridge2f(fpp::insurance, lags = 2, 114 | h = 10, level = 95) 115 | 116 | 117 | # Forecast using VAR 118 | fit_obj_VAR <- ahead::varf(fpp::insurance, lags = 2, 119 | h = 10, level = 95) 120 | 121 | 122 | # Plotting forecasts 123 | # fpp::insurance contains 2 time series, Quotes and TV.advert 124 | plot(fit_obj_ridge2, "Quotes") 125 | plot(fit_obj_VAR, "Quotes") 126 | plot(fit_obj_ridge2, "TV.advert") 127 | plot(fit_obj_VAR, "TV.advert") 128 | ``` 129 | 130 | -------------------------------------------------------------------------------- /vignettes/caretfitpredict.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Fit and forecast using caret+dynrmf" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Fit and forecast using caret+dynrmf} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | 11 | ```{r} 12 | library(ahead) 13 | library(forecast) 14 | ``` 15 | 16 | ```{r} 17 | myfitfunc <- function(x, y) ahead::fit_func(x, y, method = "glmnet") 18 | ``` 19 | 20 | 21 | ```{r fig.width=7.5} 22 | (obj1 <- ahead::dynrmf(USAccDeaths, h=20L, level=99)) 23 | (obj2 <- ahead::dynrmf(USAccDeaths, fit_func = myfitfunc, predict_func = ahead::predict_func, h=20L, level=99)) 24 | ``` 25 | 26 | ```{r fig.width=7.5} 27 | plot(obj1) 28 | ``` 29 | 30 | ```{r fig.width=7.5} 31 | plot(obj2) 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /vignettes/comb_OLS.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "comb OLS Electricity" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{comb OLS Electricity} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r setup, include=FALSE} 11 | knitr::opts_chunk$set(echo = TRUE) 12 | ``` 13 | 14 | # 1 - Comb OLS 15 | 16 | ```{r} 17 | library(ForecastComb) 18 | ``` 19 | 20 | ```{r} 21 | data(electricity) 22 | 23 | print(head(electricity)) 24 | 25 | (forecasting_methods <- colnames(electricity)[1:5]) 26 | 27 | train_obs <- electricity[1:84, "Actual"] 28 | train_pred <- electricity[1:84, forecasting_methods] 29 | test_obs <- electricity[85:123, "Actual"] 30 | test_pred <- electricity[85:123, forecasting_methods] 31 | ``` 32 | 33 | ```{r} 34 | data <- ForecastComb::foreccomb(train_obs, train_pred, test_obs, test_pred) 35 | ``` 36 | 37 | ```{r} 38 | start <- proc.time()[3] 39 | obj <- ahead::comb_OLS(data) 40 | print(proc.time()[3] - start) 41 | 42 | print(class(obj)) 43 | 44 | print(obj$Accuracy_Test) 45 | 46 | print(obj$Weights) 47 | 48 | # check 49 | print(mean(predict(obj, test_pred) - test_obs)) 50 | ``` 51 | 52 | ```{r fig.width=7.5, eval=FALSE} 53 | plot(obj) 54 | ``` 55 | 56 | # 2 - Comb Ridge 57 | 58 | ```{r eval=TRUE} 59 | start <- proc.time()[3] 60 | obj <- ahead::comb_Ridge(data) 61 | print(proc.time()[3] - start) 62 | ``` 63 | 64 | ```{r eval=TRUE} 65 | 66 | print(obj$Weights) 67 | 68 | print(class(obj)) 69 | 70 | print(obj$Accuracy_Test) 71 | 72 | # check 73 | print(mean(predict(obj, test_pred) - test_obs)) 74 | ``` 75 | 76 | ```{r fig.width=7.5, eval=FALSE} 77 | plot(obj) 78 | ``` 79 | -------------------------------------------------------------------------------- /vignettes/comb_OLS2.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "comb OLS AirPassengers" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{comb OLS AirPassengers} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r setup, include=FALSE} 11 | knitr::opts_chunk$set(echo = TRUE) 12 | ``` 13 | 14 | # 1 - Comb OLS 15 | 16 | ```{r} 17 | library(forecast) 18 | library(ForecastComb) 19 | ``` 20 | 21 | ```{r} 22 | custom_error <- function(actual, forecast_) { 23 | return(mean(abs(forecast_ - actual))) 24 | } 25 | ``` 26 | 27 | ```{r} 28 | h <- 29L 29 | 30 | train_AirPassengers <- ts(AirPassengers[1:115], start = start(AirPassengers), frequency = frequency(AirPassengers)) 31 | 32 | arima_forecast <- forecast::forecast(forecast::auto.arima(train_AirPassengers), h=h) 33 | ets_forecast <- forecast::forecast(forecast::ets(train_AirPassengers), h=h) 34 | theta_forecast <- forecast::thetaf(train_AirPassengers, h=h) 35 | ridge_forecast <- ahead::dynrmf(train_AirPassengers, h=h) 36 | glmnet_forecast <- ahead::dynrmf(train_AirPassengers, h=h, 37 | fit_func = glmnet::cv.glmnet, predict_func = predict) 38 | ``` 39 | 40 | ```{r} 41 | print(forecast::accuracy(arima_forecast, AirPassengers[116:144])) 42 | print(forecast::accuracy(ets_forecast, AirPassengers[116:144])) 43 | print(forecast::accuracy(theta_forecast, AirPassengers[116:144])) 44 | print(forecast::accuracy(ridge_forecast, AirPassengers[116:144])) 45 | print(forecast::accuracy(glmnet_forecast, AirPassengers[116:144])) 46 | ``` 47 | 48 | ```{r} 49 | airpass <- cbind(arima_forecast$mean, 50 | ets_forecast$mean, theta_forecast$mean, 51 | ridge_forecast$mean, glmnet_forecast$mean, 52 | ts(AirPassengers[116:144], 53 | start=start(arima_forecast$mean), 54 | frequency=frequency(AirPassengers))) 55 | ``` 56 | 57 | ```{r} 58 | colnames(airpass) <- c("ARIMA", "ETS", "Theta", "Ridge", "GLMNET", "Actual") 59 | ``` 60 | 61 | ```{r} 62 | (forecasting_methods <- colnames(airpass)[1:5]) 63 | 64 | train_obs <- airpass[1:21, 6] 65 | train_pred <- airpass[1:21, 1:5] 66 | test_obs <- airpass[22:29, 6] 67 | test_pred <- airpass[22:29, 1:5] 68 | 69 | data <- ForecastComb::foreccomb(train_obs, train_pred, test_obs, test_pred) 70 | ``` 71 | 72 | ```{r fig.width=7.5} 73 | start <- proc.time()[3] 74 | obj <- ahead::comb_OLS(data, custom_error=custom_error) 75 | print(proc.time()[3] - start) 76 | 77 | print(obj$Accuracy_Test) 78 | 79 | print(obj$Weights) 80 | 81 | # check 82 | print(mean(predict(obj, test_pred) - test_obs)) 83 | ``` 84 | 85 | # 2 - Comb Ridge 86 | 87 | ```{r eval=TRUE} 88 | start <- proc.time()[3] 89 | obj <- ahead::comb_Ridge(data, custom_error=custom_error) 90 | print(proc.time()[3] - start) 91 | ``` 92 | 93 | ```{r eval=TRUE} 94 | print(class(obj)) 95 | 96 | print(obj$Accuracy_Test) 97 | 98 | # check 99 | print(mean(predict(obj, test_pred) - test_obs)) 100 | ``` 101 | 102 | ```{r fig.width=7.5, eval=FALSE} 103 | plot(obj) 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /vignettes/conformal-ml.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Conformalized Forecasting using Machine Leaning models" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Conformalized Forecasting using Machine Leaning models} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r fig.width=7.5} 11 | res <- ahead::mlf(USAccDeaths, h=10L, lags=15L, type_pi="surrogate", B=250L) 12 | plot(res) 13 | 14 | res <- ahead::mlf(USAccDeaths, fit_func = glmnet::cv.glmnet, h=15L, lags=15L, 15 | type_pi="kde", B=250L) 16 | plot(res) 17 | 18 | (res <- ahead::mlf(USAccDeaths, fit_func = e1071::svm, h=15L, lags=15L, 19 | type_pi="kde", B=250L)) 20 | plot(res) 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /vignettes/fitforecastbench.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Fit and forecast for benchmarking purposes" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Fit and forecast for benchmarking purposes} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | 11 | ```{r} 12 | library(ahead) 13 | library(forecast) 14 | ``` 15 | 16 | 17 | ```{r fig.width=7.5} 18 | obj1 <- ahead::fitforecast(AirPassengers) 19 | obj2 <- ahead::fitforecast(AirPassengers, 20 | conformalize = TRUE) 21 | obj3 <- ahead::fitforecast(USAccDeaths, method = "dynrmf") 22 | obj4 <- ahead::fitforecast(USAccDeaths, 23 | conformalize = TRUE, method = "dynrmf") 24 | obj6 <- ahead::fitforecast(USAccDeaths, 25 | conformalize = TRUE, method = "te") 26 | 27 | 28 | par(mfrow=c(1, 2)) 29 | plot(AirPassengers) 30 | plot(obj1) 31 | 32 | par(mfrow=c(1, 2)) 33 | plot(AirPassengers) 34 | plot(obj2) 35 | 36 | par(mfrow=c(1, 2)) 37 | obj2$plot() 38 | obj2$plot("simulations") 39 | 40 | par(mfrow=c(1, 2)) 41 | obj3$plot() 42 | obj4$plot() 43 | 44 | obj6$plot() 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /vignettes/generic-conformal.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Generic forecasting and conformal prediction" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Generic forecasting and conformal prediction} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | Obtain forecasts for any object of class `forecast`, and conformalize them. 11 | 12 | # 0 - Packages 13 | 14 | ```{r} 15 | library(ahead) 16 | library(forecast) 17 | ``` 18 | 19 | 20 | ```{r} 21 | y <- fdeaths #AirPassengers #Nile #mdeaths #fdeaths #USAccDeaths 22 | h <- 25L 23 | ``` 24 | 25 | # 1 - Generic forecaster 26 | 27 | Unified interface 28 | 29 | ```{r fig.width=7.5} 30 | plot(ahead::genericforecast(FUN=forecast::thetaf, y, h)) 31 | plot(ahead::genericforecast(FUN=forecast::meanf, y, h)) 32 | plot(ahead::genericforecast(FUN=forecast::rwf, y, h)) 33 | plot(ahead::genericforecast(FUN=forecast::ets, y, h)) 34 | plot(ahead::genericforecast(FUN=forecast::auto.arima, y, h)) 35 | plot(ahead::genericforecast(FUN=forecast::tbats, y, h)) 36 | plot(ahead::genericforecast(FUN=HoltWinters, y, h)) 37 | plot(ahead::genericforecast(FUN=forecast::Arima, y, h)) 38 | plot(ahead::genericforecast(FUN=ahead::dynrmf, y, h)) 39 | plot(ahead::genericforecast(FUN=ahead::dynrmf, y=y, h=h, fit_func=e1071::svm, predict_func=predict)) 40 | plot(ahead::genericforecast(FUN=ahead::dynrmf, y=y, h=h, fit_func=glmnet::cv.glmnet, predict_func=predict)) 41 | plot(ahead::genericforecast(FUN=forecast::tbats, y=y, h=h, use.box.cox = TRUE, use.trend=FALSE)) 42 | plot(ahead::genericforecast(FUN=forecast::rwf, y=y, h=h, lambda=1.1)) 43 | ``` 44 | 45 | # 2 - Conformal prediction 46 | 47 | ```{r fig.width=7.5} 48 | y <- USAccDeaths 49 | 50 | obj <- ahead::conformalize(FUN=forecast::thetaf, y, h); plot(obj) 51 | obj <- ahead::conformalize(FUN=forecast::meanf, y, h); plot(obj) 52 | obj <- ahead::conformalize(FUN=forecast::rwf, y, h); plot(obj) 53 | obj <- ahead::conformalize(FUN=forecast::ets, y, h); plot(obj) 54 | obj <- ahead::conformalize(FUN=forecast::auto.arima, y, h); plot(obj) 55 | obj <- ahead::conformalize(FUN=forecast::tbats, y, h); plot(obj) 56 | obj <- ahead::conformalize(FUN=HoltWinters, y, h); plot(obj) 57 | obj <- ahead::conformalize(FUN=forecast::Arima, y, h); plot(obj) 58 | ``` 59 | 60 | ```{r fig.width=7.5} 61 | y <- AirPassengers 62 | 63 | obj <- ahead::conformalize(FUN=forecast::thetaf, y, h); plot(obj) 64 | obj <- ahead::conformalize(FUN=forecast::rwf, y=y, h=h, drift=TRUE); plot(obj) 65 | obj <- ahead::conformalize(FUN=forecast::ets, y, h); plot(obj) 66 | obj <- ahead::conformalize(FUN=forecast::tbats, y, h); plot(obj) 67 | obj <- ahead::conformalize(FUN=HoltWinters, y=y, h=h, seasonal = "mult"); plot(obj) 68 | obj <- ahead::conformalize(FUN=ahead::dynrmf, y=y, h=h, 69 | fit_func=glmnet::cv.glmnet, predict_func=predict); plot(obj) 70 | ``` 71 | 72 | 73 | ```{r fig.width=7.5} 74 | y <- fdeaths 75 | 76 | obj <- ahead::conformalize(FUN=forecast::thetaf, y=y, h=h, method="block-bootstrap"); plot(obj) 77 | obj <- ahead::conformalize(FUN=forecast::rwf, y=y, h=h, drift=TRUE, method="bootstrap"); plot(obj) 78 | obj <- ahead::conformalize(FUN=forecast::ets, y, h, method="kde"); plot(obj) 79 | obj <- ahead::conformalize(FUN=forecast::tbats, y=y, h=h, method="surrogate"); plot(obj) 80 | obj <- ahead::conformalize(FUN=HoltWinters, y=y, h=h, seasonal = "mult", method="block-bootstrap"); plot(obj) 81 | obj <- ahead::conformalize(FUN=ahead::dynrmf, y=y, h=h, 82 | fit_func=glmnet::cv.glmnet, predict_func=predict, method="surrogate"); plot(obj) 83 | ``` 84 | -------------------------------------------------------------------------------- /vignettes/glmthetaf-attention-conformal.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Generalized Linear Model Theta Forecast with attention - conformal uncertainty" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Generalized Linear Model Theta Forecast with attention - conformal uncertainty} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | # USAccDeaths (method='adj') 11 | 12 | 13 | ```{r fig.width=7.5} 14 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention = TRUE, type_pi = "conformal-split"))) 15 | plot(obj) 16 | 17 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::glm, attention = TRUE, type_pi = "conformal-split"))) 18 | plot(obj) 19 | 20 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::rlm, attention = TRUE, type_pi = "conformal-split"))) 21 | plot(obj) 22 | 23 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::lqs, attention = TRUE, type_pi = "conformal-split"))) 24 | plot(obj) 25 | ``` 26 | 27 | ```{r fig.width=7.5} 28 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::lm, attention = TRUE, type_pi = "conformal-split"))) 29 | plot(obj) 30 | ``` 31 | 32 | ```{r fig.width=7.5} 33 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=gam::gam, attention = TRUE, type_pi = "conformal-split"))) 34 | plot(obj) 35 | ``` 36 | 37 | ```{r fig.width=7.5} 38 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=quantreg::rq, attention = TRUE, type_pi = "conformal-split"))) 39 | plot(obj) 40 | ``` 41 | 42 | # AirPassengers (method='adj') 43 | 44 | ```{r fig.width=5.5} 45 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention = TRUE, type_pi = "conformal-split"))) 46 | plot(obj) 47 | 48 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::glm, attention = TRUE, type_pi = "conformal-split"))) 49 | plot(obj) 50 | 51 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::rlm, attention = TRUE, type_pi = "conformal-split"))) 52 | plot(obj) 53 | ``` 54 | 55 | ```{r fig.width=5.5} 56 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::lm, attention = TRUE, type_pi = "conformal-split"))) 57 | plot(obj) 58 | ``` 59 | 60 | ```{r fig.width=5.5} 61 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::lqs, attention = TRUE, type_pi = "conformal-split"))) 62 | plot(obj) 63 | ``` 64 | 65 | ```{r fig.width=5.5} 66 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=gam::gam, attention = TRUE, type_pi = "conformal-split"))) 67 | plot(obj) 68 | ``` 69 | 70 | ```{r fig.width=5.5} 71 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=quantreg::rq, attention = TRUE, type_pi = "conformal-split"))) 72 | plot(obj) 73 | ``` 74 | -------------------------------------------------------------------------------- /vignettes/glmthetaf-attention.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Generalized Linear Model Theta Forecast with attention" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Generalized Linear Model Theta Forecast with attention} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | # USAccDeaths (method="adj") 11 | 12 | ```{r fig.width=7.5} 13 | library(forecast) 14 | library(ahead) 15 | 16 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention = TRUE))) 17 | plot(obj) 18 | 19 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::glm, attention = TRUE))) 20 | plot(obj) 21 | 22 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::rlm, attention = TRUE))) 23 | plot(obj) 24 | 25 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::lqs, attention = TRUE))) 26 | plot(obj) 27 | ``` 28 | 29 | ```{r fig.width=7.5} 30 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::lm, attention = TRUE))) 31 | plot(obj) 32 | ``` 33 | 34 | ```{r fig.width=7.5} 35 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=gam::gam, attention = TRUE))) 36 | plot(obj) 37 | ``` 38 | 39 | ```{r fig.width=7.5} 40 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=quantreg::rq, attention = TRUE))) 41 | plot(obj) 42 | ``` 43 | 44 | 45 | # AirPassengers (method="adj") 46 | 47 | ```{r fig.width=5.5} 48 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention = TRUE))) 49 | plot(obj) 50 | 51 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::glm, attention = TRUE))) 52 | plot(obj) 53 | 54 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::rlm, attention = TRUE))) 55 | plot(obj) 56 | ``` 57 | 58 | ```{r fig.width=5.5} 59 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::lm, attention = TRUE))) 60 | plot(obj) 61 | ``` 62 | 63 | ```{r fig.width=5.5} 64 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::lqs, attention = TRUE))) 65 | plot(obj) 66 | ``` 67 | 68 | ```{r fig.width=5.5} 69 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=gam::gam, attention = TRUE))) 70 | plot(obj) 71 | ``` 72 | 73 | ```{r fig.width=5.5} 74 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=quantreg::rq, attention = TRUE))) 75 | plot(obj) 76 | ``` 77 | 78 | 79 | # USAccDeaths (method='adj') 80 | 81 | 82 | ```{r fig.width=7.5} 83 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention = TRUE))) 84 | plot(obj) 85 | 86 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::glm, attention = TRUE))) 87 | plot(obj) 88 | 89 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::rlm, attention = TRUE))) 90 | plot(obj) 91 | 92 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::lqs, attention = TRUE))) 93 | plot(obj) 94 | ``` 95 | 96 | ```{r fig.width=7.5} 97 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::lm, attention = TRUE))) 98 | plot(obj) 99 | ``` 100 | 101 | ```{r fig.width=7.5} 102 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=gam::gam, attention = TRUE))) 103 | plot(obj) 104 | ``` 105 | 106 | ```{r fig.width=7.5} 107 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=quantreg::rq, attention = TRUE))) 108 | plot(obj) 109 | ``` 110 | 111 | # AirPassengers (method='adj') 112 | 113 | ```{r fig.width=5.5} 114 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention = TRUE))) 115 | plot(obj) 116 | 117 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::glm, attention = TRUE))) 118 | plot(obj) 119 | 120 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::rlm, attention = TRUE))) 121 | plot(obj) 122 | ``` 123 | 124 | ```{r fig.width=5.5} 125 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::lm, attention = TRUE))) 126 | plot(obj) 127 | ``` 128 | 129 | ```{r fig.width=5.5} 130 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::lqs, attention = TRUE))) 131 | plot(obj) 132 | ``` 133 | 134 | ```{r fig.width=5.5} 135 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=gam::gam, attention = TRUE))) 136 | plot(obj) 137 | ``` 138 | 139 | ```{r fig.width=5.5} 140 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=quantreg::rq, attention = TRUE))) 141 | plot(obj) 142 | ``` 143 | -------------------------------------------------------------------------------- /vignettes/glmthetaf-ridge-attention.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Ridge Theta Forecast with attention - conformal uncertainty" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Ridge Theta Forecast with attention - conformal uncertainty} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | # USAccDeaths 11 | 12 | 13 | ```{r fig.width=7.5} 14 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention = TRUE, type_pi = "conformal-split"))) 15 | plot(obj) 16 | ``` 17 | 18 | # AirPassengers 19 | 20 | ```{r fig.width=5.5} 21 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention = TRUE, type_pi = "conformal-split"))) 22 | ``` 23 | -------------------------------------------------------------------------------- /vignettes/glmthetaf.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Generalized Linear Model Theta Forecast" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Generalized Linear Model Theta Forecast} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | # USAccDeaths 11 | 12 | ```{r fig.width=7.5} 13 | library(forecast) 14 | library(ahead) 15 | 16 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::glm.nb, attention=FALSE))) 17 | 18 | plot(obj) 19 | 20 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::glm, attention=FALSE))) 21 | plot(obj) 22 | 23 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::rlm, attention=FALSE))) 24 | plot(obj) 25 | 26 | #(obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=rvfl::rvfl, attention=FALSE))) 27 | #plot(obj) 28 | 29 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=MASS::lqs, attention=FALSE))) 30 | plot(obj) 31 | ``` 32 | 33 | ```{r fig.width=7.5} 34 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=stats::lm, attention=FALSE))) 35 | plot(obj) 36 | ``` 37 | 38 | ```{r fig.width=7.5} 39 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=gam::gam, attention=FALSE))) 40 | plot(obj) 41 | ``` 42 | 43 | ```{r fig.width=7.5} 44 | (obj <- suppressWarnings(ahead::glmthetaf(USAccDeaths, h=25L, fit_func=quantreg::rq, attention=FALSE))) 45 | plot(obj) 46 | ``` 47 | 48 | # AirPassengers 49 | 50 | ```{r fig.width=5.5} 51 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::glm.nb, attention=FALSE))) 52 | plot(obj) 53 | 54 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::glm, attention=FALSE))) 55 | plot(obj) 56 | 57 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::rlm, attention=FALSE))) 58 | plot(obj) 59 | 60 | #(obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=rvfl::rvfl, attention=FALSE))) 61 | #plot(obj) 62 | ``` 63 | 64 | ```{r fig.width=5.5} 65 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=stats::lm, attention=FALSE))) 66 | plot(obj) 67 | ``` 68 | 69 | ```{r fig.width=5.5} 70 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=MASS::lqs, attention=FALSE))) 71 | plot(obj) 72 | ``` 73 | 74 | ```{r fig.width=5.5} 75 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=gam::gam, attention=FALSE))) 76 | plot(obj) 77 | ``` 78 | 79 | ```{r fig.width=5.5} 80 | (obj <- suppressWarnings(ahead::glmthetaf(AirPassengers, h=25L, fit_func=quantreg::rq, attention=FALSE))) 81 | plot(obj) 82 | ``` 83 | 84 | -------------------------------------------------------------------------------- /vignettes/mlarch.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Beyond GARCH" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Beyond GARCH} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | # Introduction 11 | 12 | Probabilistic stock forecasting often relies on parametric models like ARIMA for the mean and GARCH for volatility. The `mlarchf` function in the `ahead` package offers a flexible hybrid alternative to ARMA-GARCH by combining machine learning approaches with ARCH effects. 13 | 14 | The model decomposes the time series into two components: 15 | 16 | 1. Mean component: $y_t = \mu_t + \sigma_t \varepsilon_t$ 17 | 2. Volatility component: $\sigma_t^2 = f(\varepsilon_{t-1}^2, \varepsilon_{t-2}^2, ...)$ 18 | 19 | where: 20 | 21 | - $\mu_t$ is the conditional mean (modeled using **any forecasting method**) 22 | - $\sigma_t$ is the conditional volatility (modeled using **machine learning**) 23 | - $\varepsilon_t$ are standardized residuals 24 | 25 | The **key innovation** is using machine learning methods and conformal prediction to model the volatility component, allowing for more flexible and potentially more accurate volatility forecasts than traditional GARCH models. The function supports various machine learning methods through parameters `fit_func` and `predict_func` as in other `ahead` models, and through the `caret` package. 26 | 27 | The forecasting process involves: 28 | 29 | - Fitting a mean model (default: `auto.arima`) 30 | - Modeling the squared residuals using machine learning. For this to work, the residuals from the mean model need to be centered, so that 31 | 32 | $$ 33 | \mathbb{E}[\epsilon_t^2|F_{t-1}] 34 | $$ 35 | 36 | (basically a supervised regression of squared residuals on their lags) is a good approximation of the latent conditional volatility 37 | 38 | - Conformalizing the standardized residuals for prediction intervals 39 | 40 | This new approach combines the interpretability of traditional time series models with the flexibility of machine learning, while maintaining proper uncertainty quantification through conformal prediction. 41 | 42 | # Basic Usage 43 | 44 | Let's start with a simple example using the Google stock price data from the `fpp2` package: 45 | 46 | ```{r setup, include=FALSE} 47 | library(forecast) 48 | library(ahead) 49 | library(randomForest) 50 | library(e1071) 51 | library(glmnet) 52 | ``` 53 | 54 | ```{r basic_example, fig.width=7.2} 55 | y <- fpp2::goog200 56 | 57 | # Default model for volatility (Ridge regression for volatility) 58 | (obj_ridge <- ahead::mlarchf(y, h=20L, B=500L)) 59 | ``` 60 | 61 | # Different Machine Learning Methods 62 | 63 | The package supports various machine learning methods for volatility modeling. Here are some examples: 64 | 65 | ```{r ml_methods, fig.width=7.2} 66 | # Random Forest 67 | (obj_rf <- ahead::mlarchf(y, fit_func = randomForest::randomForest, 68 | predict_func = predict, h=20L, B=500L)) 69 | 70 | # Support Vector Machine 71 | (obj_svm <- ahead::mlarchf(y, fit_func = e1071::svm, 72 | predict_func = predict, h=20L, B=500L)) 73 | 74 | # Elastic Net 75 | (obj_glmnet <- ahead::mlarchf(y, fit_func = glmnet::cv.glmnet, 76 | predict_func = predict, h=20L, B=500L)) 77 | ``` 78 | 79 | Let's visualize the forecasts: 80 | 81 | ```{r plot_ridge_rf, fig.width=7.2} 82 | par(mfrow=c(1, 2)) 83 | plot(obj_ridge, main="Ridge Regression") 84 | plot(obj_rf, main="Random Forest") 85 | ``` 86 | 87 | ```{r plot_svm_glmnet, fig.width=7.2} 88 | par(mfrow=c(1, 2)) 89 | plot(obj_svm, main="Support Vector Machine") 90 | plot(obj_glmnet, main="Elastic Net") 91 | ``` 92 | 93 | # Using caret Models 94 | 95 | The package also supports models from the `caret` package, which provides access to hundreds of machine learning methods. Here's how to use them: 96 | 97 | ```{r caret_example, fig.width=7} 98 | y <- window(fpp2::goog200, start=100) 99 | 100 | # Random Forest via caret 101 | (obj_rf <- ahead::mlarchf(y, ml_method="ranger", h=20L)) 102 | 103 | # Gradient Boosting via caret 104 | (obj_glmboost <- ahead::mlarchf(y, ml_method="glmboost", h=20L)) 105 | ``` 106 | 107 | Visualizing the forecasts: 108 | 109 | ```{r plot_caret, fig.width=7.2} 110 | par(mfrow=c(1, 2)) 111 | plot(obj_rf, main="Random Forest (caret)") 112 | plot(obj_glmboost, main="Gradient Boosting (caret)") 113 | ``` 114 | 115 | Looking at the simulation paths: 116 | 117 | ```{r plot_sims, fig.width=7.2} 118 | par(mfrow=c(1, 2)) 119 | matplot(obj_rf$sims, type='l', main="RF Simulation Paths") 120 | matplot(obj_glmboost$sims, type='l', main="GBM Simulation Paths") 121 | ``` 122 | 123 | # Customizing Mean and Residual Models 124 | 125 | You can also customize both the mean forecasting model and the model for forecasting standardized residuals: 126 | 127 | ```{r custom_models, fig.width=7} 128 | # Using RW + Theta method for mean and residuals along with SVM for volatility 129 | (obj_svm <- ahead::mlarchf(y, fit_func = e1071::svm, 130 | predict_func = predict, h=20L, 131 | mean_model=forecast::rwf, 132 | model_residuals=forecast::thetaf)) 133 | 134 | # Using Theta + Theta method for mean and residuals along with GLMNET for volatility 135 | (obj_glmnet <- ahead::mlarchf(y, fit_func = glmnet::cv.glmnet, 136 | predict_func = predict, h=20L, 137 | mean_model=forecast::thetaf, 138 | model_residuals=forecast::thetaf)) 139 | ``` 140 | 141 | ```{r plot_custom, fig.width=7.2} 142 | plot(obj_svm, main="SVM with RW + Theta") 143 | plot(obj_glmnet, main="Elastic Net with Theta + Theta") 144 | ``` 145 | 146 | When using non-ARIMA models for the mean forecast, it's important to check if the residuals of the mean forecasting model are centered and stationary: 147 | 148 | ```{r diagnostics} 149 | # Diagnostic tests for residuals 150 | print(obj_svm$resids_t_test) 151 | print(obj_svm$resids_kpss_test) 152 | print(obj_glmnet$resids_t_test) 153 | print(obj_glmnet$resids_kpss_test) 154 | ``` 155 | --------------------------------------------------------------------------------