├── .Rbuildignore ├── .github └── workflows │ ├── python_ci.yml │ ├── revdep.yaml │ ├── rhub.yaml │ └── test.yml ├── .gitignore ├── .gitmodules ├── CRAN-RELEASE ├── CRAN-SUBMISSION ├── DESCRIPTION ├── NAMESPACE ├── NEWS ├── R ├── RcppExports.R ├── adam-ces.R ├── adam-es.R ├── adam-gum.R ├── adam-msarima.R ├── adam-sma.R ├── adam-ssarima.R ├── adam.R ├── adamGeneral.R ├── arimaCompact.R ├── autoadam.R ├── autoces.R ├── autogum.R ├── automsarima.R ├── autossarima.R ├── ces.R ├── cma.R ├── depricator.R ├── es.R ├── gum.R ├── isFunctions.R ├── iss.R ├── methods.R ├── msarima.R ├── msdecompose.R ├── oes.R ├── oesg.R ├── randomARIMA.R ├── simces.R ├── simes.R ├── simgum.R ├── simoes.R ├── simsma.R ├── simssarima.R ├── sm.R ├── sma.R ├── smooth-package.R ├── smoothCombine.R ├── sowhat.R ├── ssarima.R ├── ssfunctions.R ├── variance-covariance.R └── zzz.R ├── README.md ├── cran-comments.md ├── man-roxygen ├── ADAMDataFormulaRegLossSilentHHoldout.R ├── ADAMInitial.R ├── smoothRef.R ├── ssADAMRef.R ├── ssARIMARef.R ├── ssAdvancedParam.R ├── ssAuthor.R ├── ssBasicParam.R ├── ssCESRef.R ├── ssETSRef.R ├── ssGeneralRef.R ├── ssInitialParam.R ├── ssIntermittentRef.R ├── ssIntervals.R ├── ssIntervalsRef.R ├── ssKeywords.R ├── ssPersistenceParam.R ├── ssSimParam.R └── ssXregParam.R ├── man ├── accuracy.Rd ├── adam.Rd ├── ces.Rd ├── cma.Rd ├── es.Rd ├── figures │ └── smooth-web.png ├── forecast.smooth.Rd ├── gum.Rd ├── isFunctions.Rd ├── msarima.Rd ├── msdecompose.Rd ├── multicov.Rd ├── oes.Rd ├── oesg.Rd ├── orders.Rd ├── plot.smooth.Rd ├── pls.Rd ├── reapply.Rd ├── reexports.Rd ├── rmultistep.Rd ├── sim.ces.Rd ├── sim.es.Rd ├── sim.gum.Rd ├── sim.oes.Rd ├── sim.sma.Rd ├── sim.ssarima.Rd ├── sma.Rd ├── smooth.Rd ├── smoothCombine.Rd ├── sowhat.Rd └── ssarima.Rd ├── python ├── CMakeLists.txt ├── Makefile ├── README.md ├── pyproject.toml ├── setup.cfg └── smooth │ ├── __init__.py │ └── adam_general │ ├── __init__.py │ ├── adam_profile.py │ ├── core │ ├── __init__.py │ ├── adam.py │ ├── checker.py │ ├── creator.py │ ├── estimator.py │ ├── forecaster.py │ ├── sma.py │ └── utils │ │ ├── cost_functions.py │ │ ├── dump.py │ │ ├── ic.py │ │ ├── likelihood.py │ │ ├── polynomials.py │ │ └── utils.py │ ├── load_r_package.py │ ├── sma.py │ ├── test.py │ ├── test_3.ipynb │ ├── test_adam.ipynb │ ├── test_adam_r.ipynb │ ├── test_script.py │ ├── tests.ipynb │ └── tests_2.ipynb ├── smooth.Rproj ├── src ├── Makevars ├── Makevars.win ├── RcppExports.cpp ├── adamGeneral.cpp ├── adamGeneral.h ├── adamRefitter.cpp ├── adamSimulator.cpp ├── matrixPowerWrap.cpp ├── python_examples │ ├── adamGeneral copy.cpp │ ├── adamGeneral.cpp │ ├── adamGeneral.h │ └── my_linalg.cpp ├── registerDynamicSymbol.c ├── ssGeneral.cpp ├── ssGeneral.h ├── ssOccurrence.cpp └── ssSimulator.cpp ├── tests ├── testthat.R └── testthat │ ├── test_adam.R │ ├── test_ces.R │ ├── test_es.R │ ├── test_gum.R │ ├── test_oes.R │ ├── test_simulate.R │ └── test_ssarima.R └── vignettes ├── .install_extras ├── adam.Rmd ├── ces.Rmd ├── es.Rmd ├── gum.Rmd ├── library.bib ├── oes.Rmd ├── simulate.Rmd ├── sma.Rmd ├── smooth-Documentation.pdf ├── smooth.Rmd └── ssarima.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CRAN-RELEASE$ 2 | ^Meta$ 3 | ^doc$ 4 | ^.*\.Rproj$ 5 | ^\.Rproj\.user$ 6 | .github 7 | vignettes/rsconnect 8 | man-roxygen 9 | ^revdep$ 10 | cran-comments.md 11 | ^CRAN-SUBMISSION$ 12 | ^python 13 | ^src/python_examples 14 | ^src/libs 15 | dev_load.R 16 | -------------------------------------------------------------------------------- /.github/workflows/python_ci.yml: -------------------------------------------------------------------------------- 1 | name: Python CI 2 | 3 | on: 4 | push: 5 | branches: [Python] 6 | pull_request: 7 | branches: [Python] 8 | 9 | jobs: 10 | linting: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: chartboost/ruff-action@v1 15 | with: 16 | src: "./python" 17 | -------------------------------------------------------------------------------- /.github/workflows/revdep.yaml: -------------------------------------------------------------------------------- 1 | name: R-Revdep-check 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | R-CMD-check: 8 | runs-on: ${{ matrix.config.os }} 9 | 10 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 11 | 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | config: 16 | # - {os: macos-latest, r: 'release'} 17 | # - {os: windows-latest, r: 'release'} 18 | #- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 19 | - {os: ubuntu-latest, r: 'release'} 20 | #- {os: ubuntu-latest, r: 'oldrel-1'} 21 | 22 | env: 23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 24 | R_KEEP_PKG_SOURCE: yes 25 | 26 | steps: 27 | - uses: actions/checkout@v4 28 | 29 | - uses: r-lib/actions/setup-pandoc@v2 30 | 31 | - uses: r-lib/actions/setup-r@v2 32 | with: 33 | r-version: ${{ matrix.config.r }} 34 | http-user-agent: ${{ matrix.config.http-user-agent }} 35 | use-public-rspm: true 36 | 37 | - uses: r-lib/actions/setup-r-dependencies@v2 38 | with: 39 | # Don't check suggests to avoid Windows issues with doMC 40 | cache: false 41 | extra-packages: | 42 | any::rcmdcheck 43 | any::testthat 44 | any::knitr 45 | any::rmarkdown 46 | any::numDeriv 47 | any::doParallel 48 | any::foreach 49 | any::remotes 50 | needs: check 51 | 52 | - name: Install revdepcheck 53 | run: | 54 | Rscript -e 'remotes::install_github("r-lib/revdepcheck")' 55 | 56 | - name: Run revdepcheck 57 | run: | 58 | Rscript -e 'revdepcheck::revdep_check(num_workers = 4)' 59 | -------------------------------------------------------------------------------- /.github/workflows/rhub.yaml: -------------------------------------------------------------------------------- 1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at 2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml 3 | # You can update this file to a newer version using the rhub2 package: 4 | # 5 | # rhub::rhub_setup() 6 | # 7 | # It is unlikely that you need to modify this file manually. 8 | 9 | name: R-hub 10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}" 11 | 12 | on: 13 | workflow_dispatch: 14 | inputs: 15 | config: 16 | description: 'A comma separated list of R-hub platforms to use.' 17 | type: string 18 | default: 'linux,windows,macos' 19 | name: 20 | description: 'Run name. You can leave this empty now.' 21 | type: string 22 | id: 23 | description: 'Unique ID. You can leave this empty now.' 24 | type: string 25 | 26 | jobs: 27 | 28 | setup: 29 | runs-on: ubuntu-latest 30 | outputs: 31 | containers: ${{ steps.rhub-setup.outputs.containers }} 32 | platforms: ${{ steps.rhub-setup.outputs.platforms }} 33 | 34 | steps: 35 | # NO NEED TO CHECKOUT HERE 36 | - uses: r-hub/actions/setup@v1 37 | with: 38 | config: ${{ github.event.inputs.config }} 39 | id: rhub-setup 40 | 41 | linux-containers: 42 | needs: setup 43 | if: ${{ needs.setup.outputs.containers != '[]' }} 44 | runs-on: ubuntu-latest 45 | name: ${{ matrix.config.label }} 46 | strategy: 47 | fail-fast: false 48 | matrix: 49 | config: ${{ fromJson(needs.setup.outputs.containers) }} 50 | container: 51 | image: ${{ matrix.config.container }} 52 | 53 | steps: 54 | - uses: r-hub/actions/checkout@v1 55 | - uses: r-hub/actions/platform-info@v1 56 | with: 57 | token: ${{ secrets.RHUB_TOKEN }} 58 | job-config: ${{ matrix.config.job-config }} 59 | - uses: r-hub/actions/setup-deps@v1 60 | with: 61 | token: ${{ secrets.RHUB_TOKEN }} 62 | job-config: ${{ matrix.config.job-config }} 63 | - uses: r-hub/actions/run-check@v1 64 | with: 65 | token: ${{ secrets.RHUB_TOKEN }} 66 | job-config: ${{ matrix.config.job-config }} 67 | 68 | other-platforms: 69 | needs: setup 70 | if: ${{ needs.setup.outputs.platforms != '[]' }} 71 | runs-on: ${{ matrix.config.os }} 72 | name: ${{ matrix.config.label }} 73 | strategy: 74 | fail-fast: false 75 | matrix: 76 | config: ${{ fromJson(needs.setup.outputs.platforms) }} 77 | 78 | steps: 79 | - uses: r-hub/actions/checkout@v1 80 | - uses: r-hub/actions/setup-r@v1 81 | with: 82 | job-config: ${{ matrix.config.job-config }} 83 | token: ${{ secrets.RHUB_TOKEN }} 84 | - uses: r-hub/actions/platform-info@v1 85 | with: 86 | token: ${{ secrets.RHUB_TOKEN }} 87 | job-config: ${{ matrix.config.job-config }} 88 | - uses: r-hub/actions/setup-deps@v1 89 | with: 90 | job-config: ${{ matrix.config.job-config }} 91 | token: ${{ secrets.RHUB_TOKEN }} 92 | - uses: r-hub/actions/run-check@v1 93 | with: 94 | job-config: ${{ matrix.config.job-config }} 95 | token: ${{ secrets.RHUB_TOKEN }} 96 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: R-CMD-check 2 | 3 | on: 4 | pull_request: 5 | workflow_dispatch: 6 | schedule: 7 | - cron: '0 0 * * 1' 8 | 9 | jobs: 10 | R-CMD-check: 11 | runs-on: ${{ matrix.config.os }} 12 | 13 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 14 | 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | config: 19 | - {os: macos-latest, r: 'release'} 20 | - {os: windows-latest, r: 'release'} 21 | #- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 22 | - {os: ubuntu-latest, r: 'release'} 23 | #- {os: ubuntu-latest, r: 'oldrel-1'} 24 | 25 | env: 26 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 27 | R_KEEP_PKG_SOURCE: yes 28 | 29 | steps: 30 | - uses: actions/checkout@v4 31 | 32 | - uses: r-lib/actions/setup-pandoc@v2 33 | 34 | - uses: r-lib/actions/setup-r@v2 35 | with: 36 | r-version: ${{ matrix.config.r }} 37 | http-user-agent: ${{ matrix.config.http-user-agent }} 38 | use-public-rspm: true 39 | 40 | - uses: r-lib/actions/setup-r-dependencies@v2 41 | with: 42 | # Don't check suggests to avoid Windows issues with doMC 43 | dependencies: '"hard"' 44 | cache: false 45 | extra-packages: | 46 | any::rcmdcheck 47 | any::testthat 48 | any::knitr 49 | any::rmarkdown 50 | any::numDeriv 51 | any::doParallel 52 | any::foreach 53 | needs: check 54 | 55 | - uses: r-lib/actions/check-r-package@v2 56 | with: 57 | upload-snapshots: true 58 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Meta 2 | doc 3 | # History files 4 | .Rhistory 5 | .Rapp.history 6 | # Session Data files 7 | .RData 8 | # RStudio files 9 | .Rproj.user/ 10 | # bak files 11 | *.bak 12 | # produced vignettes 13 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 14 | .httr-oauth 15 | # stuff precompiled by R 16 | src/*.o 17 | src/*.so 18 | src/*.dll 19 | .directory 20 | .Rproj.user 21 | inst/doc/*.html 22 | inst/doc/*.R 23 | inst/doc/*.Rmd 24 | vignettes/rsconnect 25 | vignettes/Figs 26 | # Rprofile 27 | .Rprofile 28 | 29 | ######################## 30 | ### python gitignore ### 31 | ######################## 32 | 33 | # Byte-compiled / optimized / DLL files 34 | __pycache__/ 35 | *.py[cod] 36 | *$py.class 37 | 38 | # C extensions 39 | *.so 40 | 41 | # Distribution / packaging 42 | .Python 43 | build/ 44 | develop-eggs/ 45 | dist/ 46 | downloads/ 47 | eggs/ 48 | .eggs/ 49 | lib/ 50 | lib64/ 51 | parts/ 52 | sdist/ 53 | var/ 54 | wheels/ 55 | pip-wheel-metadata/ 56 | share/python-wheels/ 57 | *.egg-info/ 58 | .installed.cfg 59 | *.egg 60 | MANIFEST 61 | 62 | # PyInstaller 63 | # Usually these files are written by a python script from a template 64 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 65 | *.manifest 66 | *.spec 67 | 68 | # Installer logs 69 | pip-log.txt 70 | pip-delete-this-directory.txt 71 | 72 | # Unit test / coverage reports 73 | htmlcov/ 74 | .tox/ 75 | .nox/ 76 | .coverage 77 | .coverage.* 78 | .cache 79 | nosetests.xml 80 | coverage.xml 81 | *.cover 82 | *.py,cover 83 | .hypothesis/ 84 | .pytest_cache/ 85 | 86 | # Translations 87 | *.mo 88 | *.pot 89 | 90 | # Django stuff: 91 | *.log 92 | local_settings.py 93 | db.sqlite3 94 | db.sqlite3-journal 95 | 96 | # Flask stuff: 97 | instance/ 98 | .webassets-cache 99 | 100 | # Scrapy stuff: 101 | .scrapy 102 | 103 | # Sphinx documentation 104 | docs/_build/ 105 | 106 | # PyBuilder 107 | target/ 108 | 109 | # Jupyter Notebook 110 | .ipynb_checkpoints 111 | 112 | # IPython 113 | profile_default/ 114 | ipython_config.py 115 | 116 | # pyenv 117 | .python-version 118 | 119 | # pipenv 120 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 121 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 122 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 123 | # install all needed dependencies. 124 | #Pipfile.lock 125 | 126 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 127 | __pypackages__/ 128 | 129 | # Celery stuff 130 | celerybeat-schedule 131 | celerybeat.pid 132 | 133 | # SageMath parsed files 134 | *.sage.py 135 | 136 | # Environments 137 | .env 138 | .venv 139 | env/ 140 | venv/ 141 | ENV/ 142 | env.bak/ 143 | venv.bak/ 144 | 145 | # Spyder project settings 146 | .spyderproject 147 | .spyproject 148 | 149 | # Rope project settings 150 | .ropeproject 151 | 152 | # mkdocs documentation 153 | /site 154 | 155 | # mypy 156 | .mypy_cache/ 157 | .dmypy.json 158 | dmypy.json 159 | 160 | # Pyre type checker 161 | .pyre/ 162 | 163 | #IDEs 164 | .vscode 165 | 166 | # memory system file 167 | .DS_Store 168 | 169 | #vim swap files 170 | *.swp 171 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/libs/carma"] 2 | path = src/libs/carma 3 | url = https://github.com/RUrlus/carma.git 4 | -------------------------------------------------------------------------------- /CRAN-RELEASE: -------------------------------------------------------------------------------- 1 | This package was submitted to CRAN on 2021-12-01. 2 | Once it is accepted, delete this file and tag the release (commit 944d190). 3 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 4.2.0 2 | Date: 2025-04-02 15:23:55 UTC 3 | SHA: 970bef2a416d48314c7105d8dd4214385f5d2231 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: smooth 2 | Type: Package 3 | Title: Forecasting Using State Space Models 4 | Version: 4.3.0.41005 5 | Date: 2025-06-03 6 | Authors@R: person("Ivan", "Svetunkov", email = "ivan@svetunkov.com", role = c("aut", "cre"), 7 | comment="Senior Lecturer at Centre for Marketing Analytics and Forecasting, Lancaster University, UK") 8 | URL: https://github.com/config-i1/smooth 9 | BugReports: https://github.com/config-i1/smooth/issues 10 | Language: en-GB 11 | Description: Functions implementing Single Source of Error state space models for purposes of time series analysis and forecasting. 12 | The package includes ADAM (Svetunkov, 2023, ), 13 | Exponential Smoothing (Hyndman et al., 2008, ), 14 | SARIMA (Svetunkov & Boylan, 2019 ), 15 | Complex Exponential Smoothing (Svetunkov & Kourentzes, 2018, ), 16 | Simple Moving Average (Svetunkov & Petropoulos, 2018 ) 17 | and several simulation functions. It also allows dealing with intermittent demand based on the 18 | iETS framework (Svetunkov & Boylan, 2019, ). 19 | License: LGPL-2.1 20 | Depends: 21 | R (>= 3.0.2), 22 | greybox (>= 2.0.2) 23 | Imports: 24 | Rcpp (>= 0.12.3), 25 | stats, 26 | generics (>= 0.1.2), 27 | graphics, 28 | grDevices, 29 | pracma, 30 | statmod, 31 | MASS, 32 | nloptr, 33 | utils, 34 | xtable, 35 | zoo 36 | LinkingTo: Rcpp, RcppArmadillo (>= 0.8.100.0.0) 37 | Suggests: 38 | legion, 39 | numDeriv, 40 | testthat, 41 | knitr, 42 | rmarkdown, 43 | doMC, 44 | doParallel, 45 | foreach 46 | VignetteBuilder: knitr 47 | RoxygenNote: 7.3.2 48 | Encoding: UTF-8 49 | Roxygen: list(old_usage = TRUE) 50 | ByteCompile: true 51 | -------------------------------------------------------------------------------- /R/arimaCompact.R: -------------------------------------------------------------------------------- 1 | # arimaCompact <- function(y, lags=c(1,frequency(y)), ic=c("AICc","AIC","BIC","BICc"), ...){ 2 | # 3 | # # Start measuring the time of calculations 4 | # startTime <- Sys.time(); 5 | # 6 | # # If there are no lags for the basic components, correct this. 7 | # if(sum(lags==1)==0){ 8 | # lags <- c(1,lags); 9 | # } 10 | # 11 | # orderLength <- length(lags); 12 | # ic <- match.arg(ic); 13 | # IC <- switch(ic, 14 | # "AIC"=AIC, 15 | # "AICc"=AICc, 16 | # "BIC"=BIC, 17 | # "BICc"=BICc); 18 | # 19 | # # We consider the following list of models: 20 | # # ARIMA(0,1,1), (1,1,2), (0,2,2), 21 | # # ARIMA(0,0,0)+c, ARIMA(0,1,1)+c, 22 | # # seasonal orders (0,1,1), (1,1,2), (0,2,2) 23 | # # And all combinations between seasonal and non-seasonal parts 24 | # # 25 | # # Encode all non-seasonal parts 26 | # nNonSeasonal <- 5 27 | # arimaNonSeasonal <- matrix(c(0,0,0,1, 0,1,1,0, 0,1,1,1, 1,1,2,0, 0,2,2,0), nNonSeasonal,4, 28 | # dimnames=list(NULL, c("ar","i","ma","const")), byrow=TRUE) 29 | # # Encode all seasonal parts () 30 | # nSeasonal <- 4 31 | # arimaSeasonal <- matrix(c(0,0,0, 0,1,1, 1,1,2, 0,2,2), nSeasonal,3, 32 | # dimnames=list(NULL, c("sar","si","sma")), byrow=TRUE) 33 | # 34 | # # Check all the models in the pool 35 | # testModels <- vector("list", nSeasonal*nNonSeasonal); 36 | # stop <- FALSE; 37 | # m <- 1; 38 | # for(i in 1:nSeasonal){ 39 | # for(j in 1:nNonSeasonal){ 40 | # testModels[[m]] <- msarima(y, orders=list(ar=c(arimaNonSeasonal[j,1],arimaSeasonal[i,1]), 41 | # i=c(arimaNonSeasonal[j,2],arimaSeasonal[i,2]), 42 | # ma=c(arimaNonSeasonal[j,3],arimaSeasonal[i,3])), 43 | # constant=arimaNonSeasonal[j,4]==1, lags=lags, ...); 44 | # # If SARIMA(0,1,1)(0,1,1) is worse than ARIMA(0,1,1), don't check other seasonal models 45 | # # If SARIMA(0,1,1)(1,1,2) is worse than SARIMA(0,1,1)(0,1,1), stop 46 | # # etc 47 | # if(j==1 && i>1){ 48 | # if(IC(testModels[[m-nNonSeasonal]])obsInSample){ 30 | pFitted <- matrix(fitted(occurrenceModel)[1:obsInSample],obsInSample,1); 31 | } 32 | else if(length(fitted(occurrenceModel))=h){ 42 | pForecast <- matrix(occurrenceModel$forecast[1:h],h,1); 43 | } 44 | else{ 45 | pForecast <- matrix(c(occurrenceModel$forecast, 46 | rep(occurrenceModel$forecast[1],h-length(occurrenceModel$forecast))),h,1); 47 | } 48 | 49 | } 50 | } 51 | else{ 52 | obsNonzero <- obsInSample; 53 | obsZero <- 0; 54 | } 55 | 56 | if(occurrence=="n"){ 57 | ot <- rep(1,obsInSample); 58 | obsNonzero <- obsInSample; 59 | yot <- yInSample; 60 | pFitted <- matrix(1,obsInSample,1); 61 | pForecast <- matrix(1,h,1); 62 | nParamOccurrence <- 0; 63 | } 64 | ot <- ts(ot,start=dataStart,frequency=dataFreq); 65 | 66 | assign("ot",ot,ParentEnvironment); 67 | assign("obsNonzero",obsNonzero,ParentEnvironment); 68 | assign("obsZero",obsZero,ParentEnvironment); 69 | assign("yot",yot,ParentEnvironment); 70 | assign("pFitted",pFitted,ParentEnvironment); 71 | assign("pForecast",pForecast,ParentEnvironment); 72 | assign("nParamOccurrence",nParamOccurrence,ParentEnvironment); 73 | } 74 | 75 | intermittentMaker <- function(occurrence="n",...){ 76 | # Function returns all the necessary stuff from occurrence models 77 | ellipsis <- list(...); 78 | ParentEnvironment <- ellipsis[['ParentEnvironment']]; 79 | 80 | ##### If occurrence is not absent or provided, then work normally ##### 81 | if(all(occurrence!=c("n","p"))){ 82 | if(!occurrenceModelProvided){ 83 | occurrenceModel <- oes(ot, model=occurrenceModel, occurrence=occurrence, h=h); 84 | } 85 | else{ 86 | occurrenceModel <- oes(ot, model=occurrenceModel, h=h); 87 | } 88 | nParamOccurrence <- nparam(occurrenceModel); 89 | pFitted[,] <- fitted(occurrenceModel); 90 | pForecast <- occurrenceModel$forecast; 91 | occurrence <- occurrenceModel$occurrence; 92 | } 93 | else{ 94 | occurrenceModel <- NULL; 95 | nParamOccurrence <- 0; 96 | } 97 | 98 | assign("occurrence",occurrence,ParentEnvironment); 99 | assign("pFitted",pFitted,ParentEnvironment); 100 | assign("pForecast",pForecast,ParentEnvironment); 101 | assign("nParamOccurrence",nParamOccurrence,ParentEnvironment); 102 | assign("occurrenceModel",occurrenceModel,ParentEnvironment); 103 | } 104 | -------------------------------------------------------------------------------- /R/simsma.R: -------------------------------------------------------------------------------- 1 | #' Simulate Simple Moving Average 2 | #' 3 | #' Function generates data using SMA in a Single Source of Error state space 4 | #' model as a data generating process. 5 | #' 6 | #' For the information about the function, see the vignette: 7 | #' \code{vignette("simulate","smooth")} 8 | #' 9 | #' @template ssSimParam 10 | #' @template ssAuthor 11 | #' @template ssKeywords 12 | #' 13 | #' @template ssGeneralRef 14 | #' 15 | #' @param order Order of the modelled series. If omitted, then a random order from 1 to 100 is selected. 16 | #' @param initial Vector of initial states for the model. If \code{NULL}, 17 | #' values are generated. 18 | #' @param ... Additional parameters passed to the chosen randomizer. All the 19 | #' parameters should be passed in the order they are used in chosen randomizer. 20 | #' For example, passing just \code{sd=0.5} to \code{rnorm} function will lead 21 | #' to the call \code{rnorm(obs, mean=0.5, sd=1)}. 22 | #' 23 | #' @return List of the following values is returned: 24 | #' \itemize{ 25 | #' \item \code{model} - Name of SMA model. 26 | #' \item \code{data} - Time series vector (or matrix if \code{nsim>1}) of the generated 27 | #' series. 28 | #' \item \code{states} - Matrix (or array if \code{nsim>1}) of states. States are in 29 | #' columns, time is in rows. 30 | #' \item \code{initial} - Vector (or matrix) of initial values. 31 | #' \item \code{probability} - vector of probabilities used in the simulation. 32 | #' \item \code{intermittent} - type of the intermittent model used. 33 | #' \item \code{residuals} - Error terms used in the simulation. Either vector or matrix, 34 | #' depending on \code{nsim}. 35 | #' \item \code{occurrence} - Values of occurrence variable. Once again, can be either 36 | #' a vector or a matrix... 37 | #' \item \code{logLik} - Log-likelihood of the constructed model. 38 | #' } 39 | #' 40 | #' @seealso \code{\link[smooth]{es}, \link[stats]{ts}, \link[stats]{Distributions}} 41 | #' 42 | #' @examples 43 | #' 44 | #' # Create 40 observations of quarterly data using AAA model with errors from normal distribution 45 | #' sma10 <- sim.sma(order=10,frequency=4,obs=40,randomizer="rnorm",mean=0,sd=100) 46 | #' 47 | #' @export sim.sma 48 | sim.sma <- function(order=NULL, obs=10, nsim=1, 49 | frequency=1, 50 | initial=NULL, 51 | randomizer=c("rnorm","rt","rlaplace","rs"), 52 | probability=1, ...){ 53 | # Function generates data using SMA model as a data generating process. 54 | # Copyright (C) 2017 Ivan Svetunkov 55 | 56 | randomizer <- randomizer[1]; 57 | 58 | if(is.null(order)){ 59 | order <- ceiling(runif(1,0,100)); 60 | } 61 | 62 | # In the case of wrong nsim, make it natural number. The same is for obs and frequency. 63 | nsim <- abs(round(nsim,0)); 64 | obs <- abs(round(obs,0)); 65 | frequency <- abs(round(frequency,0)); 66 | 67 | # Check the inital vector length 68 | if(!is.null(initial)){ 69 | if(order!=length(initial)){ 70 | warning(paste0("The length of initial state vector does not correspond to the chosen model!\n", 71 | "Falling back to random number generator."),call.=FALSE); 72 | initial <- NULL; 73 | } 74 | } 75 | 76 | ARIMAModel <- sim.ssarima(orders=list(ar=order,i=0,ma=0), lags=1, 77 | obs=obs, nsim=nsim, 78 | frequency=frequency, AR=rep(1/order,order), MA=NULL, constant=FALSE, 79 | initial=initial, bounds="none", 80 | randomizer=randomizer, 81 | probability=probability, ...) 82 | 83 | ARIMAModel$model <- paste0("SMA(",order,")"); 84 | if(any(probability!=1)){ 85 | ARIMAModel$model <- paste0("i",ARIMAModel$model); 86 | } 87 | ARIMAModel$AR <- NULL; 88 | ARIMAModel$MA <- NULL; 89 | ARIMAModel$constant <- NULL; 90 | return(ARIMAModel) 91 | } 92 | -------------------------------------------------------------------------------- /R/smooth-package.R: -------------------------------------------------------------------------------- 1 | #' Smooth package 2 | #' 3 | #' Package contains functions implementing Single Source of Error state space models for 4 | #' purposes of time series analysis and forecasting. 5 | #' 6 | #' \tabular{ll}{ Package: \tab smooth\cr Type: \tab Package\cr Date: \tab 7 | #' 2016-01-27 - Inf\cr License: \tab GPL-2 \cr } The following functions are 8 | #' included in the package: 9 | #' \itemize{ 10 | #' \item \link[smooth]{es} - Exponential Smoothing in Single Source of Errors State Space form. 11 | #' \item \link[smooth]{ces} - Complex Exponential Smoothing. 12 | #' \item \link[smooth]{gum} - Generalised Exponential Smoothing. 13 | #' \item \link[smooth]{ssarima} - SARIMA in state space framework. 14 | #' % \item \link[smooth]{nus} - Non-Uniform Smoothing. 15 | #' \item \link[smooth]{auto.ces} - Automatic selection between seasonal and non-seasonal CES. 16 | #' \item \link[smooth]{auto.ssarima} - Automatic selection of ARIMA orders. 17 | #' \item \link[smooth]{sma} - Simple Moving Average in state space form. 18 | #' \item \link[smooth]{smoothCombine} - the function that combines forecasts from es(), 19 | #' ces(), gum(), ssarima() and sma() functions. 20 | #' \item \link[smooth]{cma} - Centered Moving Average. This is for smoothing time series, 21 | #' not for forecasting. 22 | #' \item \link[smooth]{sim.es} - simulate time series using ETS as a model. 23 | #' \item \link[smooth]{sim.ces} - simulate time series using CES as a model. 24 | #' \item \link[smooth]{sim.ssarima} - simulate time series using SARIMA as a model. 25 | #' \item \link[smooth]{sim.gum} - simulate time series using GUM as a model. 26 | #' \item \link[smooth]{sim.sma} - simulate time series using SMA. 27 | #' \item \link[smooth]{sim.oes} - simulate time series based on occurrence part of ETS model. 28 | #' \item \link[smooth]{oes} - occurrence part of the intermittent state space model. 29 | #' } 30 | #' There are also several methods implemented in the package for the classes 31 | #' "smooth" and "smooth.sim": 32 | #' \itemize{ 33 | #' \item \link[smooth]{orders} - extracts orders of the fitted model. 34 | #' \item lags - extracts lags of the fitted model. 35 | #' \item modelType - extracts type of the fitted model. 36 | #' \item forecast - produces forecast using provided model. 37 | #' \item \link[smooth]{multicov} - returns covariance matrix of multiple steps ahead forecast errors. 38 | #' \item \link[smooth]{pls} - returns Prediction Likelihood Score. 39 | #' \item \link[greybox]{nparam} - returns number of the estimated parameters. 40 | #' \item fitted - extracts fitted values from provided model. 41 | #' \item getResponse - returns actual values from the provided model. 42 | #' \item residuals - extracts residuals of provided model. 43 | #' \item plot - plots either states of the model or produced forecast (depending on what object 44 | #' is passed). 45 | #' \item simulate - uses sim functions (\link[smooth]{sim.es}, \link[smooth]{sim.ces}, 46 | #' \link[smooth]{sim.ssarima}, \link[smooth]{sim.gum}, \link[smooth]{sim.sma} and 47 | #' \link[smooth]{sim.oes}) in order to simulate data using the provided object. 48 | #' \item summary - provides summary of the object. 49 | #' \item AICc, BICc - return, guess what... 50 | #' } 51 | #' 52 | #' @name smooth 53 | #' @aliases smooth-package 54 | #' @template ssAuthor 55 | #' 56 | #' @seealso \code{\link[greybox]{forecast}, \link[smooth]{es}, 57 | #' \link[smooth]{ssarima}, \link[smooth]{ces}, \link[smooth]{gum}} 58 | #' 59 | #' @template ssGeneralRef 60 | #' @template ssIntermittentRef 61 | #' @template ssCESRef 62 | #' @template smoothRef 63 | #' @template ssETSRef 64 | #' @template ssIntervalsRef 65 | #' @template ssKeywords 66 | #' 67 | #' @examples 68 | #' 69 | #' \donttest{y <- ts(rnorm(100,10,3), frequency=12) 70 | #' 71 | #' adam(y, h=20, holdout=TRUE) 72 | #' es(y, h=20, holdout=TRUE) 73 | #' gum(y, h=20, holdout=TRUE) 74 | #' auto.ces(y, h=20, holdout=TRUE) 75 | #' auto.ssarima(y, h=20, holdout=TRUE)} 76 | #' 77 | #' @import zoo Rcpp 78 | #' @importFrom nloptr nloptr 79 | #' @importFrom graphics abline layout legend lines par points polygon 80 | #' @importFrom stats AIC BIC cov decompose median coef optimize nlminb cor var simulate lm as.formula residuals 81 | #' @importFrom stats dbeta qnorm qt qlnorm quantile rbinom rlnorm rnorm rt runif plnorm pnorm 82 | #' @importFrom stats deltat end frequency is.ts start time ts 83 | #' @importFrom utils packageVersion 84 | #' @importFrom greybox xregExpander stepwise qs qlaplace ps plaplace ds dlaplace graphmaker measures hm 85 | #' @useDynLib smooth 86 | NULL 87 | -------------------------------------------------------------------------------- /R/sowhat.R: -------------------------------------------------------------------------------- 1 | #' Function returns the ultimate answer to any question 2 | #' 3 | #' You need a description? So what? 4 | #' 5 | #' You need details? So what? 6 | #' 7 | #' @param ... Any number of variables or string with a question. 8 | #' @return It doesn't return any value, only messages. So what? 9 | #' @template ssAuthor 10 | #' @seealso Nowwhat (to be implemented), 11 | #' @references \itemize{ 12 | #' \item\href{https://en.wiktionary.org/wiki/so_what}{Sowhat?} 13 | #' \item\href{https://www.youtube.com/watch?v=FJfFZqTlWrQ}{Sowhat?} 14 | #' \item\href{https://en.wikipedia.org/wiki/Douglas_Adams}{42} 15 | #' } 16 | #' @keywords sowhat 42 17 | #' @examples 18 | #' 19 | #' x <- rnorm(10000,0,1); 20 | #' sowhat(x); 21 | #' 22 | #' sowhat("What's the meaning of life?") 23 | #' 24 | #' sowhat("I don't have a girlfriend.") 25 | #' 26 | #' @export sowhat 27 | sowhat <- function(...){ 28 | # Function returns ultimate answer to any question 29 | if(any(grepl("\\?",unlist(list(...))))){ 30 | message("42"); 31 | } 32 | message("So what?"); 33 | } 34 | 35 | # Function is needed to ask additional question before the release 36 | release_questions <- function(){ 37 | c("i1: Did you check package with --use-valgrind if C++ code changed?"); 38 | } 39 | -------------------------------------------------------------------------------- /R/variance-covariance.R: -------------------------------------------------------------------------------- 1 | covarAnal <- function(lagsModel, h, measurement, transition, persistence, s2){ 2 | # Function returns analytical conditional h-steps ahead covariance matrix 3 | # This is used in covar() method and in the construction of parametric prediction intervals 4 | covarMat <- diag(h); 5 | if(h > min(lagsModel)){ 6 | lagsUnique <- unique(lagsModel); 7 | steps <- sort(lagsUnique[lagsUnique<=h]); 8 | stepsNumber <- length(steps); 9 | nComponents <- nrow(transition); 10 | arrayTransition <- array(0,c(nComponents,nComponents,stepsNumber)); 11 | arrayMeasurement <- array(0,c(1,nComponents,stepsNumber)); 12 | for(i in 1:stepsNumber){ 13 | arrayTransition[,lagsModel==steps[i],i] <- transition[,lagsModel==steps[i]]; 14 | arrayMeasurement[,lagsModel==steps[i],i] <- measurement[,lagsModel==steps[i]]; 15 | } 16 | cValues <- rep(0,h); 17 | 18 | # Prepare transition array 19 | transitionPowered <- array(0,c(nComponents,nComponents,h,stepsNumber)); 20 | transitionPowered[,,1:min(steps),] <- diag(nComponents); 21 | 22 | # Generate values for the transition matrix 23 | for(i in (min(steps)+1):h){ 24 | for(k in 1:sum(steps1)){ 30 | transitionNew <- arrayTransition[,,j]; 31 | } 32 | else{ 33 | transitionNew <- diag(nComponents); 34 | } 35 | 36 | # If this is a zero matrix, do simple multiplication 37 | if(all(transitionPowered[,,i,k]==0)){ 38 | transitionPowered[,,i,k] <- (transitionNew %*% 39 | transitionPowered[,,i-steps[j],k]); 40 | } 41 | else{ 42 | # Check that the multiplication is not an identity matrix 43 | if(!all((transitionNew %*% transitionPowered[,,i-steps[j],k])==diag(nComponents))){ 44 | transitionPowered[,,i,k] <- transitionPowered[,,i,k] + (transitionNew %*% 45 | transitionPowered[,,i-steps[j],k]); 46 | } 47 | } 48 | } 49 | } 50 | # Copy the structure from the lower lags 51 | else{ 52 | transitionPowered[,,i,k] <- transitionPowered[,,i-steps[k]+1,1]; 53 | } 54 | # Generate values of cj 55 | cValues[i] <- cValues[i] + arrayMeasurement[,,k] %*% transitionPowered[,,i,k] %*% persistence; 56 | } 57 | } 58 | 59 | # Fill in diagonals 60 | for(i in 2:h){ 61 | covarMat[i,i] <- covarMat[i-1,i-1] + cValues[i]^2; 62 | } 63 | # Fill in off-diagonals 64 | for(i in 1:h){ 65 | for(j in 1:h){ 66 | if(i==j){ 67 | next; 68 | } 69 | else if(i==1){ 70 | covarMat[i,j] = cValues[j]; 71 | } 72 | else if(i>j){ 73 | covarMat[i,j] <- covarMat[j,i]; 74 | } 75 | else{ 76 | covarMat[i,j] = covarMat[i-1,j-1] + covarMat[1,j] * covarMat[1,i]; 77 | } 78 | } 79 | } 80 | } 81 | # Multiply the matrix by the one-step-ahead variance 82 | covarMat <- covarMat * s2; 83 | 84 | return(covarMat); 85 | } 86 | 87 | adamVarAnal <- function(lagsModel, h, measurement, transition, persistence, s2){ 88 | #### The function returns variances for the multiplicative error ETS models 89 | # Prepare the necessary parameters 90 | lagsUnique <- unique(lagsModel); 91 | steps <- sort(lagsUnique[lagsUnique<=h]); 92 | stepsNumber <- length(steps); 93 | nComponents <- nrow(transition); 94 | k <- length(persistence); 95 | 96 | # Prepare the persistence array and measurement matrix 97 | arrayPersistenceQ <- array(0,c(nComponents,nComponents,stepsNumber)); 98 | matrixMeasurement <- matrix(measurement,1,nComponents); 99 | 100 | # Form partial matrices for different steps 101 | for(i in 1:stepsNumber){ 102 | arrayPersistenceQ[,lagsModel==steps[i],i] <- diag(as.vector(persistence),k,k)[,lagsModel==steps[i]]; 103 | } 104 | 105 | ## The matrices that will be used in the loop 106 | matrixPersistenceQ <- matrix(0,nComponents,nComponents); 107 | # The interrim value (Q), which accumulates the values before taking logs 108 | IQ <- vector("numeric",1); 109 | Ik <- diag(k); 110 | 111 | # The vector of variances 112 | varMat <- rep(0, h); 113 | 114 | if(h>1){ 115 | # Start the loop for varMat 116 | for(i in 2:h){ 117 | IQ[] <- 0; 118 | # Form the correct interrim Q that will be used for variances 119 | for(k in 1:sum(steps install.packages("smooth") 72 | 73 | A recent, development version, is available via github and can be installed using "remotes" in R. First, make sure that you have remotes: 74 | > if (!require("remotes")){install.packages("remotes")} 75 | 76 | and after that run: 77 | > remotes::install_github("config-i1/smooth") 78 | 79 | ## Notes 80 | 81 | The package depends on Rcpp and RcppArmadillo, which will be installed automatically. 82 | 83 | However Mac OS users may need to install gfortran libraries in order to use Rcpp. Follow the link for the instructions: http://www.thecoatlessprofessor.com/programming/rcpp-rcpparmadillo-and-os-x-mavericks-lgfortran-and-lquadmath-error/ 84 | 85 | Sometimes after upgrade of smooth from previous versions some functions stop working. This is because C++ functions are occasionally stored in deeper unknown corners of R's mind. Restarting R usually solves the problem. If it doesn't, completely remove smooth (uninstal + delete the folder "smooth" from R packages folder), restart R and reinstall smooth. 86 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Cran Comments" 3 | author: "Ivan Svetunkov" 4 | date: "02 April 2025" 5 | output: html_document 6 | --- 7 | 8 | ## Version 9 | This is ``smooth`` package, v4.2.0 10 | 11 | This is a try to fix the errors on CRAN. 12 | 13 | ## Test environments 14 | * local Ubuntu 24.04.1, R 4.4.1 15 | * github actions 16 | * win-builder (devel and release) 17 | * rhub v2 18 | 19 | ## R CMD check results 20 | R CMD check results 21 | checking installed package size ... NOTE 22 | installed size is 20.8Mb 23 | sub-directories of 1Mb or more: 24 | R 1.2Mb 25 | doc 3.3Mb 26 | libs 15.7Mb 27 | 0 errors | 0 warnings | 1 note 28 | 29 | ## Github actions 30 | Successful checks for: 31 | 32 | - Windows latest release with R 4.4.1 33 | - MacOS latest macOS Sonoma 14.6.1 with R 4.4.1 34 | - Ubuntu 22.04.5 LTS with R 4.4.1 35 | 36 | ## win-builder check results 37 | >* checking package dependencies ... NOTE 38 | >Package suggested but not available for checking: 'doMC' 39 | 40 | This is expected, because doMC is not available for Windows. 41 | 42 | ## R-hub 43 | All is fine 44 | 45 | ## Downstream dependencies 46 | I have also run R CMD check on reverse dependencies of smooth. 47 | No ERRORs or WARNINGs found. 48 | -------------------------------------------------------------------------------- /man-roxygen/ADAMDataFormulaRegLossSilentHHoldout.R: -------------------------------------------------------------------------------- 1 | #' @param data Vector, containing data needed to be forecasted. If a matrix (or 2 | #' data.frame / data.table) is provided, then the first column is used as a 3 | #' response variable, while the rest of the matrix is used as a set of explanatory 4 | #' variables. \code{formula} can be used in the latter case in order to define what 5 | #' relation to have. 6 | #' @param formula Formula to use in case of explanatory variables. If \code{NULL}, 7 | #' then all the variables are used as is. Can also include \code{trend}, which would add 8 | #' the global trend. Only needed if \code{data} is a matrix or if \code{trend} is provided. 9 | #' @param regressors The variable defines what to do with the provided explanatory 10 | #' variables: 11 | #' \code{"use"} means that all of the data should be used, while 12 | #' \code{"select"} means that a selection using \code{ic} should be done, 13 | #' \code{"adapt"} will trigger the mechanism of time varying parameters for the 14 | #' explanatory variables. 15 | #' @param loss The type of Loss Function used in optimization. \code{loss} can 16 | #' be: 17 | #' \itemize{ 18 | #' \item \code{likelihood} - the model is estimated via the maximisation of the 19 | #' likelihood of the function specified in \code{distribution}; 20 | #' \item \code{MSE} (Mean Squared Error), 21 | #' \item \code{MAE} (Mean Absolute Error), 22 | #' \item \code{HAM} (Half Absolute Moment), 23 | #' \item \code{LASSO} - use LASSO to shrink the parameters of the model; 24 | #' \item \code{RIDGE} - use RIDGE to shrink the parameters of the model; 25 | #' \item \code{TMSE} - Trace Mean Squared Error, 26 | #' \item \code{GTMSE} - Geometric Trace Mean Squared Error, 27 | #' \item \code{MSEh} - optimisation using only h-steps ahead error, 28 | #' \item \code{MSCE} - Mean Squared Cumulative Error. 29 | #' } 30 | #' In case of LASSO / RIDGE, the variables are not normalised prior to the estimation, 31 | #' but the parameters are divided by the mean values of explanatory variables. 32 | #' 33 | #' Note that model selection and combination works properly only for the default 34 | #' \code{loss="likelihood"}. 35 | #' 36 | #' Furthermore, just for fun the absolute and half analogues of multistep estimators 37 | #' are available: \code{MAEh}, \code{TMAE}, \code{GTMAE}, \code{MACE}, 38 | #' \code{HAMh}, \code{THAM}, \code{GTHAM}, \code{CHAM}. 39 | #' 40 | #' Last but not least, user can provide their own function here as well, making sure 41 | #' that it accepts parameters \code{actual}, \code{fitted} and \code{B}. Here is an 42 | #' example: 43 | #' 44 | #' \code{lossFunction <- function(actual, fitted, B) return(mean(abs(actual-fitted)))} 45 | #' 46 | #' \code{loss=lossFunction} 47 | #' @param silent Specifies, whether to provide the progress of the function or not. 48 | #' If \code{TRUE}, then the function will print what it does and how much it has 49 | #' already done. 50 | #' @param h The forecast horizon. Mainly needed for the multistep loss functions. 51 | #' @param holdout Logical. If \code{TRUE}, then the holdout of the size \code{h} 52 | #' is taken from the data (can be used for the model testing purposes). 53 | -------------------------------------------------------------------------------- /man-roxygen/ADAMInitial.R: -------------------------------------------------------------------------------- 1 | #' @param initial Can be either character or a list, or a vector of initial states. 2 | #' If it is character, then it can be \code{"backcasting"}, meaning that the initials of 3 | #' dynamic part of the model are produced using backcasting procedure (advised 4 | #' for data with high frequency), or \code{"optimal"}, meaning that all initial 5 | #' states are optimised, or \code{"two-stage"}, meaning that optimisation is done 6 | #' after the backcasting, refining the states. In case of backcasting, the parameters of the 7 | #' explanatory variables are optimised. Alternatively, you can set \code{initial="complete"} 8 | #' backcasting, which means that all states (including explanatory variables) are initialised 9 | #' via backcasting. 10 | -------------------------------------------------------------------------------- /man-roxygen/smoothRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Svetunkov I. (2023) Smooth forecasting with the smooth package in R. arXiv:2301.01790. 3 | #' \doi{10.48550/arXiv.2301.01790}. 4 | #' \item Svetunkov I. (2015 - Inf) "smooth" package for R - series of posts about the underlying 5 | #' models and how to use them: \url{https://openforecast.org/category/r-en/smooth/}. 6 | #' } 7 | -------------------------------------------------------------------------------- /man-roxygen/ssADAMRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Svetunkov, I. (2023). Forecasting and Analytics with the Augmented 3 | #' Dynamic Adaptive Model (ADAM) (1st ed.). Chapman and Hall/CRC. 4 | #' \doi{10.1201/9781003452652}, online version: \url{https://openforecast.org/adam/}. 5 | #' } 6 | -------------------------------------------------------------------------------- /man-roxygen/ssARIMARef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Svetunkov, I., & Boylan, J. E. (2019). State-space ARIMA for supply-chain forecasting. 3 | #' International Journal of Production Research, 0(0), 1–10. 4 | #' \doi{10.1080/00207543.2019.1600764} 5 | #' } 6 | -------------------------------------------------------------------------------- /man-roxygen/ssAdvancedParam.R: -------------------------------------------------------------------------------- 1 | #' @param loss The type of Loss Function used in optimization. \code{loss} can 2 | #' be: \code{likelihood} (assuming Normal distribution of error term), 3 | #' \code{MSE} (Mean Squared Error), \code{MAE} (Mean Absolute Error), 4 | #' \code{HAM} (Half Absolute Moment), \code{TMSE} - Trace Mean Squared Error, 5 | #' \code{GTMSE} - Geometric Trace Mean Squared Error, \code{MSEh} - optimisation 6 | #' using only h-steps ahead error, \code{MSCE} - Mean Squared Cumulative Error. 7 | #' If \code{loss!="MSE"}, then likelihood and model selection is done based 8 | #' on equivalent \code{MSE}. Model selection in this cases becomes not optimal. 9 | #' 10 | #' There are also available analytical approximations for multistep functions: 11 | #' \code{aMSEh}, \code{aTMSE} and \code{aGTMSE}. These can be useful in cases 12 | #' of small samples. 13 | #' 14 | #' Finally, just for fun the absolute and half analogues of multistep estimators 15 | #' are available: \code{MAEh}, \code{TMAE}, \code{GTMAE}, \code{MACE}, \code{TMAE}, 16 | #' \code{HAMh}, \code{THAM}, \code{GTHAM}, \code{CHAM}. 17 | -------------------------------------------------------------------------------- /man-roxygen/ssAuthor.R: -------------------------------------------------------------------------------- 1 | #' @author Ivan Svetunkov, \email{ivan@svetunkov.com} 2 | -------------------------------------------------------------------------------- /man-roxygen/ssBasicParam.R: -------------------------------------------------------------------------------- 1 | #' @param y Vector or ts object, containing data needed to be forecasted. 2 | #' @param h Length of forecasting horizon. 3 | #' @param holdout If \code{TRUE}, holdout sample of size \code{h} is taken from 4 | #' the end of the data. 5 | #' @param ic The information criterion used in the model selection procedure. 6 | #' @param silent accepts \code{TRUE} and \code{FALSE}. If FALSE, the function 7 | #' will print its progress and produce a plot at the end. 8 | -------------------------------------------------------------------------------- /man-roxygen/ssCESRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Svetunkov, I., Kourentzes, N., & Ord, J. K. (2022). 3 | #' Complex exponential smoothing. Naval Research Logistics, 69(8), 4 | #' 1108–1123. https://doi.org/10.1002/nav.22074 5 | #' } 6 | -------------------------------------------------------------------------------- /man-roxygen/ssETSRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Kolassa, S. (2011) Combining exponential smoothing forecasts using Akaike 3 | #' weights. International Journal of Forecasting, 27, pp 238 - 251. 4 | #' \item Svetunkov, I., Boylan, J.E., 2023b. Staying Positive: Challenges and 5 | #' Solutions in Using Pure Multiplicative ETS Models. IMA Journal of 6 | #' Management Mathematics. p. 403-425. \doi{10.1093/imaman/dpad028} 7 | #' } 8 | -------------------------------------------------------------------------------- /man-roxygen/ssGeneralRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Svetunkov, I., 2023. Smooth Forecasting with the Smooth Package in R. arXiv. 3 | #' \doi{10.48550/arXiv.2301.01790} 4 | #' \item Snyder, R. D., 1985. Recursive Estimation of Dynamic Linear Models. 5 | #' Journal of the Royal Statistical Society, Series B (Methodological) 47 (2), 272-276. 6 | #' \item Hyndman, R.J., Koehler, A.B., Ord, J.K., and Snyder, R.D. (2008) 7 | #' Forecasting with exponential smoothing: the state space approach, 8 | #' Springer-Verlag. \doi{10.1007/978-3-540-71918-2}. 9 | #' } 10 | -------------------------------------------------------------------------------- /man-roxygen/ssInitialParam.R: -------------------------------------------------------------------------------- 1 | #' @param initial Can be either character or a vector of initial states. If it 2 | #' is character, then it can be \code{"optimal"}, meaning that the initial 3 | #' states are optimised, or \code{"backcasting"}, meaning that the initials are 4 | #' produced using backcasting procedure. 5 | -------------------------------------------------------------------------------- /man-roxygen/ssIntermittentRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Svetunkov, I., Boylan, J.E., 2023a. iETS: State Space Model for 3 | #' Intermittent Demand Forecastings. International Journal of Production 4 | #' Economics. 109013. \doi{10.1016/j.ijpe.2023.109013} 5 | #' \item Teunter R., Syntetos A., Babai Z. (2011). Intermittent demand: 6 | #' Linking forecasting to inventory obsolescence. European Journal of 7 | #' Operational Research, 214, 606-615. 8 | #' \item Croston, J. (1972) Forecasting and stock control for intermittent 9 | #' demands. Operational Research Quarterly, 23(3), 289-303. 10 | #' } 11 | -------------------------------------------------------------------------------- /man-roxygen/ssIntervals.R: -------------------------------------------------------------------------------- 1 | #' @param interval Type of interval to construct. This can be: 2 | #' 3 | #' \itemize{ 4 | #' \item \code{"none"}, aka \code{"n"} - do not produce prediction 5 | #' interval. 6 | #' \item \code{"parametric"}, \code{"p"} - use state-space structure of ETS. In 7 | #' case of mixed models this is done using simulations, which may take longer 8 | #' time than for the pure additive and pure multiplicative models. This type 9 | #' of interval relies on unbiased estimate of in-sample error variance, which 10 | #' divides the sume of squared errors by T-k rather than just T. 11 | #' \item \code{"likelihood"}, \code{"l"} - these are the same as \code{"p"}, but 12 | #' relies on the biased estimate of variance from the likelihood (division by 13 | #' T, not by T-k). 14 | #' \item \code{"semiparametric"}, \code{"sp"} - interval based on covariance 15 | #' matrix of 1 to h steps ahead errors and assumption of normal / log-normal 16 | #' distribution (depending on error type). 17 | #' \item \code{"nonparametric"}, \code{"np"} - interval based on values from a 18 | #' quantile regression on error matrix (see Taylor and Bunn, 1999). The model 19 | #' used in this process is e[j] = a j^b, where j=1,..,h. 20 | #' } 21 | #' The parameter also accepts \code{TRUE} and \code{FALSE}. The former means that 22 | #' parametric interval are constructed, while the latter is equivalent to 23 | #' \code{none}. 24 | #' If the forecasts of the models were combined, then the interval are combined 25 | #' quantile-wise (Lichtendahl et al., 2013). 26 | #' @param level Confidence level. Defines width of prediction interval. 27 | #' @param cumulative If \code{TRUE}, then the cumulative forecast and prediction 28 | #' interval are produced instead of the normal ones. This is useful for 29 | #' inventory control systems. 30 | -------------------------------------------------------------------------------- /man-roxygen/ssIntervalsRef.R: -------------------------------------------------------------------------------- 1 | #' @references \itemize{ 2 | #' \item Taylor, J.W. and Bunn, D.W. (1999) A Quantile Regression Approach to 3 | #' Generating Prediction Intervals. Management Science, Vol 45, No 2, pp 4 | #' 225-237. 5 | #' \item Lichtendahl Kenneth C., Jr., Grushka-Cockayne Yael, Winkler 6 | #' Robert L., (2013) Is It Better to Average Probabilities or 7 | #' Quantiles? Management Science 59(7):1594-1611. DOI: 8 | #' \doi{10.1287/mnsc.1120.1667} 9 | #' } 10 | -------------------------------------------------------------------------------- /man-roxygen/ssKeywords.R: -------------------------------------------------------------------------------- 1 | #' @keywords univar ts models smooth regression nonlinear 2 | -------------------------------------------------------------------------------- /man-roxygen/ssPersistenceParam.R: -------------------------------------------------------------------------------- 1 | #' @param persistence Persistence vector \eqn{g}, containing smoothing 2 | #' parameters. If \code{NULL}, then estimated. 3 | -------------------------------------------------------------------------------- /man-roxygen/ssSimParam.R: -------------------------------------------------------------------------------- 1 | #' @param frequency Frequency of generated data. In cases of seasonal models 2 | #' must be greater than 1. 3 | #' @param obs Number of observations in each generated time series. 4 | #' @param nsim Number of series to generate (number of simulations to do). 5 | #' @param randomizer Type of random number generator function used for error 6 | #' term. Defaults are: \code{rnorm}, \code{rt}, \code{rlaplace} and \code{rs}. 7 | #' \code{rlnorm} should be used for multiplicative models (e.g. ETS(M,N,N)). 8 | #' But any function from \link[stats]{Distributions} will do the trick if the 9 | #' appropriate parameters are passed. For example \code{rpois} with 10 | #' \code{lambda=2} can be used as well, but might result in weird values. 11 | #' @param probability Probability of occurrence, used for intermittent data 12 | #' generation. This can be a vector, implying that probability varies in time 13 | #' (in TSB or Croston style). 14 | -------------------------------------------------------------------------------- /man-roxygen/ssXregParam.R: -------------------------------------------------------------------------------- 1 | #' @param xreg The vector (either numeric or time series) or the matrix (or 2 | #' data.frame) of exogenous variables that should be included in the model. If 3 | #' matrix included than columns should contain variables and rows - observations. 4 | #' Note that \code{xreg} should have number of observations equal either to 5 | #' in-sample or to the whole series. If the number of observations in 6 | #' \code{xreg} is equal to in-sample, then values for the holdout sample are 7 | #' produced using \link[smooth]{es} function. 8 | #' @param regressors The variable defines what to do with the provided xreg: 9 | #' \code{"use"} means that all of the data should be used, while 10 | #' \code{"select"} means that a selection using \code{ic} should be done. 11 | #' @param initialX The vector of initial parameters for exogenous variables. 12 | #' Ignored if \code{xreg} is NULL. 13 | -------------------------------------------------------------------------------- /man/accuracy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/methods.R 3 | \name{accuracy.smooth} 4 | \alias{accuracy.smooth} 5 | \alias{accuracy.smooth.forecast} 6 | \title{Error measures for an estimated model} 7 | \usage{ 8 | \method{accuracy}{smooth}(object, holdout = NULL, ...) 9 | 10 | \method{accuracy}{smooth.forecast}(object, holdout = NULL, ...) 11 | } 12 | \arguments{ 13 | \item{object}{The estimated model or a forecast from the estimated model generated via 14 | either \code{predict()} or \code{forecast()} functions.} 15 | 16 | \item{holdout}{The vector of values of the response variable in the holdout (test) set. 17 | If not provided, then the function will return the in-sample error measures. If the 18 | \code{holdout=TRUE} parameter was used in the estimation of a model, the holdout values 19 | will be extracted automatically.} 20 | 21 | \item{...}{Other variables passed to the \code{forecast()} function (e.g. \code{newdata}).} 22 | } 23 | \description{ 24 | Function produces error measures for the provided object and the holdout values of the 25 | response variable. Note that instead of parameters \code{x}, \code{test}, the function 26 | accepts the vector of values in \code{holdout}. Also, the parameters \code{d} and \code{D} 27 | are not supported - MASE is always calculated via division by first differences. 28 | } 29 | \details{ 30 | The function is a wrapper for the \link[greybox]{measures} function and is implemented 31 | for convenience. 32 | } 33 | \examples{ 34 | 35 | y <- rnorm(100, 100, 10) 36 | ourModel <- adam(y, holdout=TRUE, h=10) 37 | accuracy(ourModel) 38 | 39 | } 40 | \author{ 41 | Ivan Svetunkov, \email{ivan@svetunkov.com} 42 | } 43 | -------------------------------------------------------------------------------- /man/cma.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cma.R 3 | \name{cma} 4 | \alias{cma} 5 | \title{Centered Moving Average} 6 | \usage{ 7 | cma(y, order = NULL, silent = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{y}{Vector or ts object, containing data needed to be smoothed.} 11 | 12 | \item{order}{Order of centered moving average. If \code{NULL}, then the 13 | function will try to select order of SMA based on information criteria. 14 | See \link[smooth]{sma} for details.} 15 | 16 | \item{silent}{If \code{TRUE}, then plot is not produced. Otherwise, there 17 | is a plot...} 18 | 19 | \item{...}{Nothing. Needed only for the transition to the new name of variables.} 20 | } 21 | \value{ 22 | Object of class "smooth" is returned. It contains the list of the 23 | following values: 24 | 25 | \itemize{ 26 | \item \code{model} - the name of the estimated model. 27 | \item \code{timeElapsed} - time elapsed for the construction of the model. 28 | \item \code{order} - order of the moving average. 29 | \item \code{nParam} - table with the number of estimated / provided parameters. 30 | If a previous model was reused, then its initials are reused and the number of 31 | provided parameters will take this into account. 32 | \item \code{fitted} - the fitted values, shifted in time. 33 | \item \code{forecast} - NAs, because this function does not produce forecasts. 34 | \item \code{residuals} - the residuals of the SMA / AR model. 35 | \item \code{s2} - variance of the residuals (taking degrees of freedom into 36 | account) of the SMA / AR model. 37 | \item \code{y} - the original data. 38 | \item \code{ICs} - values of information criteria from the respective SMA or 39 | AR model. Includes AIC, AICc, BIC and BICc. 40 | \item \code{logLik} - log-likelihood of the SMA / AR model. 41 | \item \code{lossValue} - Cost function value (for the SMA / AR model). 42 | \item \code{loss} - Type of loss function used in the estimation. 43 | } 44 | } 45 | \description{ 46 | Function constructs centered moving average based on state space SMA 47 | } 48 | \details{ 49 | If the order is odd, then the function constructs SMA(order) and 50 | shifts it back in time. Otherwise an AR(order+1) model is constructed 51 | with the preset parameters: 52 | 53 | \deqn{phi_i = {0.5,1,1,...,0.5} / order} 54 | 55 | This then corresponds to the centered MA with 0.5 weight for the 56 | first observation and 0.5 weight for an additional one. e.g. if this is 57 | monthly data and we use order=12, then half of the first January and 58 | half of the new one is taken. 59 | 60 | This is not a forecasting tool. This is supposed to smooth the time 61 | series in order to find trend. So don't expect any forecasts from this 62 | function! 63 | } 64 | \examples{ 65 | 66 | # CMA of specific order 67 | ourModel <- cma(rnorm(118,100,3),order=12) 68 | 69 | # CMA of arbitrary order 70 | ourModel <- cma(rnorm(118,100,3)) 71 | 72 | summary(ourModel) 73 | 74 | } 75 | \references{ 76 | \itemize{ 77 | \item Svetunkov I. (2023) Smooth forecasting with the smooth package in R. arXiv:2301.01790. 78 | \doi{10.48550/arXiv.2301.01790}. 79 | \item Svetunkov I. (2015 - Inf) "smooth" package for R - series of posts about the underlying 80 | models and how to use them: \url{https://openforecast.org/category/r-en/smooth/}. 81 | } 82 | } 83 | \seealso{ 84 | \code{\link[smooth]{es}, \link[smooth]{ssarima}} 85 | } 86 | \author{ 87 | Ivan Svetunkov, \email{ivan@svetunkov.com} 88 | } 89 | \keyword{models} 90 | \keyword{nonlinear} 91 | \keyword{regression} 92 | \keyword{smooth} 93 | \keyword{ts} 94 | \keyword{univar} 95 | -------------------------------------------------------------------------------- /man/figures/smooth-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/config-i1/smooth/c529c51c1aa221fd49117f17e68064b57d2ae9ff/man/figures/smooth-web.png -------------------------------------------------------------------------------- /man/forecast.smooth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/adam.R, R/methods.R, R/msdecompose.R 3 | \name{forecast.adam} 4 | \alias{forecast.adam} 5 | \alias{forecast.smooth} 6 | \alias{forecast} 7 | \alias{forecast.oes} 8 | \alias{forecast.msdecompose} 9 | \title{Forecasting time series using smooth functions} 10 | \usage{ 11 | \method{forecast}{adam}(object, h = 10, newdata = NULL, 12 | occurrence = NULL, interval = c("none", "prediction", "confidence", 13 | "simulated", "approximate", "semiparametric", "nonparametric", "empirical", 14 | "complete"), level = 0.95, side = c("both", "upper", "lower"), 15 | cumulative = FALSE, nsim = NULL, scenarios = FALSE, ...) 16 | 17 | \method{forecast}{smooth}(object, h = 10, interval = c("parametric", 18 | "semiparametric", "nonparametric", "none"), level = 0.95, 19 | side = c("both", "upper", "lower"), ...) 20 | 21 | \method{forecast}{oes}(object, h = 10, ...) 22 | 23 | \method{forecast}{msdecompose}(object, h = 10, interval = c("parametric", 24 | "semiparametric", "nonparametric", "none"), level = 0.95, model = NULL, 25 | ...) 26 | } 27 | \arguments{ 28 | \item{object}{Time series model for which forecasts are required.} 29 | 30 | \item{h}{Forecast horizon.} 31 | 32 | \item{newdata}{The new data needed in order to produce forecasts.} 33 | 34 | \item{occurrence}{The vector containing the future occurrence variable 35 | (values in [0,1]), if it is known.} 36 | 37 | \item{interval}{What type of mechanism to use for interval construction. 38 | the recommended option is \code{interval="prediction"}, which will use analytical 39 | solutions for pure additive models and simulations for the others. 40 | \code{interval="simulated"} is the slowest method, but is robust to the type of 41 | model. \code{interval="approximate"} (aka \code{interval="parametric"}) uses 42 | analytical formulae for conditional h-steps ahead variance, but is approximate 43 | for the non-additive error models. \code{interval="semiparametric"} relies on the 44 | multiple steps ahead forecast error (extracted via \code{rmultistep} method) and on 45 | the assumed distribution of the error term. \code{interval="nonparametric"} uses 46 | Taylor & Bunn (1999) approach with quantile regressions. \code{interval="empirical"} 47 | constructs intervals based on empirical quantiles of multistep forecast errors. 48 | \code{interval="complete"} will call for \code{reforecast()} function and produce 49 | interval based on the uncertainty around the parameters of the model. 50 | Finally, \code{interval="confidence"} tries to generate the confidence intervals 51 | for the point forecast based on the \code{reforecast} method.} 52 | 53 | \item{level}{Confidence level. Defines width of prediction interval.} 54 | 55 | \item{side}{Defines, whether to provide \code{"both"} sides of prediction 56 | interval or only \code{"upper"}, or \code{"lower"}.} 57 | 58 | \item{cumulative}{If \code{TRUE}, then the cumulative forecast and prediction 59 | interval are produced instead of the normal ones. This is useful for 60 | inventory control systems.} 61 | 62 | \item{nsim}{Number of iterations to do in cases of \code{interval="simulated"}, 63 | \code{interval="prediction"} (for mixed and multiplicative model), 64 | \code{interval="confidence"} and \code{interval="complete"}. 65 | The default value for the prediction / simulated interval is 1000. In case of 66 | confidence or complete intervals, this is set to 100.} 67 | 68 | \item{scenarios}{Binary, defining whether to return scenarios produced via 69 | simulations or not. Only works if \code{interval="simulated"}. If \code{TRUE} 70 | the object will contain \code{scenarios} variable.} 71 | 72 | \item{...}{Other arguments accepted by either \link[smooth]{es}, 73 | \link[smooth]{ces}, \link[smooth]{gum} or \link[smooth]{ssarima}.} 74 | 75 | \item{model}{The type of ETS model to fit on the decomposed trend. Only applicable to 76 | "msdecompose" class. This is then returned in parameter "esmodel". If \code{NULL}, then 77 | it will be selected automatically based on the type of the used decomposition (either 78 | among pure additive or among pure multiplicative ETS models).} 79 | } 80 | \value{ 81 | Returns object of class "smooth.forecast", which contains: 82 | 83 | \itemize{ 84 | \item \code{model} - the estimated model (ES / CES / GUM / SSARIMA). 85 | \item \code{method} - the name of the estimated model (ES / CES / GUM / SSARIMA). 86 | \item \code{forecast} aka \code{mean} - point forecasts of the model 87 | (conditional mean). 88 | \item \code{lower} - lower bound of prediction interval. 89 | \item \code{upper} - upper bound of prediction interval. 90 | \item \code{level} - confidence level. 91 | \item \code{interval} - binary variable (whether interval were produced or not). 92 | \item \code{scenarios} - in case of \code{forecast.adam()} and 93 | \code{interval="simulated"} returns matrix with scenarios (future paths) that were 94 | used in simulations. 95 | } 96 | } 97 | \description{ 98 | Function produces conditional expectation (point forecasts) and prediction 99 | intervals for the estimated model. 100 | } 101 | \details{ 102 | By default the function will generate conditional expectations from the 103 | estimated model and will also produce a variety of prediction intervals 104 | based on user preferences. 105 | } 106 | \examples{ 107 | 108 | ourModel <- es(rnorm(100,0,1), h=10) 109 | forecast(ourModel, h=10, interval="parametric") 110 | 111 | } 112 | \references{ 113 | Hyndman, R.J., Koehler, A.B., Ord, J.K., and Snyder, R.D. (2008) 114 | Forecasting with exponential smoothing: the state space approach, 115 | Springer-Verlag. 116 | } 117 | \seealso{ 118 | \code{\link[generics]{forecast}} 119 | } 120 | \author{ 121 | Ivan Svetunkov, \email{ivan@svetunkov.com} 122 | } 123 | \keyword{ts} 124 | \keyword{univar} 125 | -------------------------------------------------------------------------------- /man/isFunctions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/isFunctions.R, R/msdecompose.R 3 | \name{is.smooth} 4 | \alias{is.smooth} 5 | \alias{is.smoothC} 6 | \alias{is.msarima} 7 | \alias{is.oes} 8 | \alias{is.oesg} 9 | \alias{is.smooth.sim} 10 | \alias{is.smooth.forecast} 11 | \alias{is.adam} 12 | \alias{is.adam.sim} 13 | \alias{is.msdecompose} 14 | \alias{is.msdecompose.forecast} 15 | \title{Smooth classes checkers} 16 | \usage{ 17 | is.smooth(x) 18 | 19 | is.smoothC(x) 20 | 21 | is.msarima(x) 22 | 23 | is.oes(x) 24 | 25 | is.oesg(x) 26 | 27 | is.smooth.sim(x) 28 | 29 | is.smooth.forecast(x) 30 | 31 | is.adam(x) 32 | 33 | is.adam.sim(x) 34 | 35 | is.msdecompose(x) 36 | 37 | is.msdecompose.forecast(x) 38 | } 39 | \arguments{ 40 | \item{x}{The object to check.} 41 | } 42 | \value{ 43 | \code{TRUE} if this is the specified class and \code{FALSE} otherwise. 44 | 45 | \code{TRUE} if this is the specified class and \code{FALSE} otherwise. 46 | } 47 | \description{ 48 | Functions to check if an object is of the specified class 49 | 50 | Functions to check if an object is of the specified class 51 | } 52 | \details{ 53 | The list of functions includes: 54 | \itemize{ 55 | \item \code{is.smooth()} tests if the object was produced by a smooth function 56 | (e.g. \link[smooth]{es} / \link[smooth]{ces} / \link[smooth]{ssarima} / 57 | \link[smooth]{gum} / \link[smooth]{sma} / \link[smooth]{msarima}); 58 | \item \code{is.msarima()} tests if the object was produced by the 59 | \link[smooth]{msarima} function; 60 | \item \code{is.smoothC()} tests if the object was produced by a combination 61 | function (currently applies only to \link[smooth]{smoothCombine}); 62 | \item \code{is.oes()} tests if the object was produced by \link[smooth]{oes} 63 | function; 64 | \item \code{is.smooth.sim()} tests if the object was produced by simulate functions 65 | (e.g. \link[smooth]{sim.es} / \link[smooth]{sim.ces} / \link[smooth]{sim.ssarima} 66 | / \link[smooth]{sim.sma} / \link[smooth]{sim.gum}); 67 | \item \code{is.smooth.forecast()} checks if the forecast was produced from a smooth 68 | function using forecast() function. 69 | } 70 | 71 | The list of functions includes: 72 | \itemize{ 73 | \item \code{is.adam()} tests if the object was produced by a \link[smooth]{adam} function 74 | \item \code{is.adam.sim()} tests if the object was produced by sim.adam() function (not implemented yet); 75 | } 76 | } 77 | \examples{ 78 | 79 | ourModel <- msarima(rnorm(100,100,10)) 80 | 81 | is.smooth(ourModel) 82 | is.msarima(ourModel) 83 | 84 | 85 | ourModel <- adam(rnorm(100,100,10)) 86 | is.adam(ourModel) 87 | 88 | } 89 | \author{ 90 | Ivan Svetunkov, \email{ivan@svetunkov.com} 91 | } 92 | \keyword{ts} 93 | \keyword{univar} 94 | -------------------------------------------------------------------------------- /man/msdecompose.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/msdecompose.R 3 | \name{msdecompose} 4 | \alias{msdecompose} 5 | \title{Multiple seasonal classical decomposition} 6 | \usage{ 7 | msdecompose(y, lags = c(12), type = c("additive", "multiplicative"), 8 | smoother = c("ma", "lowess", "supsmu"), ...) 9 | } 10 | \arguments{ 11 | \item{y}{Vector or ts object, containing data needed to be smoothed.} 12 | 13 | \item{lags}{Vector of lags, corresponding to the frequencies in the data.} 14 | 15 | \item{type}{The type of decomposition. If \code{"multiplicative"} is selected, 16 | then the logarithm of data is taken prior to the decomposition.} 17 | 18 | \item{smoother}{The type of function used in the smoother of the data to 19 | extract the trend and in seasonality smoothing. \code{smoother="ma"} relies 20 | on the centred moving average and will result in the classical decomposition. 21 | \code{smoother="lowess"} will use \link[stats]{lowess}, resulting in a 22 | decomposition similar to the STL (\link[stats]{stl}). Finally, 23 | \code{smoother="supsmu"} will use the Friedman's super smoother via 24 | \link[stats]{supsmu}.} 25 | 26 | \item{...}{Other parameters passed to smoothers. Only works with 27 | lowess/supsmu.} 28 | } 29 | \value{ 30 | The object of the class "msdecompose" is return, containing: 31 | \itemize{ 32 | \item \code{y} - the original time series. 33 | \item \code{initial} - the estimates of the initial level and trend. 34 | \item \code{trend} - the long term trend in the data. 35 | \item \code{seasonal} - the list of seasonal parameters. 36 | \item \code{lags} - the provided lags. 37 | \item \code{type} - the selected type of the decomposition. 38 | \item \code{yName} - the name of the provided data. 39 | } 40 | } 41 | \description{ 42 | Function decomposes multiple seasonal time series into components using 43 | the principles of classical decomposition. 44 | } 45 | \details{ 46 | The function applies centred moving averages based on \link[stats]{filter} 47 | function and order specified in \code{lags} variable in order to smooth the 48 | original series and obtain level, trend and seasonal components of the series. 49 | } 50 | \examples{ 51 | 52 | # Decomposition of multiple frequency data 53 | \dontrun{ourModel <- msdecompose(forecast::taylor, lags=c(48,336), type="m")} 54 | ourModel <- msdecompose(AirPassengers, lags=c(12), type="m") 55 | 56 | plot(ourModel) 57 | plot(forecast(ourModel, model="AAN", h=12)) 58 | 59 | } 60 | \references{ 61 | \itemize{ 62 | \item Svetunkov I. (2023) Smooth forecasting with the smooth package in R. arXiv:2301.01790. 63 | \doi{10.48550/arXiv.2301.01790}. 64 | \item Svetunkov I. (2015 - Inf) "smooth" package for R - series of posts about the underlying 65 | models and how to use them: \url{https://openforecast.org/category/r-en/smooth/}. 66 | } 67 | } 68 | \seealso{ 69 | \code{\link[stats]{filter}} 70 | } 71 | \author{ 72 | Ivan Svetunkov, \email{ivan@svetunkov.com} 73 | } 74 | \keyword{models} 75 | \keyword{nonlinear} 76 | \keyword{regression} 77 | \keyword{smooth} 78 | \keyword{ts} 79 | \keyword{univar} 80 | -------------------------------------------------------------------------------- /man/multicov.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/methods.R 3 | \name{multicov} 4 | \alias{multicov} 5 | \alias{multicov.smooth} 6 | \title{Function returns the multiple steps ahead covariance matrix of forecast errors} 7 | \usage{ 8 | multicov(object, type = c("analytical", "empirical", "simulated"), h = 10, 9 | nsim = 1000, ...) 10 | 11 | \method{multicov}{smooth}(object, type = c("analytical", "empirical", 12 | "simulated"), h = 10, nsim = 1000, ...) 13 | } 14 | \arguments{ 15 | \item{object}{Model estimated using one of the functions of smooth package.} 16 | 17 | \item{type}{What method to use in order to produce covariance matrix: 18 | \enumerate{ 19 | \item \code{analytical} - based on the state space structure of the model and the 20 | one-step-ahead forecast error. This works for pure additive and pure multiplicative 21 | models. The values for the mixed models might be off. 22 | \item \code{empirical} - based on the in-sample 1 to h steps ahead forecast errors 23 | (works fine on larger samples); 24 | \item \code{simulated} - the data is simulated from the estimated model, then the 25 | same model is applied to it and then the empirical 1 to h steps ahead forecast 26 | errors are produced; 27 | }} 28 | 29 | \item{h}{Forecast horizon to use in the calculations.} 30 | 31 | \item{nsim}{Number of iterations to produce in the simulation. Only needed if 32 | \code{type="simulated"}} 33 | 34 | \item{...}{Other parameters passed to simulate function (if \code{type="simulated"} 35 | is used). These are \code{obs} and \code{seed}. By default \code{obs=1000}. 36 | This approach increases the accuracy of covariance matrix on small samples 37 | and intermittent data;} 38 | } 39 | \value{ 40 | Scalar in cases of non-smooth functions. (h x h) matrix otherwise. 41 | } 42 | \description{ 43 | This function extracts covariance matrix of 1 to h steps ahead forecast errors for 44 | \code{adam()}, \code{ssarima()}, \code{gum()}, \code{sma()}, \code{es()} and 45 | \code{ces()} models. 46 | } 47 | \details{ 48 | The function returns either scalar (if it is a non-smooth model) 49 | or the matrix of (h x h) size with variances and covariances of 1 to h steps ahead 50 | forecast errors. 51 | } 52 | \examples{ 53 | 54 | x <- rnorm(100,0,1) 55 | 56 | # A simple example with a 5x5 covariance matrix 57 | ourModel <- ces(x, h=5) 58 | multicov(ourModel) 59 | 60 | } 61 | \seealso{ 62 | \link[smooth]{orders} 63 | } 64 | \author{ 65 | Ivan Svetunkov, \email{ivan@svetunkov.com} 66 | } 67 | \keyword{models} 68 | \keyword{nonlinear} 69 | \keyword{regression} 70 | \keyword{smooth} 71 | \keyword{ts} 72 | \keyword{univar} 73 | -------------------------------------------------------------------------------- /man/oesg.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/oesg.R 3 | \name{oesg} 4 | \alias{oesg} 5 | \title{Occurrence ETS, general model} 6 | \usage{ 7 | oesg(y, modelA = "MNN", modelB = "MNN", persistenceA = NULL, 8 | persistenceB = NULL, phiA = NULL, phiB = NULL, initialA = "o", 9 | initialB = "o", initialSeasonA = NULL, initialSeasonB = NULL, 10 | ic = c("AICc", "AIC", "BIC", "BICc"), h = 10, holdout = FALSE, 11 | bounds = c("usual", "admissible", "none"), silent = c("all", "graph", 12 | "legend", "output", "none"), xregA = NULL, xregB = NULL, 13 | initialXA = NULL, initialXB = NULL, regressorsA = c("use", "select"), 14 | regressorsB = c("use", "select"), ...) 15 | } 16 | \arguments{ 17 | \item{y}{Either numeric vector or time series vector.} 18 | 19 | \item{modelA}{The type of the ETS for the model A.} 20 | 21 | \item{modelB}{The type of the ETS for the model B.} 22 | 23 | \item{persistenceA}{The persistence vector \eqn{g}, containing smoothing 24 | parameters used in the model A. If \code{NULL}, then estimated.} 25 | 26 | \item{persistenceB}{The persistence vector \eqn{g}, containing smoothing 27 | parameters used in the model B. If \code{NULL}, then estimated.} 28 | 29 | \item{phiA}{The value of the dampening parameter in the model A. Used only 30 | for damped-trend models.} 31 | 32 | \item{phiB}{The value of the dampening parameter in the model B. Used only 33 | for damped-trend models.} 34 | 35 | \item{initialA}{Either \code{"o"} - optimal or the vector of initials for the 36 | level and / or trend for the model A.} 37 | 38 | \item{initialB}{Either \code{"o"} - optimal or the vector of initials for the 39 | level and / or trend for the model B.} 40 | 41 | \item{initialSeasonA}{The vector of the initial seasonal components for the 42 | model A. If \code{NULL}, then it is estimated.} 43 | 44 | \item{initialSeasonB}{The vector of the initial seasonal components for the 45 | model B. If \code{NULL}, then it is estimated.} 46 | 47 | \item{ic}{Information criteria to use in case of model selection.} 48 | 49 | \item{h}{Forecast horizon.} 50 | 51 | \item{holdout}{If \code{TRUE}, holdout sample of size \code{h} is taken from 52 | the end of the data.} 53 | 54 | \item{bounds}{What type of bounds to use in the model estimation. The first 55 | letter can be used instead of the whole word.} 56 | 57 | \item{silent}{If \code{silent="none"}, then nothing is silent, everything is 58 | printed out and drawn. \code{silent="all"} means that nothing is produced or 59 | drawn (except for warnings). In case of \code{silent="graph"}, no graph is 60 | produced. If \code{silent="legend"}, then legend of the graph is skipped. 61 | And finally \code{silent="output"} means that nothing is printed out in the 62 | console, but the graph is produced. \code{silent} also accepts \code{TRUE} 63 | and \code{FALSE}. In this case \code{silent=TRUE} is equivalent to 64 | \code{silent="all"}, while \code{silent=FALSE} is equivalent to 65 | \code{silent="none"}. The parameter also accepts first letter of words ("n", 66 | "a", "g", "l", "o").} 67 | 68 | \item{xregA}{The vector or the matrix of exogenous variables, explaining some parts 69 | of occurrence variable of the model A.} 70 | 71 | \item{xregB}{The vector or the matrix of exogenous variables, explaining some parts 72 | of occurrence variable of the model B.} 73 | 74 | \item{initialXA}{The vector of initial parameters for exogenous variables in the model 75 | A. Ignored if \code{xregA} is NULL.} 76 | 77 | \item{initialXB}{The vector of initial parameters for exogenous variables in the model 78 | B. Ignored if \code{xregB} is NULL.} 79 | 80 | \item{regressorsA}{Variable defines what to do with the provided \code{xregA}: 81 | \code{"use"} means that all of the data should be used, while 82 | \code{"select"} means that a selection using \code{ic} should be done.} 83 | 84 | \item{regressorsB}{Similar to the \code{regressorsA}, but for the part B of the model.} 85 | 86 | \item{...}{The parameters passed to the optimiser, such as \code{maxeval}, 87 | \code{xtol_rel}, \code{algorithm} and \code{print_level}. The description of 88 | these is printed out by \code{nloptr.print.options()} function from the \code{nloptr} 89 | package. The default values in the oes function are \code{maxeval=500}, 90 | \code{xtol_rel=1E-8}, \code{algorithm="NLOPT_LN_NELDERMEAD"} and \code{print_level=0}.} 91 | } 92 | \value{ 93 | The object of class "occurrence" is returned. It contains following list of 94 | values: 95 | 96 | \itemize{ 97 | \item \code{modelA} - the model A of the class oes, that contains the output similar 98 | to the one from the \code{oes()} function; 99 | \item \code{modelB} - the model B of the class oes, that contains the output similar 100 | to the one from the \code{oes()} function. 101 | \item \code{B} - the vector of all the estimated parameters. 102 | } 103 | } 104 | \description{ 105 | Function returns the general occurrence model of the of iETS model. 106 | } 107 | \details{ 108 | The function estimates probability of demand occurrence, based on the iETS_G 109 | state-space model. It involves the estimation and modelling of the two 110 | simultaneous state space equations. Thus two parts for the model type, 111 | persistence, initials etc. 112 | 113 | For the details about the model and its implementation, see the respective 114 | vignette: \code{vignette("oes","smooth")} 115 | 116 | The model is based on: 117 | 118 | \deqn{o_t \sim Bernoulli(p_t)} 119 | \deqn{p_t = \frac{a_t}{a_t+b_t}}, 120 | 121 | where a_t and b_t are the parameters of the Beta distribution and are modelled 122 | using separate ETS models. 123 | } 124 | \examples{ 125 | 126 | y <- rpois(100,0.1) 127 | oesg(y, modelA="MNN", modelB="ANN") 128 | 129 | } 130 | \seealso{ 131 | \code{\link[smooth]{es}, \link[smooth]{oes}} 132 | } 133 | \author{ 134 | Ivan Svetunkov, \email{ivan@svetunkov.com} 135 | } 136 | \keyword{demand} 137 | \keyword{exponential} 138 | \keyword{forecasting} 139 | \keyword{intermittent} 140 | \keyword{iss} 141 | \keyword{model} 142 | \keyword{models} 143 | \keyword{nonlinear} 144 | \keyword{regression} 145 | \keyword{smooth} 146 | \keyword{smoothing} 147 | \keyword{space} 148 | \keyword{state} 149 | \keyword{ts} 150 | \keyword{univar} 151 | -------------------------------------------------------------------------------- /man/orders.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/methods.R 3 | \name{orders} 4 | \alias{orders} 5 | \alias{lags} 6 | \alias{modelName} 7 | \alias{modelType} 8 | \title{Functions that extract values from the fitted model} 9 | \usage{ 10 | orders(object, ...) 11 | 12 | lags(object, ...) 13 | 14 | modelName(object, ...) 15 | 16 | modelType(object, ...) 17 | } 18 | \arguments{ 19 | \item{object}{Model estimated using one of the functions of smooth package.} 20 | 21 | \item{...}{Currently nothing is accepted via ellipsis.} 22 | } 23 | \value{ 24 | Either vector, scalar or list with values is returned. 25 | \code{orders()} in case of ssarima returns list of values: 26 | \itemize{ 27 | \item \code{ar} - AR orders. 28 | \item \code{i} - I orders. 29 | \item \code{ma} - MA orders. 30 | } 31 | \code{lags()} returns the vector of lags of the model. 32 | All the other functions return strings of character. 33 | } 34 | \description{ 35 | These functions allow extracting orders and lags for \code{ssarima()}, \code{gum()} and \code{sma()}, 36 | type of model from \code{es()} and \code{ces()} and name of model. 37 | } 38 | \details{ 39 | \code{orders()} and \code{lags()} are useful only for SSARIMA, GUM and SMA. They return \code{NA} for other functions. 40 | This can also be applied to \code{arima()}, \code{Arima()} and \code{auto.arima()} functions from stats and forecast packages. 41 | \code{modelType()} is useful only for ETS and CES. They return \code{NA} for other functions. 42 | This can also be applied to \code{ets()} function from forecast package. \code{errorType} 43 | extracts the type of error from the model (either additive or multiplicative). Finally, \code{modelName} 44 | returns the name of the fitted model. For example, "ARIMA(0,1,1)". This is purely descriptive and 45 | can also be applied to non-smooth classes, so that, for example, you can easily extract the name 46 | of the fitted AR model from \code{ar()} function from \code{stats} package. 47 | } 48 | \examples{ 49 | 50 | x <- rnorm(100,0,1) 51 | 52 | # Just as example. orders and lags do not return anything for ces() and es(). But modelType() does. 53 | ourModel <- ces(x, h=10) 54 | orders(ourModel) 55 | lags(ourModel) 56 | modelType(ourModel) 57 | modelName(ourModel) 58 | 59 | # And as another example it does the opposite for gum() and ssarima() 60 | ourModel <- gum(x, h=10, orders=c(1,1), lags=c(1,4)) 61 | orders(ourModel) 62 | lags(ourModel) 63 | modelType(ourModel) 64 | modelName(ourModel) 65 | 66 | # Finally these values can be used for simulate functions or original functions. 67 | ourModel <- auto.ssarima(x) 68 | ssarima(x, orders=orders(ourModel), lags=lags(ourModel), constant=ourModel$constant) 69 | sim.ssarima(orders=orders(ourModel), lags=lags(ourModel), constant=ourModel$constant) 70 | 71 | ourModel <- es(x) 72 | es(x, model=modelType(ourModel)) 73 | sim.es(model=modelType(ourModel)) 74 | 75 | } 76 | \seealso{ 77 | \link[smooth]{ssarima}, \link[smooth]{msarima} 78 | } 79 | \author{ 80 | Ivan Svetunkov, \email{ivan@svetunkov.com} 81 | } 82 | \keyword{models} 83 | \keyword{nonlinear} 84 | \keyword{regression} 85 | \keyword{smooth} 86 | \keyword{ts} 87 | \keyword{univar} 88 | -------------------------------------------------------------------------------- /man/plot.smooth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/adam.R, R/methods.R, R/msdecompose.R 3 | \name{plot.adam} 4 | \alias{plot.adam} 5 | \alias{plot.smooth} 6 | \alias{plot.msdecompose} 7 | \title{Plots for the fit and states} 8 | \usage{ 9 | \method{plot}{adam}(x, which = c(1, 2, 4, 6), level = 0.95, 10 | legend = FALSE, ask = prod(par("mfcol")) < length(which) && 11 | dev.interactive(), lowess = TRUE, ...) 12 | 13 | \method{plot}{smooth}(x, which = c(1, 2, 4, 6), level = 0.95, 14 | legend = FALSE, ask = prod(par("mfcol")) < length(which) && 15 | dev.interactive(), lowess = TRUE, ...) 16 | 17 | \method{plot}{msdecompose}(x, which = c(1, 2, 4, 6), level = 0.95, 18 | legend = FALSE, ask = prod(par("mfcol")) < length(which) && 19 | dev.interactive(), lowess = TRUE, ...) 20 | } 21 | \arguments{ 22 | \item{x}{Estimated smooth model.} 23 | 24 | \item{which}{Which of the plots to produce. The possible options (see details for explanations): 25 | \enumerate{ 26 | \item Actuals vs Fitted values; 27 | \item Standardised residuals vs Fitted; 28 | \item Studentised residuals vs Fitted; 29 | \item Absolute residuals vs Fitted; 30 | \item Squared residuals vs Fitted; 31 | \item Q-Q plot with the specified distribution; 32 | \item Fitted over time; 33 | \item Standardised residuals vs Time; 34 | \item Studentised residuals vs Time; 35 | \item ACF of the residuals; 36 | \item PACF of the residuals; 37 | \item Plot of states of the model; 38 | \item Absolute standardised residuals vs Fitted; 39 | \item Squared standardised residuals vs Fitted; 40 | \item ACF of the squared residuals; 41 | \item PACF of the squared residuals. 42 | }} 43 | 44 | \item{level}{Confidence level. Defines width of confidence interval. Used in plots (2), (3), (7), (8), 45 | (9), (10) and (11).} 46 | 47 | \item{legend}{If \code{TRUE}, then the legend is produced on plots (2), (3) and (7).} 48 | 49 | \item{ask}{Logical; if \code{TRUE}, the user is asked to press Enter before each plot.} 50 | 51 | \item{lowess}{Logical; if \code{TRUE}, LOWESS lines are drawn on scatterplots, see \link[stats]{lowess}.} 52 | 53 | \item{...}{The parameters passed to the plot functions. Recommended to use with separate plots.} 54 | } 55 | \value{ 56 | The function produces the number of plots, specified in the parameter \code{which}. 57 | } 58 | \description{ 59 | The function produces diagnostics plots for a \code{smooth} model 60 | } 61 | \details{ 62 | The list of produced plots includes: 63 | \enumerate{ 64 | \item Actuals vs Fitted values. Allows analysing, whether there are any issues in the fit. 65 | Does the variability of actuals increase with the increase of fitted values? Is the relation 66 | well captured? They grey line on the plot corresponds to the perfect fit of the model. 67 | \item Standardised residuals vs Fitted. Plots the points and the confidence bounds 68 | (red lines) for the specified confidence \code{level}. Useful for the analysis of outliers; 69 | \item Studentised residuals vs Fitted. This is similar to the previous plot, but with the 70 | residuals divided by the scales with the leave-one-out approach. Should be more sensitive 71 | to outliers; 72 | \item Absolute residuals vs Fitted. Useful for the analysis of heteroscedasticity; 73 | \item Squared residuals vs Fitted - similar to (3), but with squared values; 74 | \item Q-Q plot with the specified distribution. Can be used in order to see if the 75 | residuals follow the assumed distribution. The type of distribution depends on the one used 76 | in the estimation (see \code{distribution} parameter in \link[greybox]{alm}); 77 | \item ACF of the residuals. Are the residuals autocorrelated? See \link[stats]{acf} for 78 | details; 79 | \item Fitted over time. Plots actuals (black line), fitted values (purple line), point forecast 80 | (blue line) and prediction interval (grey lines). Can be used in order to make sure that the model 81 | did not miss any important events over time; 82 | \item Standardised residuals vs Time. Useful if you want to see, if there is autocorrelation or 83 | if there is heteroscedasticity in time. This also shows, when the outliers happen; 84 | \item Studentised residuals vs Time. Similar to previous, but with studentised residuals; 85 | \item PACF of the residuals. No, really, are they autocorrelated? See pacf function from stats 86 | package for details; 87 | \item Plot of the states of the model. It is not recommended to produce this plot together with 88 | the others, because there might be several states, which would cause the creation of a different 89 | canvas. In case of "msdecompose", this will produce the decomposition of the series into states 90 | on a different canvas; 91 | \item Absolute standardised residuals vs Fitted. Similar to the previous, but with absolute 92 | values. This is more relevant to the models where scale is calculated as an absolute value of 93 | something (e.g. Laplace); 94 | \item Squared standardised residuals vs Fitted. This is an additional plot needed to diagnose 95 | heteroscedasticity in a model with varying scale. The variance on this plot will be constant if 96 | the adequate model for \code{scale} was constructed. This is more appropriate for normal and 97 | the related distributions. 98 | } 99 | Which of the plots to produce, is specified via the \code{which} parameter. 100 | } 101 | \examples{ 102 | 103 | ourModel <- es(c(rnorm(50,100,10),rnorm(50,120,10)), "ANN", h=10) 104 | par(mfcol=c(3,4)) 105 | plot(ourModel, c(1:11)) 106 | plot(ourModel, 12) 107 | 108 | } 109 | \seealso{ 110 | \link[greybox]{plot.greybox} 111 | } 112 | \author{ 113 | Ivan Svetunkov, \email{ivan@svetunkov.com} 114 | } 115 | \keyword{ts} 116 | \keyword{univar} 117 | -------------------------------------------------------------------------------- /man/pls.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/methods.R 3 | \name{pls} 4 | \alias{pls} 5 | \alias{pls.smooth} 6 | \title{Prediction Likelihood Score} 7 | \usage{ 8 | pls(object, holdout = NULL, ...) 9 | 10 | \method{pls}{smooth}(object, holdout = NULL, ...) 11 | } 12 | \arguments{ 13 | \item{object}{The model estimated using smooth functions. This thing also accepts 14 | other models (e.g. estimated using functions from forecast package), but may not always 15 | work properly with them.} 16 | 17 | \item{holdout}{The values for the holdout part of the sample. If the model was fitted 18 | on the data with the \code{holdout=TRUE}, then the parameter is not needed.} 19 | 20 | \item{...}{Parameters passed to multicov function. The function is called in order to get 21 | the covariance matrix of 1 to h steps ahead forecast errors.} 22 | } 23 | \value{ 24 | A value of the log-likelihood. 25 | } 26 | \description{ 27 | Function estimates Prediction Likelihood Score for the provided model 28 | } 29 | \details{ 30 | Prediction likelihood score (PLS) is based on either normal or log-normal 31 | distribution of errors. This is extracted from the provided model. The likelihood 32 | based on the distribution of 1 to h steps ahead forecast errors is used in the process. 33 | } 34 | \examples{ 35 | 36 | # Generate data, apply es() with the holdout parameter and calculate PLS 37 | x <- rnorm(100,0,1) 38 | ourModel <- es(x, h=10, holdout=TRUE) 39 | pls(ourModel, type="a") 40 | pls(ourModel, type="e") 41 | pls(ourModel, type="s", obs=100, nsim=100) 42 | 43 | } 44 | \references{ 45 | \itemize{ 46 | %\item Eltoft, T., Taesu, K., Te-Won, L. (2006). On the multivariate Laplace 47 | distribution. IEEE Signal Processing Letters. 13 (5): 300-303. 48 | \doi{10.1109/LSP.2006.870353} - this is not yet used in the function. 49 | \item Snyder, R. D., Ord, J. K., Beaumont, A., 2012. Forecasting the intermittent 50 | demand for slow-moving inventories: A modelling approach. International 51 | Journal of Forecasting 28 (2), 485-496. 52 | \item Kolassa, S., 2016. Evaluating predictive count data distributions in retail 53 | sales forecasting. International Journal of Forecasting 32 (3), 788-803.. 54 | } 55 | } 56 | \author{ 57 | Ivan Svetunkov, \email{ivan@svetunkov.com} 58 | } 59 | \keyword{models} 60 | \keyword{nonlinear} 61 | \keyword{regression} 62 | \keyword{smooth} 63 | \keyword{ts} 64 | \keyword{univar} 65 | -------------------------------------------------------------------------------- /man/reapply.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/adam.R 3 | \name{reapply} 4 | \alias{reapply} 5 | \alias{reforecast} 6 | \title{Reapply the model with randomly generated initial parameters and produce forecasts} 7 | \usage{ 8 | reapply(object, nsim = 1000, bootstrap = FALSE, heuristics = NULL, ...) 9 | 10 | reforecast(object, h = 10, newdata = NULL, occurrence = NULL, 11 | interval = c("prediction", "confidence", "none"), level = 0.95, 12 | side = c("both", "upper", "lower"), cumulative = FALSE, nsim = 100, 13 | ...) 14 | } 15 | \arguments{ 16 | \item{object}{Model estimated using one of the functions of smooth package.} 17 | 18 | \item{nsim}{Number of paths to generate (number of simulations to do).} 19 | 20 | \item{bootstrap}{The logical, which determines, whether to use bootstrap for the 21 | covariance matrix of parameters or not.} 22 | 23 | \item{heuristics}{The value for proportion to use for heuristic estimation of the 24 | standard deviation of parameters. If \code{NULL}, it is not used.} 25 | 26 | \item{...}{Other parameters passed to \code{reapply()} and \code{mean()} functions in case of 27 | \code{reforecast} (\code{trim} parameter in \code{mean()} is set to 28 | 0.01 by default) and to \code{vcov} in case of \code{reapply}.} 29 | 30 | \item{h}{Forecast horizon.} 31 | 32 | \item{newdata}{The new data needed in order to produce forecasts.} 33 | 34 | \item{occurrence}{The vector containing the future occurrence variable 35 | (values in [0,1]), if it is known.} 36 | 37 | \item{interval}{What type of mechanism to use for interval construction. The options 38 | include \code{interval="none"}, \code{interval="prediction"} (prediction intervals) 39 | and \code{interval="confidence"} (intervals for the point forecast). The other options 40 | are not supported and do not make much sense for the refitted model.} 41 | 42 | \item{level}{Confidence level. Defines width of prediction interval.} 43 | 44 | \item{side}{Defines, whether to provide \code{"both"} sides of prediction 45 | interval or only \code{"upper"}, or \code{"lower"}.} 46 | 47 | \item{cumulative}{If \code{TRUE}, then the cumulative forecast and prediction 48 | interval are produced instead of the normal ones. This is useful for 49 | inventory control systems.} 50 | } 51 | \value{ 52 | \code{reapply()} returns object of the class "reapply", which contains: 53 | \itemize{ 54 | \item \code{timeElapsed} - Time elapsed for the code execution; 55 | \item \code{y} - The actual values; 56 | \item \code{states} - The array of states of the model; 57 | \item \code{refitted} - The matrix with fitted values, where columns correspond 58 | to different paths; 59 | \item \code{fitted} - The vector of fitted values (conditional mean); 60 | \item \code{model} - The name of the constructed model; 61 | \item \code{transition} - The array of transition matrices; 62 | \item \code{measurement} - The array of measurement matrices; 63 | \item \code{persistence} - The matrix of persistence vectors (paths in columns); 64 | \item \code{profile} - The array of profiles obtained by the end of each fit. 65 | } 66 | 67 | \code{reforecast()} returns the object of the class \link[smooth]{forecast.smooth}, 68 | which contains in addition to the standard list the variable \code{paths} - all 69 | simulated trajectories with h in rows, simulated future paths for each state in 70 | columns and different states (obtained from \code{reapply()} function) in the 71 | third dimension. 72 | } 73 | \description{ 74 | \code{reapply} function generates the parameters based on the values in the provided 75 | object and then reapplies the same model with those parameters to the data, getting 76 | the fitted paths and updated states. \code{reforecast} function uses those values 77 | in order to produce forecasts for the \code{h} steps ahead. 78 | } 79 | \details{ 80 | The main motivation of the function is to take the randomness due to the in-sample 81 | estimation of parameters into account when fitting the model and to propagate 82 | this randomness to the forecasts. The methods can be considered as a special case 83 | of recursive bootstrap. 84 | } 85 | \examples{ 86 | 87 | x <- rnorm(100,0,1) 88 | 89 | # Just as example. orders and lags do not return anything for ces() and es(). But modelType() does. 90 | ourModel <- adam(x, "ANN") 91 | refittedModel <- reapply(ourModel, nsim=50) 92 | plot(refittedModel) 93 | 94 | ourForecast <- reforecast(ourModel, nsim=50) 95 | 96 | } 97 | \seealso{ 98 | \link[smooth]{forecast.smooth} 99 | } 100 | \author{ 101 | Ivan Svetunkov, \email{ivan@svetunkov.com} 102 | } 103 | \keyword{models} 104 | \keyword{nonlinear} 105 | \keyword{regression} 106 | \keyword{smooth} 107 | \keyword{ts} 108 | \keyword{univar} 109 | -------------------------------------------------------------------------------- /man/reexports.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/adam.R, R/methods.R 3 | \docType{import} 4 | \name{reexports} 5 | \alias{reexports} 6 | \alias{xtable} 7 | \alias{accuracy} 8 | \title{Objects exported from other packages} 9 | \keyword{internal} 10 | \description{ 11 | These objects are imported from other packages. Follow the links 12 | below to see their documentation. 13 | 14 | \describe{ 15 | \item{generics}{\code{\link[generics]{accuracy}}} 16 | 17 | \item{xtable}{\code{\link[xtable]{xtable}}} 18 | }} 19 | 20 | -------------------------------------------------------------------------------- /man/rmultistep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/adam.R 3 | \name{rmultistep} 4 | \alias{rmultistep} 5 | \title{Multiple steps ahead forecast errors} 6 | \usage{ 7 | rmultistep(object, h = 10, ...) 8 | } 9 | \arguments{ 10 | \item{object}{Model estimated using one of the forecasting functions.} 11 | 12 | \item{h}{The forecasting horizon to use.} 13 | 14 | \item{...}{Currently nothing is accepted via ellipsis.} 15 | } 16 | \value{ 17 | The matrix with observations in rows and h steps ahead values in columns. 18 | So, the first row corresponds to the forecast produced from the 0th observation 19 | from 1 to h steps ahead. 20 | } 21 | \description{ 22 | The function extracts 1 to h steps ahead forecast errors from the model. 23 | } 24 | \details{ 25 | The errors correspond to the error term epsilon_t in the ETS models. Don't forget 26 | that different models make different assumptions about epsilon_t and / or 1+epsilon_t. 27 | } 28 | \examples{ 29 | 30 | x <- rnorm(100,0,1) 31 | ourModel <- adam(x) 32 | rmultistep(ourModel, h=13) 33 | 34 | } 35 | \seealso{ 36 | \link[stats]{residuals}, 37 | } 38 | \author{ 39 | Ivan Svetunkov, \email{ivan@svetunkov.com} 40 | } 41 | \keyword{models} 42 | \keyword{nonlinear} 43 | \keyword{regression} 44 | \keyword{smooth} 45 | \keyword{ts} 46 | \keyword{univar} 47 | -------------------------------------------------------------------------------- /man/sim.ces.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simces.R 3 | \name{sim.ces} 4 | \alias{sim.ces} 5 | \title{Simulate Complex Exponential Smoothing} 6 | \usage{ 7 | sim.ces(seasonality = c("none", "simple", "partial", "full"), obs = 10, 8 | nsim = 1, frequency = 1, a = NULL, b = NULL, initial = NULL, 9 | randomizer = c("rnorm", "rt", "rlaplace", "rs"), probability = 1, ...) 10 | } 11 | \arguments{ 12 | \item{seasonality}{The type of seasonality used in CES. Can be: \code{none} 13 | - No seasonality; \code{simple} - Simple seasonality, using lagged CES 14 | (based on \code{t-m} observation, where \code{m} is the seasonality lag); 15 | \code{partial} - Partial seasonality with real seasonal components 16 | (equivalent to additive seasonality); \code{full} - Full seasonality with 17 | complex seasonal components (can do both multiplicative and additive 18 | seasonality, depending on the data). First letter can be used instead of 19 | full words. Any seasonal CES can only be constructed for time series 20 | vectors.} 21 | 22 | \item{obs}{Number of observations in each generated time series.} 23 | 24 | \item{nsim}{Number of series to generate (number of simulations to do).} 25 | 26 | \item{frequency}{Frequency of generated data. In cases of seasonal models 27 | must be greater than 1.} 28 | 29 | \item{a}{First complex smoothing parameter. Should be a complex number. 30 | 31 | NOTE! CES is very sensitive to a and b values so it is advised to use values 32 | from previously estimated model.} 33 | 34 | \item{b}{Second complex smoothing parameter. Can be real if 35 | \code{seasonality="partial"}. In case of \code{seasonality="full"} must be 36 | complex number.} 37 | 38 | \item{initial}{A matrix with initial values for CES. In case with 39 | \code{seasonality="partial"} and \code{seasonality="full"} first two columns 40 | should contain initial values for non-seasonal components, repeated 41 | \code{frequency} times.} 42 | 43 | \item{randomizer}{Type of random number generator function used for error 44 | term. Defaults are: \code{rnorm}, \code{rt}, \code{rlaplace} and \code{rs}. 45 | \code{rlnorm} should be used for multiplicative models (e.g. ETS(M,N,N)). 46 | But any function from \link[stats]{Distributions} will do the trick if the 47 | appropriate parameters are passed. For example \code{rpois} with 48 | \code{lambda=2} can be used as well, but might result in weird values.} 49 | 50 | \item{probability}{Probability of occurrence, used for intermittent data 51 | generation. This can be a vector, implying that probability varies in time 52 | (in TSB or Croston style).} 53 | 54 | \item{...}{Additional parameters passed to the chosen randomizer. All the 55 | parameters should be passed in the order they are used in chosen randomizer. 56 | For example, passing just \code{sd=0.5} to \code{rnorm} function will lead 57 | to the call \code{rnorm(obs, mean=0.5, sd=1)}.} 58 | } 59 | \value{ 60 | List of the following values is returned: 61 | \itemize{ 62 | \item \code{model} - Name of CES model. 63 | \item \code{a} - Value of complex smoothing parameter a. If \code{nsim>1}, then 64 | this is a vector. 65 | \item \code{b} - Value of complex smoothing parameter b. If \code{seasonality="n"} 66 | or \code{seasonality="s"}, then this is equal to NULL. If \code{nsim>1}, 67 | then this is a vector. 68 | \item \code{initial} - Initial values of CES in a form of matrix. If \code{nsim>1}, 69 | then this is an array. 70 | \item \code{data} - Time series vector (or matrix if \code{nsim>1}) of the generated 71 | series. 72 | \item \code{states} - Matrix (or array if \code{nsim>1}) of states. States are in 73 | columns, time is in rows. 74 | \item \code{residuals} - Error terms used in the simulation. Either vector or matrix, 75 | depending on \code{nsim}. 76 | \item \code{occurrence} - Values of occurrence variable. Once again, can be either 77 | a vector or a matrix... 78 | \item \code{logLik} - Log-likelihood of the constructed model. 79 | } 80 | } 81 | \description{ 82 | Function generates data using CES with Single Source of Error as a data 83 | generating process. 84 | } 85 | \details{ 86 | For the information about the function, see the vignette: 87 | \code{vignette("simulate","smooth")} 88 | } 89 | \examples{ 90 | 91 | # Create 120 observations from CES(n). Generate 100 time series of this kind. 92 | x <- sim.ces("n",obs=120,nsim=100) 93 | 94 | # Generate similar thing for seasonal series of CES(s)_4 95 | x <- sim.ces("s",frequency=4,obs=80,nsim=100) 96 | 97 | # Estimate model and then generate 10 time series from it 98 | ourModel <- ces(rnorm(100,100,5)) 99 | simulate(ourModel,nsim=10) 100 | 101 | } 102 | \references{ 103 | \itemize{ 104 | \item Svetunkov, I., Kourentzes, N., & Ord, J. K. (2022). 105 | Complex exponential smoothing. Naval Research Logistics, 69(8), 106 | 1108–1123. https://doi.org/10.1002/nav.22074 107 | } 108 | } 109 | \seealso{ 110 | \code{\link[smooth]{sim.es}, \link[smooth]{sim.ssarima}, 111 | \link[smooth]{ces}, \link[stats]{Distributions}} 112 | } 113 | \author{ 114 | Ivan Svetunkov, \email{ivan@svetunkov.com} 115 | } 116 | \keyword{models} 117 | \keyword{nonlinear} 118 | \keyword{regression} 119 | \keyword{smooth} 120 | \keyword{ts} 121 | \keyword{univar} 122 | -------------------------------------------------------------------------------- /man/sim.gum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simgum.R 3 | \name{sim.gum} 4 | \alias{sim.gum} 5 | \title{Simulate Generalised Exponential Smoothing} 6 | \usage{ 7 | sim.gum(orders = c(1), lags = c(1), obs = 10, nsim = 1, 8 | frequency = 1, measurement = NULL, transition = NULL, 9 | persistence = NULL, initial = NULL, randomizer = c("rnorm", "rt", 10 | "rlaplace", "rs"), probability = 1, ...) 11 | } 12 | \arguments{ 13 | \item{orders}{Order of the model. Specified as vector of number of states 14 | with different lags. For example, \code{orders=c(1,1)} means that there are 15 | two states: one of the first lag type, the second of the second type.} 16 | 17 | \item{lags}{Defines lags for the corresponding orders. If, for example, 18 | \code{orders=c(1,1)} and lags are defined as \code{lags=c(1,12)}, then the 19 | model will have two states: the first will have lag 1 and the second will 20 | have lag 12. The length of \code{lags} must correspond to the length of 21 | \code{orders}.} 22 | 23 | \item{obs}{Number of observations in each generated time series.} 24 | 25 | \item{nsim}{Number of series to generate (number of simulations to do).} 26 | 27 | \item{frequency}{Frequency of generated data. In cases of seasonal models 28 | must be greater than 1.} 29 | 30 | \item{measurement}{Measurement vector \eqn{w}. If \code{NULL}, then 31 | estimated.} 32 | 33 | \item{transition}{Transition matrix \eqn{F}. Can be provided as a vector. 34 | Matrix will be formed using the default \code{matrix(transition,nc,nc)}, 35 | where \code{nc} is the number of components in state vector. If \code{NULL}, 36 | then estimated.} 37 | 38 | \item{persistence}{Persistence vector \eqn{g}, containing smoothing 39 | parameters. If \code{NULL}, then estimated.} 40 | 41 | \item{initial}{Vector of initial values for state matrix. If \code{NULL}, 42 | then generated using advanced, sophisticated technique - uniform 43 | distribution.} 44 | 45 | \item{randomizer}{Type of random number generator function used for error 46 | term. Defaults are: \code{rnorm}, \code{rt}, \code{rlaplace} and \code{rs}. 47 | \code{rlnorm} should be used for multiplicative models (e.g. ETS(M,N,N)). 48 | But any function from \link[stats]{Distributions} will do the trick if the 49 | appropriate parameters are passed. For example \code{rpois} with 50 | \code{lambda=2} can be used as well, but might result in weird values.} 51 | 52 | \item{probability}{Probability of occurrence, used for intermittent data 53 | generation. This can be a vector, implying that probability varies in time 54 | (in TSB or Croston style).} 55 | 56 | \item{...}{Additional parameters passed to the chosen randomizer. All the 57 | parameters should be passed in the order they are used in chosen randomizer. 58 | For example, passing just \code{sd=0.5} to \code{rnorm} function will lead 59 | to the call \code{rnorm(obs, mean=0.5, sd=1)}.} 60 | } 61 | \value{ 62 | List of the following values is returned: 63 | \itemize{ 64 | \item \code{model} - Name of GUM model. 65 | \item \code{measurement} - Matrix w. 66 | \item \code{transition} - Matrix F. 67 | \item \code{persistence} - Persistence vector. This is the place, where 68 | smoothing parameters live. 69 | \item \code{initial} - Initial values of GUM in a form of matrix. If \code{nsim>1}, 70 | then this is an array. 71 | \item \code{data} - Time series vector (or matrix if \code{nsim>1}) of the generated 72 | series. 73 | \item \code{states} - Matrix (or array if \code{nsim>1}) of states. States are in 74 | columns, time is in rows. 75 | \item \code{residuals} - Error terms used in the simulation. Either vector or matrix, 76 | depending on \code{nsim}. 77 | \item \code{occurrence} - Values of occurrence variable. Once again, can be either 78 | a vector or a matrix... 79 | \item \code{logLik} - Log-likelihood of the constructed model. 80 | } 81 | } 82 | \description{ 83 | Function generates data using GUM with Single Source of Error as a data 84 | generating process. 85 | } 86 | \details{ 87 | For the information about the function, see the vignette: 88 | \code{vignette("simulate","smooth")} 89 | } 90 | \examples{ 91 | 92 | # Create 120 observations from GUM(1[1]). Generate 100 time series of this kind. 93 | x <- sim.gum(orders=c(1),lags=c(1),obs=120,nsim=100) 94 | 95 | # Generate similar thing for seasonal series of GUM(1[1],1[4]]) 96 | x <- sim.gum(orders=c(1,1),lags=c(1,4),frequency=4,obs=80,nsim=100,transition=c(1,0,0.9,0.9)) 97 | 98 | # Estimate model and then generate 10 time series from it 99 | ourModel <- gum(rnorm(100,100,5)) 100 | simulate(ourModel,nsim=10) 101 | 102 | } 103 | \references{ 104 | \itemize{ 105 | \item Svetunkov I. (2023) Smooth forecasting with the smooth package in R. arXiv:2301.01790. 106 | \doi{10.48550/arXiv.2301.01790}. 107 | \item Svetunkov I. (2015 - Inf) "smooth" package for R - series of posts about the underlying 108 | models and how to use them: \url{https://openforecast.org/category/r-en/smooth/}. 109 | } 110 | } 111 | \seealso{ 112 | \code{\link[smooth]{sim.es}, \link[smooth]{sim.ssarima}, 113 | \link[smooth]{sim.ces}, \link[smooth]{gum}, \link[stats]{Distributions}} 114 | } 115 | \author{ 116 | Ivan Svetunkov, \email{ivan@svetunkov.com} 117 | } 118 | \keyword{models} 119 | \keyword{nonlinear} 120 | \keyword{regression} 121 | \keyword{smooth} 122 | \keyword{ts} 123 | \keyword{univar} 124 | -------------------------------------------------------------------------------- /man/sim.oes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simoes.R 3 | \name{sim.oes} 4 | \alias{sim.oes} 5 | \title{Simulate Occurrence Part of ETS model} 6 | \usage{ 7 | sim.oes(model = "MNN", obs = 10, nsim = 1, frequency = 1, 8 | occurrence = c("odds-ratio", "inverse-odds-ratio", "direct", "general"), 9 | bounds = c("usual", "admissible", "restricted"), randomizer = c("rlnorm", 10 | "rinvgauss", "rgamma", "rnorm"), persistence = NULL, phi = 1, 11 | initial = NULL, initialSeason = NULL, modelB = model, 12 | persistenceB = persistence, phiB = phi, initialB = initial, 13 | initialSeasonB = initialSeason, ...) 14 | } 15 | \arguments{ 16 | \item{model}{Type of ETS model according to [Hyndman et. al., 2008] 17 | taxonomy. Can consist of 3 or 4 chars: \code{ANN}, \code{AAN}, \code{AAdN}, 18 | \code{AAA}, \code{AAdA}, \code{MAdM} etc. The conventional oETS model assumes 19 | that the error term is positive, so "MZZ" models are recommended for this. 20 | If you use additive error models, then the function will exponentiate the 21 | obtained values before transforming them and getting the probability. This 22 | is the type of model A.} 23 | 24 | \item{obs}{Number of observations in each generated time series.} 25 | 26 | \item{nsim}{Number of series to generate (number of simulations to do).} 27 | 28 | \item{frequency}{Frequency of generated data. In cases of seasonal models 29 | must be greater than 1.} 30 | 31 | \item{occurrence}{Type of occurrence model. See \code{vignette("oes","smooth")} 32 | for details.} 33 | 34 | \item{bounds}{Type of bounds to use for persistence vector if values are 35 | generated. \code{"usual"} - bounds from p.156 by Hyndman et. al., 2008. 36 | \code{"restricted"} - similar to \code{"usual"} but with upper bound equal 37 | to 0.3. \code{"admissible"} - bounds from tables 10.1 and 10.2 of Hyndman 38 | et. al., 2008. Using first letter of the type of bounds also works. These 39 | bounds are also used for multiplicative models, but the models are much 40 | more restrictive, so weird results might be obtained. Be careful!} 41 | 42 | \item{randomizer}{Type of random number generator function used for error 43 | term. It is advised to use \code{rlnorm()} or \code{rinvgauss()} in case of 44 | multiplicative error models. If a randomiser is used, it is advised to 45 | specify the parameters in the ellipsis.} 46 | 47 | \item{persistence}{Persistence vector, which includes all the smoothing 48 | parameters. Must correspond to the chosen model. The maximum length is 3: 49 | level, trend and seasonal smoothing parameters. If \code{NULL}, values are 50 | generated.} 51 | 52 | \item{phi}{Value of damping parameter. If trend is not chosen in the model, 53 | the parameter is ignored.} 54 | 55 | \item{initial}{Vector of initial states of level and trend. The maximum 56 | length is 2. If \code{NULL}, values are generated.} 57 | 58 | \item{initialSeason}{Vector of initial states for seasonal coefficients. 59 | Should have length equal to \code{frequency} parameter. If \code{NULL}, 60 | values are generated.} 61 | 62 | \item{modelB}{Type of model B. This is used in \code{occurrence="general"} 63 | and \code{occurrence="inverse-odds-ratio"}.} 64 | 65 | \item{persistenceB}{The persistence vector for the model B.} 66 | 67 | \item{phiB}{Value of damping parameter for the model B.} 68 | 69 | \item{initialB}{Vector of initial states of level and trend for the model B.} 70 | 71 | \item{initialSeasonB}{Vector of initial states for seasonal coefficients for 72 | the model B.} 73 | 74 | \item{...}{Additional parameters passed to the chosen randomizer. All the 75 | parameters should be passed in the order they are used in chosen randomizer. 76 | Both model A and model B share the same parameters for the randomizer.} 77 | } 78 | \value{ 79 | List of the following values is returned: 80 | \itemize{ 81 | \item \code{model} - Name of ETS model. 82 | \item \code{modelA} - Model A, generated using \code{sim.es()} function; 83 | \item \code{modelB} - Model B, generated using \code{sim.es()} function; 84 | \item \code{probability} - The value of probability generated by the model; 85 | \item \code{occurrence} - Type of occurrence used in the model; 86 | \item \code{logLik} - Log-likelihood of the constructed model. 87 | } 88 | } 89 | \description{ 90 | Function generates data using ETS with Single Source of Error as a data 91 | generating process for the demand occurrence. As the main output it produces 92 | probabilities of occurrence. 93 | } 94 | \details{ 95 | For the information about the function, see the vignette: 96 | \code{vignette("simulate","smooth")} 97 | } 98 | \examples{ 99 | 100 | # This example uses rinvgauss function from statmod package. 101 | \donttest{oETSMNNIG <- sim.oes(model="MNN",frequency=12,obs=60, 102 | randomizer="rinvgauss",mean=1,dispersion=0.5)} 103 | 104 | # A simpler example with log normal distribution 105 | oETSMNNlogN <- sim.oes(model="MNN",frequency=12,obs=60,initial=1, 106 | randomizer="rlnorm",meanlog=0,sdlog=0.1) 107 | 108 | } 109 | \references{ 110 | \itemize{ 111 | \item Svetunkov, I., 2023. Smooth Forecasting with the Smooth Package in R. arXiv. 112 | \doi{10.48550/arXiv.2301.01790} 113 | \item Snyder, R. D., 1985. Recursive Estimation of Dynamic Linear Models. 114 | Journal of the Royal Statistical Society, Series B (Methodological) 47 (2), 272-276. 115 | \item Hyndman, R.J., Koehler, A.B., Ord, J.K., and Snyder, R.D. (2008) 116 | Forecasting with exponential smoothing: the state space approach, 117 | Springer-Verlag. \doi{10.1007/978-3-540-71918-2}. 118 | } 119 | } 120 | \seealso{ 121 | \code{\link[smooth]{oes}, \link[smooth]{sim.es}, \link[stats]{Distributions}} 122 | } 123 | \author{ 124 | Ivan Svetunkov, \email{ivan@svetunkov.com} 125 | } 126 | \keyword{models} 127 | \keyword{nonlinear} 128 | \keyword{regression} 129 | \keyword{smooth} 130 | \keyword{ts} 131 | \keyword{univar} 132 | -------------------------------------------------------------------------------- /man/sim.sma.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simsma.R 3 | \name{sim.sma} 4 | \alias{sim.sma} 5 | \title{Simulate Simple Moving Average} 6 | \usage{ 7 | sim.sma(order = NULL, obs = 10, nsim = 1, frequency = 1, 8 | initial = NULL, randomizer = c("rnorm", "rt", "rlaplace", "rs"), 9 | probability = 1, ...) 10 | } 11 | \arguments{ 12 | \item{order}{Order of the modelled series. If omitted, then a random order from 1 to 100 is selected.} 13 | 14 | \item{obs}{Number of observations in each generated time series.} 15 | 16 | \item{nsim}{Number of series to generate (number of simulations to do).} 17 | 18 | \item{frequency}{Frequency of generated data. In cases of seasonal models 19 | must be greater than 1.} 20 | 21 | \item{initial}{Vector of initial states for the model. If \code{NULL}, 22 | values are generated.} 23 | 24 | \item{randomizer}{Type of random number generator function used for error 25 | term. Defaults are: \code{rnorm}, \code{rt}, \code{rlaplace} and \code{rs}. 26 | \code{rlnorm} should be used for multiplicative models (e.g. ETS(M,N,N)). 27 | But any function from \link[stats]{Distributions} will do the trick if the 28 | appropriate parameters are passed. For example \code{rpois} with 29 | \code{lambda=2} can be used as well, but might result in weird values.} 30 | 31 | \item{probability}{Probability of occurrence, used for intermittent data 32 | generation. This can be a vector, implying that probability varies in time 33 | (in TSB or Croston style).} 34 | 35 | \item{...}{Additional parameters passed to the chosen randomizer. All the 36 | parameters should be passed in the order they are used in chosen randomizer. 37 | For example, passing just \code{sd=0.5} to \code{rnorm} function will lead 38 | to the call \code{rnorm(obs, mean=0.5, sd=1)}.} 39 | } 40 | \value{ 41 | List of the following values is returned: 42 | \itemize{ 43 | \item \code{model} - Name of SMA model. 44 | \item \code{data} - Time series vector (or matrix if \code{nsim>1}) of the generated 45 | series. 46 | \item \code{states} - Matrix (or array if \code{nsim>1}) of states. States are in 47 | columns, time is in rows. 48 | \item \code{initial} - Vector (or matrix) of initial values. 49 | \item \code{probability} - vector of probabilities used in the simulation. 50 | \item \code{intermittent} - type of the intermittent model used. 51 | \item \code{residuals} - Error terms used in the simulation. Either vector or matrix, 52 | depending on \code{nsim}. 53 | \item \code{occurrence} - Values of occurrence variable. Once again, can be either 54 | a vector or a matrix... 55 | \item \code{logLik} - Log-likelihood of the constructed model. 56 | } 57 | } 58 | \description{ 59 | Function generates data using SMA in a Single Source of Error state space 60 | model as a data generating process. 61 | } 62 | \details{ 63 | For the information about the function, see the vignette: 64 | \code{vignette("simulate","smooth")} 65 | } 66 | \examples{ 67 | 68 | # Create 40 observations of quarterly data using AAA model with errors from normal distribution 69 | sma10 <- sim.sma(order=10,frequency=4,obs=40,randomizer="rnorm",mean=0,sd=100) 70 | 71 | } 72 | \references{ 73 | \itemize{ 74 | \item Svetunkov, I., 2023. Smooth Forecasting with the Smooth Package in R. arXiv. 75 | \doi{10.48550/arXiv.2301.01790} 76 | \item Snyder, R. D., 1985. Recursive Estimation of Dynamic Linear Models. 77 | Journal of the Royal Statistical Society, Series B (Methodological) 47 (2), 272-276. 78 | \item Hyndman, R.J., Koehler, A.B., Ord, J.K., and Snyder, R.D. (2008) 79 | Forecasting with exponential smoothing: the state space approach, 80 | Springer-Verlag. \doi{10.1007/978-3-540-71918-2}. 81 | } 82 | } 83 | \seealso{ 84 | \code{\link[smooth]{es}, \link[stats]{ts}, \link[stats]{Distributions}} 85 | } 86 | \author{ 87 | Ivan Svetunkov, \email{ivan@svetunkov.com} 88 | } 89 | \keyword{models} 90 | \keyword{nonlinear} 91 | \keyword{regression} 92 | \keyword{smooth} 93 | \keyword{ts} 94 | \keyword{univar} 95 | -------------------------------------------------------------------------------- /man/smooth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/smooth-package.R 3 | \name{smooth} 4 | \alias{smooth} 5 | \alias{smooth-package} 6 | \title{Smooth package} 7 | \description{ 8 | Package contains functions implementing Single Source of Error state space models for 9 | purposes of time series analysis and forecasting. 10 | } 11 | \details{ 12 | \tabular{ll}{ Package: \tab smooth\cr Type: \tab Package\cr Date: \tab 13 | 2016-01-27 - Inf\cr License: \tab GPL-2 \cr } The following functions are 14 | included in the package: 15 | \itemize{ 16 | \item \link[smooth]{es} - Exponential Smoothing in Single Source of Errors State Space form. 17 | \item \link[smooth]{ces} - Complex Exponential Smoothing. 18 | \item \link[smooth]{gum} - Generalised Exponential Smoothing. 19 | \item \link[smooth]{ssarima} - SARIMA in state space framework. 20 | % \item \link[smooth]{nus} - Non-Uniform Smoothing. 21 | \item \link[smooth]{auto.ces} - Automatic selection between seasonal and non-seasonal CES. 22 | \item \link[smooth]{auto.ssarima} - Automatic selection of ARIMA orders. 23 | \item \link[smooth]{sma} - Simple Moving Average in state space form. 24 | \item \link[smooth]{smoothCombine} - the function that combines forecasts from es(), 25 | ces(), gum(), ssarima() and sma() functions. 26 | \item \link[smooth]{cma} - Centered Moving Average. This is for smoothing time series, 27 | not for forecasting. 28 | \item \link[smooth]{sim.es} - simulate time series using ETS as a model. 29 | \item \link[smooth]{sim.ces} - simulate time series using CES as a model. 30 | \item \link[smooth]{sim.ssarima} - simulate time series using SARIMA as a model. 31 | \item \link[smooth]{sim.gum} - simulate time series using GUM as a model. 32 | \item \link[smooth]{sim.sma} - simulate time series using SMA. 33 | \item \link[smooth]{sim.oes} - simulate time series based on occurrence part of ETS model. 34 | \item \link[smooth]{oes} - occurrence part of the intermittent state space model. 35 | } 36 | There are also several methods implemented in the package for the classes 37 | "smooth" and "smooth.sim": 38 | \itemize{ 39 | \item \link[smooth]{orders} - extracts orders of the fitted model. 40 | \item lags - extracts lags of the fitted model. 41 | \item modelType - extracts type of the fitted model. 42 | \item forecast - produces forecast using provided model. 43 | \item \link[smooth]{multicov} - returns covariance matrix of multiple steps ahead forecast errors. 44 | \item \link[smooth]{pls} - returns Prediction Likelihood Score. 45 | \item \link[greybox]{nparam} - returns number of the estimated parameters. 46 | \item fitted - extracts fitted values from provided model. 47 | \item getResponse - returns actual values from the provided model. 48 | \item residuals - extracts residuals of provided model. 49 | \item plot - plots either states of the model or produced forecast (depending on what object 50 | is passed). 51 | \item simulate - uses sim functions (\link[smooth]{sim.es}, \link[smooth]{sim.ces}, 52 | \link[smooth]{sim.ssarima}, \link[smooth]{sim.gum}, \link[smooth]{sim.sma} and 53 | \link[smooth]{sim.oes}) in order to simulate data using the provided object. 54 | \item summary - provides summary of the object. 55 | \item AICc, BICc - return, guess what... 56 | } 57 | } 58 | \examples{ 59 | 60 | \donttest{y <- ts(rnorm(100,10,3), frequency=12) 61 | 62 | adam(y, h=20, holdout=TRUE) 63 | es(y, h=20, holdout=TRUE) 64 | gum(y, h=20, holdout=TRUE) 65 | auto.ces(y, h=20, holdout=TRUE) 66 | auto.ssarima(y, h=20, holdout=TRUE)} 67 | 68 | } 69 | \references{ 70 | \itemize{ 71 | \item Svetunkov, I., 2023. Smooth Forecasting with the Smooth Package in R. arXiv. 72 | \doi{10.48550/arXiv.2301.01790} 73 | \item Snyder, R. D., 1985. Recursive Estimation of Dynamic Linear Models. 74 | Journal of the Royal Statistical Society, Series B (Methodological) 47 (2), 272-276. 75 | \item Hyndman, R.J., Koehler, A.B., Ord, J.K., and Snyder, R.D. (2008) 76 | Forecasting with exponential smoothing: the state space approach, 77 | Springer-Verlag. \doi{10.1007/978-3-540-71918-2}. 78 | } 79 | 80 | \itemize{ 81 | \item Svetunkov, I., Boylan, J.E., 2023a. iETS: State Space Model for 82 | Intermittent Demand Forecastings. International Journal of Production 83 | Economics. 109013. \doi{10.1016/j.ijpe.2023.109013} 84 | \item Teunter R., Syntetos A., Babai Z. (2011). Intermittent demand: 85 | Linking forecasting to inventory obsolescence. European Journal of 86 | Operational Research, 214, 606-615. 87 | \item Croston, J. (1972) Forecasting and stock control for intermittent 88 | demands. Operational Research Quarterly, 23(3), 289-303. 89 | } 90 | 91 | \itemize{ 92 | \item Svetunkov, I., Kourentzes, N., & Ord, J. K. (2022). 93 | Complex exponential smoothing. Naval Research Logistics, 69(8), 94 | 1108–1123. https://doi.org/10.1002/nav.22074 95 | } 96 | 97 | \itemize{ 98 | \item Svetunkov I. (2023) Smooth forecasting with the smooth package in R. arXiv:2301.01790. 99 | \doi{10.48550/arXiv.2301.01790}. 100 | \item Svetunkov I. (2015 - Inf) "smooth" package for R - series of posts about the underlying 101 | models and how to use them: \url{https://openforecast.org/category/r-en/smooth/}. 102 | } 103 | 104 | \itemize{ 105 | \item Kolassa, S. (2011) Combining exponential smoothing forecasts using Akaike 106 | weights. International Journal of Forecasting, 27, pp 238 - 251. 107 | \item Svetunkov, I., Boylan, J.E., 2023b. Staying Positive: Challenges and 108 | Solutions in Using Pure Multiplicative ETS Models. IMA Journal of 109 | Management Mathematics. p. 403-425. \doi{10.1093/imaman/dpad028} 110 | } 111 | 112 | \itemize{ 113 | \item Taylor, J.W. and Bunn, D.W. (1999) A Quantile Regression Approach to 114 | Generating Prediction Intervals. Management Science, Vol 45, No 2, pp 115 | 225-237. 116 | \item Lichtendahl Kenneth C., Jr., Grushka-Cockayne Yael, Winkler 117 | Robert L., (2013) Is It Better to Average Probabilities or 118 | Quantiles? Management Science 59(7):1594-1611. DOI: 119 | \doi{10.1287/mnsc.1120.1667} 120 | } 121 | } 122 | \seealso{ 123 | \code{\link[greybox]{forecast}, \link[smooth]{es}, 124 | \link[smooth]{ssarima}, \link[smooth]{ces}, \link[smooth]{gum}} 125 | } 126 | \author{ 127 | Ivan Svetunkov, \email{ivan@svetunkov.com} 128 | } 129 | \keyword{models} 130 | \keyword{nonlinear} 131 | \keyword{regression} 132 | \keyword{smooth} 133 | \keyword{ts} 134 | \keyword{univar} 135 | -------------------------------------------------------------------------------- /man/sowhat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sowhat.R 3 | \name{sowhat} 4 | \alias{sowhat} 5 | \title{Function returns the ultimate answer to any question} 6 | \usage{ 7 | sowhat(...) 8 | } 9 | \arguments{ 10 | \item{...}{Any number of variables or string with a question.} 11 | } 12 | \value{ 13 | It doesn't return any value, only messages. So what? 14 | } 15 | \description{ 16 | You need a description? So what? 17 | } 18 | \details{ 19 | You need details? So what? 20 | } 21 | \examples{ 22 | 23 | x <- rnorm(10000,0,1); 24 | sowhat(x); 25 | 26 | sowhat("What's the meaning of life?") 27 | 28 | sowhat("I don't have a girlfriend.") 29 | 30 | } 31 | \references{ 32 | \itemize{ 33 | \item\href{https://en.wiktionary.org/wiki/so_what}{Sowhat?} 34 | \item\href{https://www.youtube.com/watch?v=FJfFZqTlWrQ}{Sowhat?} 35 | \item\href{https://en.wikipedia.org/wiki/Douglas_Adams}{42} 36 | } 37 | } 38 | \seealso{ 39 | Nowwhat (to be implemented), 40 | } 41 | \author{ 42 | Ivan Svetunkov, \email{ivan@svetunkov.com} 43 | } 44 | \keyword{42} 45 | \keyword{sowhat} 46 | -------------------------------------------------------------------------------- /python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set(CMAKE_CXX_STANDARD 17) 4 | set(CMAKE_CXX_STANDARD_REQUIRED True) 5 | set(CMAKE_CXX_EXTENSIONS OFF) 6 | 7 | project(smooth VERSION 0.0.1) 8 | 9 | if(SKBUILD) 10 | message(STATUS "The project is built using scikit-build") 11 | endif() 12 | 13 | # Pybind11 14 | find_package(pybind11 REQUIRED) 15 | 16 | # CARMA 17 | ADD_SUBDIRECTORY(../src/libs/carma carma) 18 | 19 | # BLAS and LAPACK. Needed by Armadillo 20 | find_package(BLAS) 21 | find_package(LAPACK) 22 | if(LAPACK_FOUND AND BLAS_FOUND) 23 | set(lapackblas_libraries ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES}) 24 | else() 25 | # IS: This is where they are on my system. This might change from one OS to another 26 | set(lapackblas_libraries "/usr/lib/x86_64-linux-gnu/") 27 | endif() 28 | 29 | # Armadillo 30 | find_package(armadillo) 31 | IF(NOT ARMADILLO_FOUND) 32 | set(ARMADILLO_INCLUDE_DIRS "/usr/lib/") 33 | ENDIF() 34 | include_directories(${ARMADILLO_INCLUDE_DIRS}) 35 | 36 | # Adam General 37 | pybind11_add_module(_adam_general ../src/python_examples/adamGeneral.cpp) 38 | target_include_directories(_adam_general PRIVATE ../src/python_examples/.) 39 | target_link_libraries(_adam_general PRIVATE carma::carma ${ARMADILLO_LIBRARIES} ${lapackblas_libraries}) 40 | install(TARGETS _adam_general DESTINATION smooth/adam_general) 41 | 42 | 43 | # Old experimental stuff by Leo 44 | # code to add the pybind11 cpp module, look at demo project 45 | # (https://github.com/ltsaprounis/python-cpp-experiments/tree/main) for details. 46 | #pybind11_add_module(_my_linalg ../src/python_examples/my_linalg.cpp) 47 | 48 | # add CARMA as a subdirectory 49 | #add_subdirectory(../src/libs/carma build) 50 | #target_link_libraries(_my_linalg 51 | # PRIVATE carma::carma 52 | # ${ARMADILLO_LIBRARIES} 53 | #) 54 | 55 | # install(TARGETS _my_linalg DESTINATION smooth/my_linalg) 56 | 57 | -------------------------------------------------------------------------------- /python/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all lint test install environment 2 | 3 | SRC_DIR = smooth 4 | 5 | lint: 6 | flake8 $(SRC_DIR) 7 | pydocstyle $(SRC_DIR) 8 | 9 | test: 10 | pytest $(SRC_DIR) 11 | 12 | install: 13 | pip install -e ".[dev]" 14 | 15 | environment: 16 | (\ 17 | echo "> Creating venv"; \ 18 | python -m venv .venv; \ 19 | source .venv/bin/activate; \ 20 | echo "> Installing local package in editable mode"; \ 21 | pip install -e ".[dev]"; \ 22 | echo "> Making venv available in jupyter notebooks"; \ 23 | python -m ipykernel install --name=$(SRC_DIR); \ 24 | jupyter kernelspec list; \ 25 | echo "> Installing pre-commit"; \ 26 | pre-commit install; \ 27 | ) 28 | 29 | clean: 30 | echo "> Removing virtual environment" 31 | rm -r .venv 32 | echo "> Uninstalling from jupyter" 33 | jupyter kernelspec uninstall $(SRC_DIR) 34 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # PY-SMOOTH 2 | Python version of smooth. 3 | 4 | **⚠️WORK IN PROGRESS⚠️** 5 | 6 | # Notes: 7 | 8 | 1. To build the project using [scikit-build-core](https://github.com/scikit-build/scikit-build-core) simply do `pip install -e .` 9 | 2. The files in python/smooth/mylinalg and src/my_linalg.cpp are example files for carma and pybind11 and will be removed later. 10 | 11 | 12 | # TODOs: 13 | - [X] use scikit-build-core to compile the C++ modules 14 | - [ ] (TBC) Refactor src code to use armadillo instead of rcpparmadillo in common Cpp code. 15 | - [ ] CI pipelines for tests 16 | - [ ] Add sphinx docs for python package 17 | - [ ] Check how to automate the Armadillo installation either as a github submodule or using [cmake's FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html#fetchcontent) like in [carma](https://github.com/RUrlus/carma/blob/2fbc2e6faf2e40e41003c06cbb13744405732b5f/integration_test/CMakeLists.txt#L36) 18 | -------------------------------------------------------------------------------- /python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["scikit-build-core>=0.3.3", "pybind11", "numpy>=1.14"] 3 | build-backend = "scikit_build_core.build" 4 | 5 | [project] 6 | name = "smooth" 7 | version = "0.0.1" 8 | description = "Python vesrion of the smooth forecasting library" 9 | readme = "README.md" 10 | requires-python = ">=3.8,<3.11" 11 | dependencies = ["pybind11[global]>=2.6.0", "numpy>=1.14"] 12 | 13 | [project.optional-dependencies] 14 | dev = ["pytest", "ruff", "pre-commit", "ipykernel"] 15 | 16 | [tool.scikit-build] 17 | # wheel.expand-macos-universal-tags = true 18 | build-dir = "build" 19 | logging.level = "INFO" 20 | ninja.make-fallback = true 21 | # This activates verbose builds 22 | cmake.verbose = true 23 | ninja.minimum-version = "1.5" 24 | cmake.minimum-version = "3.25" 25 | 26 | [tool.ruff] 27 | # Exclude a variety of commonly ignored directories. 28 | exclude = [ 29 | ".bzr", 30 | ".direnv", 31 | ".eggs", 32 | ".git", 33 | ".git-rewrite", 34 | ".hg", 35 | ".mypy_cache", 36 | ".nox", 37 | ".pants.d", 38 | ".pytype", 39 | ".ruff_cache", 40 | ".svn", 41 | ".tox", 42 | ".venv", 43 | "__pypackages__", 44 | "_build", 45 | "buck-out", 46 | "build", 47 | "dist", 48 | "node_modules", 49 | "venv", 50 | "tools/cookiecutter_templates", 51 | ] 52 | 53 | # Same as Black. 54 | line-length = 88 55 | indent-width = 4 56 | 57 | # Assume Python 3.8 58 | target-version = "py38" 59 | 60 | [tool.ruff.lint] 61 | # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. 62 | # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or 63 | # McCabe complexity (`C901`) by default. 64 | # Rules for ruff are found here: https://docs.astral.sh/ruff/rules/ 65 | select = [ 66 | "E4", 67 | "E7", 68 | "E9", 69 | "E501", 70 | "F", 71 | "I", # isort rules 72 | "N", # PEP-8 naming rules 73 | ] 74 | ignore = [ 75 | # uppercase names are used for matrices 76 | "N803", # allow uppercase argument names 77 | "N806", # allow uppercase variable names 78 | ] 79 | 80 | # Allow fix for all enabled rules (when `--fix`) is provided. 81 | fixable = ["ALL"] 82 | unfixable = [] 83 | 84 | # Allow unused variables when underscore-prefixed. 85 | dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" 86 | 87 | [tool.ruff.format] 88 | # Like Black, use double quotes for strings. 89 | quote-style = "double" 90 | 91 | # Like Black, indent with spaces, rather than tabs. 92 | indent-style = "space" 93 | 94 | # Like Black, respect magic trailing commas. 95 | skip-magic-trailing-comma = false 96 | 97 | # Like Black, automatically detect the appropriate line ending. 98 | line-ending = "auto" 99 | -------------------------------------------------------------------------------- /python/setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | # inline with Black code formatter 3 | max-line-length = 88 4 | 5 | [pydocstyle] 6 | convention=numpy 7 | add-ignore = 8 | # First line should end with a period 9 | D400, 10 | # First line should be in imperative mood 11 | D401, 12 | # __init__.py can be empty 13 | D104 14 | # ignore test files and the init in the 15 | match = (?!test_).*\.py 16 | -------------------------------------------------------------------------------- /python/smooth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/config-i1/smooth/c529c51c1aa221fd49117f17e68064b57d2ae9ff/python/smooth/__init__.py -------------------------------------------------------------------------------- /python/smooth/adam_general/__init__.py: -------------------------------------------------------------------------------- 1 | from ._adam_general import adam_fitter 2 | 3 | __all__ = ["adam_fitter"] 4 | -------------------------------------------------------------------------------- /python/smooth/adam_general/adam_profile.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def adam_profile_creator( 5 | lags_model_all, lags_model_max, obs_all, lags=None, y_index=None, y_classes=None 6 | ): 7 | """ 8 | Creates recent profile and the lookup table for adam. 9 | Parameters: 10 | lagsModelAll (list): All lags used in the model for ETS + ARIMA + xreg. 11 | lagsModelMax (int): The maximum lag used in the model. 12 | obsAll (int): Number of observations to create. 13 | lags (list): The original lags provided by user (optional). 14 | yIndex (list): The indices needed to get the specific dates (optional). 15 | yClasses (list): The class used for the actual data (optional). 16 | Returns: 17 | dict: A dictionary with 'recent' (profilesRecentTable) and 'lookup' 18 | (indexLookupTable) as keys. 19 | """ 20 | # Initialize matrices 21 | profiles_recent_table = np.zeros((len(lags_model_all), lags_model_max)) 22 | index_lookup_table = np.ones((len(lags_model_all), obs_all + lags_model_max)) 23 | profile_indices = ( 24 | np.arange(1, lags_model_max * len(lags_model_all) + 1) 25 | .reshape(-1, len(lags_model_all)) 26 | .T 27 | ) 28 | 29 | # Update matrices based on lagsModelAll 30 | for i, lag in enumerate(lags_model_all): 31 | # Create the matrix with profiles based on the provided lags. 32 | # For every row, fill the first 'lag' elements from 1 to lag 33 | profiles_recent_table[i, : lag[0]] = np.arange(1, lag[0] + 1) 34 | 35 | # For the i-th row in indexLookupTable, fill with a repeated sequence starting 36 | # from lagsModelMax to the end of the row. 37 | # The repeated sequence is the i-th row of profileIndices, repeated enough times 38 | # to cover 'obsAll' observations. 39 | # '- 1' at the end adjusts these values to Python's zero-based indexing. 40 | index_lookup_table[i, lags_model_max : (lags_model_max + obs_all)] = ( 41 | np.tile( 42 | profile_indices[i, : lags_model_all[i][0]], 43 | int(np.ceil(obs_all / lags_model_all[i][0])), 44 | )[0:obs_all] 45 | - 1 46 | ) 47 | 48 | # Extract unique values from from lagsModelMax to lagsModelMax + obsAll of 49 | # indexLookupTable 50 | unique_values = np.unique( 51 | index_lookup_table[i, lags_model_max : lags_model_max + obs_all] # noqa 52 | ) 53 | 54 | # fix the head of teh data before the sample starts 55 | # Repeat the unique values lagsModelMax times and then trim the sequence to only 56 | # keep the first lagsModelMax elements 57 | index_lookup_table[i, :lags_model_max] = np.tile(unique_values, lags_model_max)[ 58 | -lags_model_max: 59 | ] 60 | 61 | # Convert to int! 62 | index_lookup_table = index_lookup_table.astype(int) 63 | 64 | # Note: I skip andling of special cases (e.g., daylight saving time, leap years) 65 | return { 66 | "recent": np.array(profiles_recent_table, dtype="float64"), 67 | "lookup": np.array(index_lookup_table, dtype="int64"), 68 | } 69 | -------------------------------------------------------------------------------- /python/smooth/adam_general/core/__init__.py: -------------------------------------------------------------------------------- 1 | # lol -------------------------------------------------------------------------------- /python/smooth/adam_general/core/sma.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from smooth.adam_general._adam_general import adam_fitter, adam_forecaster 4 | from smooth.adam_general.adam_profile import adam_profile_creator 5 | 6 | 7 | def sma(y, order=1, h=10, holdout=False): 8 | """SMA""" 9 | y = y.astype(np.float64) 10 | 11 | # ic = lambda e: np.sum(e**2) 12 | obs_all = len(y) + h * (1 - holdout) 13 | obs_in_sample = len(y) - h * holdout 14 | y_in_sample = y 15 | 16 | E_type = "A" 17 | T_type = "N" 18 | S_type = "N" 19 | 20 | components_num_ETS = 0 21 | components_num_ETS_seasonal = 0 22 | xreg_number = 0 23 | constant_required = False 24 | ot = np.ones_like(y_in_sample) 25 | 26 | def creator_sma(order): 27 | # lags_model_all = np.ones(shape=(order, 1)) 28 | # This needs to be a vector of values 29 | lags_model_all = np.arange(1, order + 1, dtype="int32").reshape(order, 1) 30 | lags_model_max = int(max(lags_model_all)) 31 | obs_states = obs_in_sample + lags_model_max 32 | 33 | profiles_recent_table, index_lookup_table = adam_profile_creator( 34 | lags_model_all=lags_model_all, 35 | lags_model_max=lags_model_max, 36 | obs_all=obs_all, 37 | ).values() 38 | 39 | # # This needs to be generated by a profileCreator() function 40 | # profiles_recent_table = np.mean(y_in_sample[0 : (order - 1)]) * np.ones( 41 | # shape=(order, lags_model_max), dtype=np.float64 42 | # ) 43 | 44 | # # This as well... 45 | # index_lookup_table = np.tile( 46 | # np.arange(order), (obs_all + lags_model_max, 1) 47 | # ).T 48 | 49 | mat_F = np.ones((order, order)) / order 50 | mat_Wt = np.ones((obs_in_sample, order)) 51 | 52 | vec_G = np.ones(order) / order 53 | # matVt = np.zeros((order, obs_states)) 54 | mat_Vt = np.empty((order, obs_states)) 55 | # matVt.fill(np.nan) 56 | 57 | adam_fitted = adam_fitter( 58 | matrixVt=mat_Vt, 59 | matrixWt=mat_Wt, 60 | matrixF=mat_F, 61 | vectorG=vec_G, 62 | lags=lags_model_all, 63 | indexLookupTable=index_lookup_table, 64 | profilesRecent=profiles_recent_table, 65 | E=E_type, 66 | T=T_type, 67 | S=S_type, 68 | nNonSeasonal=components_num_ETS, 69 | nSeasonal=components_num_ETS_seasonal, 70 | nArima=order, 71 | nXreg=xreg_number, 72 | constant=constant_required, 73 | vectorYt=y_in_sample, 74 | vectorOt=ot, 75 | backcast=True, 76 | ) 77 | 78 | fitted_args = dict( 79 | matrixVt=mat_Vt, 80 | matrixWt=mat_Wt, 81 | matrixF=mat_F, 82 | vectorG=vec_G, 83 | lags=lags_model_all, 84 | indexLookupTable=index_lookup_table, 85 | profilesRecent=profiles_recent_table, 86 | E=E_type, 87 | T=T_type, 88 | S=S_type, 89 | nNonSeasonal=components_num_ETS, 90 | nSeasonal=components_num_ETS_seasonal, 91 | nArima=order, 92 | nXreg=xreg_number, 93 | constant=constant_required, 94 | vectorYt=y_in_sample, 95 | vectorOt=ot, 96 | backcast=True, 97 | ) 98 | 99 | return adam_fitted, fitted_args 100 | 101 | sma_fitted, fitted_args = creator_sma(order=order) 102 | 103 | # need to convert some inputs to the expected dtypes. This is a temporary fix. 104 | fitted_args["lags"] = np.array(fitted_args["lags"], dtype="uint64") 105 | fitted_args["indexLookupTable"] = np.array( 106 | fitted_args["indexLookupTable"], dtype="uint64" 107 | ) 108 | 109 | sma_forecast = adam_forecaster( 110 | matrixWt=fitted_args["matrixWt"], 111 | matrixF=fitted_args["matrixF"], 112 | lags=fitted_args["lags"], 113 | indexLookupTable=fitted_args["indexLookupTable"], 114 | profilesRecent=sma_fitted["profile"], 115 | E=fitted_args["E"], 116 | T=fitted_args["T"], 117 | S=fitted_args["S"], 118 | nNonSeasonal=fitted_args["nNonSeasonal"], 119 | nSeasonal=fitted_args["nSeasonal"], 120 | nArima=fitted_args["nArima"], 121 | nXreg=fitted_args["nXreg"], 122 | constant=fitted_args["constant"], 123 | horizon=h, 124 | ) 125 | 126 | return sma_forecast 127 | -------------------------------------------------------------------------------- /python/smooth/adam_general/core/utils/dump.py: -------------------------------------------------------------------------------- 1 | # estimator commented out lines 2754 to 2821 2 | adam_created_arima = filler( 3 | b_values['B'], 4 | ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, 5 | components_number_ets, components_number_ets_non_seasonal, 6 | components_number_ets_seasonal, components_number_arima, 7 | lags, lags_model, lags_model_max, 8 | adam_created['mat_vt'], adam_created['mat_wt'], adam_created['mat_f'], adam_created['vec_g'], 9 | persistence_estimate, persistence_level_estimate, persistence_trend_estimate, 10 | persistence_seasonal_estimate, persistence_xreg_estimate, 11 | phi_estimate, 12 | initial_type, initial_estimate, 13 | initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, 14 | initial_arima_estimate, initial_xreg_estimate, 15 | arima_model, ar_estimate, ma_estimate, ar_orders, i_orders, ma_orders, 16 | ar_required, ma_required, arma_parameters, 17 | non_zero_ari, non_zero_ma, adam_created['arima_polynomials'], 18 | xreg_model, xreg_number, 19 | xreg_parameters_missing, xreg_parameters_included, 20 | xreg_parameters_estimated, xreg_parameters_persistence, constant_estimate 21 | ) 22 | 23 | # Write down the initials in the recent profile 24 | profiles_recent_table[:] = adam_created_arima['mat_vt'][:, :lags_model_max] 25 | 26 | # Do initial fit to get the state values from the backcasting 27 | adam_fitted = adam_fitter_wrap( 28 | adam_created_arima['mat_vt'], adam_created_arima['mat_wt'], adam_created_arima['mat_f'], adam_created_arima['vec_g'], 29 | lags_model_all, index_lookup_table, profiles_recent_table, 30 | e_type, t_type, s_type, components_number_ets, components_number_ets_seasonal, 31 | components_number_arima, xreg_number, constant_required, 32 | y_in_sample, ot, True 33 | ) 34 | 35 | adam_created['mat_vt'][:, :lags_model_max] = adam_fitted['mat_vt'][:, :lags_model_max] 36 | # Produce new initials 37 | b_values_new = initialiser( 38 | ets_model, e_type, t_type, s_type, model_is_trendy, model_is_seasonal, 39 | components_number_ets_non_seasonal, components_number_ets_seasonal, components_number_ets, 40 | lags, lags_model, lags_model_seasonal, lags_model_arima, lags_model_max, 41 | adam_created['mat_vt'], 42 | persistence_estimate, persistence_level_estimate, persistence_trend_estimate, 43 | persistence_seasonal_estimate, persistence_xreg_estimate, 44 | phi_estimate, initial_type, initial_estimate, 45 | initial_level_estimate, initial_trend_estimate, initial_seasonal_estimate, 46 | initial_arima_estimate, initial_xreg_estimate, 47 | arima_model, ar_required, ma_required, ar_estimate, ma_estimate, ar_orders, ma_orders, 48 | components_number_arima, components_names_arima, initial_arima_number, 49 | xreg_model, xreg_number, 50 | xreg_parameters_estimated, xreg_parameters_persistence, 51 | constant_estimate, constant_name, other_parameter_estimate 52 | ) 53 | B = b_values_new['B'] 54 | # Failsafe, just in case if the initial values contain NA / NaN 55 | B[np.isnan(B)] = b_values['B'][np.isnan(B)] 56 | 57 | 58 | 59 | # Fix for mixed ETS models producing negative values 60 | if (e_type == "M" and any(t in ["A", "Ad"] for t in [t_type, s_type]) or 61 | t_type == "M" and any(t in ["A", "Ad"] for t in [e_type, s_type]) or 62 | s_type == "M" and any(t in ["A", "Ad"] for t in [e_type, t_type])): 63 | if e_type == "M" and ("level" in B) and (B["level"] <= 0): 64 | B["level"] = y_in_sample[0] 65 | if t_type == "M" and ("trend" in B) and (B["trend"] <= 0): 66 | B["trend"] = 1 67 | seasonal_params = [p for p in B.keys() if p.startswith("seasonal")] 68 | if s_type == "M" and any(B[p] <= 0 for p in seasonal_params): 69 | for p in seasonal_params: 70 | if B[p] <= 0: 71 | B[p] = 1 -------------------------------------------------------------------------------- /python/smooth/adam_general/core/utils/ic.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def AIC(loglik, nobs=None, df=None): 4 | """ 5 | Calculate Akaike Information Criterion 6 | 7 | Parameters 8 | ---------- 9 | loglik : float or object with loglik attribute 10 | Log-likelihood value 11 | nobs : int, optional 12 | Number of observations 13 | df : int, optional 14 | Degrees of freedom (number of parameters) 15 | 16 | Returns 17 | ------- 18 | float 19 | AIC value 20 | """ 21 | # Extract loglik value if object is passed 22 | if hasattr(loglik, 'loglik'): 23 | loglik = loglik.loglik 24 | if hasattr(loglik, 'nobs'): 25 | nobs = loglik.nobs 26 | if hasattr(loglik, 'df'): 27 | df = loglik.df 28 | 29 | return -2 * loglik + 2 * df 30 | 31 | def AICc(loglik, nobs=None, df=None): 32 | """ 33 | Calculate corrected Akaike Information Criterion 34 | 35 | Parameters 36 | ---------- 37 | loglik : float or object with loglik attribute 38 | Log-likelihood value 39 | nobs : int, optional 40 | Number of observations 41 | df : int, optional 42 | Degrees of freedom (number of parameters) 43 | 44 | Returns 45 | ------- 46 | float 47 | AICc value 48 | """ 49 | # Extract loglik value if object is passed 50 | if hasattr(loglik, 'loglik'): 51 | loglik = loglik.loglik 52 | if hasattr(loglik, 'nobs'): 53 | nobs = loglik.nobs 54 | if hasattr(loglik, 'df'): 55 | df = loglik.df 56 | 57 | aic = AIC(loglik, nobs, df) 58 | return aic + (2 * df * (df + 1)) / (nobs - df - 1) 59 | 60 | def BIC(loglik, nobs=None, df=None): 61 | """ 62 | Calculate Bayesian Information Criterion 63 | 64 | Parameters 65 | ---------- 66 | loglik : float or object with loglik attribute 67 | Log-likelihood value 68 | nobs : int, optional 69 | Number of observations 70 | df : int, optional 71 | Degrees of freedom (number of parameters) 72 | 73 | Returns 74 | ------- 75 | float 76 | BIC value 77 | """ 78 | # Extract loglik value if object is passed 79 | if hasattr(loglik, 'loglik'): 80 | loglik = loglik.loglik 81 | if hasattr(loglik, 'nobs'): 82 | nobs = loglik.nobs 83 | if hasattr(loglik, 'df'): 84 | df = loglik.df 85 | 86 | return -2 * loglik + np.log(nobs) * df 87 | 88 | def BICc(loglik, nobs=None, df=None): 89 | """ 90 | Calculate corrected Bayesian Information Criterion 91 | 92 | Parameters 93 | ---------- 94 | loglik : float or object with loglik attribute 95 | Log-likelihood value 96 | nobs : int, optional 97 | Number of observations 98 | df : int, optional 99 | Degrees of freedom (number of parameters) 100 | 101 | Returns 102 | ------- 103 | float 104 | BICc value 105 | """ 106 | # Extract loglik value if object is passed 107 | if hasattr(loglik, 'loglik'): 108 | loglik = loglik.loglik 109 | if hasattr(loglik, 'nobs'): 110 | nobs = loglik.nobs 111 | if hasattr(loglik, 'df'): 112 | df = loglik.df 113 | 114 | bic = BIC(loglik, nobs, df) 115 | return bic + (np.log(nobs) * df * (df + 1)) / (nobs - df - 1) 116 | 117 | def ic_function(ic_name, loglik): 118 | """ 119 | Select information criterion function based on name 120 | 121 | Parameters 122 | ---------- 123 | ic_name : str 124 | Name of information criterion ('AIC', 'AICc', 'BIC', or 'BICc') 125 | 126 | Returns 127 | ------- 128 | function 129 | Selected information criterion function 130 | """ 131 | value = loglik['value'] 132 | nobs = loglik['nobs'] 133 | df = loglik['df'] 134 | ic_functions = { 135 | 'AIC': AIC(value, nobs, df), 136 | 'AICc': AICc(value, nobs, df), 137 | 'BIC': BIC(value, nobs, df), 138 | 'BICc': BICc(value, nobs, df) 139 | } 140 | 141 | if ic_name not in ic_functions: 142 | raise ValueError(f"Invalid information criterion: {ic_name}. Must be one of {list(ic_functions.keys())}") 143 | 144 | return ic_functions[ic_name] -------------------------------------------------------------------------------- /python/smooth/adam_general/core/utils/likelihood.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/config-i1/smooth/c529c51c1aa221fd49117f17e68064b57d2ae9ff/python/smooth/adam_general/core/utils/likelihood.py -------------------------------------------------------------------------------- /python/smooth/adam_general/core/utils/polynomials.py: -------------------------------------------------------------------------------- 1 | def adam_polynomialiser(parameters, ar_orders, i_orders, ma_orders, 2 | ar_estimate, ma_estimate, arma_parameters, lags): 3 | """ 4 | Creates polynomials for ARIMA models. 5 | """ 6 | # Implementation of adam_polynomialiser goes here 7 | # You'll need to move this function from wherever it's currently defined 8 | pass -------------------------------------------------------------------------------- /python/smooth/adam_general/load_r_package.py: -------------------------------------------------------------------------------- 1 | import os 2 | import rpy2.robjects as robjects 3 | 4 | def load_smooth_package(): 5 | """ 6 | Load the smooth R package in development mode. 7 | This ensures that any changes to the R code are immediately reflected. 8 | """ 9 | # Get the path to the root of the smooth package 10 | current_dir = os.path.dirname(os.path.abspath(__file__)) 11 | # Navigate up to the root directory (assuming we're in python/smooth/adam_general) 12 | root_dir = os.path.abspath(os.path.join(current_dir, "../../../")) 13 | 14 | # Load devtools and use load_all to load the package in development mode 15 | r_command = f""" 16 | if (!requireNamespace("devtools", quietly = TRUE)) {{ 17 | install.packages("devtools", repos = "https://cran.rstudio.com/") 18 | }} 19 | devtools::load_all("{root_dir}") 20 | """ 21 | 22 | # Execute the R command 23 | robjects.r(r_command) 24 | 25 | print("smooth R package loaded in development mode") 26 | return True 27 | 28 | # If this script is run directly, load the package 29 | if __name__ == "__main__": 30 | load_smooth_package() -------------------------------------------------------------------------------- /python/smooth/adam_general/sma.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from smooth.adam_general._adam_general import adam_fitter, adam_forecaster 4 | from smooth.adam_general.adam_profile import adam_profile_creator 5 | 6 | 7 | def sma(y, order=1, h=10, holdout=False): 8 | """SMA""" 9 | y = y.astype(np.float64) 10 | 11 | # ic = lambda e: np.sum(e**2) 12 | obs_all = len(y) + h * (1 - holdout) 13 | obs_in_sample = len(y) - h * holdout 14 | y_in_sample = y 15 | 16 | E_type = "A" 17 | T_type = "N" 18 | S_type = "N" 19 | 20 | components_num_ETS = 0 21 | components_num_ETS_seasonal = 0 22 | xreg_number = 0 23 | constant_required = False 24 | ot = np.ones_like(y_in_sample) 25 | 26 | def creator_sma(order): 27 | # lags_model_all = np.ones(shape=(order, 1)) 28 | # This needs to be a vector of values 29 | lags_model_all = np.arange(1, order + 1, dtype="int32").reshape(order, 1) 30 | lags_model_max = int(max(lags_model_all)) 31 | obs_states = obs_in_sample + lags_model_max 32 | 33 | profiles_recent_table, index_lookup_table = adam_profile_creator( 34 | lags_model_all=lags_model_all, 35 | lags_model_max=lags_model_max, 36 | obs_all=obs_all, 37 | ).values() 38 | 39 | # # This needs to be generated by a profileCreator() function 40 | # profiles_recent_table = np.mean(y_in_sample[0 : (order - 1)]) * np.ones( 41 | # shape=(order, lags_model_max), dtype=np.float64 42 | # ) 43 | 44 | # # This as well... 45 | # index_lookup_table = np.tile( 46 | # np.arange(order), (obs_all + lags_model_max, 1) 47 | # ).T 48 | 49 | mat_F = np.ones((order, order)) / order 50 | mat_Wt = np.ones((obs_in_sample, order)) 51 | 52 | vec_G = np.ones(order) / order 53 | # matVt = np.zeros((order, obs_states)) 54 | mat_Vt = np.empty((order, obs_states)) 55 | # matVt.fill(np.nan) 56 | 57 | adam_fitted = adam_fitter( 58 | matrixVt=mat_Vt, 59 | matrixWt=mat_Wt, 60 | matrixF=mat_F, 61 | vectorG=vec_G, 62 | lags=lags_model_all, 63 | indexLookupTable=index_lookup_table, 64 | profilesRecent=profiles_recent_table, 65 | E=E_type, 66 | T=T_type, 67 | S=S_type, 68 | nNonSeasonal=components_num_ETS, 69 | nSeasonal=components_num_ETS_seasonal, 70 | nArima=order, 71 | nXreg=xreg_number, 72 | constant=constant_required, 73 | vectorYt=y_in_sample, 74 | vectorOt=ot, 75 | backcast=True, 76 | ) 77 | 78 | fitted_args = dict( 79 | matrixVt=mat_Vt, 80 | matrixWt=mat_Wt, 81 | matrixF=mat_F, 82 | vectorG=vec_G, 83 | lags=lags_model_all, 84 | indexLookupTable=index_lookup_table, 85 | profilesRecent=profiles_recent_table, 86 | E=E_type, 87 | T=T_type, 88 | S=S_type, 89 | nNonSeasonal=components_num_ETS, 90 | nSeasonal=components_num_ETS_seasonal, 91 | nArima=order, 92 | nXreg=xreg_number, 93 | constant=constant_required, 94 | vectorYt=y_in_sample, 95 | vectorOt=ot, 96 | backcast=True, 97 | ) 98 | 99 | return adam_fitted, fitted_args 100 | 101 | sma_fitted, fitted_args = creator_sma(order=order) 102 | 103 | # need to convert some inputs to the expected dtypes. This is a temporary fix. 104 | fitted_args["lags"] = np.array(fitted_args["lags"], dtype="uint64") 105 | fitted_args["indexLookupTable"] = np.array( 106 | fitted_args["indexLookupTable"], dtype="uint64" 107 | ) 108 | 109 | sma_forecast = adam_forecaster( 110 | matrixWt=fitted_args["matrixWt"], 111 | matrixF=fitted_args["matrixF"], 112 | lags=fitted_args["lags"], 113 | indexLookupTable=fitted_args["indexLookupTable"], 114 | profilesRecent=sma_fitted["profile"], 115 | E=fitted_args["E"], 116 | T=fitted_args["T"], 117 | S=fitted_args["S"], 118 | nNonSeasonal=fitted_args["nNonSeasonal"], 119 | nSeasonal=fitted_args["nSeasonal"], 120 | nArima=fitted_args["nArima"], 121 | nXreg=fitted_args["nXreg"], 122 | constant=fitted_args["constant"], 123 | horizon=h, 124 | ) 125 | 126 | return sma_forecast 127 | -------------------------------------------------------------------------------- /python/smooth/adam_general/test.py: -------------------------------------------------------------------------------- 1 | 2 | import pandas as pd 3 | import numpy as np 4 | from core.checker import parameters_checker 5 | from typing import List, Union, Dict, Any 6 | from smooth.adam_general._adam_general import adam_fitter, adam_forecaster 7 | from core.utils.utils import measurement_inverter, scaler, calculate_likelihood, calculate_entropy, calculate_multistep_loss 8 | from numpy.linalg import eigvals 9 | import nlopt 10 | from core.adam import Adam 11 | 12 | 13 | import pandas as pd 14 | import numpy as np 15 | # Create the AirPassengers dataset manually 16 | data = [ 17 | 112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 18 | 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 19 | 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 20 | 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 21 | 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 22 | 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 23 | 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 24 | 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 25 | 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 26 | 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 27 | 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 28 | 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432 29 | ] 30 | 31 | # Create a proper datetime index 32 | dates = pd.date_range(start='1949-01-01', periods=len(data), freq='MS') 33 | 34 | # Create a pandas Series with the data 35 | air_passengers_series = pd.Series(data, index=dates, name='AirPassengers') 36 | 37 | # Create a DataFrame with the time series 38 | ts_df = pd.DataFrame({'value': air_passengers_series}) 39 | 40 | print("AirPassengers dataset loaded:") 41 | print(ts_df.head()) 42 | 43 | import time 44 | 45 | start_time = time.time() 46 | 47 | model = "AAA" 48 | lags = [12] 49 | h = 12 50 | 51 | adam = Adam(model, lags) 52 | adam.fit(ts_df, h = h) 53 | fc = adam.predict() 54 | execution_time = time.time() - start_time 55 | print(f"Execution time: {execution_time:.4f} seconds") 56 | fc['forecast'] 57 | -------------------------------------------------------------------------------- /python/smooth/adam_general/test_script.py: -------------------------------------------------------------------------------- 1 | from core.adam import Adam 2 | 3 | import pandas as pd 4 | import numpy as np 5 | from core.checker import parameters_checker 6 | from typing import List, Union, Dict, Any 7 | from smooth.adam_general._adam_general import adam_fitter, adam_forecaster 8 | from core.utils.utils import measurement_inverter, scaler, calculate_likelihood, calculate_entropy, calculate_multistep_loss 9 | from numpy.linalg import eigvals 10 | import nlopt 11 | 12 | from core.estimator import estimator, selector 13 | from core.creator import creator, initialiser, architector, filler 14 | from core.utils.ic import ic_function 15 | 16 | from smooth.adam_general._adam_general import adam_fitter, adam_forecaster 17 | 18 | import warnings 19 | 20 | # Generate random monthly time series data 21 | np.random.seed(41) # For reproducibility 22 | n_points = 24 # 2 years of monthly data 23 | time_series = np.random.randint(1, 100, size=n_points).cumsum() # Random walk with strictly positive integers 24 | dates = pd.date_range(start='2023-01-01', periods=n_points, freq='M') # Monthly frequency 25 | ts_df = pd.DataFrame({'value': time_series}, index=dates) 26 | 27 | model = "ANN" 28 | lags = [12] 29 | multisteps = False, 30 | lb = None, 31 | ub = None, 32 | maxtime = None, 33 | print_level = 1, # 1 or 0 34 | maxeval = None, 35 | h = 12 36 | 37 | 38 | 39 | # Assume that the model is not provided 40 | # these will be default arguments 41 | profiles_recent_provided = False 42 | profiles_recent_table = None 43 | 44 | adam = Adam(model, lags) 45 | adam.fit(ts_df, h = h) -------------------------------------------------------------------------------- /python/smooth/adam_general/tests_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "import pandas as pd\n", 11 | "from statsmodels.tsa.stattools import acf, pacf" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 6, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "def calculate_acf(data, nlags=40):\n", 21 | " \"\"\"\n", 22 | " Calculate Autocorrelation Function for numpy array or pandas Series.\n", 23 | " \n", 24 | " Parameters:\n", 25 | " data (np.array or pd.Series): Input time series data\n", 26 | " nlags (int): Number of lags to calculate ACF for\n", 27 | " \n", 28 | " Returns:\n", 29 | " np.array: ACF values\n", 30 | " \"\"\"\n", 31 | " if isinstance(data, pd.Series):\n", 32 | " data = data.values\n", 33 | " \n", 34 | " return acf(data, nlags=nlags, fft=False)\n", 35 | "\n", 36 | "def calculate_pacf(data, nlags=40):\n", 37 | " \"\"\"\n", 38 | " Calculate Partial Autocorrelation Function for numpy array or pandas Series.\n", 39 | " \n", 40 | " Parameters:\n", 41 | " data (np.array or pd.Series): Input time series data\n", 42 | " nlags (int): Number of lags to calculate PACF for\n", 43 | " \n", 44 | " Returns:\n", 45 | " np.array: PACF values\n", 46 | " \"\"\"\n", 47 | " if isinstance(data, pd.Series):\n", 48 | " data = data.values\n", 49 | " \n", 50 | " return pacf(data, nlags=nlags, method='ols')\n" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 7, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "# Example usage\n", 60 | "np.random.seed(42)\n", 61 | "date_rng = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')\n", 62 | "data = np.random.randn(len(date_rng)).cumsum() + 100\n", 63 | "\n", 64 | "# Create both numpy array and pandas Series\n", 65 | "np_array = data\n", 66 | "pd_series = pd.Series(data, index=date_rng)\n", 67 | "\n", 68 | "# Calculate ACF and PACF for numpy array\n", 69 | "acf_values_np = calculate_acf(np_array)\n", 70 | "pacf_values_np = calculate_pacf(np_array)\n", 71 | "\n", 72 | "# Calculate ACF and PACF for pandas Series\n", 73 | "acf_values_pd = calculate_acf(pd_series)\n", 74 | "pacf_values_pd = calculate_pacf(pd_series)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 8, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "data": { 84 | "text/plain": [ 85 | "array([1. , 0.98020447, 0.96291875, 0.9463405 , 0.92780577,\n", 86 | " 0.91353458, 0.89787089, 0.87908942, 0.85978813, 0.8416599 ,\n", 87 | " 0.82210143, 0.80328791, 0.78346136, 0.76302172, 0.74567016,\n", 88 | " 0.73017225, 0.71631451, 0.7022657 , 0.68757643, 0.67004954,\n", 89 | " 0.65347832, 0.6397477 , 0.6274798 , 0.61489008, 0.60059905,\n", 90 | " 0.5850292 , 0.57013909, 0.55543017, 0.54231908, 0.52999088,\n", 91 | " 0.51743239, 0.50457837, 0.49134351, 0.47703597, 0.46376578,\n", 92 | " 0.44944496, 0.43629551, 0.42195921, 0.41021392, 0.40102178,\n", 93 | " 0.39067492])" 94 | ] 95 | }, 96 | "execution_count": 8, 97 | "metadata": {}, 98 | "output_type": "execute_result" 99 | } 100 | ], 101 | "source": [ 102 | "acf_values_np" 103 | ] 104 | } 105 | ], 106 | "metadata": { 107 | "kernelspec": { 108 | "display_name": ".venv", 109 | "language": "python", 110 | "name": "python3" 111 | }, 112 | "language_info": { 113 | "codemirror_mode": { 114 | "name": "ipython", 115 | "version": 3 116 | }, 117 | "file_extension": ".py", 118 | "mimetype": "text/x-python", 119 | "name": "python", 120 | "nbconvert_exporter": "python", 121 | "pygments_lexer": "ipython3", 122 | "version": "3.8.10" 123 | } 124 | }, 125 | "nbformat": 4, 126 | "nbformat_minor": 2 127 | } 128 | -------------------------------------------------------------------------------- /smooth.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: f8f33844-318a-42de-9bed-71e43b9ac780 3 | 4 | RestoreWorkspace: Default 5 | SaveWorkspace: Default 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 4 11 | Encoding: UTF-8 12 | 13 | RnwWeave: knitr 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /src/Makevars: -------------------------------------------------------------------------------- 1 | ## Use the R_HOME indirection to support installations of multiple R version 2 | ##PKG_CXXFLAGS=`Rscript -e "Rcpp:::CxxFlags()"` 3 | ##PKG_LIBS=$(`Rscript -e "Rcpp:::LdFlags()"`) 4 | PKG_LIBS=$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) 5 | #CXX_STD = CXX11 6 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | #PKG_CXXFLAGS=$(shell $(R_HOME)/bin${R_ARCH_BIN}/Rscript.exe -e "Rcpp:::CxxFlags()") 2 | #PKG_LIBS = $(shell $(R_HOME)/bin${R_ARCH_BIN}/Rscript.exe -e "Rcpp:::LdFlags()") $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) 3 | PKG_LIBS=$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS) 4 | #CXX_STD = CXX11 5 | -------------------------------------------------------------------------------- /src/adamSimulator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "adamGeneral.h" 5 | // [[Rcpp::depends(RcppArmadillo)]] 6 | 7 | using namespace Rcpp; 8 | 9 | // ##### Script for simulate functions 10 | List adamSimulator(arma::cube &arrayVt, arma::mat const &matrixErrors, arma::mat const &matrixOt, 11 | arma::cube const &arrayF, arma::mat const &matrixWt, arma::mat const &matrixG, 12 | char const &E, char const &T, char const &S, arma::uvec &lags, 13 | arma::umat const &indexLookupTable, arma::mat profilesRecent, 14 | unsigned int const &nNonSeasonal, unsigned int const &nSeasonal, 15 | unsigned int const &nArima, unsigned int const &nXreg, bool const &constant) { 16 | 17 | unsigned int obs = matrixErrors.n_rows; 18 | unsigned int nSeries = matrixErrors.n_cols; 19 | 20 | int lagsModelMax = max(lags); 21 | unsigned int nETS = nNonSeasonal + nSeasonal; 22 | int nComponents = lags.n_rows; 23 | int obsAll = obs + lagsModelMax; 24 | arma::mat profilesRecentOriginal = profilesRecent; 25 | 26 | arma::mat matrixVt(nComponents, obsAll, arma::fill::zeros); 27 | arma::mat matrixF(arrayF.n_rows, arrayF.n_cols, arma::fill::zeros); 28 | 29 | arma::mat matY(obs, nSeries); 30 | 31 | for(unsigned int i=0; i1e+100)){ 72 | // matrixVt.col(j) = matrixVt(lagrows); 73 | // } 74 | matrixVt.col(j) = profilesRecent(indexLookupTable.col(j-lagsModelMax)); 75 | } 76 | arrayVt.slice(i) = matrixVt; 77 | } 78 | 79 | return List::create(Named("arrayVt") = arrayVt, Named("matrixYt") = matY); 80 | } 81 | 82 | /* # Wrapper for simulator */ 83 | // [[Rcpp::export]] 84 | RcppExport SEXP adamSimulatorWrap(arma::cube arrayVt, arma::mat matrixErrors, arma::mat matrixOt, 85 | arma::cube arrayF, arma::mat matrixWt, arma::mat matrixG, 86 | char const &E, char const &T, char const &S, arma::uvec lags, 87 | arma::umat indexLookupTable, arma::mat profilesRecent, 88 | unsigned int const &nSeasonal, unsigned int const &componentsNumber, 89 | unsigned int const &nArima, unsigned int const &nXreg, bool const &constant){ 90 | 91 | unsigned int nNonSeasonal = componentsNumber - nSeasonal; 92 | 93 | return wrap(adamSimulator(arrayVt, matrixErrors, matrixOt, arrayF, matrixWt, matrixG, 94 | E, T, S, lags, indexLookupTable, profilesRecent, 95 | nNonSeasonal, nSeasonal, nArima, nXreg, constant)); 96 | } 97 | -------------------------------------------------------------------------------- /src/matrixPowerWrap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ssGeneral.h" 3 | 4 | // [[Rcpp::export]] 5 | RcppExport SEXP matrixPowerWrap(SEXP matA, SEXP power){ 6 | NumericMatrix matA_n(matA); 7 | arma::mat matrixA(matA_n.begin(), matA_n.nrow(), matA_n.ncol(), false); 8 | 9 | int pow = as(power); 10 | 11 | return wrap(matrixPower(matrixA, pow)); 12 | } 13 | -------------------------------------------------------------------------------- /src/python_examples/my_linalg.cpp: -------------------------------------------------------------------------------- 1 | // example.cpp: Leonidas Tsaprounis 2 | // Description: Example for pybind11 and carma. Adjusted from the example from https://pybind11.readthedocs.io/en/stable/basics.html#first-steps 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | namespace py = pybind11; 10 | 11 | int add(int i, int j) 12 | { 13 | return i + j; 14 | } 15 | 16 | float dot_product(py::array_t arr1, py::array_t arr2) 17 | { 18 | float result = 0; 19 | py::buffer_info buff1 = arr1.request(); 20 | py::buffer_info buff2 = arr2.request(); 21 | int length = buff1.shape[0]; 22 | double *ptr1 = (double *)buff1.ptr; 23 | double *ptr2 = (double *)buff2.ptr; 24 | for (int i = 0; i < length; i++) 25 | { 26 | result += ptr1[i] * ptr2[i]; 27 | } 28 | return result; 29 | } 30 | 31 | py::array_t array_sum(py::array_t arr1, py::array_t arr2) 32 | { 33 | py::buffer_info buff1 = arr1.request(); 34 | py::buffer_info buff2 = arr2.request(); 35 | int length = buff1.shape[0]; 36 | // define the result variable. 37 | py::array_t result = py::array_t(buff1.size); 38 | py::buffer_info buff_result = result.request(); 39 | double *ptr1 = (double *)buff1.ptr; 40 | double *ptr2 = (double *)buff2.ptr; 41 | double *ptr3 = (double *)buff_result.ptr; 42 | #pragma omp parallel for simd 43 | for (int i = 0; i < length; i++) 44 | { 45 | ptr3[i] = ptr1[i] + ptr2[i]; 46 | } 47 | return result; 48 | } 49 | 50 | // armadillo dot product with carma autoconversion 51 | double arma_dot_product(arma::Col arr1, arma::Col arr2) 52 | { 53 | double result = arma::dot(arr1, arr2); 54 | return result; 55 | } 56 | 57 | PYBIND11_MODULE(_my_linalg, m) 58 | { 59 | m.doc() = "pybind11 example plugin"; // module docstring 60 | m.attr("example_attr") = "An example attr"; 61 | m.def("add", &add, "A function that adds two numbers", py::arg("i"), py::arg("j")); 62 | m.def( 63 | "dot_product", 64 | &dot_product, 65 | "dot product of 2 simple numpy arrays", 66 | py::arg("arr1"), 67 | py::arg("arr2")); 68 | m.def( 69 | "arma_dot_product", 70 | &arma_dot_product, 71 | "armadillo based dot product of 2 simple numpy arrays", 72 | py::arg("arr1"), 73 | py::arg("arr2")); 74 | m.def( 75 | "array_sum", 76 | &array_sum, 77 | "Sums 2 numpy arrays", 78 | py::arg("arr1"), 79 | py::arg("arr2")); 80 | } 81 | -------------------------------------------------------------------------------- /src/registerDynamicSymbol.c: -------------------------------------------------------------------------------- 1 | // RegisteringDynamic Symbols 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void R_init_smooth(DllInfo* info) { 8 | R_registerRoutines(info, NULL, NULL, NULL, NULL); 9 | R_useDynamicSymbols(info, TRUE); 10 | } 11 | -------------------------------------------------------------------------------- /src/ssSimulator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ssGeneral.h" 5 | // [[Rcpp::depends(RcppArmadillo)]] 6 | 7 | using namespace Rcpp; 8 | 9 | 10 | // ##### Script for simulate functions 11 | List simulator(arma::cube &arrayVt, arma::mat const &matrixerrors, arma::mat const &matrixot, 12 | arma::cube const &arrayF, arma::rowvec const &rowvecW, arma::mat const &matrixG, 13 | unsigned int const &obs, unsigned int const &nseries, 14 | char const &E, char const &T, char const &S, arma::uvec &lags) { 15 | 16 | arma::mat matY(obs, nseries); 17 | arma::rowvec rowvecXt(1, arma::fill::zeros); 18 | arma::vec vecAt(1, arma::fill::zeros); 19 | 20 | int lagslength = lags.n_rows; 21 | unsigned int maxlag = max(lags); 22 | int obsall = obs + maxlag; 23 | 24 | lags = maxlag - lags; 25 | 26 | for(int i=1; i(Etype); 96 | char T = as(Ttype); 97 | char S = as(Stype); 98 | 99 | IntegerVector modellags_n(modellags); 100 | arma::uvec lags = as(modellags_n); 101 | 102 | return wrap(simulator(arrayVt, matrixerrors, matrixot, arrayF, rowvecW, matrixG, 103 | obs, nseries, E, T, S, lags)); 104 | } 105 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(smooth) 3 | 4 | test_check("smooth") 5 | -------------------------------------------------------------------------------- /tests/testthat/test_ces.R: -------------------------------------------------------------------------------- 1 | context("Tests for ces() function"); 2 | 3 | # Basic CES selection 4 | testModel <- auto.ces(AirPassengers, silent=TRUE); 5 | test_that("Test CES selection on BJsales", { 6 | expect_match(testModel$seasonality, "partial"); 7 | }) 8 | 9 | # Reuse previous CES 10 | test_that("Test on AirPassengers, predefined CES", { 11 | expect_equal(ces(AirPassengers, model=testModel, silent=TRUE)$loss, testModel$loss); 12 | }) 13 | 14 | # Test trace cost function for CES 15 | testModel <- ces(AirPassengers, seasonality="f", h=18, holdout=TRUE, silent=TRUE) 16 | test_that("Test AICc of CES based on MSTFE on AirPassengers", { 17 | expect_equal(as.numeric(logLik(testModel)), as.numeric(testModel$logLik)); 18 | }) 19 | 20 | # Test how different passed values are accepted by CES 21 | test_that("Test provided a and b of CES on AirPassengers", { 22 | expect_equal(ces(AirPassengers, seasonality="f", a=testModel$parameters$a, silent=TRUE)$parameters$a, 23 | testModel$parameters$a); 24 | expect_equal(ces(AirPassengers, seasonality="f", b=testModel$parameters$b, silent=TRUE)$parameters$b, 25 | testModel$parameters$b); 26 | }) 27 | 28 | # Test selection of exogenous with CES 29 | test_that("Use exogenous variables for CESX on BJsales", { 30 | skip_on_cran() 31 | testModel <- ces(BJsales, h=18, holdout=TRUE, silent=TRUE, regressors="use", xreg=BJsales.lead) 32 | expect_equal(length(testModel$initial$xreg),1); 33 | }) 34 | -------------------------------------------------------------------------------- /tests/testthat/test_es.R: -------------------------------------------------------------------------------- 1 | context("Tests for es() function"); 2 | 3 | # Basic ETS selection 4 | testModel <- es(BJsales, silent=TRUE); 5 | test_that("Test ETS selection on BJsales", { 6 | expect_equal(length(testModel$ICs), 9); 7 | }) 8 | 9 | test_that("Test damped-trend ETS on BJsales", { 10 | expect_equal(es(BJsales,model="AAdN", silent=TRUE)$phi, 0.88, tolerance=0.1); 11 | }) 12 | 13 | # Reuse previous ETS 14 | test_that("Test on BJsales, predefined ETS", { 15 | expect_equal(es(BJsales, model=testModel, silent=TRUE)$cf, testModel$cf); 16 | }) 17 | 18 | # Test combinations of ETS 19 | test_that("Test ETS(CCC) with BIC on AirPassengers", { 20 | skip_on_cran 21 | testModel <- es(AirPassengers, "CCC", silent=TRUE, ic="BIC"); 22 | expect_equal(testModel$scale^2, mean(residuals(testModel)^2)); 23 | }) 24 | 25 | # Test model selection of non-multiplicative trend ETS 26 | test_that("Test ETS(MXM) with AIC on AirPassengers", { 27 | skip_on_cran() 28 | testModel <- es(AirPassengers, "MXM", silent=TRUE, ic="AIC"); 29 | expect_match(testModel$loss, "likelihood"); 30 | }) 31 | 32 | # Test trace cost function for ETS 33 | testModel <- es(AirPassengers, model="MAdM", h=18, holdout=TRUE, silent=TRUE) 34 | test_that("Test AIC of ETS on AirPassengers", { 35 | expect_equal(as.numeric(round(AICc(testModel),2)), as.numeric(round(testModel$ICs,2))); 36 | }) 37 | 38 | # Test how different passed values are accepted by ETS 39 | test_that("Test initials, initialSeason and persistence of ETS on AirPassengers", { 40 | skip_on_cran() 41 | expect_equal(es(AirPassengers, model="MAdM", initial=testModel$initial, silent=TRUE)$initial, testModel$initial); 42 | expect_equal(es(AirPassengers, model="MAdM", persistence=testModel$persistence, silent=TRUE)$persistence, testModel$persistence); 43 | expect_equal(es(AirPassengers, model="MAdM", initialSeason=testModel$initialSeason, silent=TRUE)$initialSeason, testModel$initialSeason); 44 | expect_equal(es(AirPassengers, model="MAdM", phi=testModel$phi, silent=TRUE)$phi, testModel$phi); 45 | }) 46 | 47 | x <- BJsales.lead; 48 | y <- BJsales; 49 | # Test selection of exogenous with ETS 50 | test_that("Use exogenous variables for ETS on BJsales", { 51 | skip_on_cran() 52 | testModel <- es(y, h=18, holdout=TRUE, xreg=xregExpander(x), silent=TRUE, regressors="use") 53 | expect_equal(length(testModel$initial$xreg),3); 54 | }) 55 | 56 | # Test combination of ETS with exogenous selection 57 | test_that("Select exogenous variables for ETSX combined on BJsales", { 58 | skip_on_cran() 59 | testModel <- es(y, "CCC", h=18, holdout=TRUE, xreg=x, silent=TRUE, regressors="select") 60 | expect_match(modelType(testModel), "CCN"); 61 | }) 62 | -------------------------------------------------------------------------------- /tests/testthat/test_gum.R: -------------------------------------------------------------------------------- 1 | context("Tests for gum() function") 2 | 3 | # Basic GUM selection 4 | testModel <- gum(BJsales, orders=c(2,1),lags=c(1,4), silent=TRUE, initial="optimal") 5 | test_that("Test if GUM worked on BJsales", { 6 | expect_equal(testModel$model, "GUM(2[1],1[4])") 7 | }) 8 | 9 | # Reuse previous GUM 10 | test_that("Reuse previous GUM on BJsales", { 11 | expect_equal(gum(BJsales, model=testModel, silent=TRUE)$lossValue, testModel$lossValue) 12 | }) 13 | 14 | # Test some crazy order of GUM 15 | test_that("Test if crazy order GUM was estimated on BJsales", { 16 | skip_on_cran() 17 | testModel <- gum(BJsales, orders=c(1,1,1), lags=c(1,3,5), h=18, holdout=TRUE, initial="o", silent=TRUE) 18 | expect_equal(testModel$model, "GUM(1[1],1[3],1[5])") 19 | }) 20 | 21 | # Test how different passed values are accepted by GUM 22 | test_that("Test initials, measurement, transition and persistence of GUM on AirPassengers", { 23 | skip_on_cran() 24 | testModel <- gum(AirPassengers, orders=c(1,1,1), lags=c(1,3,5), 25 | h=18, holdout=TRUE, initial="o", silent=TRUE) 26 | expect_equal(gum(AirPassengers, orders=c(1,1,1), lags=c(1,3,5), 27 | initial=testModel$initial, h=18, holdout=TRUE, silent=TRUE)$initial, testModel$initial) 28 | expect_equal(gum(AirPassengers, orders=c(1,1,1), lags=c(1,3,5), 29 | measurement=testModel$measurement, h=18, holdout=TRUE, silent=TRUE)$measurement, testModel$measurement) 30 | expect_equal(gum(AirPassengers, orders=c(1,1,1), lags=c(1,3,5), 31 | transition=testModel$transition, h=18, holdout=TRUE, silent=TRUE)$transition, testModel$transition) 32 | expect_equal(gum(AirPassengers, orders=c(1,1,1), lags=c(1,3,5), 33 | persistence=testModel$persistence, h=18, holdout=TRUE, silent=TRUE)$persistence, testModel$persistence) 34 | }) 35 | 36 | # Test selection of exogenous with GUM 37 | test_that("Select exogenous variables for GUMX on BJsales", { 38 | skip_on_cran() 39 | xregData <- cbind(y=BJsales, x=BJsales.lead) 40 | testModel <- gum(xregData, h=18, holdout=TRUE, silent=TRUE) 41 | expect_match(errorType(testModel),"A") 42 | }) 43 | 44 | # Use automatic GUM 45 | test_that("Use automatic GUM on BJsales", { 46 | skip_on_cran() 47 | expect_equal(auto.gum(BJsales, silent=TRUE)$loss, "likelihood") 48 | }) 49 | -------------------------------------------------------------------------------- /tests/testthat/test_oes.R: -------------------------------------------------------------------------------- 1 | context("Tests for oes() function") 2 | 3 | # ISS with fixed probability 4 | testModel <- oes(rpois(100,0.2), occurrence="f") 5 | test_that("Test oes with fixed probability", { 6 | expect_equal(testModel$occurrence, "fixed") 7 | }) 8 | 9 | # oes with Inverse odds ratio probability 10 | testModel <- oes(rpois(100,0.2), occurrence="i") 11 | test_that("Test oes with Iverse odds ratio probability", { 12 | expect_equal(testModel$occurrence, "inverse-odds-ratio") 13 | }) 14 | 15 | # oes with odds ratio probability 16 | testModel <- oes(rpois(100,0.2), occurrence="o") 17 | test_that("Test oes with Odds ratio probability", { 18 | expect_equal(testModel$occurrence, "odds-ratio") 19 | }) 20 | 21 | # oes with odds ratio probability and ETS(MMN) 22 | testModel <- oes(rpois(100,0.2), occurrence="o", model="MMN") 23 | test_that("Test oes with Odds ratio probability and ETS(MMN)", { 24 | expect_equal(length(testModel$persistence), 2) 25 | }) 26 | 27 | # oes with automatically selected type of model and ETS(MMN) 28 | test_that("Test oes with auto probability selected", { 29 | skip_on_cran() 30 | testModel <- oes(rpois(100,0.2), occurrence="a") 31 | expect_equal(length(testModel$persistence), 1) 32 | }) 33 | -------------------------------------------------------------------------------- /tests/testthat/test_simulate.R: -------------------------------------------------------------------------------- 1 | context("Tests for simulate() functions") 2 | 3 | #### ETS #### 4 | testData <- sim.es("MNN", frequency=12, bounds="a", obs=100) 5 | test_that("ETS(MNN) simulated with admissible bounds", { 6 | expect_match(testData$model, "MNN") 7 | }) 8 | 9 | testData <- sim.es("AAdM", frequency=12, phi=0.9, obs=120) 10 | test_that("ETS(AAdM) simulated with phi=0.9", { 11 | expect_match(testData$model, "AAdM") 12 | }) 13 | 14 | testData <- sim.es("MNN", frequency=12, obs=120, nsim=100, probability=0.2) 15 | test_that("iETS(MNN) simulated with probability=0.2 and nsim=100", { 16 | expect_match(testData$model, "MNN") 17 | }) 18 | 19 | testModel <- es(AirPassengers, "ANA", h=18, silent=TRUE) 20 | test_that("ETS(ANA) simulated from estimated model", { 21 | expect_match(simulate(testModel,nsim=10,seed=5,obs=100)$model, "ANA") 22 | }) 23 | 24 | #### SSARIMA #### 25 | testModel <- auto.ssarima(BJsales, h=8, silent=TRUE) 26 | test_that("ARIMA(0,1,3) with drift simulated from estimated model", { 27 | expect_match(errorType(simulate(testModel,nsim=10,seed=5,obs=100)), "A") 28 | }) 29 | 30 | test_that("ARIMA(0,1,1) with intermittent data", { 31 | expect_match(sim.ssarima(nsim=10,obs=100,probability=0.2)$model, "iARIMA") 32 | }) 33 | 34 | #### CES #### 35 | testModel <- auto.ces(BJsales, h=8, silent=TRUE) 36 | test_that("CES(n) simulated from estimated model", { 37 | expect_match(simulate(testModel,nsim=10,seed=5,obs=100)$model, "(n)") 38 | }) 39 | 40 | test_that("CES(s) with some random parameters", { 41 | expect_match(sim.ces(seasonality="s",frequency=4,nsim=1,obs=100)$model, "(s)") 42 | }) 43 | 44 | test_that("CES(p) with some random A parameter and fixed b=0.1 ", { 45 | expect_equal(sim.ces(seasonality="p",frequency=4,b=0.1,nsim=1,obs=100)$b[1], 0.1) 46 | }) 47 | 48 | test_that("CES(f) with intermittent data", { 49 | expect_match(sim.ces(seasonality="f",frequency=12,nsim=10,obs=100,probability=0.2)$model, "iCES") 50 | }) 51 | 52 | #### GUM #### 53 | testModel <- gum(BJsales, orders=1, lags=1, h=8, silent=TRUE) 54 | test_that("GUM(1[1]) simulated from estimated model", { 55 | expect_match(simulate(testModel,nsim=10,seed=5,obs=100)$model, "GUM") 56 | }) 57 | 58 | test_that("GUM(1[1]) with intermittent data", { 59 | expect_match(sim.gum(nsim=10,obs=100,probability=0.2)$model, "iGUM") 60 | }) 61 | 62 | #### SMA #### 63 | test_that("SMA(10) with intermittent data", { 64 | expect_match(sim.sma(10,nsim=10,obs=100,probability=0.2)$model, "iSMA") 65 | }) 66 | -------------------------------------------------------------------------------- /tests/testthat/test_ssarima.R: -------------------------------------------------------------------------------- 1 | context("Tests for ssarima() function") 2 | 3 | # Basic SSARIMA selection 4 | testModel <- auto.ssarima(BJsales, silent=TRUE) 5 | test_that("Test if Auto SSARIMA selected correct model for BJsales", { 6 | expect_equal(testModel$model, ssarima(BJsales, model=testModel)$model) 7 | }) 8 | 9 | # Reuse previous SSARIMA 10 | test_that("Reuse previous SSARIMA on BJsales", { 11 | expect_equal(ssarima(BJsales, model=testModel, silent=TRUE)$cf, testModel$cf) 12 | }) 13 | 14 | # Test some crazy order of SSARIMA 15 | test_that("Test if crazy order SSARIMA was estimated on AirPassengers", { 16 | skip_on_cran() 17 | testModel <- ssarima(AirPassengers, orders=list(ar=c(1,1,0), i=c(1,0,1),ma=c(0,1,1)), 18 | lags=c(1,6,12), h=18, holdout=TRUE, initial="o", silent=TRUE, interval=TRUE) 19 | expect_equal(testModel$model, "SSARIMA(1,1,0)[1](1,0,1)[6](0,1,1)[12]") 20 | }) 21 | 22 | # Test selection of exogenous with Auto.SSARIMA 23 | test_that("Use exogenous variables for auto SSARIMAX on BJsales with selection", { 24 | skip_on_cran() 25 | testModel <- auto.ssarima(BJsales, orders=list(ar=3,i=2,ma=3), lags=1, h=18, holdout=TRUE, 26 | regressors="use", silent=TRUE, xreg=xregExpander(BJsales.lead)) 27 | expect_equal(length(testModel$initial$xreg),3) 28 | }) 29 | -------------------------------------------------------------------------------- /vignettes/.install_extras: -------------------------------------------------------------------------------- 1 | smooth-Documentation.pdf 2 | -------------------------------------------------------------------------------- /vignettes/ces.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "ces() - Complex Exponential Smoothing" 3 | author: "Ivan Svetunkov" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{ces() - Complex Exponential Smoothing} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r global_options, include=FALSE} 13 | knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold', 14 | warning=FALSE, message=FALSE) 15 | ``` 16 | 17 | This vignette covers `ces()` and `auto.ces()` functions, which are part of [smooth package](smooth.html). 18 | 19 | Let's load the necessary packages: 20 | 21 | ```{r load_libraries, message=FALSE, warning=FALSE} 22 | require(smooth) 23 | ``` 24 | 25 | `ces()` function allows constructing Complex Exponential Smoothing either with no seasonality, or with simple/partial/full one. A simple call for `ces()` results in estimation of non-seasonal model: 26 | 27 | For the same series from M3 dataset `ces()` can be constructed using: 28 | ```{r ces_N2457} 29 | ces(BJsales, h=12, holdout=TRUE, silent=FALSE) 30 | ``` 31 | 32 | This output is very similar to ones printed out by `adam()` function. The only difference is complex smoothing parameter values which are printed out instead of persistence vector in `adam()`. 33 | 34 | If we want automatic model selection, then we use `auto.ces()` function: 35 | ```{r auto_ces_N2457} 36 | auto.ces(AirPassengers, h=12, holdout=TRUE, silent=FALSE) 37 | ``` 38 | 39 | By default, the function optimises the initial values, but other options ("backcasting" and "complete") are supported as well: 40 | ```{r auto_ces_N2457_optimal} 41 | ces(BJsales, h=12, holdout=TRUE, initial="back") 42 | ``` 43 | 44 | The function also works with explanatory variables if the data frame or a matrix is provided instead of the vector of values: 45 | ```{r es_N2457_xreg_create} 46 | BJData <- cbind(y=BJsales, x=BJsales.lead) 47 | cesModel <- ces(BJData, h=12, holdout=TRUE, regressors="use") 48 | ``` 49 | 50 | Finally, all the main methods for the [adam](adam.html) function are supported by `ces()` as well. For example, here how we can produce prediction interval: 51 | ```{r} 52 | forecast(cesModel, h=12, interval="pred") |> plot() 53 | ``` 54 | 55 | 56 | -------------------------------------------------------------------------------- /vignettes/es.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "es() - Exponential Smoothing" 3 | author: "Ivan Svetunkov" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{es() - Exponential Smoothing} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r global_options, include=FALSE} 13 | knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold', 14 | warning=FALSE, message=FALSE) 15 | ``` 16 | 17 | `es()` is a part of [smooth package](smooth.html) and is a wrapper for the [ADAM](adam.html) function with `distribution="dnorm"`. It implements Exponential Smoothing in the ETS form, selecting the most appropriate model among 30 possible ones. 18 | 19 | We will use some of the functions of the `greybox` package in this vignette for demonstrational purposes. 20 | 21 | Let's load the necessary packages: 22 | ```{r load_libraries, message=FALSE, warning=FALSE} 23 | require(smooth) 24 | require(greybox) 25 | ``` 26 | 27 | The simplest call for the `es()` function is: 28 | 29 | ```{r es_N2457} 30 | ourModel <- es(BJsales, h=12, holdout=TRUE, silent=FALSE) 31 | ourModel 32 | ``` 33 | 34 | In this case function uses branch and bound algorithm to form a pool of models to check and after that constructs a model with the lowest information criterion. As we can see, it also produces an output with brief information about the model, which contains: 35 | 36 | 1. How much time was elapsed for the model construction; 37 | 2. What type of ETS was selected; 38 | 3. Values of persistence vector (smoothing parameters); 39 | 4. What type of initialisation was used; 40 | 5. How many parameters were estimated (standard deviation is included); 41 | 6. Cost function type and the value of that cost function; 42 | 7. Information criteria for this model; 43 | 8. Forecast errors (because we have set `holdout=TRUE`). 44 | 45 | The function has also produced a graph with actual values, fitted values and point forecasts. 46 | 47 | If we need prediction interval, then we can use the `forecast()` method: 48 | ```{r es_N2457_with_interval} 49 | plot(forecast(ourModel, h=12, interval="prediction")) 50 | ``` 51 | 52 | The same model can be reused for different purposes, for example to produce forecasts based on newly available data: 53 | ```{r es_N2457_reuse_model} 54 | es(BJsales, model=ourModel, h=12, holdout=FALSE) 55 | ``` 56 | 57 | We can also extract the type of model in order to reuse it later: 58 | ```{r es_N2457_modelType} 59 | modelType(ourModel) 60 | ``` 61 | 62 | This handy function also works with `ets()` from forecast package. 63 | 64 | If we need actual values from the model, we can use `actuals()` method from `greybox` package: 65 | ```{r es_N2457_actuals} 66 | actuals(ourModel) 67 | ``` 68 | 69 | We can also use persistence or initials only from the model to construct the other one: 70 | ```{r es_N2457_reuse_model_parts} 71 | # Provided initials 72 | es(BJsales, model=modelType(ourModel), 73 | h=12, holdout=FALSE, 74 | initial=ourModel$initial) 75 | # Provided persistence 76 | es(BJsales, model=modelType(ourModel), 77 | h=12, holdout=FALSE, 78 | persistence=ourModel$persistence) 79 | ``` 80 | or provide some arbitrary values: 81 | ```{r es_N2457_set_initial} 82 | es(BJsales, model=modelType(ourModel), 83 | h=12, holdout=FALSE, 84 | initial=200) 85 | ``` 86 | 87 | Using some other parameters may lead to completely different model and forecasts (see discussion of the additional parameters in the [online textbook about ADAM](https://openforecast.org/adam/)): 88 | ```{r es_N2457_aMSTFE} 89 | es(BJsales, h=12, holdout=TRUE, loss="MSEh", bounds="a", ic="BIC") 90 | ``` 91 | 92 | You can play around with all the available parameters to see what's their effect on the final model. 93 | 94 | In order to combine forecasts we need to use "C" letter: 95 | ```{r es_N2457_combine} 96 | es(BJsales, model="CCN", h=12, holdout=TRUE) 97 | ``` 98 | 99 | Model selection from a specified pool and forecasts combination are called using respectively: 100 | ```{r es_N2457_pool} 101 | # Select the best model in the pool 102 | es(BJsales, model=c("ANN","AAN","AAdN","MNN","MAN","MAdN"), 103 | h=12, holdout=TRUE) 104 | # Combine the pool of models 105 | es(BJsales, model=c("CCC","ANN","AAN","AAdN","MNN","MAN","MAdN"), 106 | h=12, holdout=TRUE) 107 | ``` 108 | 109 | Now we introduce explanatory variable in ETS: 110 | ```{r es_N2457_xreg_create} 111 | x <- BJsales.lead 112 | ``` 113 | 114 | and fit an ETSX model with the exogenous variable first: 115 | ```{r es_N2457_xreg} 116 | es(BJsales, model="ZZZ", h=12, holdout=TRUE, 117 | xreg=x) 118 | ``` 119 | 120 | If we want to check if lagged x can be used for forecasting purposes, we can use `xregExpander()` function from `greybox` package: 121 | ```{r es_N2457_xreg_expanded_select} 122 | es(BJsales, model="ZZZ", h=12, holdout=TRUE, 123 | xreg=xregExpander(x), regressors="use") 124 | ``` 125 | 126 | We can also construct a model with selected exogenous (based on IC): 127 | ```{r es_N2457_xreg_select} 128 | es(BJsales, model="ZZZ", h=12, holdout=TRUE, 129 | xreg=xregExpander(x), regressors="select") 130 | ``` 131 | 132 | Finally, if you work with M or M3 data, and need to test a function on a specific time series, you can use the following simplified call: 133 | ```{r es_N2457_M3, eval=FALSE} 134 | es(Mcomp::M3$N2457, silent=FALSE) 135 | ``` 136 | 137 | This command has taken the data, split it into in-sample and holdout and produced the forecast of appropriate length to the holdout. 138 | -------------------------------------------------------------------------------- /vignettes/gum.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "gum() - Generalised Univariate Model" 3 | author: "Ivan Svetunkov" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{gum() - Generalised Univariate Model} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r global_options, include=FALSE} 13 | knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold', 14 | warning=FALSE, message=FALSE) 15 | ``` 16 | 17 | `gum()` constructs Generalised Exponential Smoothing - pure additive state-space model. It is a part of [smooth package](smooth.html). 18 | 19 | Let's load the necessary packages: 20 | ```{r load_libraries, message=FALSE, warning=FALSE} 21 | require(smooth) 22 | ``` 23 | 24 | Generalised Exponential Smoothing is a next step from CES. It is a state-space model in which all the matrices and vectors are estimated. It is very demanding in sample size, but is also insanely flexible. 25 | 26 | A simple call by default constructs GUM$(1^1,1^m)$, where $m$ is frequency of the data. So for our example with `AirPassengers` data, we will have GUM$(1^1,1^{12})$: 27 | 28 | ```{r gum_N2457} 29 | gum(AirPassengers, h=18, holdout=TRUE) 30 | ``` 31 | 32 | But some different orders and lags can be specified. For example: 33 | ```{r gum_N2457_2[1]_1[12]} 34 | gum(AirPassengers, h=18, holdout=TRUE, orders=c(2,1), lags=c(1,12)) 35 | ``` 36 | 37 | Function `auto.gum()` is now implemented in `smooth`, but it works slowly as it needs to check a large number of models: 38 | ```{r Autogum_N2457_1[1]} 39 | auto.gum(AirPassengers, silent=FALSE) 40 | ``` 41 | 42 | In addition to standard values that other functions accept, GUM accepts predefined values for transition matrix, measurement and persistence vectors. For example, something more common can be passed to the function: 43 | ```{r gum_N2457_predefined} 44 | transition <- matrix(c(1,0,0,1,1,0,0,0,1),3,3) 45 | measurement <- c(1,1,1) 46 | gum(AirPassengers, h=18, holdout=TRUE, orders=c(2,1), lags=c(1,12), transition=transition, measurement=measurement) 47 | ``` 48 | 49 | The resulting model will be equivalent to ETS(A,A,A). However due to different initialisation of optimisers and different method of number of parameters calculation, `gum()` above and `es(y, "AAA", h=h, holdout=TRUE)` will lead to different models. 50 | -------------------------------------------------------------------------------- /vignettes/library.bib: -------------------------------------------------------------------------------- 1 | @book{Lutkepohl2005, 2 | author = {L{\"{u}}tkepohl, Helmut}, 3 | booktitle = {New introduction to Multiple Time Series Analysis}, 4 | doi = {10.1007/978-3-540-27752-1}, 5 | pages = {1--764}, 6 | publisher = {Springer Berlin Heidelberg}, 7 | title = {{New Introduction to Multiple Time Series Analysis}}, 8 | year = {2005} 9 | } 10 | 11 | @article{Bedrick1994, 12 | author = {Bedrick, Edward J and Tsai, Chih-Ling}, 13 | doi = {10.2307/2533213}, 14 | journal = {Biometrics}, 15 | month = {mar}, 16 | number = {1}, 17 | pages = {226}, 18 | title = {{Model Selection for Multivariate Regression in Small Samples}}, 19 | volume = {50}, 20 | year = {1994} 21 | } 22 | 23 | @article{Tremblay2004, 24 | author = {Tremblay, Marie and Wallach, Daniel}, 25 | doi = {10.1051/agro:2004033}, 26 | journal = {Agronomie}, 27 | month = {sep}, 28 | number = {6-7}, 29 | pages = {351--365}, 30 | pmid = {647}, 31 | title = {{Comparison of parameter estimation methods for crop models}}, 32 | volume = {24}, 33 | year = {2004} 34 | } 35 | 36 | @article{Silva2010, 37 | author = {de Silva, Ashton and Hyndman, Rob J and Snyder, Ralph}, 38 | doi = {10.1177/1471082X0901000401}, 39 | journal = {Statistical Modelling: An International Journal}, 40 | month = {dec}, 41 | number = {4}, 42 | pages = {353--374}, 43 | title = {{The vector innovations structural time series framework}}, 44 | volume = {10}, 45 | year = {2010} 46 | } 47 | 48 | @article{Gneiting2007, 49 | author = {Gneiting, Tilmann and Raftery, Adrian E.}, 50 | doi = {10.1198/016214506000001437}, 51 | journal = {Journal of the American Statistical Association}, 52 | number = {477}, 53 | pages = {359--378}, 54 | title = {{Strictly proper scoring rules, prediction, and estimation}}, 55 | volume = {102}, 56 | year = {2007} 57 | } 58 | 59 | @unpublished{Svetunkov2017a, 60 | author = {Svetunkov, I. and Boylan, John E.}, 61 | doi = {10.13140/RG.2.2.35897.06242}, 62 | institution = {Department of Management Science, Lancaster University}, 63 | number = {4}, 64 | pages = {1--43}, 65 | title = {{Multiplicative State-Space Models for Intermittent Time Series}}, 66 | year = {2017} 67 | } 68 | 69 | @article{Svetunkov2019, 70 | author = {Svetunkov, Ivan and Boylan, John E.}, 71 | doi = {10.1080/00207543.2019.1600764}, 72 | issn = {0020-7543}, 73 | journal = {International Journal of Production Research}, 74 | number = {0}, 75 | pages = {1--10}, 76 | publisher = {Taylor {\&} Francis}, 77 | title = {{State-space ARIMA for supply-chain forecasting}}, 78 | volume = {0}, 79 | year = {2019} 80 | } 81 | 82 | @book{Hyndman2008b, 83 | author = {Hyndman, Rob J and Koehler, Anne B and Ord, J Keith and Snyder, Ralph D}, 84 | publisher = {Springer Berlin Heidelberg}, 85 | title = {{Forecasting with Exponential Smoothing}}, 86 | year = {2008} 87 | } 88 | -------------------------------------------------------------------------------- /vignettes/sma.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "sma() - Simple Moving Average" 3 | author: "Ivan Svetunkov" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{sma() - Simple Moving Average} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r global_options, include=FALSE} 13 | knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold', 14 | warning=FALSE, message=FALSE) 15 | ``` 16 | 17 | Simple Moving Average is a method of time series smoothing and is actually a very basic forecasting technique. It does not need estimation of parameters, but rather is based on order selection. It is a part of [smooth package](smooth.html). 18 | 19 | Let's load the necessary packages: 20 | ```{r load_libraries, message=FALSE, warning=FALSE} 21 | require(smooth) 22 | ``` 23 | 24 | By default SMA does order selection based on AICc and returns the model with the lowest value: 25 | ```{r sma_N2457} 26 | y <- structure(c(2158.1, 1086.4, 1154.7, 1125.6, 920, 2188.6, 829.2, 27 | 1353.1, 947.2, 1816.8, 1624.5, 868.5, 1783.3, 1713.1, 3479.7, 28 | 2429.4, 3074.3, 3427.4, 2783.7, 1968.7, 2045.6, 1471.3, 2763.7, 29 | 2328.4, 1821, 2409.8, 3485.8, 3289.2, 3048.3, 2914.1, 2173.9, 30 | 3018.4, 2200.1, 6844.3, 4160.4, 1548.8, 3238.9, 3252.2, 3278.8, 31 | 1766.8, 3572.8, 3467.6, 7464.7, 2748.4, 5126.7, 2870.8, 2170.2, 32 | 4326.8, 3220.7, 3586, 3249.5, 3222.5, 2488.5, 3332.4, 2036.1, 33 | 1968.2, 2967.2, 3151.6, 1610.5, 3985, 3894.1, 4625.5, 3291.7, 34 | 3065.6, 2316.5, 2453.4, 4582.8, 2291.2, 3555.5, 1785, 2020, 2026.8, 35 | 2102.9, 2307.7, 6242.1, 6170.5, 1863.5, 6318.9, 3992.8, 3435.1, 36 | 1585.8, 2106.8, 1892.1, 4310.6, 6168, 7247.4, 3579.7, 6365.2, 37 | 4658.9, 6911.8, 2143.7, 5973.9, 4017.2, 4473, 3591.9, 4676.5, 38 | 8749.1, 11931.2, 8572.3, 8257.7, 11930.5, 15757.6, 5920.5, 3064.3, 39 | 5472, 8634.7, 5032, 6236, 6356, 9857.8, 6322.2, 7907, 13842.4, 40 | 13665.1, 3272), .Tsp = c(1983, 1992.5, 12), class = "ts") 41 | sma(y, h=18, silent=FALSE) 42 | ``` 43 | 44 | It appears that SMA(13) is the optimal model for this time series, which is not obvious. Note also that the forecast trajectory of SMA(13) is not just a straight line. This is because the actual values are used in construction of point forecasts up to h=13. 45 | 46 | -------------------------------------------------------------------------------- /vignettes/smooth-Documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/config-i1/smooth/c529c51c1aa221fd49117f17e68064b57d2ae9ff/vignettes/smooth-Documentation.pdf -------------------------------------------------------------------------------- /vignettes/ssarima.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "ssarima() - State-Space ARIMA" 3 | author: "Ivan Svetunkov" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{ssarima() - State-Space ARIMA} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | bibliography: library.bib 11 | --- 12 | 13 | ```{r global_options, include=FALSE} 14 | knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold', 15 | warning=FALSE, message=FALSE) 16 | ``` 17 | 18 | SSARIMA stands for "State-space ARIMA" or "Several Seasonalities ARIMA". Both names show what happens in the heart of the function: it constructs ARIMA in a state-space form and allows to model several (actually more than several) seasonalities. `ssarima()` is a function included in [smooth package](smooth.html). This vignette covers `ssarima()` and `auto.ssarima()` functions. For more details about the underlying model, read [@Svetunkov2019]. 19 | 20 | As usual, we will use data from `Mcomp` package, so it is advised to install it. 21 | 22 | Let's load the necessary packages: 23 | 24 | ```{r load_libraries, message=FALSE, warning=FALSE} 25 | require(smooth) 26 | ``` 27 | 28 | The default call constructs ARIMA(0,1,1): 29 | 30 | ```{r ssarima_N2457} 31 | ssarima(AirPassengers, h=12, silent=FALSE) 32 | ``` 33 | 34 | Some more complicated model can be defined using parameter `orders` the following way: 35 | ```{r ssarima_N2457_orders} 36 | ssarima(AirPassengers, orders=list(ar=c(0,1),i=c(1,0),ma=c(1,1)), lags=c(1,12), h=12) 37 | ``` 38 | 39 | This would construct seasonal ARIMA(0,1,1)(1,0,1)$_{12}$. 40 | 41 | We could try selecting orders manually, but this can also be done automatically via `auto.ssarima()` function: 42 | ```{r auto_ssarima_N2457} 43 | auto.ssarima(AirPassengers, h=12) 44 | ``` 45 | 46 | Automatic order selection in SSARIMA with optimised initials does not work well and in general is not recommended. This is partially because of the possible high number of parameters in some models and partially because of potential overfitting of first observations when non-zero order of AR is selected: 47 | ```{r auto_ssarima_N1683} 48 | auto.ssarima(AirPassengers, h=12, initial="backcasting") 49 | auto.ssarima(AirPassengers, h=12, initial="optimal") 50 | ``` 51 | 52 | As can be seen from the example above the model with optimal initials takes more time and we end up with a different model than in the case of backcasting. 53 | 54 | A power of `ssarima()` function is that it can estimate SARIMA models with multiple seasonalities. For example, SARIMA(0,1,1)(0,0,1)_6(1,0,1)_12 model can be estimated the following way: 55 | ```{r ssarima_N2457_orders_multiple_seasonalities, eval=FALSE} 56 | ssarima(AirPassengers, orders=list(ar=c(0,0,1),i=c(1,0,0),ma=c(1,1,1)), lags=c(1,6,12), h=12, silent=FALSE) 57 | ``` 58 | It probably does not make much sense for this type of data, it would make more sense on high frequency data (for example, `taylor` series from `forecast` package). However, keep in mind that multiple seasonal ARIMAs are very slow in estimation and are very capricious. So it is really hard to obtain an appropriate and efficient multiple seasonal ARIMA model. To tackle this issue, I've developed an alternative ARIMA model for multiple seasonalities, called `msarima()`. 59 | 60 | Now let's introduce some artificial exogenous variables: 61 | ```{r es_N2457_xreg_create} 62 | x <- cbind(rnorm(length(AirPassengers),50,3),rnorm(length(AirPassengers),100,7)) 63 | ``` 64 | 65 | If we save model: 66 | ```{r auto_ssarima_N2457_xreg} 67 | ourModel <- auto.ssarima(AirPassengers, h=12, holdout=TRUE, xreg=x) 68 | ``` 69 | 70 | we can then reuse it: 71 | ```{r auto_ssarima_N2457_xreg_update} 72 | ssarima(AirPassengers, model=ourModel, h=12, holdout=FALSE, xreg=x, interval=TRUE) 73 | ``` 74 | 75 | Finally, we can combine several SARIMA models: 76 | ```{r auto_ssarima_N2457_combination} 77 | ssarima(AirPassengers, h=12, holdout=FALSE, interval=TRUE, combine=TRUE) 78 | ``` 79 | 80 | # MSARIMA 81 | While SSARIMA is flexible, it is not fast. In fact, it cannot handle high frequency data well and most probably will take ages to estimate the parameter and produce forecasts. This is because of the transition matrix, which becomes huge in case of multiple seasonalities. The MSARIMA model (Multiple Seasonal ARIMA) is formulated in a different state-space form, which reduces the size of transition matrix, significantly reducing the computational time for cases with high frequency data. 82 | 83 | There are `auto.msarima()` and `msarima()` function in the package, that do things similar to `auto.ssarima()` and `ssarima()`. Here's just one example of what can be done with it: 84 | ```{r mssarima_N2457_orders_multiple_seasonalities} 85 | msarima(AirPassengers, orders=list(ar=c(0,0,1),i=c(1,0,0),ma=c(1,1,1)),lags=c(1,6,12),h=12, silent=FALSE) 86 | ``` 87 | 88 | The forecasts of the two models might differ due to the different state space form. The detailed explanation of MSARIMA is given in Chapter 9 of [ADAM textbook](https://openforecast.org/adam/). 89 | 90 | ## References 91 | --------------------------------------------------------------------------------