├── .Rbuildignore ├── .covrignore ├── .github └── workflows │ ├── R-CMD-check.yml │ └── build.yml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── bmgarch-package.R ├── bmgarch.R ├── cmdstan_path.R ├── forecasting_gq.R ├── helper.R ├── lfocv.R ├── model_weights.R ├── panas.R ├── plot.R ├── print.R ├── simulate.R ├── stanmodels.R ├── stocks.R └── zzz.R ├── README.Rmd ├── README.md ├── bmgarch.Rproj ├── configure ├── configure.win ├── cran-comments.md ├── data ├── panas.rda └── stocks.rda ├── doc ├── auto │ └── paper.el ├── paper.bib └── paper.md ├── inst ├── REFERENCES.bib ├── auto │ └── REFERENCES.el ├── include │ └── stan_meta_header.hpp └── stan │ ├── BEKKMGARCH.stan │ ├── CCCMGARCH.stan │ ├── DCCMGARCH.stan │ ├── data │ ├── data.stan │ └── gq_data.stan │ ├── forecastBEKK.stan │ ├── forecastCCC.stan │ ├── forecastDCC.stan │ ├── functions │ ├── cov2cor.stan │ └── jacobian.stan │ ├── generated │ ├── forecast_log_lik.stan │ ├── forecast_sampling.stan │ └── retrodict_H.stan │ ├── include │ └── license.stan │ ├── model_components │ └── mu.stan │ ├── parameters │ ├── arma.stan │ └── predH.stan │ ├── pdBEKKMGARCH.stan │ └── transformed_data │ └── xh_marker.stan ├── man ├── as.data.frame.fitted.bmgarch.Rd ├── as.data.frame.forecast.bmgarch.Rd ├── bmgarch-package.Rd ├── bmgarch.Rd ├── bmgarch_list.Rd ├── dot-colQTs.Rd ├── dot-cp.Rd ├── dot-f_MA.Rd ├── dot-f_array_x_mat.Rd ├── dot-get_stan_summary.Rd ├── dot-get_target_stan_path.Rd ├── dot-newline.Rd ├── dot-pred_array_to_df.Rd ├── dot-print.config.Rd ├── dot-print.summary.bekk.Rd ├── dot-print.summary.beta.Rd ├── dot-print.summary.ccc.Rd ├── dot-print.summary.dcc.Rd ├── dot-print.summary.lp.Rd ├── dot-print.summary.means.Rd ├── dot-print.summary.nu.Rd ├── dot-qtile.Rd ├── dot-refit.Rd ├── dot-sep.Rd ├── dot-sim.bekk.Rd ├── dot-square.Rd ├── dot-tab.Rd ├── figures │ ├── README-fit3ForecastPlot-1.png │ ├── README-fit3ForecastPlot-2.png │ ├── README-fit3ForecastPlot-3.png │ ├── README-forecastPlot-1.png │ ├── README-forecastPlot-2.png │ ├── README-forecastPlot-3.png │ ├── README-stockForecastPlot-1.png │ ├── README-stockForecastPlot-2.png │ ├── README-stockForecastPlot-3.png │ ├── README-weightedForecastPlot-1.png │ ├── README-weightedForecastPlot-2.png │ ├── README-weightedForecastPlot-3.png │ └── README-weightedForecastPlot-4.png ├── fitted.bmgarch.Rd ├── forecast.bmgarch.Rd ├── loo.bmgarch.Rd ├── model_weights.Rd ├── panas.Rd ├── plot.bmgarch.Rd ├── plot.forecast.bmgarch.Rd ├── print.fitted.bmgarch.Rd ├── print.forecast.bmgarch.Rd ├── print.loo.bmgarch.Rd ├── print.model_weights.Rd ├── print.summary.bmgarch.Rd ├── standat.Rd ├── stocks.Rd ├── summary.bmgarch.Rd └── supported_models.Rd ├── src ├── Makevars ├── Makevars.win └── RcppExports.cpp └── tests ├── stocks.R ├── testthat.R └── testthat ├── test-meanstr.R ├── test-models.R └── testdata.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^\.travis\.yml$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^local$ 5 | ^tests$ 6 | ^.covrignore$ 7 | ^README\.Rmd$ 8 | ^man/figures$ 9 | ^todo.org$ 10 | ^cran-comments\.md$ 11 | ^CODE_OF_CONDUCT\.md$ 12 | ^CONTRIBUTING\.md$ 13 | ^\.github$ 14 | ^/\.gitattributes$ 15 | ^CRAN-RELEASE$ 16 | ^doc$ 17 | ^CRAN-SUBMISSION$ 18 | -------------------------------------------------------------------------------- /.covrignore: -------------------------------------------------------------------------------- 1 | /tests/local 2 | /tests/stocks.R 3 | *.hpp 4 | *.cpp 5 | R/zzz.R 6 | /src -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # 6 | # See https://github.com/r-lib/actions/tree/master/examples#readme for 7 | # additional example workflows available for the R community. 8 | 9 | name: R-CMD-check 10 | 11 | on: 12 | push: 13 | branches: [ main, master ] 14 | pull_request: 15 | branches: [ main, master ] 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: # from https://github.com/r-lib/actions/tree/v2/examples 21 | R-CMD-check: 22 | runs-on: ubuntu-latest 23 | env: 24 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 25 | R_KEEP_PKG_SOURCE: yes 26 | steps: 27 | - uses: actions/checkout@v3 28 | 29 | - uses: r-lib/actions/setup-r@v2 30 | with: 31 | use-public-rspm: true # use public R package manager 32 | 33 | - name: Install dependencies 34 | run: | 35 | install.packages(c("remotes", "rcmdcheck")) 36 | remotes::install_deps(dependencies = TRUE) 37 | shell: Rscript {0} 38 | - name: Check 39 | run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "error") 40 | shell: Rscript {0} 41 | ... 42 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # 6 | # See https://github.com/r-lib/actions/tree/master/examples#readme for 7 | # additional example workflows available for the R community. 8 | 9 | name: build 10 | 11 | on: 12 | push: 13 | branches: [ master ] 14 | pull_request: 15 | branches: [ master ] 16 | 17 | jobs: 18 | build: 19 | runs-on: ${{ matrix.config.os }} 20 | 21 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 22 | 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | config: 27 | - { os: windows-latest, r: 'release'} 28 | - { os: macOS-latest, r: 'release'} 29 | - { os: ubuntu-22.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} 30 | env: 31 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 32 | RSPM: ${{ matrix.config.rspm }} 33 | # don't treat missing suggested packages as error 34 | _R_CHECK_FORCE_SUGGESTS_: false 35 | 36 | steps: 37 | - uses: actions/checkout@v3 38 | 39 | - uses: r-lib/actions/setup-r@v2 40 | with: 41 | r-version: ${{ matrix.config.r }} 42 | 43 | - uses: r-lib/actions/setup-pandoc@v2 44 | 45 | - name: Query dependencies 46 | run: | 47 | install.packages('remotes') 48 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 49 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 50 | shell: Rscript {0} 51 | 52 | - name: Cache R packages 53 | if: runner.os != 'Windows' 54 | uses: actions/cache@v3 55 | with: 56 | path: ${{ env.R_LIBS_USER }} 57 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 58 | restore-keys: | 59 | ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 60 | 61 | #- name: Install system dependencies for linux 62 | #if: runner.os == 'Linux' 63 | #env: 64 | # RHUB_PLATFORM: linux-x86_64-ubuntu-gcc 65 | #run: | 66 | # Rscript -e "remotes::install_github('r-hub/sysreqs')" 67 | # sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))") 68 | # sudo -s eval "$sysreqs" 69 | - name: Install system dependencies for mac 70 | if: runner.os == 'MacOS' 71 | run: | 72 | curl -sL https://mac.r-project.org/libs-4/ | 73 | sed -n 's/.*href=\([^>]*x86_64.tar.gz\).*/\1/p' | 74 | xargs -I % sh -c 'curl https://mac.r-project.org/libs-4/% --output %; sudo tar fvxz % -C /usr/local --strip 2' 75 | ls -la /usr/local/lib 76 | ls -la /usr/local/include 77 | - name: Install dependencies 78 | run: | 79 | remotes::install_deps(dependencies = TRUE) 80 | remotes::install_cran("rcmdcheck") 81 | shell: Rscript {0} 82 | 83 | - name: build package 84 | run: | 85 | install.packages( "remotes" ) 86 | remotes::install_deps(dependencies = TRUE) 87 | shell: Rscript {0} 88 | ... 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | *.o 6 | *.so 7 | *.hpp 8 | *.dll 9 | .Rproj.user/ 10 | 11 | ## Do not ignore this: 12 | !inst/include/stan_meta_header.hpp 13 | src/Makevars 14 | /inst/stan/CCCMGARCH 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | sudo: false 3 | r: devel 4 | cache: packages 5 | 6 | latex: true 7 | 8 | 9 | env: 10 | matrix: 11 | - CXX_OLEVEL=2 CXX=clang++ 12 | 13 | matrix: 14 | include: 15 | - os: linux 16 | compiler: clang 17 | addons: 18 | apt: 19 | sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-5.0' ] 20 | packages: 21 | - llvm-5.0-dev 22 | env: 23 | - CXX_OLEVEL=2 CXX=clang++ 24 | 25 | 26 | before_install: 27 | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y 28 | - sudo apt-get update -q 29 | - sudo apt-get -y install libv8-dev 30 | - mkdir -p ~/.R/ 31 | 32 | script: 33 | - | 34 | travis_wait 42 R CMD build . 35 | travis_wait 59 R CMD check yaml*tar.gz 36 | 37 | after_script: 38 | - tar -ztvf yaml_*.tar.gz 39 | - echo ${NOT_CRAN} 40 | 41 | after_success: 42 | - travis_wait 40 tar -C .. -xf $PKG_TARBALL 43 | 44 | after_failure: 45 | - cat yaml.Rcheck/00* 46 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | [INSERT CONTACT METHOD]. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available 126 | at [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | 134 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to `bmgarch` 2 | 3 | Contributions to `bmgarch` follow the same principles as stated in the guideline for contributors to the `tidyverse` ecosystem of R (see here for more details: [**development contributing guide**](https://rstd.io/tidy-contrib) ). 4 | 5 | ## Fixing typos 6 | 7 | You can refer to [this](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) for proposing changes with pull request from a fork. 8 | You can fix typos, spelling mistakes, or grammatical errors in the documentation directly using the GitHub web interface, as long as the changes are made in the _source_ file. 9 | 10 | If you find any typos in an `.Rd` file, then please make changes in the corresponding `.R` file, as `.Rd` files are automatically generated by [roxygen2](https://roxygen2.r-lib.org/articles/roxygen2.html) and should not be edited by hand. 11 | 12 | ## Bigger changes 13 | 14 | The first step here for you to make any changes is to install `devtools` using `install.packages("devtools")`. 15 | If you want to make a bigger change, it's a good idea to first file an issue and make sure someone from the team agrees that it’s needed. 16 | If you’ve found a bug, please file an issue that illustrates the bug with a minimal reproducible example, a 17 | [reprex](https://www.tidyverse.org/help/#reprex) (this will also help you write a unit test, if needed). 18 | 19 | ### Pull request process 20 | 21 | To contribute a change to `bmgarch`, you follow these steps: 22 | 23 | 1. Create a branch in git, give it a descriptive name, and make your changes. 24 | 2. Push branch to GitHub and issue a pull request (PR). 25 | 3. Discuss the pull request. 26 | 4. Iterate until either we accept the PR or decide that it's not a good fit for `bmgarch`. 27 | 28 | If you're not familiar with git or GitHub, please start by reading 29 | 30 | 31 | Pull requests will be evaluated against a checklist: 32 | 33 | 1. __Motivation__. Your pull request should clearly and concisely motivate the need for change. Please describe the problem your PR addresses and show how your pull request solves it as concisely as possible. 34 | 35 | Also, include this motivation in `NEWS` so that when a new release of 36 | `bmgarch` comes out it's easy for users to see what has changed. Add your 37 | item at the top of the file and use markdown for formatting. The 38 | news item should end with `(@yourGithubUsername, #the_issue_number)`. 39 | 40 | 2. __Only related changes__. Before you submit your pull request, please check to make sure that you haven't accidentally included any unrelated changes. These make it harder to see exactly what's changed, and to evaluate any unexpected side effects. 41 | 42 | Each PR corresponds to a git branch, so if you expect to submit multiple changes 43 | make sure to create multiple branches. If you have multiple changes that depend 44 | on each other, start with the first one and don't submit any others until the 45 | first one has been processed. 46 | 47 | 3. __Use `bmgarch` coding style__. We tried to adhere as closely as possible to the [official `tidyverse` style guide](http://style.tidyverse.org) -- please do so as well. Maintaining a consistent style across the whole code base makes it much easier to jump into the code. If you're modifying existing `bmgarch` code that doesn't follow the style guide, a separate pull request to fix the style would be greatly appreciated. 48 | 49 | 4. If you're adding new parameters or a new function, you'll also need to document them with [`roxygen2`](https://github.com/klutometis/roxygen). Make sure to re-run `devtools::document()` on the code before submitting. 50 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: bmgarch 2 | Title: Bayesian Multivariate GARCH Models 3 | Version: 2.0.0.9000 4 | Authors@R: c( 5 | person(given = "Philippe", 6 | family = "Rast", 7 | role = c("aut", "cre"), 8 | email = "rast.ph@gmail.com", 9 | comment = c(ORCID = "0000-0003-3630-6629")), 10 | person(given = "Stephen", 11 | family = "Martin", 12 | role = c("aut"), 13 | email = "stephenSRMmartin@gmail.com", 14 | comment = c(ORCID = "0000-0001-8085-2390")) 15 | ) 16 | Description: Fit Bayesian multivariate GARCH models using 'Stan' for full Bayesian inference. Generate (weighted) forecasts for means, variances (volatility) and correlations. Currently DCC(P,Q), CCC(P,Q), pdBEKK(P,Q), and BEKK(P,Q) parameterizations are implemented, based either on a multivariate gaussian normal or student-t distribution. DCC and CCC models are based on Engle (2002) and Bollerslev (1990). The BEKK parameterization follows Engle and Kroner (1995) while the pdBEKK as well as the estimation approach for this package is described in Rast et al. (2020) . The fitted models contain 'rstan' objects and can be examined with 'rstan' functions. 17 | License: GPL (>=3) 18 | Depends: 19 | methods, 20 | R (>= 4.0.0), 21 | Rcpp (>= 1.0.5) 22 | Imports: 23 | forecast, 24 | ggplot2, 25 | loo, 26 | MASS, 27 | Rdpack, 28 | rstan (>= 2.26.0), 29 | rstantools (>= 2.1.1) 30 | LinkingTo: 31 | BH (>= 1.72.0-0), 32 | Rcpp (>= 1.0.5), 33 | RcppParallel (>= 5.0.1), 34 | RcppEigen (>= 0.3.3.7.0), 35 | RcppParallel (>= 5.0.1), 36 | rstan (>= 2.26.0), 37 | StanHeaders (>= 2.26.0) 38 | RdMacros: Rdpack 39 | Encoding: UTF-8 40 | LazyData: true 41 | NeedsCompilation: yes 42 | SystemRequirements: GNU make 43 | RoxygenNote: 7.3.2 44 | Suggests: 45 | testthat (>= 2.3.2) 46 | BugReports: https://github.com/ph-rast/bmgarch/issues 47 | Biarch: true 48 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(as.data.frame,fitted.bmgarch) 4 | S3method(as.data.frame,forecast.bmgarch) 5 | S3method(fitted,bmgarch) 6 | S3method(forecast,bmgarch) 7 | S3method(loo,bmgarch) 8 | S3method(plot,bmgarch) 9 | S3method(plot,forecast.bmgarch) 10 | S3method(print,fitted.bmgarch) 11 | S3method(print,forecast.bmgarch) 12 | S3method(print,loo.bmgarch) 13 | S3method(print,model_weights) 14 | S3method(print,summary.bmgarch) 15 | S3method(summary,bmgarch) 16 | export(bmgarch) 17 | export(bmgarch_list) 18 | export(forecast) 19 | export(loo) 20 | export(model_weights) 21 | import(Rcpp) 22 | import(ggplot2) 23 | import(methods) 24 | import(rstantools) 25 | importFrom(Rdpack,reprompt) 26 | importFrom(forecast,forecast) 27 | importFrom(grDevices,devAskNewPage) 28 | importFrom(graphics,plot) 29 | importFrom(loo,loo) 30 | importFrom(rstan,sampling) 31 | importFrom(stats,fitted) 32 | importFrom(stats,quantile) 33 | importFrom(stats,rnorm) 34 | importFrom(stats,sd) 35 | importFrom(stats,var) 36 | importFrom(stats,weights) 37 | useDynLib(bmgarch, .registration = TRUE) 38 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # bmgarch (development version) 2 | 3 | # bmgarch 2.0.0 4 | 5 | * All stan models are rewritten to match the new `rstan 2.26.0` array syntax. 6 | 7 | # bmgarch 1.1.0 8 | 9 | * Meanstructure now also takes the `VAR` argument for a VAR(1) model. 10 | * Added variational Bayes `VB` as a sampling algorithm option. bmgarch now takes `VB` and the standard `MCMC` argument in sampling_algorithm. `VB` is inherited from `rstan` and is still experimental - use with caution. 11 | * Updated rstantools to facilitate rstan upgrade (according to rstan developer guide) 12 | * standat now checks for constant vectors in data, and returns error if there's no variance (cf. discourse [mc-stan](https://discourse.mc-stan.org/t/getting-rejected-initial-values-running-bmgarch-in-r/24002)) 13 | 14 | # bmgarch 1.0.1 15 | 16 | * `loo` function now takes `m`-ahead argument for the "backward" approximation allowing one to tune the forcast to arbitrary steps ahead. 17 | 18 | * Fixed package dependency versions. 19 | 20 | # bmgarch 1.0.0 21 | Initial CRAN release 22 | -------------------------------------------------------------------------------- /R/bmgarch-package.R: -------------------------------------------------------------------------------- 1 | #' The 'bmgarch' package. 2 | #' 3 | #' @description The *bmgarch* package fits Bayesian multivariate GARCH models specified via Stan, 4 | #' a C++ package providing HMC methods for full Bayesian inference (cf. [http://mc-stan.org]). The currently implemented parameterizations are DCC(Q,P), 5 | #' CCC(Q,P), and BEKK(Q,P) with arbitrary lags defined in Q, and P. The package provides summaries and plots for the estimates as well 6 | #' as forecasted series with corresponding plots. The fitted objects are rstan class objects that can be inspected and manipulated 7 | #' accordingly. 8 | #' 9 | #' @author Philippe Rast 10 | #' 11 | #' @keywords internal 12 | #' @name bmgarch-package 13 | #' @useDynLib bmgarch, .registration = TRUE 14 | #' @import methods 15 | #' @import Rcpp 16 | #' @import rstantools 17 | #' @importFrom rstan sampling 18 | #' 19 | #' @references 20 | #' Stan Development Team (2018). RStan: the R interface to Stan. R package version 2.18.2. http://mc-stan.org 21 | #' 22 | "_PACKAGE" 23 | -------------------------------------------------------------------------------- /R/bmgarch.R: -------------------------------------------------------------------------------- 1 | #' Standardize input data to facilitate computation 2 | #' 3 | #' @param data Time-series data 4 | #' @param xC Numeric vector or matrix. 5 | #' @param P Numeric. 6 | #' @param Q Numeric. 7 | #' @param standardize_data Logical. 8 | #' @param distribution Character. 9 | #' @param meanstructure Character. 10 | #' @return bmgarch stan data list. 11 | #' @importFrom stats var 12 | #' @keywords internal 13 | standat <- function(data, xC, P, Q, standardize_data, distribution, meanstructure){ 14 | 15 | if(dim(data)[1] < dim(data)[2]) { 16 | data = t(data) 17 | warning("data is wider than it is long. Transposing...") 18 | } 19 | if ( is.null( colnames( data ) ) ) colnames( data ) = paste0('t', 1:ncol( data ) ) 20 | 21 | ## Model for meanstructure 22 | if( meanstructure == "constant" | meanstructure == 0 ) { 23 | meanstructure <- 0 24 | } else if ( meanstructure == "arma" | meanstructure == "ARMA" | meanstructure == 1 ){ 25 | meanstructure <- 1 26 | } else if ( meanstructure == "var" | meanstructure == "VAR" | meanstructure == 2) { 27 | meanstructure <- 2 28 | } else { 29 | stop("meanstructure must be either 'constant', 'ARMA' or 'VAR'.") 30 | } 31 | 32 | ## Test that all data vectors have variance > 0 33 | ## Stop if a vector has zero variance 34 | dvar <- apply(data, 2, var ) 35 | if( sum(ifelse(dvar == 0, 1, 0)) > 0 ) stop( 36 | paste0("Datavector ", names(which(dvar == 0 ) ), " has zero variance.") ) 37 | 38 | ## Tests on predictor 39 | ## Pass in a 0 matrix, so that stan does not complain 40 | if ( is.null(xC) ) { 41 | xC = matrix(0, nrow = nrow(data), ncol = ncol(data)) 42 | } 43 | ## Match dimension of predictor to TS. If only one vector is given, it's assumed that it is the same for all TS's 44 | if ( is.null(ncol(xC)) ) { 45 | warning("xC is assumed constant across TS's") 46 | xC <- matrix(xC, nrow = nrow(data), ncol = ncol(data)) ## Risky, better to throw an error 47 | } else if ( dim( xC )[2] != dim( data )[2] ) { ## xC is not a vector - check if it is of right dimension 48 | warning("xC is not of right dimension - adapt xC dimension to match number of TS") 49 | } 50 | 51 | if( standardize_data ) { 52 | ## Standardize time-series 53 | stdx <- scale(data) 54 | centered_data <- attr(stdx, "scaled:center") 55 | scaled_data <- attr(stdx, "scaled:scale") 56 | return_standat <- list(T = nrow(stdx), 57 | rts = stdx, 58 | xC = xC, 59 | nt = ncol(stdx), 60 | centered_data = centered_data, 61 | scaled_data = scaled_data, 62 | distribution = distribution, 63 | P = P, 64 | Q = Q, 65 | meanstructure = meanstructure) 66 | } else { 67 | ## Unstandardized 68 | return_standat <- list(T = nrow(data), 69 | rts = data, 70 | xC = xC, 71 | nt = ncol(data), 72 | distribution = distribution, 73 | P = P, 74 | Q = Q, 75 | meanstructure = meanstructure) 76 | } 77 | return(return_standat) 78 | } 79 | 80 | ##' Draw samples from a specified multivariate GARCH model using 'Stan', given multivariate time-series. Currently supports CCC, DCC, BEKK, and pdBEKK model parameterizations. 81 | ##' 82 | ##' Four types of paramerizations are implemented. The constant conditional correlation (CCC) and the dynamic conditional correlation \insertCite{@DCC; Engle2002,Engle2001a}{bmgarch}, as well as BEKK \insertCite{Engle1995}{bmgarch} and a BEKK model with positivity constraints on the diagonals of the ARCH and GARCH parameters "pdBEKK" \insertCite{Rast2020}{bmgarch}. 83 | ##' 84 | ##' The fitted models are 'rstan' objects and all posterior parameter estimates can be obtained and can be examined with either the 'rstan' toolbox, plotted and printed using generic functions or passed to 'bmgarch' functions to 'forecast' or compute 'model_weights' or compute fit statistics based on leave-future-out cross-validation. 85 | ##' 86 | ##' @title Estimate Bayesian Multivariate GARCH 87 | ##' @param data Time-series or matrix object. A time-series or matrix object containing observations at the same interval. 88 | ##' @param xC Numeric vector or matrix. Covariates(s) for the constant variance terms in C, or c, used in a log-linear model on the constant variance terms \insertCite{Rast2020}{bmgarch}. If vector, then it acts as a covariate for all constant variance terms. If matrix, must have columns equal to number of time series, and each column acts as a covariate for the respective time series (e.g., column 1 predicts constant variance for time series 1). 89 | ##' @param parameterization Character (Default: "CCC"). The type of of parameterization. Must be one of "CCC", "DCC", "BEKK", or "pdBEKK". 90 | ##' @param P Integer. Dimension of GARCH component in MGARCH(P,Q). 91 | ##' @param Q Integer. Dimension of ARCH component in MGARCH(P,Q). 92 | ##' @param iterations Integer (Default: 2000). Number of iterations for each chain (including warmup). 93 | ##' @param chains Integer (Default: 4). The number of Markov chains. 94 | ##' @param standardize_data Logical (Default: FALSE). Whether data should be standardized to easy computations. 95 | ##' @param distribution Character (Default: "Student_t"). Distribution of innovation: "Student_t" or "Gaussian" 96 | ##' @param meanstructure Character (Default: "constant"). Defines model for means. Either 'constant' or 'ARMA'. Currently ARMA(1,1) only. OR 'VAR' (VAR1). 97 | ##' @param sampling_algorithm Character (Default" "MCMC"). Define sampling algorithm. Either 'MCMC'for Hamiltonian Monte Carlo or 'VB' for variational Bayes. 'VB' is inherited from stan and is currently in heavy development -- do not trust estimates. 98 | ##' @param backend Select backend. Defaults to 'rstan' or select 'cmdstanr' if installed. 99 | ##' @param ... Additional arguments can be ‘chain_id’, ‘init_r’, ‘test_grad’, ‘append_samples’, ‘refresh’, ‘enable_random_init’ etc. See the documentation in \code{\link[rstan]{stan}}. 100 | ##' @return \code{bmgarch} object. 101 | ##' @importFrom Rdpack reprompt 102 | ##' @author Philippe Rast, Stephen R. Martin 103 | ##' @references 104 | ##' \insertAllCited() 105 | ##' @export 106 | ##' @examples 107 | ##' \dontrun{ 108 | ##' data(panas) 109 | ##' # Fit BEKK(1,1) mgarch model with a ARMA(1,1) meanstructure, 110 | ##' # and student-t residual distribution 111 | ##' fit <- bmgarch(panas, parameterization = "BEKK", 112 | ##' P = 1, Q = 1, 113 | ##' meanstructure = "arma", 114 | ##' distribution = "Student_t") 115 | ##' 116 | ##' # Summarize the parameters 117 | ##' summary(fit) 118 | ##' 119 | ##' # Forecast 5 ahead 120 | ##' fit.fc <- forecast(fit, ahead = 5) 121 | ##' print(fit.fc) 122 | ##' 123 | ##' # Plot mean forecasts 124 | ##' plot(fit.fc, type = "mean") 125 | ##' 126 | ##' # Plot variance forecasts 127 | ##' plot(fit.fc, type = "var") 128 | ##' 129 | ##' # Plot correlation forecasts 130 | ##' plot(fit.fc, type = "cor") 131 | ##' 132 | ##' # Plot modeled data ("backcasted values"). 133 | ##' plot(fit, type = "mean") 134 | ##' 135 | ##' # Save "backcasted" values 136 | ##' fit.bc <- fitted(fit) 137 | ##' 138 | ##' # Save estimated and forecasted data as a data.frame 139 | ##' df.fc <- as.data.frame(fit.fc) 140 | ##' 141 | ##' # Access rstan's model fit object 142 | ##' mf <- fit$model_fit 143 | ##' 144 | ##' # Return diagnostics and a plot of the first 10 parameters 145 | ##' rstan::check_hmc_diagnostics(mf) 146 | ##' rstan::plot(mf) 147 | ##' } 148 | bmgarch <- function(data, 149 | xC = NULL, 150 | parameterization = "CCC", 151 | P = 1, 152 | Q = 1, 153 | iterations = 2000, 154 | chains = 4, 155 | standardize_data = FALSE, 156 | distribution = "Student_t", 157 | meanstructure = "constant", 158 | sampling_algorithm = "MCMC", 159 | backend = "rstan", ...) { 160 | if ( tolower(distribution) == "gaussian" ) { 161 | num_dist <- 0 162 | } else if ( tolower(distribution) == "student_t" ) { 163 | num_dist <- 1 164 | } else { 165 | stop( "\n\n Specify distribution: Gaussian or Student_t \n\n") 166 | } 167 | 168 | return_standat <- standat(data, xC, P, Q, standardize_data, distribution = num_dist, meanstructure ) 169 | stan_data <- return_standat[ c("T", "xC", "rts", "nt", "distribution", "P", "Q", "meanstructure")] 170 | 171 | if(backend == 'rstan') { 172 | stanmodel <- switch(parameterization, 173 | CCC = stanmodels$CCCMGARCH, 174 | DCC = stanmodels$DCCMGARCH, 175 | BEKK = stanmodels$BEKKMGARCH, 176 | pdBEKK = stanmodels$pdBEKKMGARCH, 177 | NULL) 178 | } else if(backend == 'cmdstanr') { 179 | stan_path <- .get_target_stan_path() 180 | 181 | ccc_file <- file.path(stan_path, "CCCMGARCH.stan" ) 182 | dcc_file <- file.path(stan_path, "DCCMGARCH.stan" ) 183 | bekk_file <-file.path(stan_path, "BEKKMGARCH.stan" ) 184 | pdbekk_file <-file.path(stan_path, "pdBEKKMGARCH.stan" ) 185 | stanmodel <- switch(parameterization, 186 | CCC = cmdstanr::cmdstan_model(ccc_file, include_paths = stan_path, 187 | cpp_options = list(stan_threads = TRUE)), 188 | DCC = cmdstanr::cmdstan_model(dcc_file, include_paths = stan_path, 189 | cpp_options = list(stan_threads = TRUE)), 190 | BEKK = cmdstanr::cmdstan_model(bekk_file, include_paths = stan_path, 191 | cpp_options = list(stan_threads = TRUE)), 192 | pdBEKK = cmdstanr::cmdstan_model(pdbekk_file, include_paths = stan_path, 193 | cpp_options = list(stan_threads = TRUE)), 194 | NULL) 195 | } 196 | if(is.null(stanmodel)) { 197 | stop("Not a valid model specification. ", 198 | parameterization, 199 | "must be one of: ", 200 | paste0(supported_models, collapse = ", "), 201 | ".") 202 | } 203 | 204 | ## MCMC Sampling with NUTS 205 | if(sampling_algorithm == 'MCMC' ) { 206 | model_fit <- rstan::sampling(stanmodel, 207 | data = stan_data, 208 | verbose = TRUE, 209 | iter = iterations, 210 | control = list(adapt_delta = .99), 211 | chains = chains, 212 | init_r = .05, ...) 213 | } else if (sampling_algorithm == 'VB' ) { 214 | if(backend == 'rstan') { 215 | ## Sampling via Variational Bayes 216 | model_fit <- rstan::vb(stanmodel, 217 | data = stan_data, 218 | iter = iterations, 219 | importance_resampling = TRUE, ...) 220 | } else if (backend == 'cmdstanr') { 221 | model_fit <- stanmodel$variational(stanmodel, 222 | data = stan_data, 223 | iter = iterations, 224 | ...) 225 | } else { 226 | stop("Invalid backend specified.") 227 | } 228 | } else { 229 | stop( "\n\n Provide sampling algorithm: 'MCMC' or 'VB'\n\n" ) 230 | } 231 | 232 | ## Model fit is based on standardized values. 233 | mns <- return_standat$centered_data 234 | sds <- return_standat$scaled_data 235 | ## Values could be converted to original scale using something like this on the estimates 236 | ## orig_sd = stan_data$rts %*% diag(sds) 237 | ## orig_scale = orig_sd + array(rep(mns, each = aussi[[1]]$T), dim = c(aussi[[1]]$T, aussi[[1]]$nt) ) 238 | return_fit <- list(model_fit = model_fit, 239 | param = parameterization, 240 | distribution = distribution, 241 | num_dist = num_dist, 242 | iter = iterations, 243 | chains = chains, 244 | elapsed_time = rstan::get_elapsed_time(model_fit), 245 | date = date(), 246 | nt = stan_data$nt, 247 | TS_length = stan_data$T, 248 | TS_names = colnames(stan_data$rts), 249 | RTS_last = stan_data$rts[stan_data$T,], 250 | RTS_full = stan_data$rts, 251 | mgarchQ = stan_data$Q, 252 | mgarchP = stan_data$P, 253 | xC = stan_data$xC, 254 | meanstructure = stan_data$meanstructure, 255 | std_data = standardize_data, 256 | sampling_algorithm = sampling_algorithm) 257 | class(return_fit) <- "bmgarch" 258 | return(return_fit) 259 | } 260 | 261 | 262 | #' Models supported by bmgarch 263 | #' 264 | #' To be used when checking whether a parameterization or object type is a supported type. 265 | #' May facilitate more parameterizations, as we only have to update these, and the switch statements. 266 | #' @keywords internal 267 | #' @author Philippe Rast and Stephen R. Martin 268 | supported_models <- c("DCC", "CCC", "BEKK", "pdBEKK") 269 | -------------------------------------------------------------------------------- /R/cmdstan_path.R: -------------------------------------------------------------------------------- 1 | ##' Internal function to obtain stan code paths 2 | ##' @title Path to stan files 3 | ##' @return Full path to folder containing stan files 4 | ##' @author philippe 5 | ##' @keywords internal 6 | .get_target_stan_path <- function() { 7 | package_path <- 8 | system.file(package = "bmgarch", "stan") 9 | return(package_path) 10 | } 11 | -------------------------------------------------------------------------------- /R/helper.R: -------------------------------------------------------------------------------- 1 | ## obtain MA piece for Forecasting 2 | ##' @title Multiply matrices in array with a vector 3 | ##' @param MA 4 | ##' @param theta 5 | ##' @param mu 6 | ##' @param rts 7 | ##' @param i 8 | ##' @return matrix 9 | ##' @author Philippe Rast 10 | ##' @keywords internal 11 | .f_MA = function(MA, theta, mu, rts, i){ 12 | res = ( -sweep( mu, 2, rts ) ) 13 | MA[i,] = t( theta[i, ,] %*% res[i,] ) 14 | } 15 | 16 | ##' @title Multiply matrices in array with a vector -- generic 17 | ##' @param mat_out 18 | ##' @param array_obj 19 | ##' @param mat_obj 20 | ##' @param i 21 | ##' @return matrix 22 | ##' @author Philippe Rast 23 | ##' @keywords internal 24 | .f_array_x_mat = function(mat_out, array_obj, mat_obj, i){ 25 | mat_out[i,] = t( array_obj[i, ,] %*% mat_obj[i,] ) 26 | } 27 | 28 | ##' @title Internal function to be used in sweep() 29 | ##' @param x Value to be squared 30 | ##' @return Squared value 31 | ##' @author Philippe Rast 32 | ##' @keywords internal 33 | .square = function(x){ 34 | x^2 35 | } 36 | 37 | ##' @title Internal function 38 | ##' @param x stan objec 39 | ##' @keywords internal 40 | .cp = function(x){ 41 | cls = length( x ) 42 | x_a = array( x, dim = c(cls, 1) ) 43 | x_a %*% t( x_a ) 44 | } 45 | 46 | ##' @title Internal function to be used 47 | ##' @param x 48 | ##' @keywords internal 49 | ##' @importFrom stats quantile 50 | .qtile <- function(x, CrI = c(.025, .975) ) { 51 | cis <- quantile(x, CrI ) 52 | return(cis) 53 | } 54 | -------------------------------------------------------------------------------- /R/lfocv.R: -------------------------------------------------------------------------------- 1 | ##' @title Refit model 2 | ##' @param object bmgarch model object 3 | ##' @param data new data 4 | ##' @param xC_data new predictor 5 | ##' @keywords internal 6 | .refit <- function(object, data, xC_data ) { 7 | fit_past <- bmgarch(data, 8 | xC = xC_data, 9 | parameterization = object$param, 10 | P = object$mgarchP, 11 | Q = object$mgarchQ, 12 | chains = object$chains, 13 | iterations = object$iter, 14 | standardize_data = FALSE, 15 | distribution = object$distribution, 16 | meanstructure = object$meanstructure, 17 | sampling_algorithm = object$sampling_algorithm) 18 | } 19 | 20 | ##' @keywords internal 21 | ## compute log of raw importance ratios 22 | ## sums over observations *not* over posterior samples 23 | .sum_log_ratios <- function(ll, ids = NULL) { 24 | if (!is.null(ids)) ll <- ll[, ids , drop = FALSE] 25 | - rowSums(ll) 26 | } 27 | 28 | ##' @keywords internal 29 | ## more stable than log(sum(exp(x))) 30 | .log_sum_exp <- function(x) { 31 | max_x <- max(x) 32 | max_x + log(sum(exp(x - max_x))) 33 | } 34 | 35 | ##' @keywords internal 36 | .log_lik <- function(x) { 37 | rstan::extract(x$model_fit, pars = "log_lik")$log_lik 38 | } 39 | 40 | ##' @keywords internal 41 | ## more stable than log(mean(exp(x))) 42 | .log_mean_exp <- function(x) { 43 | .log_sum_exp(x) - log(length(x)) 44 | } 45 | 46 | ##' \code{lfocv} returns the LFO-CV ELPD by either computing the exact ELDP or 47 | ##' by approximating it via 48 | ##' forward or backward approximation strategies based on Pareto smoothed 49 | ##' importance sampling 50 | ##' described in \insertCite{Buerkner2019}{bmgarch}. 51 | ##' @title Leave-Future-Out Cross Validation (LFO-CV) 52 | ##' @param x Fitted bmgarch model. \code{lfocv} inherits all attributes 53 | ##' from the bmgarch object 54 | ##' @param type Takes \code{lfo} (default) or \code{loo}. LFO-CV is recommended 55 | ##' for time-series but LOO-CV may be obtained to assess the structural part of the model. 56 | ##' @param L Minimal length of times series before computing LFO 57 | ##' @param M M step head predictions. Defines to what period the LFO-CV should be tuned to. Defaults to M=1. 58 | ##' @param mode backward elpd_lfo approximation, or exact elpd-lfo; 59 | ##' Takes 'backward', and 'exact'. 'exact' fits N-L models and may 60 | ##' take a \emph{very} long time to complete. \code{forward} works too but is not 61 | ##' complete yet. 62 | ##' @param ... Not used 63 | ##' @return Approximate LFO-CV value and log-likelihood values across (L+1):N 64 | ##' timepoints 65 | ##' @references 66 | ##' \insertAllCited{} 67 | ##' @aliases loo 68 | ##' @importFrom loo loo 69 | ##' @importFrom stats sd weights 70 | ##' @examples 71 | ##' \dontrun{ 72 | ##' data(stocks) 73 | ##' # Fit a DCC model 74 | ##' fit <- bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 75 | ##' parameterization = "DCC", standardize_data = TRUE, 76 | ##' iterations = 500) 77 | ##' 78 | ##' # Compute expected log-predictive density (elpd) using the backward mode 79 | ##' # L is the upper boundary of the time-series before we engage in LFO-CV 80 | ##' lfob <- loo(fit, mode = 'backward', L = 50 ) 81 | ##' print(lfob) 82 | ##' } 83 | ##' @export 84 | ##' @export loo 85 | loo.bmgarch <- function(x, ..., type = 'lfo', L = NULL, M = 1, mode = "backward") { 86 | object <- x 87 | ahead <- M 88 | N <- object$TS_length 89 | ## List for returned objects 90 | outl <- list( ) 91 | 92 | ## "Classic" loo, based on backcasted log_lik 93 | if( type == 'loo' ) { 94 | if( is.null( L ) ) L <- 0 95 | ll <- rstan::extract(object$model_fit, pars = "log_lik")$log_lik 96 | LL <- ll[, (L + 1):N] 97 | ## obtain chain id vector for relative_eff 98 | n_chains <- object$model_fit@sim$chains 99 | n_samples <- object$model_fit@sim$iter - object$model_fit@sim$warmup 100 | chain_id <- rep(seq_len(n_chains ), each = n_samples ) 101 | r_eff <- loo::relative_eff(exp(LL), chain_id = chain_id) 102 | backcast_loo <- loo::loo( LL, r_eff = r_eff ) 103 | outl$backcast_loo <- backcast_loo$estimates[,'Estimate']['elpd_loo'] 104 | outl$type <- type 105 | } else if ( type == 'lfo' ) { 106 | if( is.null( L ) ) stop( "Provide L, length of time-series before fitting computing LFO-CV") 107 | 108 | ## Backward approach: start with log_lik from fully fitted model with all observations 109 | ## Go backwards until k threshold is reched and refit 110 | 111 | loglik <- matrix(nrow = dim( .log_lik( object ) )[1], ncol = N) 112 | approx_elpds_1sap <- rep(NA, N) 113 | ks <- NULL 114 | 115 | refits <- ks <- NULL 116 | 117 | if( mode == "backward" ) { 118 | k_thres <- 0.6 # Threshold of .6 based on Buerkner at al (2020) paper 119 | fit_past <- object 120 | i_refit <- N 121 | 122 | for (i in seq((N - ahead), L, by = -ahead) ) { 123 | loglik[, (i + 1):( i + ahead)] <- .log_lik(fit_past)[, (i + 1):( i + ahead)] 124 | logratio <- .sum_log_ratios(loglik, (i + 1):i_refit) 125 | psis_obj <- suppressWarnings(loo::psis(logratio)) 126 | k <- loo::pareto_k_values(psis_obj) 127 | ks <- c(ks, k) 128 | if (k > k_thres) { 129 | ## refit the model based on the first i observations 130 | i_refit <- i 131 | refits <- c(refits, i) 132 | past <- 1:i 133 | oos <- (i+1):(i+ahead) 134 | df_past <- object$RTS_full[past, , drop = FALSE] 135 | xC_past <- object$xC[past, , drop = FALSE] 136 | df_oos <- object$RTS_full[c(past, oos), , drop = FALSE] 137 | xC_oos <- object$xC[c(past, oos), , drop = FALSE] 138 | fit_past <- .refit(object, data = df_past, xC_data = xC_past ) 139 | fc <- bmgarch::forecast(object = fit_past, ahead = ahead, 140 | xC = xC_oos[oos, ,drop = FALSE], 141 | newdata = df_oos[oos,,drop = FALSE]) 142 | loglik[, (i+1):(i+ahead) ] <- fc$forecast$log_lik[[1]] 143 | if(ahead == 1 ) { 144 | approx_elpds_1sap[ i+1 ] <- .log_mean_exp(loglik[, i+1 ]) 145 | } else { 146 | approx_elpds_1sap[(i+1):(i+ahead)] <- 147 | apply(loglik[, (i+1):(i+ahead) ], MARGIN = 2, FUN = .log_mean_exp ) 148 | } 149 | } else { 150 | lw <- weights(psis_obj, normalize = TRUE)[, 1] 151 | if(ahead == 1 ) { 152 | approx_elpds_1sap[ i+1 ] <- .log_sum_exp(lw + loglik[, i+1 ]) 153 | } else { 154 | approx_elpds_1sap[(i+1):(i+ahead)] <- 155 | apply((lw + loglik[, (i+1):(i+ahead)]),2,.log_sum_exp ) 156 | } 157 | } 158 | } 159 | out <- approx_elpds_1sap 160 | 161 | } else if ( mode == "forward" ) { 162 | warn <- function() warning("'forward' method not fully implemented") 163 | if( mode == 'forward' ) warn( ) 164 | 165 | k_thres <- 0.7 166 | 167 | out <- rep( NA, N ) 168 | exact_elpds_1sap <- rep( NA, N ) 169 | 170 | df_dat <- object$RTS_full 171 | xC_dat <- object$xC 172 | 173 | oos <- L + 1 174 | 175 | ## Refit the model using the first L observations 176 | df_start <- object$RTS_full[1:L, , drop = FALSE] 177 | xC_start <- object$xC[1:L, , drop = FALSE] 178 | fit_start <- .refit(object, data = df_start, xC_data = xC_start ) 179 | 180 | ## Exact ELPD: Computed from log_lik of forecast function 181 | fc <- bmgarch::forecast(fit_start, ahead = ahead, 182 | xC = xC_dat[ oos, , drop = FALSE], 183 | newdata = df_dat[ oos, ,drop = FALSE]) 184 | 185 | ## Exact log_lik 186 | loglik[, oos ] <- fc$forecast$log_lik[[1]] 187 | exact_elpds_1sap[ L ] <- .log_mean_exp( loglik[, oos ] ) 188 | out[ L ] <- exact_elpds_1sap[L] 189 | ## Also write content to approx_elpds as the summary for 190 | ## "forward" is obtained over all approx_elpds's 191 | approx_elpds_1sap[ L ] <- exact_elpds_1sap[L] 192 | i_refit <- L + 1 193 | 194 | if( L < N - ahead ) { 195 | for (i in (L + 1):(N-ahead) ) { 196 | 197 | logratio <- .sum_log_ratios(loglik, i_refit:i )#(L+1):(i+1)) 198 | psis_obj <- suppressWarnings(loo::psis(logratio)) 199 | k <- loo::pareto_k_values(psis_obj) 200 | ks <- c(ks, k) 201 | print( ks ) 202 | if( k > k_thres ) { 203 | refits <- c(refits, i) 204 | 205 | df_start <- object$RTS_full[1:i, , drop = FALSE] 206 | xC_start <- object$xC[1:i, , drop = FALSE] 207 | 208 | fit_start <- .refit(object, data = df_start, xC_data = xC_start ) 209 | ahead <- 1 210 | fc <- bmgarch::forecast(fit_start, ahead = ahead, 211 | xC = xC_dat[ i+1, , drop = FALSE], 212 | newdata = df_dat[ i+1, ,drop = FALSE]) 213 | 214 | ## Exact log_lik 215 | loglik[, i+1 ] <- fc$forecast$log_lik[[1]] 216 | 217 | exact_elpds_1sap[ i ] <- .log_mean_exp( loglik[, i+1 ] ) 218 | 219 | logratio <- .sum_log_ratios(loglik, i+1 )#(L+1):(i+1)) 220 | out[ i ] <- exact_elpds_1sap[ i ] 221 | psis_obj <- suppressWarnings(loo::psis(logratio)) 222 | k <- loo::pareto_k_values(psis_obj) 223 | i_refit <- i+1 224 | #k <- 0 225 | } else { 226 | lw <- weights(psis_obj, normalize = TRUE)[, 1] 227 | ahead <- ( i+1 )-( i_refit-1 ) 228 | fc <- bmgarch::forecast(fit_start, ahead = ahead, 229 | xC = xC_dat[ ( i_refit ):(i+1), , drop = FALSE], 230 | newdata = df_dat[ ( i_refit ):(i+1), ,drop = FALSE]) 231 | 232 | loglik[, i+1 ] <- fc$forecast$log_lik[[1]][, ahead] 233 | approx_elpds_1sap[ i ] <- .log_sum_exp(lw + loglik[, i+1 ]) 234 | out[i] <- approx_elpds_1sap[ i ] 235 | } 236 | } 237 | } 238 | } else if (mode == "exact" ) { 239 | k_thres <- 0 240 | refits <- N - ( L+1 ) 241 | df_dat <- object$RTS_full 242 | xC_dat <- object$xC 243 | exact_elpds_1sap <- rep( NA, N ) 244 | 245 | for(i in L:( N-1 ) ) { 246 | fit_start <- .refit(object, data = df_dat[1:i, , drop = FALSE], xC_data = xC_dat[1:i, , drop = FALSE] ) 247 | fc <- bmgarch::forecast(fit_start, ahead = ahead, xC = xC_dat[ i+1, , drop = FALSE], newdata = df_dat[ i+1, ,drop = FALSE]) 248 | loglik[, i+1 ] <- fc$forecast$log_lik[[1]] 249 | } 250 | loglik_exact <- loglik[, (L+1):N] 251 | exact_elpds_1sap <- apply(loglik_exact, 2, .log_mean_exp ) 252 | out <- exact_elpds_1sap 253 | } else { 254 | stop("'mode' needs to be either 'forward', 'backward' or 'exact'." ) 255 | } 256 | 257 | 258 | refit_info <- cat("Using threshold ", k_thres, 259 | ", model was refit ", length(refits), 260 | " times, at observations", refits, "\n") 261 | 262 | ## Return relevant objects 263 | 264 | outl$refits <-refits 265 | outl$ks <- ks 266 | outl$approx_elpd_1sap <- sum( approx_elpds_1sap, na.rm = TRUE ) 267 | outl$out <- out 268 | outl$mode <- mode 269 | outl$L <- L 270 | outl$type <- type 271 | 272 | outl$loglik <- loglik[, ( L + 1 ):N ] 273 | } 274 | 275 | attr(outl, "class" ) <- "loo.bmgarch" 276 | return( outl ) 277 | } 278 | 279 | ##' @title print method for lfocv 280 | ##' @param x lfo object 281 | ##' @param ... Not used. 282 | ##' @return Invisible lfocv object 283 | ##' @author philippe 284 | ##' @export 285 | print.loo.bmgarch <- function( x, ... ) { 286 | if( x$type == 'loo' ) { 287 | cat('elpd_loo ', x$backcast_loo) 288 | } else if( x$type == 'lfo' ) { 289 | if(x$mode == 'backward' | x$mode == 'forward' ) { 290 | cat("Model was fit using ", x$mode, " mode.\n") 291 | cat("Approximate ELPD_LFO: ", x$approx_elpd_1sap, "\n" ) 292 | } else if(x$mode == 'exact' ){ 293 | cat("Model was fit using ", x$mode, " mode.\n") 294 | cat("Exact ELPD_LFO: ", sum( x$out, na.rm = TRUE), "\n" ) 295 | } 296 | } 297 | return(invisible(x)) 298 | } 299 | -------------------------------------------------------------------------------- /R/model_weights.R: -------------------------------------------------------------------------------- 1 | ##' @keywords internal 2 | ##' @author philippe 3 | .ll_lfo <- function(x, L = NA, M = M, mode = 'backward') { 4 | loo( x, type = 'lfo', L = L, M = M, mode = mode)$loglik 5 | } 6 | 7 | ##' @keywords internal 8 | .rel_eff <- function(ll, x) { 9 | warmup <- x$model_fit@sim$warmup 10 | iter <- x$model_fit@sim$iter 11 | n_chains <- x$model_fit@sim$chains 12 | loo::relative_eff( exp(ll), 13 | chain_id = rep(1:n_chains, each = iter-warmup )) 14 | } 15 | 16 | ##' Compute model weights for a list of candidate models based on leave-future-out 17 | ##' cross validation (lfocv) expected log-predictive density (elpd). 18 | ##' elpd can be approximated via the 'backward' mode described in \insertCite{Buerkner2019;textual}{bmgarch} or via exact cross-validation. 19 | ##' The obtained weights can be passed to the forecast function to obtain weighted forecasts. 20 | ##' \code{bmgarch_objects} takes a \code{bmgarch_object} lists. 21 | ##' @title Model weights 22 | ##' @param bmgarch_objects list of bmgarch model objects in \code{bmgarch_object} 23 | ##' @param L Minimal length of time series before engaging in lfocv 24 | ##' @param M M step head predictions. Defines to what period the LFO-CV should be tuned to. Defaults to M=1. 25 | ##' @param method Ensemble methods, 'stacking' (default) or 'pseudobma' 26 | ##' @param mode Either 'backward' (default) or 'exact' 27 | ##' @return Model weights 28 | ##' @details 29 | ##' `model_weights()` is a wrapper around the leave-future-out 'lfo' type in `loo.bmgarch()`. 30 | ##' The weights can be either obtained from an approximate or exact leave-future-out cross-validation 31 | ##' to compute expected log predictive density (ELPD). 32 | ##' 33 | ##' We can either obtain stacking weights or pseudo-BMA+ weigths as described in \insertCite{Yao2018}{bmgarch}. 34 | ##' @examples 35 | ##' \dontrun{ 36 | ##' data(stocks) 37 | ##' # Fit at least two models on a subset of the stocks data 38 | ##' # to compute model weights 39 | ##' fit <- bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 40 | ##' parameterization = "DCC", standardize_data = TRUE, 41 | ##' iterations = 500) 42 | ##' 43 | ##' fit2 <- bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 44 | ##' P = 2, Q = 2, 45 | ##' parameterization = "DCC", standardize_data = TRUE, 46 | ##' iterations = 500) 47 | ##' # create a bmgarch_list object 48 | ##' blist <- bmgarch_list(fit, fit2 ) 49 | ##' 50 | ##' # Compute model weights with the default stacking metod 51 | ##' # L is the upper boundary of the time-series before we engage in LFO-CV 52 | ##' mw <- model_weights( blist, L = 50, method = 'stacking', order = 'backwards' ) 53 | ##' 54 | ##' # Print model weights in the ordert of the bmgarch_list() 55 | ##' print(mw) 56 | ##' } 57 | ##' @references 58 | ##' \insertAllCited{} 59 | ##' @export 60 | model_weights <- function(bmgarch_objects = NULL, 61 | L = NULL, M = 1, 62 | method = "stacking", mode = 'backward') { 63 | 64 | ## Check if model list is based on same alogrithm, if not, stop 65 | same_algo <- length(unique(lapply(bmgarch_objects, FUN = function(x) x$sampling_algorithm))) 66 | if( same_algo > 1 ) stop( "All models in list must be estimated with same sampling algorithm") 67 | ## if( !is.null(bmgarch_objects ) & !is.null(lfo_objects )) stop( "Supply only 'bmgarch_objects' or 'lfo_objects', not both" ) 68 | if( is.null(bmgarch_objects ) ) stop( "Supply 'bmgarch_objects'" ) 69 | 70 | if( !is.null(bmgarch_objects ) ) { 71 | ## Approximates LFO; Ie. results in refitting models. 72 | ll_list <- lapply(bmgarch_objects, FUN = .ll_lfo, L = L, M = M, mode = mode) 73 | } 74 | 75 | ## Insert lfo_objects 76 | ## obtain iter, warmup and n_chains from each model - loop through all models in list 77 | r_eff_list <- list(NA) 78 | for( i in seq_len(length(bmgarch_objects))) { 79 | r_eff_list[[i]] <- .rel_eff( ll_list[[i]], bmgarch_objects[[i]] ) 80 | } 81 | 82 | wts <- loo::loo_model_weights( ll_list, method = method, 83 | r_eff_list = r_eff_list, 84 | optim_control = list(reltol=1e-10)) 85 | out <- list() 86 | out$wts <- wts 87 | out$ll_list <- ll_list 88 | out$r_eff_list <- r_eff_list 89 | 90 | attr( out, "class" ) <- "model_weights" 91 | return(out) 92 | } 93 | 94 | 95 | ##' @title Print method for model_weights 96 | ##' @param x Model weights object 97 | ##' @param ... Not used. 98 | ##' @return model_weights objects with weights, list of log-likelihoods, and r_eff_list 99 | ##' @author philippe 100 | ##' @export 101 | print.model_weights <- function(x, ...) { 102 | print(x$wts) 103 | return(invisible(x) ) 104 | } 105 | -------------------------------------------------------------------------------- /R/panas.R: -------------------------------------------------------------------------------- 1 | #' Positive and Negative Affect Scores. 2 | #' 3 | #' A dataset containing simulated values for Positive and Negative Affect scores across 200 measurement occasions for a single individual. 4 | #' 5 | #' @format Data frame with 200 rows and 2 variables: 6 | #' \describe{ 7 | #' \item{Pos}{Positive Affect score} 8 | #' \item{Neg}{Negative Affect score} 9 | #' } 10 | "panas" 11 | -------------------------------------------------------------------------------- /R/plot.R: -------------------------------------------------------------------------------- 1 | ##' @title Plot method for bmgarch objects. 2 | ##' @param x bmgarch object. 3 | ##' @param type String (Default: "mean"). Whether to plot conditional means ("mean"), variance ("var"), or correlations ("cor"). 4 | ##' @param askNewPage askNewPage Logical (Default: True). Whether to ask for new plotting page. 5 | ##' @param CrI CrI Numeric vector (Default: \code{c(.025, .975)}). Lower and upper bound of predictive credible interval. 6 | ##' @param ... Not used 7 | ##' @return List of ggplot objects (one per time series). 8 | ##' @author Stephen R. Martin 9 | ##' @import ggplot2 10 | ##' @importFrom graphics plot 11 | ##' @importFrom grDevices devAskNewPage 12 | ##' @export 13 | plot.bmgarch <- function(x, type = "mean", askNewPage = TRUE, CrI = c(.025, .975), ...) { 14 | ## Bind period, L, U locally to plot.bmgarch to avoid CMD R check note 15 | period <- L <- U <- NULL 16 | x.fitted <- fitted(x, CrI = CrI, digits = 4) 17 | x.observed <- x$RTS_full 18 | nt <- x$nt 19 | TS_names <- lapply(x.fitted$backcast, function(x) {dimnames(x)[[3]]}) 20 | TS_length <- x$TS_length 21 | 22 | df <- as.data.frame(x.fitted) 23 | 24 | # rename % cols to L and U. 25 | LU <- paste0(CrI * 100, "%") 26 | colnames(df)[colnames(df) %in% LU] <- c("L", "U") 27 | 28 | plt <- list() 29 | 30 | # Subset by correct param type. 31 | if(!(type %in% c("mean","var","cor"))) { 32 | stop("'type' must be 'mean', 'var', or 'cor'.") 33 | } 34 | if(type == "cor" & x$param == "CCC") { 35 | stop("CCC does not model correlations over time.") 36 | } 37 | 38 | df <- df[df$param == type, ] 39 | 40 | for(i in TS_names[[type]]) { 41 | df.i <- df[df$TS == i,] 42 | 43 | plt[[i]] <- ggplot(data = df.i, aes(x = period, y = mean, ymin = L, ymax = U)) + 44 | geom_line() + 45 | geom_ribbon(alpha = .3) 46 | l <- labs(x = "Time Period", 47 | y = switch(type, 48 | mean = "Conditional Means", 49 | var = "Conditional Variances", 50 | cor = "Conditional Correlations", 51 | NULL), 52 | title = paste0(x$param, "-MGARCH"), 53 | subtitle = i) 54 | plt[[i]] <- plt[[i]] + l 55 | print(plt[[i]]) 56 | if(which(i %in% TS_names[[type]]) == 1) { 57 | devAskNewPage(ask = askNewPage) 58 | } 59 | } 60 | 61 | return(invisible(plt)) 62 | } 63 | ##' @title Plot method for forecast.bmgarch objects. 64 | ##' @param x forecast.bmgarch object. See \code{\link{forecast.bmgarch}}. 65 | ##' @param type String (Default: "mean"). Whether to plot conditional means ("mean"), variance ("var"), or correlations ("cor"). 66 | ##' @param askNewPage Logical (Default: True). Whether to ask for new plotting page. 67 | ##' @param last_t Integer (Default: 100). Only show \code{last_t} observations in plot. 68 | ##' @param ... Not used 69 | ##' @return List of ggplot objects (one per time series). 70 | ##' @author Stephen R. Martin 71 | ##' @import ggplot2 72 | ##' @importFrom graphics plot 73 | ##' @importFrom grDevices devAskNewPage 74 | ##' @export 75 | plot.forecast.bmgarch <- function(x, type = "mean", askNewPage = TRUE, last_t = 100, ...) { 76 | ## Bind period, L, U locally to plot.bmgarch to avoid CMD R check note 77 | period <- L <- U <- NULL 78 | nt <- x$meta$nt 79 | TS_names <- lapply(x$forecast, function(x) {dimnames(x)[[3]]}) 80 | x.observed <- as.data.frame(x$meta$RTS_full) 81 | x.observed$period <- seq_len(x$meta$TS_length) 82 | 83 | df <- as.data.frame(x, backcast = TRUE) 84 | 85 | # rename % cols to L and U. 86 | LU <- paste0(x$meta$CrI * 100, "%") 87 | colnames(df)[colnames(df) %in% LU] <- c("L", "U") 88 | 89 | # Subset by correct param type. 90 | if(!(type %in% c("mean","var","cor"))) { 91 | stop("'type' must be 'mean', 'var', or 'cor'.") 92 | } 93 | condCor <- any(sapply(x$meta_list, function(x) {x$param != "CCC"})) 94 | ## if(type == "cor" & x$meta$param == "CCC") { 95 | if(type == "cor" & !condCor) { 96 | stop("CCC does not model correlations over time.") 97 | } 98 | df <- df[df$param == type, ] 99 | df$type <- ifelse(df$type == "backcast", "Backcast", "Forecast") 100 | 101 | plt <- list() 102 | TS_length <- max(df$period) 103 | 104 | for(i in TS_names[[type]]) { 105 | df.i <- df[df$TS == i,] 106 | 107 | plt[[i]] <- ggplot(data = df.i, aes(x = period, y = mean, ymin = L, ymax = U, color = type, fill = type)) + 108 | geom_line() + 109 | geom_ribbon(alpha = .3) 110 | l <- labs(x = "Time Period", 111 | y = switch(type, 112 | mean = "Conditional Means", 113 | var = "Conditional Variances", 114 | cor = "Conditional Correlations", 115 | NULL), 116 | title = paste0(x$meta$param, "-MGARCH"), 117 | subtitle = i, 118 | color = "Type", 119 | fill = "Type") 120 | plt[[i]] <- plt[[i]] + l 121 | plt[[i]] <- plt[[i]] + coord_cartesian(xlim = c(TS_length - last_t, TS_length)) 122 | 123 | print(plt[[i]]) 124 | if(which(i %in% TS_names[[type]]) == 1) { 125 | devAskNewPage(ask = askNewPage) 126 | } 127 | } 128 | 129 | return(invisible(plt)) 130 | } 131 | -------------------------------------------------------------------------------- /R/simulate.R: -------------------------------------------------------------------------------- 1 | ##' Simulates time series data from specified BEKK model. 2 | ##' 3 | ##' Simulates timeseries data from specified BEKK model. 4 | ##' Number of time series computed from the number of columns in C. 5 | ##' All matrices must be of the same dimension. 6 | ##' If ARMA parameters (phi, theta) unspecified (NULL), then assumes a constant mean of zero. 7 | ##' @title Simulate BEKK data. 8 | ##' @param N Integer. Length of time series. 9 | ##' @param C Numeric square matrix. Constant covariance matrix (C). Must be symmetric. 10 | ##' @param A Numeric square matrix. Moving average GARCH matrix (A). 11 | ##' @param B Numeric square matrix. Autoregressive ARCH matrix (B). 12 | ##' @param phi Numeric square matrix (Optional). Autoregressive coefficients (Phi). 13 | ##' @param theta Numeric square matrix (Optional). Moving average coefficients (Theta). 14 | ##' @return Matrix of observations. 15 | ##' @author Stephen R. Martin 16 | ##' @keywords internal 17 | ##' @importFrom stats rnorm 18 | .sim.bekk <- function(N,C,A,B, phi = NULL, theta = NULL) { 19 | if(ncol(C) != nrow(C)){ 20 | stop("C must be symmetric, square, PD.") 21 | } 22 | if(ncol(A) != nrow(A)){ 23 | stop("A must be square.") 24 | } 25 | if(ncol(B) != nrow(B)){ 26 | stop("B must be square.") 27 | } 28 | nt <- ncol(C) 29 | 30 | y <- array(0, dim = c(N, nt)) 31 | y[1,] <- rnorm(nt, 0, sqrt(diag(C))) 32 | 33 | H <- array(0, dim = c(nt, nt, N)) 34 | H[,,1] <- C 35 | 36 | for(i in 2:N) { 37 | H[,,i] <- C + t(A) %*% (t(y[i - 1,, drop = FALSE]) %*% y[i - 1,,drop = FALSE]) %*% A + t(B) %*% H[,,i-1] %*% B 38 | y[i,] <- MASS::mvrnorm(1, rep(0, nt), H[,,i]) 39 | } 40 | 41 | if (!is.null(phi) & !is.null(theta)) { 42 | ## Assume phi0 (intercept) is zero. 43 | if (ncol(phi) != nrow(phi)) { 44 | stop("phi must be square [nt, nt].") 45 | } 46 | if (ncol(theta) != nrow(theta)) { 47 | stop("theta must be square [nt, nt].") 48 | } 49 | if (ncol(phi) != nt) { 50 | stop("phi must be square [nt, nt].") 51 | } 52 | if (ncol(theta) != nt) { 53 | stop("theta must be square [nt, nt].") 54 | } 55 | mu <- array(0, dim = c(N, nt)) 56 | mu[1,] <- 0 57 | for(i in 2:N) { 58 | mu[i,] <- 10 + y[i - 1, , drop = FALSE] %*% phi + (y[i - 1, ,drop = FALSE] - mu[i - 1,,drop = FALSE])%*%theta 59 | y[i,] <- y[i,,drop = FALSE] + mu[i,,drop = FALSE] 60 | } 61 | ## y <- mu + y 62 | } 63 | 64 | return(y) 65 | } 66 | -------------------------------------------------------------------------------- /R/stanmodels.R: -------------------------------------------------------------------------------- 1 | # Generated by rstantools. Do not edit by hand. 2 | 3 | # names of stan models 4 | stanmodels <- c("BEKKMGARCH", "CCCMGARCH", "DCCMGARCH", "forecastBEKK", "forecastCCC", "forecastDCC", "pdBEKKMGARCH") 5 | 6 | # load each stan module 7 | Rcpp::loadModule("stan_fit4BEKKMGARCH_mod", what = TRUE) 8 | Rcpp::loadModule("stan_fit4CCCMGARCH_mod", what = TRUE) 9 | Rcpp::loadModule("stan_fit4DCCMGARCH_mod", what = TRUE) 10 | Rcpp::loadModule("stan_fit4forecastBEKK_mod", what = TRUE) 11 | Rcpp::loadModule("stan_fit4forecastCCC_mod", what = TRUE) 12 | Rcpp::loadModule("stan_fit4forecastDCC_mod", what = TRUE) 13 | Rcpp::loadModule("stan_fit4pdBEKKMGARCH_mod", what = TRUE) 14 | 15 | # instantiate each stanmodel object 16 | stanmodels <- sapply(stanmodels, function(model_name) { 17 | # create C++ code for stan model 18 | stan_file <- if(dir.exists("stan")) "stan" else file.path("inst", "stan") 19 | stan_file <- file.path(stan_file, paste0(model_name, ".stan")) 20 | stanfit <- rstan::stanc_builder(stan_file, 21 | allow_undefined = TRUE, 22 | obfuscate_model_name = FALSE) 23 | stanfit$model_cpp <- list(model_cppname = stanfit$model_name, 24 | model_cppcode = stanfit$cppcode) 25 | # create stanmodel object 26 | methods::new(Class = "stanmodel", 27 | model_name = stanfit$model_name, 28 | model_code = stanfit$model_code, 29 | model_cpp = stanfit$model_cpp, 30 | mk_cppmodule = function(x) get(paste0("rstantools_model_", model_name))) 31 | }) 32 | -------------------------------------------------------------------------------- /R/stocks.R: -------------------------------------------------------------------------------- 1 | #' Daily data on returns of Toyota, Nissan, and Honda stocks. 2 | #' 3 | #' A dataset used by Stata to illustrate MGARCH models containing daily data on returns of Toyota, Nissan, and Honda stocks. 4 | #' 5 | #' @format Data frame with 2015 rows and 5 variables: 6 | #' \describe{ 7 | #' \item{date}{Date} 8 | #' \item{t}{Sequential time index} 9 | #' \item{toyota}{Daily returns for Toyota stock} 10 | #' \item{nissan}{Daily returns for Nissan stock} 11 | #' \item{honda}{Daily returns for Honda stock} 12 | #' } 13 | "stocks" 14 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | modules <- paste0("stan_fit4", names(stanmodels), "_mod") 3 | for (m in modules) loadModule(m, what = TRUE) 4 | 5 | ## set core options 6 | op = options() 7 | options(mc.cores = parallel::detectCores()) 8 | 9 | ## Check for optional presence of cmdstanr 10 | if (!requireNamespace("cmdstanr", quietly = TRUE)) { 11 | packageStartupMessage( 12 | "The `cmdstanr` package is not installed. Some functionality may be limited. ", 13 | "To fully use `bmgarch`, consider installing `cmdstanr` from https://mc-stan.org/cmdstanr" 14 | ) 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: 3 | github_document: 4 | df_print: kable 5 | --- 6 | 7 | 8 | 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>", 14 | fig.path = "man/figures/README-", 15 | out.width = "100%" 16 | ) 17 | ``` 18 | 19 | [![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/bmgarch)](https://cran.r-project.org/package=bmgarch) 20 | ![build](https://github.com/ph-rast/bmgarch/workflows/build/badge.svg) 21 | ![R-CMD-check](https://github.com/ph-rast/bmgarch/workflows/R-CMD-check/badge.svg) 22 | [![codecov](https://codecov.io/gh/ph-rast/bmgarch/branch/master/graph/badge.svg?token=HWhk5QKhQp)](https://app.codecov.io/gh/ph-rast/bmgarch) 23 | [![DOI](https://joss.theoj.org/papers/10.21105/joss.03452/status.svg)](https://doi.org/10.21105/joss.03452) 24 | 25 | 26 | # bmgarch 27 | 28 | `bmgarch` estimates Bayesian multivariate generalized autoregressive conditional heteroskedasticity (MGARCH) models. 29 | Currently, bmgarch supports a variety of MGARCH(P,Q) parameterizations and simultaneous estimation of ARMA(1,1), VAR(1) and intercept-only (Constant) mean structures. 30 | In increasing order of complexity: 31 | 32 | * CCC(P, Q): Constant Conditional Correlation 33 | * DCC(P, Q): Dynamic Conditional Correlation 34 | * BEKK(P, Q): Baba, Engle, Kraft, and Kroner 35 | * pdBEKK(P, Q): BEKK(P, Q) with positive diagonal constraints 36 | 37 | ## Installation 38 | 39 | `bmgarch` is available on CRAN and can be installed with: 40 | ``` r 41 | install.packages('bmgarch') 42 | ``` 43 | 44 | ### Linux 45 | 46 | Linux users may need to install `libv8` prior to installing `bmgarch`. 47 | For example, in Ubuntu, run `sudo apt install libv8-dev` before installing the package from CRAN or github. 48 | For those who's distro installs `libnode-dev` instead of `libv8-dev`, run `install.packages("V8")` in R 49 | prior to installing `bmgarch` (during installation`rstan` looks explicitly for V8). 50 | 51 | ### Development Version 52 | 53 | The development version can be installed from [GitHub](https://github.com/) with: 54 | 55 | ``` r 56 | devtools::install_github("ph-rast/bmgarch") 57 | ``` 58 | 59 | ## How to cite this package 60 | Please add at least one of the following citations when referring to to this package: 61 | 62 | Rast, P., & Martin, S. R. (2021). bmgarch: An R-Package for Bayesian Multivariate GARCH models. _Journal of Open Source Software_, 6, 3452 - 4354. doi: https://joss.theoj.org/papers/10.21105/joss.03452 63 | 64 | Rast, P., Martin, S. R., Liu, S., & Williams, D. R. (2022). A New Frontier for Studying Within-Person Variability: Bayesian Multivariate Generalized Autoregressive Conditional Heteroskedasticity Models. _Psychological Methods, 27_, 856--873. https://doi.apa.org/10.1037/met0000357; Preprint-doi: https://psyarxiv.com/j57pk 65 | 66 | 67 | 68 | ## Examples: 69 | 70 | We present two examples, one with behavioral data and one with stocks from three major Japanese automakers. 71 | 72 | ## Example 1: Behavioral Data 73 | 74 | In this example, we use the pdBEKK(1,1) model for the variances, and an intercept-only model for the means. 75 | 76 | ```{r label="example 1", error = FALSE, warning = FALSE, message = FALSE} 77 | library(bmgarch) 78 | 79 | data(panas) 80 | head(panas) 81 | 82 | ## Fit pdBEKK(1, 1) with ARMA(1,1) on the mean structure. 83 | fit <- bmgarch(panas, 84 | parameterization = "pdBEKK", 85 | iterations = 1000, 86 | P = 1, Q = 1, 87 | distribution = "Student_t", 88 | meanstructure = "arma") 89 | ``` 90 | 91 | ### Parameter estimates 92 | ```{r} 93 | summary(fit) 94 | ``` 95 | 96 | ### Forecasted values 97 | ```{r} 98 | fit.fc <- forecast(fit, ahead = 5) 99 | 100 | fit.fc 101 | ``` 102 | 103 | ```{r forecastPlot} 104 | plot(fit.fc, askNewPage = FALSE, type = "var") 105 | 106 | plot(fit.fc, askNewPage = FALSE, type = "cor") 107 | ``` 108 | 109 | ## Example 2: Stocks 110 | 111 | Here we use the first 100 days (we only base our analyses on 100 days to reduce wait time -- this is not meant to be a serious analysis) of Stata's stocks data on daily returns of three Japanese automakers, Toyota, Nissan, and Honda. 112 | 113 | ```{r label="example 2", error = FALSE, warning = FALSE, message = FALSE} 114 | library(bmgarch) 115 | 116 | data(stocks) 117 | head(stocks) 118 | ``` 119 | Ease computation by first standardizing the time series 120 | ```{r error = FALSE, warning = FALSE, message = FALSE} 121 | stocks.z <- scale(stocks[,c("toyota", "nissan", "honda")]) 122 | head(stocks.z ) 123 | 124 | # Fit CCC(1, 1) with constant on the mean structure. 125 | fit1 <- bmgarch(stocks.z[1:100, c("toyota", "nissan", "honda")], 126 | parameterization = "CCC", 127 | iterations = 1000, 128 | P = 1, Q = 1, 129 | distribution = "Student_t", 130 | meanstructure = "constant") 131 | 132 | ``` 133 | 134 | ### Parameter Estimates 135 | ```{r} 136 | summary( fit1 ) 137 | ``` 138 | 139 | ### Forecasted Values 140 | Forecast volatility 10 days ahead 141 | ```{r} 142 | fc <- forecast(fit1, ahead = 10 ) 143 | fc 144 | ``` 145 | ```{r stockForecastPlot} 146 | plot(fc,askNewPage = FALSE, type = 'var' ) 147 | ``` 148 | 149 | ### Ensemble Methods 150 | Here we illustrate how to obtain model weights across three models. These weights will be used to compute weighted forecasts, thus, taking into account that we do not have a single best model. 151 | 152 | Add two additional models, one with CCC(2,2) and a DCC(1,1) 153 | 154 | ```{r error = FALSE, warning = FALSE, message = FALSE} 155 | # Fit CCC(1, 1) with constant on the mean structure. 156 | fit2 <- bmgarch(stocks.z[1:100, c("toyota", "nissan", "honda")], 157 | parameterization = "CCC", 158 | iterations = 1000, 159 | P = 2, Q = 2, 160 | distribution = "Student_t", 161 | meanstructure = "constant") 162 | 163 | fit3 <- bmgarch(stocks.z[1:100, c("toyota", "nissan", "honda")], 164 | parameterization = "DCC", 165 | iterations = 1000, 166 | P = 1, Q = 1, 167 | distribution = "Student_t", 168 | meanstructure = "arma") 169 | 170 | ``` 171 | 172 | The DCC(1,1) model also incorporates an ARMA(1,1) meanstructure. The output will have the according information: 173 | 174 | ```{r} 175 | summary( fit3 ) 176 | fc <- forecast(fit3, ahead = 10) 177 | ``` 178 | ```{r fit3ForecastPlot} 179 | plot( fc,askNewPage = FALSE, type = 'mean' ) 180 | ``` 181 | 182 | 183 | ### Compute Model Weights 184 | Obtain model weights with either the stacking or the pseudo BMA method. These methods are inherited from the `loo` package. 185 | 186 | First, gather models to a `bmgarch_list`. 187 | ```{r ModelWeights} 188 | ## use bmgarch_list function to collect bmgarch objects 189 | modfits <- bmgarch_list(fit1, fit2, fit3) 190 | ``` 191 | 192 | Compute model weights with the stacking method (default) and the approximate (default) leave-future-out cross validation (LFO CV). 193 | `L` defines the minimal length of the time series before we start engaging in cross-validation. Eg., for a time series with length 100, `L = 50` reserves values 51--100 as the cross-validation sample. Note that the standard is to use the approximate `backward` method to CV as it results in fewest refits. Exact CV is also available with `exact` but not encouraged as it results in refitting all CV models. 194 | 195 | ```{r error = FALSE, warning = FALSE, message = FALSE} 196 | mw <- model_weights(modfits, L = 50, method = 'stacking') 197 | ``` 198 | ```{r} 199 | ## Return model weights: 200 | mw 201 | ``` 202 | 203 | ### Weighted Forecasting 204 | Use model weights to obtain weighted forecasts. Here we will forecast 5 days ahead. 205 | ```{r} 206 | w_fc <- forecast(modfits, ahead = 5, weights = mw ) 207 | w_fc 208 | ``` 209 | Plot the weighted forecast. Save plots into a ggplot object and post-process 210 | ```{r weightedForecastPlot} 211 | plt <- plot(w_fc, askNewPage = FALSE, type = 'var' ) 212 | 213 | library( patchwork ) 214 | ( plt$honda + ggplot2::coord_cartesian(ylim = c(0, 2.5 ) ) ) / 215 | ( plt$toyota + ggplot2::coord_cartesian(ylim = c(0, 2.5 ) ) ) / 216 | ( plt$nissan + ggplot2::coord_cartesian(ylim = c(0, 2.5 ) ) ) 217 | ``` 218 | 219 | ### Predictors for Constant Variance (C) 220 | We can add predictors for the constant variance term, c or C, in the MGARCH model with the option `xC = ` 221 | The predictors need to be of the same dimension as the time-series object. For example, with three time-series of length 100, the predictor needs to be entered as a 100 by 3 matrix as well. 222 | 223 | To illustrate, we will add `nissan` as the predictor for C in a bivariate MGARCH: 224 | ```{r error = FALSE, warning = FALSE, message = FALSE} 225 | # Fit CCC(1, 1) with constant on the mean structure. 226 | fitx <- bmgarch(stocks.z[1:100, c("toyota", "honda")], 227 | xC = stocks.z[1:100, c("nissan", "nissan")], 228 | parameterization = "CCC", 229 | iterations = 1000, 230 | P = 2, Q = 2, 231 | distribution = "Student_t", 232 | meanstructure = "constant") 233 | ``` 234 | 235 | The estimates for the predictors for C are on a log scale in section `Exogenous predictor`: 236 | ```{r} 237 | summary(fitx) 238 | ``` 239 | The predictor results in a linear model (on the log scale) with an intercept $\beta_0$ and the effect of the predictor in the slope $\beta_1$. 240 | 241 | 242 | We can generate forecasts given the known values of the predictor. Note that the dimension of the predictor needs to match the number of timepoints that we predict ahead and the number of variables, 5 by 2, in this example: 243 | ```{r} 244 | fc2x <- forecast(fitx, ahead = 5, xC = stocks.z[101:105, c("nissan", "nissan")]) 245 | fc2x 246 | ``` 247 | 248 | ### Variational Approximation 249 | 250 | The package features the option to use Stan's variational Bayes (`sampling_algorithm = "VB"`) algorithm. Currently, this feature is lagging behind CmdStan's version and is considered to be experimental and mostly a placeholder for future improvements. 251 | 252 | ## Community Guidelines 253 | 254 | 1. Contributions and suggestions to the software are always welcome. Please consult our [contribution guidelines](https://github.com/ph-rast/bmgarch/blob/master/CONTRIBUTING.md) prior to submitting a pull request. 255 | 2. Report issues or problems with the software using github's [issue tracker](https://github.com/ph-rast/bmgarch/issues). 256 | 3. Contributors must adhere to the [Code of Conduct](https://github.com/ph-rast/bmgarch/blob/master/CODE_OF_CONDUCT.md). 257 | 258 | ## Acknowledgment 259 | This work was supported by the National Institute On Aging of the National Institutes of Health under 260 | Award Number [R01AG050720](https://reporter.nih.gov/project-details/9336761) to PR. The content is solely the responsibility of the authors and does not necessarily represent the official views of the funding agency. 261 | -------------------------------------------------------------------------------- /bmgarch.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: No 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | # Generated by rstantools. Do not edit by hand. 2 | 3 | #! /bin/sh 4 | "${R_HOME}/bin/Rscript" -e "rstantools::rstan_config()" 5 | -------------------------------------------------------------------------------- /configure.win: -------------------------------------------------------------------------------- 1 | # Generated by rstantools. Do not edit by hand. 2 | 3 | #! /bin/sh 4 | "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rstantools::rstan_config()" 5 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | * locally: Ubuntu 22.04 install, R 4.3.1 3 | * remotely: Ubuntu-latest, MacOS-latest and Windows-latest (on github actions-ci), Rhub 4 | 5 | ## R CMD check results 6 | 7 | ### Version 2.0.0 8 | 0 errors ✔ | 0 warnings ✔ | 2 notes ✖ 9 | 10 | ❯ checking installed package size ... NOTE 11 | installed size is 261.6Mb 12 | sub-directories of 1Mb or more: 13 | libs 260.8Mb 14 | 15 | ❯ checking for GNU extensions in Makefiles ... NOTE 16 | GNU make is a SystemRequirements. 17 | 18 | 19 | ### Version 1.1.0 20 | 0 errors ✔ | 0 warnings ✔ | 2 notes ✖ 21 | 22 | * checking installed package size ... NOTE 23 | installed size is 10.5Mb 24 | sub-directories of 1Mb or more: 25 | libs 9.6Mb 26 | 27 | - Compiled code bmgarch.so is relatively large 28 | 29 | * checking for GNU extensions in Makefiles ... NOTE 30 | GNU make is a SystemRequirements. 31 | 32 | - GNU make is a build time requirement for Ubuntu 33 | 34 | ## Comments from CRAN admins: 35 | * 06.12.21 and 10.12 Ligges: 36 | > Pls fix the 404s and 301s from the URL checks. 37 | - Fixed 404 and 301 errors in README and DESCRIPTION 38 | 39 | 40 | ### Version 1.0.1 41 | * This is a resubmission, initiated by CRAN package check on 2021-06-12 42 | 43 | 0 Errors or Warnings 44 | 2 Notes: 45 | 46 | * checking installed package size ... NOTE 47 | installed size is 9.4Mb 48 | sub-directories of 1Mb or more: 49 | libs 8.7Mb 50 | 51 | - Note that compiled code bmgarch.so is 11.5 Mb large 52 | 53 | * checking for GNU extensions in Makefiles ... NOTE 54 | GNU make is a SystemRequirements. 55 | 56 | - Note that GNU make is a build time requirement for Ubuntu 57 | 58 | ## Comments from CRAN admins: 59 | ### Version 1.0.0 60 | * 10.09.20 Gregor Seyer: 61 | > Please replace \dontrun with \donttest 62 | 63 | - Done 64 | 65 | * 28.08.20 Uwe Ligges: 66 | > Please single quote software names such as 'rstan' in the Description field. 67 | 68 | - Done 69 | 70 | 71 | * 26.08.20 The first submission was rejected by Swetlana Herbrandt: 72 | 73 | > examples are wrapped in \dontrun{}, hence nothing getst 74 | > tested. Please unwrap the examples if that is feasible and if they can 75 | > be executed in < 5 sec for each Rd file or create additionally small toy 76 | > examples. 77 | 78 | > Alternatively, you can write some tests (e.g. by using testthat). The 79 | > overall execution time should not exceed 10 minutes. 80 | 81 | - Fix: Examples can't be run in less than 5 sec. Instead, we added tests for 82 | all user-exposed functions for testthat. Overall execution time with 2 cores 83 | is approx 3.5 mins. Additional examples to illustrate package functions have 84 | been added as `dontrun{}` 85 | 86 | > Please ensure that you do not use more than 2 cores in your examples or 87 | > tests. 88 | 89 | - Done 90 | 91 | > If there are references describing the (theoretical background of GARCH 92 | > Models) methods in your package, please add these in the Description 93 | > field of your DESCRIPTION file in the form 94 | > authors (year) 95 | > authors (year) 96 | > authors (year, ISBN:...) 97 | > with no space after 'doi:', 'arXiv:' and angle brackets for auto-linking.c 98 | 99 | - Added corresponding information 100 | -------------------------------------------------------------------------------- /data/panas.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/data/panas.rda -------------------------------------------------------------------------------- /data/stocks.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/data/stocks.rda -------------------------------------------------------------------------------- /doc/auto/paper.el: -------------------------------------------------------------------------------- 1 | (TeX-add-style-hook 2 | "paper" 3 | (lambda () 4 | (LaTeX-add-bibitems 5 | "Bollerslev1986" 6 | "Bollerslev1990" 7 | "Buerkner2020" 8 | "Carnero2014" 9 | "DeAlmeida2018" 10 | "Engle1982" 11 | "Engle2002" 12 | "Engle1995" 13 | "Rast2020" 14 | "rmgarch" 15 | "mgarchBEKK" 16 | "rstan" 17 | "stanCppLibrary" 18 | "Tsay2013" 19 | "Yao2018")) 20 | '(or :bibtex :latex)) 21 | 22 | -------------------------------------------------------------------------------- /doc/paper.bib: -------------------------------------------------------------------------------- 1 | @article{Bollerslev1986, 2 | author = {Bollerslev, Tim}, 3 | doi = {10.1016/0304-4076(86)90063-1}, 4 | journal = {Journal of Econometrics}, 5 | number = {3}, 6 | pages = {307--327}, 7 | title = {{Generalized autoregressive conditional heteroskedasticity}}, 8 | volume = {31}, 9 | year = {1986} 10 | } 11 | 12 | @article{Bollerslev1990, 13 | author = {Bollerslev, Tim}, 14 | doi = {10.2307/2109358}, 15 | journal = {The Review of Economics and Statistics}, 16 | number = {3}, 17 | pages = {498--505}, 18 | title = {{Modelling the Coherence in Short-Run Nominal Exchange Rates: A Multivariate Generalized Arch Model}}, 19 | volume = {72}, 20 | year = {1990} 21 | } 22 | 23 | @article{Buerkner2020, 24 | author = {B{\"{u}}rkner, Paul-Christian and Gabry, Jonah and Vehtari, Aki}, 25 | journal = {Journal of Statistical Computation and Simulation}, 26 | pages = {1--25}, 27 | title = {{Approximate leave-future-out cross-validation for Bayesian time series models}}, 28 | doi = {10.1080/00949655.2020.1783262}, 29 | year = {2020} 30 | } 31 | 32 | 33 | 34 | @article{Carnero2014, 35 | author = {Carnero, M. Angeles and Eratalay, M. Hakan}, 36 | doi = {10.1515/snde-2012-0065}, 37 | journal = {Studies in Nonlinear Dynamics {\&} Econometrics}, 38 | keywords = {C32,financial markets,volatility spillovers}, 39 | number = {3}, 40 | pages = {339--365}, 41 | title = {{Estimating VAR-MGARCH models in multiple steps}}, 42 | volume = {18}, 43 | year = {2014} 44 | } 45 | 46 | @article{DeAlmeida2018, 47 | author = {de Almeida, Daniel and Hotta, Luiz K. and Ruiz, Esther}, 48 | doi = {10.1016/J.IJFORECAST.2017.08.003}, 49 | journal = {International Journal of Forecasting}, 50 | number = {1}, 51 | pages = {45--63}, 52 | title = {{MGARCH models: Trade-off between feasibility and flexibility}}, 53 | volume = {34}, 54 | year = {2018} 55 | } 56 | 57 | 58 | @article{Engle1982, 59 | author = {Engle, Robert F.}, 60 | doi = {10.2307/1912773}, 61 | issn = {00129682}, 62 | journal = {Econometrica}, 63 | number = {4}, 64 | pages = {987--1007}, 65 | title = {{Autoregressive Conditional Heteroscedasticity with Estimates of the Variance of United Kingdom Inflation}}, 66 | volume = {50}, 67 | year = {1982} 68 | } 69 | 70 | @article{Engle2002, 71 | author = {Engle, Robert F.}, 72 | doi = {10.1198/073500102288618487}, 73 | journal = {Journal of Business {\&} Economic Statistics}, 74 | number = {3}, 75 | pages = {339--350}, 76 | title = {{Dynamic Conditional Correlation}}, 77 | volume = {20}, 78 | year = {2002} 79 | } 80 | 81 | 82 | @article{Engle1995, 83 | author = {Engle, Robert F. and Kroner, Kenneth F.}, 84 | doi = {10.1017/S0266466600009063}, 85 | journal = {Econometric Theory}, 86 | number = {1}, 87 | pages = {122--150}, 88 | title = {{Multivariate simultaneous generalized arch}}, 89 | volume = {11}, 90 | year = {1995} 91 | } 92 | 93 | 94 | 95 | @article{Rast2020, 96 | author = {Rast, Philippe and Martin, Stephen R. and Liu, Siwei and Williams, Donald R.}, 97 | doi = {10.1037/met0000357}, 98 | journal = {Psychological Methods}, 99 | volume = {27}, 100 | title = {{A New Frontier for Studying Within-Person Variability: Bayesian Multivariate Generalized Autoregressive Conditional Heteroskedasticity Models}}, 101 | url = {https://psycnet.apa.org/doi/10.1037/met0000357}, 102 | pages = {856--873}, 103 | year = {2022} 104 | } 105 | 106 | @Manual{rmgarch, 107 | title = {rmgarch: Multivariate GARCH models}, 108 | author = {Ghalanos, Alexios}, 109 | year = {2019}, 110 | note = {R package version 1.3-7.}, 111 | } 112 | 113 | @Manual{mgarchBEKK, 114 | title = {mgarchBEKK: Simulating, Estimating and Diagnosing MGARCH (BEKK and mGJR) Processes}, 115 | author = {Schmidbauer, Harald and Roesch, Angi and Tunalioglu, Vehbi Sinan}, 116 | year = {2016}, 117 | note = {R package version 0.0.2}, 118 | } 119 | 120 | @Misc{rstan, 121 | title = {{RStan}: the {R} interface to {Stan}}, 122 | author = {{Stan Development Team}}, 123 | note = {R package version 2.21.2}, 124 | year = {2020}, 125 | url = {http://mc-stan.org/}, 126 | } 127 | 128 | @misc{stanCppLibrary, 129 | author = {{Stan Development Team}}, 130 | edition = {2.14.0}, 131 | title = {{The Stan C++ Library}}, 132 | url = {http://mc-stan.org}, 133 | year = {2016} 134 | } 135 | 136 | @book{Tsay2013, 137 | address = {Hoboken, NJ}, 138 | author = {Tsay, Ruey S.}, 139 | isbn = {978-0-470-89081-3}, 140 | pages = {416}, 141 | publisher = {John Wiley {\&} Sons}, 142 | title = {{An Introduction to Analysis of Financial Data with R}}, 143 | year = {2013} 144 | } 145 | 146 | 147 | @article{Yao2018, 148 | author = {Yao, Yuling and Vehtari, Aki and Simpson, Daniel and Gelman, Andrew}, 149 | doi = {10.1214/17-BA1091}, 150 | journal = {Bayesian Analysis}, 151 | number = {3}, 152 | pages = {917--1007}, 153 | title = {{Using Stacking to Average Bayesian Predictive Distributions}}, 154 | volume = {13}, 155 | year = {2018} 156 | } 157 | -------------------------------------------------------------------------------- /doc/paper.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'bmgarch: An R-Package for Bayesian Multivariate GARCH models' 3 | tags: 4 | - R 5 | - stan 6 | - GARCH 7 | authors: 8 | - name: Philippe Rast^[corresponding author] 9 | orcid: 0000-0003-3630-6629 10 | affiliation: 1 11 | - name: Stephen R. Martin 12 | orcid: 0000-0001-8085-2390 13 | affiliation: 2 14 | affiliations: 15 | - name: University of California, Davis 16 | index: 1 17 | - name: Comscore, Inc. 18 | index: 2 19 | date: June 28 2021 20 | bibliography: paper.bib 21 | --- 22 | 23 | # Introduction 24 | Generalized autoregressive conditional heteroskedasticity models (GARCH) and their multivariate extension (MGARCH) are part of the economists' toolbox ever since their introduction in the early 1980ies [@Bollerslev1986; @Engle1982; @Tsay2013]. Typically, the goal is to generate forecasts of volatility and covolatility for the next day or the near future in time series of assets or market indices. While GARCH models are primarily used in the econometric context, they can be used to capture and forecast heteroskedasticity in any time series. In fact, @Rast2020 presented a parameterization for predicting and capturing within-person variability in human behavior in intensive longitudinal designs. 25 | 26 | The main focus of MGARCH models is the estimation of the $p \times p$ conditional covariance matrix $\mathbf{H}_t$ that varies over $t = 1, ... , N$ 27 | time points and defines the (co-)volatility of $p$ time series as $\boldsymbol{\epsilon}_t = \mathbf{H}^{1/2}_t \boldsymbol{\eta}_t$, where $\boldsymbol{\epsilon}_t$ is a $p \times 1$ vector of returns or residuals, assuming a process with a conditional mean of zero. $\boldsymbol{\eta}_t$ is a serially independent multivariate white noise process with covariance matrix $\mathbf{I}_p$. While conceptually straightforward, the crux is to define a model that maintains stationarity of the variances and covariances among the time series for all time points as well as positive definiteness for all $\mathbf{H}_t$. As such, a substantial amount of research of the past decades revolved around parameterizations of the conditional covariance matrix that fulfill all those desiderata [for a comparison of some of the most common parameterizations see @DeAlmeida2018]. 28 | 29 | # Statement of need 30 | While there are a number of readily available packages for univariate GARCH models in R, multivariate implementations are scarcely available. Currently, we are aware of only two packages in the Comprehensive R Archive Network (CRAN). One is `mgarchBEKK` [@mgarchBEKK] which implements BEKK as well as a bivariate asymmetric GARCH model. The other is `rmgarch` [@rmgarch], which includes DCC, GO-GARCH and Copula-GARCH models. Both packages are based on maximum likelihood methods. Moreover, some MGARCH models are implemented in proprietary software (such as Stata), but their focus is mostly limited to CCC, DCC, and VCC models without the option of estimating the location (e.g. time-varying mean returns) and scale (e.g. time-varying volatility) at the same time [@Carnero2014]. Again, these propietary solutions are based on maximum likelihood methods, while in contrast, `bmgarch` implements Bayesian methods for parameter estimation and inference. 31 | 32 | At this current time, `bmgarch` implements a CCC [@Bollerslev1990], DCC [@Engle2002], pdBEKK [@Rast2020], and a BEKK [@Engle1995] model based on either Gaussian or Student-t distributed innovations. All parameterizations allow arbitrary ARCH and GARCH orders. 33 | The Bayesian framework is ideally suited to handle the necessary constraints imposed on the MGARCH specifications to both keep the solution stationary and all $t$ conditional covariance matrices $\mathbf{H}_t$ positive definite. Moreover, the model allows one to examine the posterior distribution in order to obtain the full range of Bayesian inference. 34 | 35 | The model parameters are estimated using the probabilistic programming language Stan [@stanCppLibrary], which also allows one to use stan related diagnostics implemented in `rstan` [@rstan]. 36 | 37 | # bmgarch 38 | 39 | The package is designed to take multivariate time series only. Hence, in terms of data, the minimum requirement is a data frame or matrix with at least two columns, representing the time series. Note that `bmgarch` currently does not support missing values in time series, nor in the predictor variables. 40 | 41 | The default behavior in `bmgarch` is to estimate a CCC(1,1) parameterized model of order 1 for the ARCH and GARCH components assuming Student-$t$ distributed innovations and a constant means (zero, typically) structure. The model is fit using 4 chains with 2000 iterations each (half of those are warm-up and the other half are sampling). 42 | As such, the minimum call will be `bmgarch( data = X )` with `X` being a matrix or data frame with at least 2 columns. 43 | 44 | In order to include the effect of an external predictor variable on the unconditional and constant covariance term $C$, one can include a time-varying predictor `Y` of the same dimension as `X` by including the preditor with `xC = Y`, resulting in`bmgarch( data = X, xC = Y )`. Further, `bmgarch` takes a number of model related arguments governing the type of parameterization (`parameterization = {"CCC", "DCC", "BEKK", "pdBEKK"}`), the order of the GARCH (`P = {1, ..., t-1}`) and ARCH (`Q = {1, ..., t-1}`) processes, the mean structure (`meanstructure = {"constant", "arma"}`) and the type of distribution (`distribution = {"Student_t", "Gaussian"}`). The function also takes arguments with respect to sampling (number of `iterations` and number of `chains`) as well as whether data should be z-standardized before sampling (`standardize_data = {FALSE, TRUE}`) -- this last argument can facilitate the estimation process. 45 | 46 | Objects of the `bmgarch` family can be passed to the `plot()` function, `print()`, and `summary()` for a summary table. 47 | 48 | Moreover, each estimated model can be passed to the `forecasting()` function to generate $m$-ahead forecasts of variances, correlations, and, if the meanstructure is included (such as with ARMA(1,1)), forecasts of means. 49 | Moreover, `bmgarch` integrates model ensemble techniques to generate model weighted forecasts (and estimates) based on Bayesian model averaging and stacking techniques described by @Yao2018 and @Buerkner2020. The forecasted objects can again be plotted and summarized via the corresponding generic functions. 50 | 51 | # Summary 52 | The `bmgarch` package implements four MGARCH parameterizations and estimates all parameters via a Bayesian framework. Sampling from the posterior distribution is based on HMC and is implemented via stan. The `bmgarch` objects can be printed and plotted as well as passed on to a forecasting function that runs either simple or ensemble forecasts. 53 | 54 | # Acknowledgements 55 | The work reported in this publication was supported by the National Institute On Aging of the National Institutes of Health under Award Number R01AG050720 to PR. The content is solely the responsibility of the authors and does not necessarily represent the official views of the funding agencies. 56 | -------------------------------------------------------------------------------- /inst/REFERENCES.bib: -------------------------------------------------------------------------------- 1 | @article{Buerkner2019, 2 | author = {B{\"{u}}rkner, Paul-Christian and Gabry, Jonah and Vehtari, Aki}, 3 | journal = {Journal of Statistical Computation and Simulation}, 4 | pages = {1--25}, 5 | title = {{Approximate leave-future-out cross-validation for Bayesian time series models}}, 6 | doi = {10.1080/00949655.2020.1783262}, 7 | year = {2020} 8 | } 9 | 10 | @article{Engle1995, 11 | author = {Engle, Robert F. and Kroner, Kenneth F.}, 12 | doi = {10.1017/S0266466600009063}, 13 | journal = {Econometric Theory}, 14 | number = {1}, 15 | pages = {122--150}, 16 | title = {{Multivariate simultaneous generalized arch}}, 17 | volume = {11}, 18 | year = {1995} 19 | } 20 | 21 | @techreport{Engle2001a, 22 | address = {Cambridge, MA}, 23 | author = {Engle, Robert F. and Sheppard, Kevin}, 24 | doi = {10.3386/w8554}, 25 | institution = {National Bureau of Economic Research}, 26 | title = {{Theoretical and Empirical properties of Dynamic Conditional Correlation Multivariate GARCH}}, 27 | year = {2001} 28 | } 29 | 30 | @article{Engle2002, 31 | author = {Engle, Robert F.}, 32 | doi = {10.1198/073500102288618487}, 33 | journal = {Journal of Business {\&} Economic Statistics}, 34 | keywords = {ARCH,Correlation,GARCH,Multivariate GARCH}, 35 | number = {3}, 36 | pages = {339--350}, 37 | title = {{Dynamic Conditional Correlation}}, 38 | volume = {20}, 39 | year = {2002} 40 | } 41 | 42 | 43 | @article{Rast2020, 44 | author = {Rast, Philippe and Martin, Stephen R. and Liu, Siwei and Williams, Donald R.}, 45 | journal = {Psychological Methods}, 46 | keywords = {Rast2020}, 47 | mendeley-tags = {Rast2020}, 48 | title = {{A New Frontier for Studying Within-Person Variability: Bayesian Multivariate Generalized Autoregressive Conditional Heteroskedasticity Models}}, 49 | url = {https://psyarxiv.com/j57pk/}, 50 | year = {2020} 51 | } 52 | 53 | @article{Yao2018, 54 | author = {Yao, Yuling and Vehtari, Aki and Simpson, Daniel and Gelman, Andrew}, 55 | doi = {10.1214/17-BA1091}, 56 | journal = {Bayesian Analysis}, 57 | number = {3}, 58 | pages = {917--1007}, 59 | title = {{Using Stacking to Average Bayesian Predictive Distributions}}, 60 | volume = {13}, 61 | year = {2018} 62 | } 63 | -------------------------------------------------------------------------------- /inst/auto/REFERENCES.el: -------------------------------------------------------------------------------- 1 | (TeX-add-style-hook 2 | "REFERENCES" 3 | (lambda () 4 | (LaTeX-add-bibitems 5 | "Buerkner2019" 6 | "Engle1995" 7 | "Engle2001a" 8 | "Engle2002" 9 | "Rast2020" 10 | "Yao2018")) 11 | :bibtex) 12 | 13 | -------------------------------------------------------------------------------- /inst/include/stan_meta_header.hpp: -------------------------------------------------------------------------------- 1 | // Insert all #include statements here 2 | -------------------------------------------------------------------------------- /inst/stan/BEKKMGARCH.stan: -------------------------------------------------------------------------------- 1 | // BEKK-Parameterization 2 | functions { 3 | #include /functions/cov2cor.stan 4 | } 5 | 6 | data { 7 | #include /data/data.stan 8 | } 9 | 10 | transformed data { 11 | 12 | // Obtain mean and sd over TS for prior in arma process phi0 13 | vector[nt] rts_m; 14 | vector[nt] rts_sd; 15 | 16 | #include /transformed_data/xh_marker.stan 17 | 18 | if( meanstructure == 0 ){ 19 | for ( i in 1:nt ){ 20 | rts_m[i] = mean(rts[,i]); 21 | rts_sd[i] = sd(rts[,i]); 22 | } 23 | } else if (meanstructure == 1 || meanstructure == 2 ){ 24 | // set rts_m to first element in ts 25 | for ( i in 1:nt ){ 26 | rts_m[i] = rts[1,i]; 27 | rts_sd[i] = sd(rts[,i]); 28 | } 29 | } 30 | } 31 | 32 | parameters { 33 | // ARMA parameters 34 | #include /parameters/arma.stan 35 | 36 | // predictor for H 37 | //cov_matrix[ xC_marker >= 1 ? nt : 0 ] beta; 38 | row_vector[nt] beta0; 39 | vector[nt] beta1; 40 | 41 | // Separate into C_sd*C_R*C_sd 42 | // C_sd is defined in tp, as function of betas 43 | corr_matrix[nt] C_R; 44 | 45 | array[Q] matrix[nt, nt] A_raw; 46 | array[P] matrix[nt, nt] B_raw; 47 | 48 | // H1 init 49 | cov_matrix[nt] H1_init; 50 | real< lower = 2 > nu; // nu for student_t 51 | 52 | } 53 | transformed parameters { 54 | array[T] cov_matrix[nt] H; 55 | array[T-1] matrix[nt,nt] rr; 56 | array[T] vector[nt] mu; 57 | 58 | matrix[nt, nt] A_part = diag_matrix( rep_vector(0.0, nt)); 59 | matrix[nt, nt] B_part = diag_matrix( rep_vector(0.0, nt)); 60 | 61 | matrix[nt+1, nt] beta = append_row( beta0, diag_matrix(beta1) ); 62 | row_vector[nt] C_sd; 63 | cov_matrix[nt] Cnst; // Const is symmetric, A, B, are not 64 | 65 | // Initialize model parameters 66 | mu[1,] = phi0; 67 | H[1,] = H1_init; 68 | 69 | for (t in 2:T){ 70 | // Meanstructure model: 71 | #include /model_components/mu.stan 72 | 73 | // reset A_part and B_part to zero for each iteration t 74 | A_part = diag_matrix( rep_vector(0.0, nt)); 75 | B_part = diag_matrix( rep_vector(0.0, nt)); 76 | 77 | for (q in 1:min( t-1, Q) ) { 78 | rr[t-q,] = ( rts[t-q,] - mu[t-q,] )*( rts[t-q,] - mu[t-q,] )'; 79 | A_part = A_part + A_raw[q]' * rr[t-q,] * A_raw[q]; 80 | } 81 | for (p in 1:min( t-1, P) ) { 82 | B_part = B_part + B_raw[p]' * H[t-p,] * B_raw[p]; 83 | } 84 | if( xC_marker == 0 ) { 85 | C_sd = exp( beta0 ); 86 | Cnst = quad_form_diag(C_R, C_sd ); 87 | H[t,] = Cnst + A_part + B_part; 88 | } else if( xC_marker >= 1) { 89 | C_sd = exp( append_col( 1.0, xC[t]' ) * beta ); 90 | Cnst = quad_form_diag(C_R, C_sd ); 91 | H[t,] = Cnst + A_part + B_part; 92 | } 93 | } 94 | } 95 | model { 96 | // priors 97 | // https://mc-stan.org/documentation/case-studies/mle-params.html 98 | 99 | // Prior on nu for student_t 100 | nu ~ normal( nt, 50 ); 101 | 102 | // Prior for initial state 103 | H1_init ~ wishart(nt + 1.0, diag_matrix(rep_vector(1.0, nt)) ); 104 | 105 | to_vector(theta) ~ std_normal(); 106 | to_vector(phi) ~ std_normal(); 107 | // to_vector(phi0) ~ normal(); 108 | phi0 ~ multi_normal(rts_m, diag_matrix( rts_sd ) ); 109 | 110 | to_vector(beta0) ~ std_normal(); 111 | to_vector(beta1) ~ std_normal(); 112 | C_R ~ lkj_corr( 1 ); 113 | 114 | for(q in 1:Q) { 115 | to_vector(A_raw[q]) ~ std_normal(); 116 | } 117 | for(p in 1:P) { 118 | to_vector(B_raw[p]) ~ std_normal(); 119 | } 120 | 121 | // likelihood 122 | if ( distribution == 0 ) { 123 | for(t in 1:T){ 124 | target += multi_normal_lpdf(rts[t, ]| mu[t,], H[t,]); 125 | } 126 | } else if ( distribution == 1 ) { 127 | for(t in 1:T){ 128 | target += multi_student_t_lpdf( rts[t, ] | nu, mu[t,], H[t,]); 129 | } 130 | } 131 | } 132 | // 133 | generated quantities { 134 | array[Q] matrix[nt, nt] A = A_raw; 135 | array[P] matrix[nt, nt] B = B_raw; 136 | matrix[nt,T] rts_out; 137 | array[T] real log_lik; 138 | corr_matrix[nt] corC; 139 | array[T] corr_matrix[nt] corH; 140 | row_vector[nt] C_var; 141 | 142 | for(q in 1:Q) { 143 | if(A[q,1,1] < 0) { 144 | A[q] = -A[q]; 145 | } 146 | } 147 | for(p in 1:P) { 148 | if(B[p,1,1] < 0) { 149 | B[p] = -B[p]; 150 | } 151 | } 152 | 153 | //Const = multiply_lower_tri_self_transpose(Cnst); 154 | corC = C_R; 155 | C_var = exp(2*beta0 ); 156 | 157 | // retrodict 158 | #include /generated/retrodict_H.stan 159 | } 160 | -------------------------------------------------------------------------------- /inst/stan/CCCMGARCH.stan: -------------------------------------------------------------------------------- 1 | // CCC-Parameterization 2 | functions { 3 | #include /functions/cov2cor.stan 4 | #include /functions/jacobian.stan 5 | } 6 | data { 7 | #include /data/data.stan 8 | } 9 | transformed data { 10 | // Obtain mean and sd over TS for prior in arma process phi0 11 | vector[nt] rts_m; 12 | vector[nt] rts_sd; 13 | 14 | #include /transformed_data/xh_marker.stan 15 | 16 | if( meanstructure == 0 ){ 17 | for ( i in 1:nt ){ 18 | rts_m[i] = mean(rts[,i]); 19 | rts_sd[i] = sd(rts[,i]); 20 | } 21 | } else if (meanstructure == 1 || meanstructure == 2){ 22 | // set rts_m to first element in ts 23 | for ( i in 1:nt ){ 24 | rts_m[i] = rts[1,i]; 25 | rts_sd[i] = sd(rts[,i]); 26 | } 27 | } 28 | } 29 | parameters { 30 | // ARMA parameters 31 | #include /parameters/arma.stan 32 | // predictor for H 33 | #include /parameters/predH.stan 34 | 35 | // GARCH h parameters on variance metric 36 | vector[nt] c_h; 37 | // vector[nt] a_h[Q]; 38 | array[nt] simplex[Q] a_h_simplex; 39 | vector[nt] a_h_sum; 40 | array[nt] simplex[P] b_h_simplex; 41 | vector[nt] b_h_sum_s; 42 | // vector[nt] b_h[P]; // TODO actually: 1 - a_h, across all Q and P... 43 | 44 | // GARCH constant correlation 45 | corr_matrix[nt] R; 46 | 47 | // D1 init 48 | vector[nt] D1_init; 49 | 50 | // DF constant nu for student t 51 | real< lower = 2 > nu; 52 | 53 | } 54 | transformed parameters { 55 | array[T] cov_matrix[nt] H; 56 | array[T-1] vector[nt] rr; 57 | array[T] vector[nt] mu; 58 | array[T] vector[nt] D; 59 | array[nt] real vd; 60 | array[nt] real ma_d; 61 | array[nt] real ar_d; 62 | array[Q] vector[nt] a_h = simplex_to_bh(a_h_simplex, a_h_sum); 63 | vector[nt] UPs = upper_limits(a_h); 64 | vector[nt] ULs = raw_sum_to_b_h_sum(b_h_sum_s, UPs); 65 | array[P] vector[nt] b_h = simplex_to_bh(b_h_simplex, ULs); 66 | // Initialize t=1 67 | // Check "Order Sensitivity and Repeated Variables" in stan reference manual 68 | mu[1,] = phi0; 69 | //u[1,] = diagonal(sigma1); 70 | D[1,] = D1_init; 71 | H[1,] = quad_form_diag(R, D[1,]); // H = DRD; 72 | // iterations geq 2 73 | for (t in 2:T){ 74 | 75 | // Meanstructure model: 76 | #include /model_components/mu.stan 77 | 78 | // scale: SD's of D 79 | for (d in 1:nt) { 80 | vd[d] = 0.0; 81 | ma_d[d] = 0.0; 82 | ar_d[d] = 0.0; 83 | // MA component 84 | for (q in 1:min( t-1, Q) ) { 85 | rr[t-q, d] = square( rts[t-q, d] - mu[t-q, d] ); 86 | ma_d[d] = ma_d[d] + a_h[q, d]*rr[t-q, d] ; 87 | } 88 | for (p in 1:min( t-1, P) ) { 89 | ar_d[d] = ar_d[d] + b_h[p, d]*D[t-p, d]^2; 90 | } 91 | if ( xC_marker >= 1) { 92 | vd[d] = exp( c_h[d] + beta[d] * xC[t, d] ) + ma_d[d] + ar_d[d]; 93 | } else if ( xC_marker == 0) { 94 | vd[d] = exp( c_h[d] ) + ma_d[d] + ar_d[d]; 95 | } 96 | D[t, d] = sqrt( vd[d] ); 97 | } 98 | H[t,] = quad_form_diag(R, D[t,]); // H = DRD; 99 | } 100 | } 101 | 102 | model { 103 | // priors 104 | for(k in 1:nt) { 105 | ULs[k] ~ uniform(0, UPs[k]); 106 | target += a_b_scale_jacobian(0, ULs[k], b_h_sum_s[k]); 107 | } 108 | to_vector(beta) ~ std_normal( ); 109 | to_vector(c_h) ~ std_normal( ); 110 | if ( distribution == 1 ) 111 | nu ~ normal( nt, 50 ); 112 | to_vector(D1_init) ~ lognormal(0, 1); 113 | to_vector(theta) ~ std_normal( ); 114 | to_vector(phi) ~ std_normal( ); 115 | phi0 ~ multi_normal(rts_m, diag_matrix( rts_sd ) ); 116 | R ~ lkj_corr( 1 ); 117 | // likelihood 118 | if ( distribution == 0 ) { 119 | for(t in 1:T){ 120 | rts[t,] ~ multi_normal(mu[t,], H[t,]); 121 | //target += multi_normal_lpdf( rts[t, ] | mu[t,], H[t,]); 122 | } 123 | } else if ( distribution == 1 ) { 124 | for(t in 1:T){ 125 | rts[t,] ~ multi_student_t(nu, mu[t,], H[t,]); 126 | //target += multi_student_t_lpdf( rts[t, ] | nu, mu[t,], H[t,]); 127 | } 128 | } 129 | } 130 | generated quantities { 131 | matrix[nt,T] rts_out; 132 | array[T] real log_lik; 133 | array[T] corr_matrix[nt] corH; 134 | vector[nt] c_h_var = exp(c_h); 135 | 136 | // retrodict 137 | #include /generated/retrodict_H.stan 138 | 139 | } 140 | -------------------------------------------------------------------------------- /inst/stan/DCCMGARCH.stan: -------------------------------------------------------------------------------- 1 | // DCC-Parameterization 2 | functions { 3 | #include /functions/cov2cor.stan 4 | #include /functions/jacobian.stan 5 | } 6 | 7 | data { 8 | #include /data/data.stan 9 | } 10 | 11 | transformed data { 12 | // Obtain mean and sd over TS for prior in arma process phi0 13 | vector[nt] rts_m; 14 | vector[nt] rts_sd; 15 | 16 | #include /transformed_data/xh_marker.stan 17 | 18 | if( meanstructure == 0 ){ 19 | for ( i in 1:nt ){ 20 | rts_m[i] = mean(rts[,i]); 21 | rts_sd[i] = sd(rts[,i]); 22 | } 23 | } else if (meanstructure == 1 || meanstructure == 2 ){ 24 | // set rts_m to first element in ts 25 | for ( i in 1:nt ){ 26 | rts_m[i] = rts[1,i]; 27 | rts_sd[i] = sd(rts[,i]); 28 | } 29 | } 30 | } 31 | 32 | parameters { 33 | // ARMA parameters 34 | #include /parameters/arma.stan 35 | // predictor for H 36 | #include /parameters/predH.stan 37 | 38 | // GARCH h parameters on variance metric 39 | vector[nt] c_h; // variance on log metric 40 | // vector[nt] a_h[Q]; 41 | array[nt] simplex[Q] a_h_simplex; 42 | vector[nt] a_h_sum; 43 | array[nt] simplex[P] b_h_simplex; // Simplex for b_h within each timeseries 44 | vector[nt] b_h_sum_s; // Unconstrained b_h_sum values. b_h[i] = U[i] b_h_simplex[i]; U[i] ~ U(0, 1 - sum(a_h[i])) 45 | // vector[nt] b_h[P]; // TODO actually: 1 - a_h, across all Q and P... 46 | // GARCH q parameters 47 | real a_q; // 48 | real b_q; // 49 | corr_matrix[nt] S; // DCC keeps this constant 50 | // Qr1 init 51 | cov_matrix[nt] Qr1_init; 52 | // D1 init 53 | vector[nt] D1_init; 54 | // u1 init 55 | vector[nt] u1_init; 56 | 57 | real< lower = 2 > nu; // nu for student_t 58 | 59 | } 60 | 61 | transformed parameters { 62 | array[T] cov_matrix[nt] H; 63 | array[T] corr_matrix[nt] R; 64 | array[T-1] vector[nt] rr; 65 | array[T] vector[nt] mu; 66 | array[T] vector[nt] D; 67 | array[T] cov_matrix[nt] Qr; 68 | array[T] vector[nt] Qr_sdi; 69 | array[T] vector[nt] u; 70 | array[nt] real vd; 71 | array[nt] real ma_d; 72 | array[nt] real ar_d; 73 | array[Q] vector[nt] a_h = simplex_to_bh(a_h_simplex, a_h_sum); 74 | vector[nt] UPs = upper_limits(a_h); 75 | vector[nt] ULs = raw_sum_to_b_h_sum(b_h_sum_s, UPs); 76 | array[P] vector[nt] b_h = simplex_to_bh(b_h_simplex, ULs); 77 | 78 | // Initialize t=1 79 | mu[1,] = phi0; 80 | u[1,] = u1_init; 81 | D[1,] = D1_init; 82 | Qr[1,] = Qr1_init; 83 | H[1] = Qr[1,]; 84 | R[1] = diag_matrix(rep_vector(1.0, nt)); 85 | Qr_sdi[1] = rep_vector(1.0, nt); 86 | 87 | // iterations geq 2 88 | for (t in 2:T){ 89 | // Meanstructure model: 90 | #include /model_components/mu.stan 91 | 92 | for(d in 1:nt){ 93 | vd[d] = 0.0; 94 | ma_d[d] = 0.0; 95 | ar_d[d] = 0.0; 96 | // GARCH MA component 97 | for (q in 1:min( t-1, Q) ) { 98 | rr[t-q, d] = square( rts[t-q, d] - mu[t-q, d] ); 99 | ma_d[d] = ma_d[d] + a_h[q, d]*rr[t-q, d] ; 100 | } 101 | // print("ma_d: ", "TS:", d, " Value:", ma_d[d], " T:", t); 102 | // GARCH AR component 103 | for (p in 1:min( t-1, P) ) { 104 | ar_d[d] = ar_d[d] + b_h[p, d]*D[t-p, d]^2; 105 | } 106 | // print("ar_d: ", "TS:", d, " Value:", ar_d[d], " T:", t); 107 | 108 | // Predictor on diag (given in xC) 109 | if ( xC_marker >= 1) { 110 | vd[d] = exp( c_h[d] + beta[d] * xC[t, d] ) + ma_d[d] + ar_d[d]; 111 | } else if ( xC_marker == 0) { 112 | vd[d] = exp( c_h[d] ) + ma_d[d] + ar_d[d]; 113 | } 114 | // print("c_h: ", "TS: ", d, " Value:", c_h[d]); 115 | 116 | D[t, d] = sqrt( vd[d] ); 117 | } 118 | u[t,] = diag_matrix(D[t,]) \ (rts[t,]- mu[t,]); // cf. comment about taking inverses in stan manual p. 482 re:Inverses - inv(D)*y = D \ a 119 | // print("u: ", "Value: ", u[t], "T:", t); 120 | Qr[t,] = (1 - a_q - b_q) * S + a_q * (u[t-1,] * u[t-1,]') + b_q * Qr[t-1,]; // S and UU' define dimension of Qr 121 | Qr_sdi[t,] = 1 ./ sqrt(diagonal(Qr[t,])); // inverse of diagonal matrix of sd's of Qr 122 | // R[t,] = quad_form_diag(Qr[t,], inv(sqrt(diagonal(Qr[t,]))) ); // Qr_sdi[t,] * Qr[t,] * Qr_sdi[t,]; 123 | R[t,] = quad_form_diag(Qr[t,], Qr_sdi[t,]); // Qr_sdi[t,] * Qr[t,] * Qr_sdi[t,]; 124 | H[t,] = quad_form_diag(R[t,], D[t,]); // H = DRD; 125 | } 126 | } 127 | model { 128 | // print("Upper Limits:", UPs); 129 | // UL transform jacobian 130 | for(k in 1:nt) { 131 | ULs[k] ~ uniform(0, UPs[k]); // Truncation not needed. 132 | target += a_b_scale_jacobian(0, ULs[k], b_h_sum_s[k]); 133 | } 134 | 135 | // priors 136 | to_vector(beta) ~ std_normal(); 137 | to_vector(c_h) ~ std_normal(); 138 | // Prior for initial state 139 | Qr1_init ~ wishart(nt + 1.0, diag_matrix(rep_vector(1.0, nt)) ); 140 | to_vector(D1_init) ~ lognormal(-1, 1); 141 | to_vector(u1_init) ~ std_normal(); 142 | // Prior on nu for student_t 143 | //if ( distribution == 1 ) 144 | nu ~ normal( nt, 50 ); 145 | to_vector(theta) ~ std_normal(); 146 | to_vector(phi) ~ std_normal(); 147 | phi0 ~ multi_normal(rts_m, diag_matrix( rts_sd ) ); 148 | // to_vector(a_h) ~ normal(0, .5); 149 | //to_vector(b_h) ~ normal(0, .5); 150 | S ~ lkj_corr( 1 ); 151 | 152 | // likelihood 153 | if ( distribution == 0 ) { 154 | for(t in 1:T){ 155 | rts[t,] ~ multi_normal(mu[t,], H[t,]); 156 | } 157 | } else if ( distribution == 1 ) { 158 | for(t in 1:T){ 159 | rts[t,] ~ multi_student_t(nu, mu[t,], H[t,]); 160 | } 161 | } 162 | } 163 | generated quantities { 164 | matrix[nt,T] rts_out; 165 | array[T] real log_lik; 166 | array[T] corr_matrix[nt] corH; 167 | // for the no-predictor case 168 | vector[nt] c_h_var = exp(c_h); 169 | // retrodict 170 | #include /generated/retrodict_H.stan 171 | 172 | } 173 | -------------------------------------------------------------------------------- /inst/stan/data/data.stan: -------------------------------------------------------------------------------- 1 | int T; // lengh of time series 2 | int nt; // number of time series 3 | int Q; // MA component in MGARCH(P,Q), matrix A 4 | int P; // AR component in MGARCH(P,Q), matrix B 5 | array[T] vector[nt] rts; // multivariate time-series 6 | array[T] vector[nt] xC; // time-varying predictor for constant variance 7 | int distribution; // 0 = Normal; 1 = student_t 8 | int meanstructure; // Select model for location 9 | -------------------------------------------------------------------------------- /inst/stan/data/gq_data.stan: -------------------------------------------------------------------------------- 1 | int T; 2 | int nt; // number of time series 3 | int Q; // MA component in MGARCH(P,Q), matrix A 4 | int P; // AR component in MGARCH(P,Q), matrix B 5 | array[T] vector[nt] rts; // multivariate time-series 6 | array[T] vector[nt] xC; // time-varying predictor for conditional H 7 | int distribution; // 0 = Normal; 1 = student_t 8 | int meanstructure; // Select model for location 9 | int ahead; // forecasted periods 10 | array[ahead] vector[nt] xC_p; // time-varying predictor for conditional H 11 | array[ahead] vector[nt] future_rts; // future observations to obtain log_lik 12 | int compute_log_lik; 13 | -------------------------------------------------------------------------------- /inst/stan/forecastBEKK.stan: -------------------------------------------------------------------------------- 1 | functions { 2 | #include /functions/cov2cor.stan 3 | } 4 | 5 | data { 6 | #include /data/gq_data.stan 7 | } 8 | 9 | transformed data { 10 | matrix[ahead + max(Q,P), nt] xC_c; 11 | #include /transformed_data/xh_marker.stan 12 | // Concatenate xC with xC_p 13 | for(i in 1:max(Q,P) ) { 14 | xC_c[i] = xC[T - (max(Q,P) - 1)]'; 15 | } 16 | for(i in 1:ahead) { 17 | xC_c[i + max(Q,P)] = xC_p[i]'; 18 | } 19 | } 20 | 21 | 22 | parameters { 23 | // ARMA parameters 24 | #include /parameters/arma.stan 25 | 26 | // predictor for H 27 | //cov_matrix[ xC_marker >= 1 ? nt : 0 ] beta; 28 | // cov_matrix[nt] beta; 29 | row_vector[nt] beta0; 30 | vector[nt] beta1; 31 | 32 | // in case Cnst is predicted, separate into C_sd*C_R*C_sd 33 | corr_matrix[nt] C_R; 34 | 35 | // DF constant nu for student t 36 | real< lower = 2 > nu; 37 | 38 | // cholesky_factor_cov[nt] Cnst; // Const is symmetric, A, B, are not 39 | cov_matrix[nt] Cnst; // Const is symmetric, A, B, are not 40 | 41 | array[T] cov_matrix[nt] H; 42 | array[T-1] matrix[nt,nt] rr; 43 | array[T] vector[nt] mu; 44 | array[Q] matrix[nt, nt] A; 45 | array[P] matrix[nt, nt] B; 46 | array[T] corr_matrix[nt] corH; 47 | } 48 | 49 | generated quantities { 50 | // Define matrix for rts prediction 51 | array[ahead + max(Q,P)] vector[nt] rts_p; 52 | array[ahead] vector[nt] rts_forecasted; 53 | 54 | array[ahead + max(Q,P)] cov_matrix[nt] H_p; 55 | array[ahead + max(Q,P)] corr_matrix[nt] R_p; 56 | array[ahead] cov_matrix[nt] H_forecasted; 57 | array[ahead] corr_matrix[nt] R_forecasted; 58 | 59 | array[ahead + max(Q,P)] matrix[nt,nt] rr_p; 60 | array[ahead + max(Q,P)] vector[nt] mu_p; 61 | array[ahead] vector[nt] mu_forecasted; 62 | 63 | matrix[nt+1, nt] beta = append_row( beta0, diag_matrix(beta1) ); 64 | 65 | // log lik for LFO-CV 66 | // only compute log_lik if it is actually requested 67 | array[compute_log_lik ==1 ? ahead:0] real log_lik; 68 | 69 | // Placeholders 70 | matrix[nt, nt] A_part_p; 71 | matrix[nt, nt] B_part_p; 72 | 73 | // Populate with non-NA values to avoid Error in stan 74 | rts_p[1:(ahead + max(Q,P)), ] = rts[ 1:(ahead + max(Q,P)), ]; 75 | H_p[ 1:(ahead + max(Q,P)), ] = H[ 1:(ahead + max(Q,P)), ]; 76 | mu_p[ 1:(ahead + max(Q,P)), ] = mu[ 1:(ahead + max(Q,P)), ]; 77 | rr_p[ 1:(ahead + max(Q,P)), ] = rr[ 1:(ahead + max(Q,P)), ]; 78 | 79 | R_p[ 1:(ahead + max(Q,P)), ] = corH[ 1:(ahead + max(Q,P)), ]; 80 | 81 | // Obtain needed elements from mu and fill into mu_p 82 | rts_p[1:max(Q, P), ] = rts[ (T-( max(Q,P)-1 ) ):T, ]; 83 | H_p[ 1:max(Q, P), ] = H[ (T-( max(Q,P)-1 ) ):T, ]; 84 | mu_p[ 1:max(Q, P), ] = mu[ (T-( max(Q,P)-1 ) ):T, ]; 85 | // rr is of length T-1 86 | rr_p[ 1:max(Q, P), ] = rr[ (T-1-( max(Q,P)-1 ) ):(T-1), ]; 87 | R_p[ 1:max(Q, P), ] = corH[ (T - ( max(Q,P)-1 ) ):T, ]; 88 | 89 | 90 | // Forecast 91 | for (t in (max(Q, P) + 1 ):( max(Q, P) + ahead ) ){ 92 | 93 | // reset both matrices to zero for each iteration t 94 | A_part_p = diag_matrix( rep_vector(0.0, nt)); 95 | B_part_p = diag_matrix( rep_vector(0.0, nt)); 96 | 97 | if( meanstructure == 0 ){ 98 | mu_p[t, ] = phi0; 99 | } else if( meanstructure == 1 ){ 100 | mu_p[t, ] = phi0 + phi * rts_p[t-1, ] + theta * (rts_p[t-1, ] - mu_p[t-1,]) ; 101 | } 102 | 103 | for (q in 1:min( t-1, Q) ) { 104 | rr_p[t-q,] = ( rts_p[t-q,] - mu_p[t-q,] )*( rts_p[t-q,] - mu_p[t-q,] )'; 105 | A_part_p = A_part_p + A[q]' * rr_p[t-q,] * A[q]; 106 | } 107 | for (p in 1:min( t-1, P) ) { 108 | B_part_p = B_part_p + B[p]' * H_p[t-p,] * B[p]; 109 | } 110 | if( xC_marker == 0 ) { 111 | H_p[t,] = quad_form_diag(C_R, exp( beta0 ) ) + A_part_p + B_part_p; 112 | } else if( xC_marker >= 1) { 113 | H_p[t,] = quad_form_diag(C_R,exp( append_col( 1.0, xC_c[ t, ] ) * beta )) + 114 | A_part_p + B_part_p; 115 | } 116 | R_p[t, ] = cov2cor(H_p[t,]); 117 | 118 | /* sampling distributions */ 119 | #include /generated/forecast_sampling.stan 120 | /* if ( distribution == 0 ) { */ 121 | /* rts_p[t,] = multi_normal_rng( mu_p[t,], H_p[t,]); */ 122 | /* if( compute_log_lik ) { */ 123 | /* for( i in 1:ahead ){ */ 124 | /* log_lik[i] = multi_normal_lpdf( future_rts[i] | mu_p[t,], H_p[t,] ); */ 125 | /* } */ 126 | /* } */ 127 | /* } else if ( distribution == 1 ) { */ 128 | /* rts_p[t,] = multi_student_t_rng( nu, mu_p[t,], H_p[t,]); */ 129 | /* if( compute_log_lik ) { */ 130 | /* for( i in 1:ahead ){ */ 131 | /* log_lik[i] = multi_student_t_lpdf( future_rts[i] | nu, mu_p[t,], H_p[t,] ); */ 132 | /* } */ 133 | /* } */ 134 | /* } */ 135 | } 136 | rts_forecasted = rts_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 137 | H_forecasted = H_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 138 | R_forecasted = R_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 139 | mu_forecasted = mu_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 140 | #include /generated/forecast_log_lik.stan 141 | } 142 | -------------------------------------------------------------------------------- /inst/stan/forecastCCC.stan: -------------------------------------------------------------------------------- 1 | data { 2 | #include /data/gq_data.stan 3 | } 4 | 5 | transformed data { 6 | matrix[ahead + max(Q,P), nt] xC_c; 7 | #include /transformed_data/xh_marker.stan 8 | // Concatenate xC with xC_p 9 | for(i in 1:max(Q,P) ) { 10 | xC_c[i] = xC[T - (max(Q,P) - 1)]'; 11 | } 12 | for(i in 1:ahead) { 13 | xC_c[i + max(Q,P)] = xC_p[i]'; 14 | } 15 | } 16 | 17 | parameters { 18 | // ARMA parameters 19 | #include /parameters/arma.stan 20 | // predictor for H 21 | #include /parameters/predH.stan 22 | // DF constant nu for student t 23 | real< lower = 2 > nu; 24 | 25 | // CCC specifics 26 | // GARCH h parameters on variance metric 27 | vector[nt] c_h; 28 | array[Q] vector[nt] a_h; 29 | array[P] vector[nt] b_h; // TODO actually: 1 - a_h, across all Q and P... 30 | 31 | // GARCH constant correlation 32 | corr_matrix[nt] R; 33 | 34 | // D1 init 35 | vector[nt] D1_init; 36 | 37 | array[T] cov_matrix[nt] H; 38 | array[T-1] vector[nt] rr; 39 | array[T] vector[nt] mu; 40 | array[T] vector[nt] D; 41 | } 42 | 43 | generated quantities { 44 | // Params for prediction 45 | array[ahead + max(Q,P)] vector[nt] D_p; 46 | array[ahead + max(Q, P)] corr_matrix[nt] R_p = rep_array(R, ahead + max(Q, P)); // R_p = R for all t. 47 | array[ahead] corr_matrix[nt] R_forecasted = rep_array(R, ahead); 48 | 49 | array[ahead + max(Q,P)] cov_matrix[nt] H_p; 50 | array[ahead] cov_matrix[nt] H_forecasted; 51 | 52 | // Define Vector that contains max of Q or P lag plus the forecasted ahead 53 | array[ahead + max(Q,P)] vector[nt] mu_p; 54 | array[ahead] vector[nt] mu_forecasted; 55 | // Define matrix for rts prediction 56 | array[ahead + max(Q,P)] vector[nt] rts_p; 57 | array[ahead] vector[nt] rts_forecasted; 58 | array[ahead + max(Q,P)] vector[nt] rr_p; 59 | 60 | // log lik for LFO-CV 61 | // only compute log_lik if it is actually requested 62 | array[ compute_log_lik ==1 ? ahead:0] real log_lik; 63 | 64 | array[nt] real vd; 65 | array[nt] real ma_d; 66 | array[nt] real ar_d; 67 | 68 | // Populate with non-NA values to avoid Error in stan 69 | mu_p[ 1:(ahead + max(Q,P)), ] = mu[ 1:(ahead + max(Q,P)), ]; 70 | rts_p[1:(ahead + max(Q,P)), ] = rts[ 1:(ahead + max(Q,P)), ]; 71 | rr_p[ 1:(ahead + max(Q,P)), ] = rr[ 1:(ahead + max(Q,P)), ]; 72 | D_p[ 1:(ahead + max(Q,P)), ] = D[ 1:(ahead + max(Q,P)), ]; 73 | H_p[1:(ahead + max(Q,P)), ] = H[1:(ahead + max(Q,P)), ]; 74 | 75 | // Obtain needed elements from mu and fill into mu_p 76 | mu_p[ 1:max(Q, P), ] = mu[ (T-(max(Q,P)-1) ):T, ]; 77 | rts_p[1:max(Q, P), ] = rts[ (T-(max(Q,P)-1) ):T, ]; 78 | // rr is of length T-1 79 | rr_p[ 1:max(Q, P), ] = rr[ (T-1-(max(Q,P)-1) ):(T-1), ]; 80 | D_p[ 1:max(Q, P), ] = D[ (T - (max(Q,P)-1) ):T, ]; 81 | H_p[1:max(Q, P), ] = H[(T - (max(Q,P)-1) ):T, ]; 82 | 83 | // Forecast 84 | 85 | // 86 | for (t in (max(Q, P) + 1 ):( max(Q, P) + ahead ) ){ 87 | 88 | if( meanstructure == 0 ){ 89 | mu_p[t, ] = phi0; 90 | } else if( meanstructure == 1 ){ 91 | mu_p[t, ] = phi0 + phi * rts_p[t-1, ] + theta * (rts_p[t-1, ] - mu_p[t-1,]) ; 92 | } 93 | 94 | // scale: SD's of D 95 | for (d in 1:nt) { 96 | vd[d] = 0.0; 97 | ma_d[d] = 0.0; 98 | ar_d[d] = 0.0; 99 | // MA component 100 | for (q in 1:min( t-1, Q) ) { 101 | rr_p[t-q, d] = square( rts_p[t-q, d] - mu_p[t-q, d] ); 102 | ma_d[d] = ma_d[d] + a_h[q, d]*rr_p[t-q, d] ; 103 | } 104 | for (p in 1:min( t-1, P) ) { 105 | ar_d[d] = ar_d[d] + b_h[p, d]*D_p[t-p, d]^2; 106 | } 107 | if ( xC_marker >= 1) { 108 | vd[d] = exp( c_h[d] + beta[d] * xC_c[t, d] ) + ma_d[d] + ar_d[d]; 109 | } else if ( xC_marker == 0) { 110 | vd[d] = exp( c_h[d] ) + ma_d[d] + ar_d[d]; 111 | } 112 | D_p[t, d] = sqrt( vd[d] ); 113 | } 114 | H_p[t,] = quad_form_diag(R, D_p[t,]); // H = DRD; 115 | 116 | /* sampling distriutions */ 117 | #include /generated/forecast_sampling.stan 118 | /* if ( distribution == 0 ) { */ 119 | /* rts_p[t,] = multi_normal_rng( mu_p[t,], H_p[t,]); */ 120 | /* if( compute_log_lik ) { */ 121 | /* for( i in 1:ahead ){ */ 122 | /* log_lik[i] = multi_normal_lpdf( future_rts[i] | mu_p[t,], H_p[t,] ); */ 123 | /* } */ 124 | /* } */ 125 | /* } else if ( distribution == 1 ) { */ 126 | /* rts_p[t,] = multi_student_t_rng( nu, mu_p[t,], H_p[t,]); */ 127 | /* if( compute_log_lik ) { */ 128 | /* for( i in 1:ahead ){ */ 129 | /* log_lik[i] = multi_student_t_lpdf( future_rts[i] | nu, mu_p[t,], H_p[t,] ); */ 130 | /* } */ 131 | /* } */ 132 | /* } */ 133 | } 134 | rts_forecasted = rts_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 135 | H_forecasted = H_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 136 | // R_forecasted = R_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 137 | mu_forecasted = mu_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 138 | #include /generated/forecast_log_lik.stan 139 | } 140 | 141 | -------------------------------------------------------------------------------- /inst/stan/forecastDCC.stan: -------------------------------------------------------------------------------- 1 | data { 2 | #include /data/gq_data.stan 3 | } 4 | 5 | transformed data { 6 | matrix[ahead + max(Q,P), nt] xC_c; 7 | #include /transformed_data/xh_marker.stan 8 | // Concatenate xC with xC_p 9 | for(i in 1:max(Q,P) ) { 10 | xC_c[i] = xC[T - (max(Q,P) - 1)]'; 11 | } 12 | for(i in 1:ahead) { 13 | xC_c[i + max(Q,P)] = xC_p[i]'; 14 | } 15 | } 16 | 17 | parameters { 18 | // ARMA parameters 19 | #include /parameters/arma.stan 20 | // predictor for H 21 | #include /parameters/predH.stan 22 | // DF constant nu for student t 23 | real< lower = 2 > nu; 24 | 25 | // GARCH h parameters on variance metric 26 | vector[nt] c_h; 27 | array[Q] vector[nt] a_h; 28 | array[P] vector[nt] b_h; // TODO actually: 1 - a_h, across all Q and P... 29 | 30 | // GARCH q parameters 31 | real a_q; // 32 | real b_q; // 33 | corr_matrix[nt] S; // DCC keeps this constant 34 | 35 | // inits 36 | array[T] cov_matrix[nt] H; 37 | array[T] corr_matrix[nt] R; 38 | array[T-1] vector[nt] rr; 39 | array[T] vector[nt] mu; 40 | array[T] vector[nt] D; 41 | array[T] cov_matrix[nt] Qr; 42 | array[T] vector[nt] Qr_sdi; 43 | array[T] vector[nt] u; 44 | } 45 | 46 | generated quantities { 47 | // Define matrix for rts prediction 48 | array[ahead + max(Q,P)] vector[nt] rts_p; 49 | array[ahead] vector[nt] rts_forecasted; 50 | array[ahead + max(Q,P)] cov_matrix[nt] H_p; 51 | array[ahead] cov_matrix[nt] H_forecasted; 52 | array[ahead + max(Q,P)] corr_matrix[nt] R_p; // 53 | array[ahead] corr_matrix[nt] R_forecasted; // 54 | array[ahead + max(Q,P)] vector[nt] rr_p; 55 | array[ahead + max(Q,P)] vector[nt] mu_p; 56 | array[ahead] vector[nt] mu_forecasted; 57 | array[ahead + max(Q,P)] vector[nt] D_p; 58 | array[ahead + max(Q,P)] cov_matrix[nt] Qr_p; 59 | array[ahead + max(Q,P)] vector[nt] u_p; 60 | array[ahead + max(Q,P)] vector[nt] Qr_sdi_p; 61 | // log lik for LFO-CV 62 | // only compute log_lik if it is actually requested 63 | array[compute_log_lik ==1 ? ahead:0] real log_lik; 64 | 65 | // Placeholders 66 | array[nt] real vd_p; 67 | array[nt] real ma_d_p; 68 | array[nt] real ar_d_p; 69 | 70 | 71 | // Populate with non-NA values to avoid Error in stan 72 | rts_p[1:(ahead + max(Q,P)), ] = rts[ 1:(ahead + max(Q,P)), ]; 73 | H_p[ 1:(ahead + max(Q,P)), ] = H[ 1:(ahead + max(Q,P)), ]; 74 | mu_p[ 1:(ahead + max(Q,P)), ] = mu[ 1:(ahead + max(Q,P)), ]; 75 | rr_p[ 1:(ahead + max(Q,P)), ] = rr[ 1:(ahead + max(Q,P)), ]; 76 | D_p[ 1:(ahead + max(Q,P)), ] = D[ 1:(ahead + max(Q,P)), ]; 77 | u_p[ 1:(ahead + max(Q,P)), ] = u[ 1:(ahead + max(Q,P)), ]; 78 | Qr_p[ 1:(ahead + max(Q,P)), ] = Qr[ 1:(ahead + max(Q,P)), ]; 79 | Qr_sdi_p[ 1:(ahead + max(Q,P)), ] = Qr_sdi[ 1:(ahead + max(Q,P)), ]; 80 | 81 | R_p[ 1:(ahead + max(Q,P)), ] = R[ 1:(ahead + max(Q,P)), ]; 82 | 83 | // Obtain needed elements (depends on lags in Q and P) from mu and fill into mu_p 84 | rts_p[1:max(Q, P), ] = rts[(T-(max(Q,P)-1) ):T, ]; 85 | H_p[ 1:max(Q, P), ] = H[ (T-(max(Q,P)-1) ):T, ]; 86 | mu_p[ 1:max(Q, P), ] = mu[ (T-(max(Q,P)-1) ):T, ]; 87 | // rr is of length T-1 88 | rr_p[ 1:max(Q, P), ] = rr[ (T-1-(max(Q,P)-1) ):(T-1), ]; 89 | D_p[ 1:max(Q, P), ] = D[ (T - (max(Q,P)-1) ):T, ]; 90 | u_p[ 1:max(Q, P), ] = u[ (T - (max(Q,P)-1) ):T, ]; 91 | Qr_p[ 1:max(Q, P), ] = Qr[ (T - (max(Q,P)-1) ):T, ]; 92 | Qr_sdi_p[ 1:max(Q, P), ] = Qr_sdi[ (T - (max(Q,P)-1) ):T, ]; 93 | R_p[ 1:max(Q, P), ] = R[ (T - (max(Q,P)-1) ):T, ]; 94 | 95 | // Forecast 96 | for (t in (max(Q, P) + 1 ):( max(Q, P) + ahead ) ){ 97 | 98 | if( meanstructure == 0 ){ 99 | mu_p[t, ] = phi0; 100 | } else if( meanstructure == 1 ){ 101 | mu_p[t, ] = phi0 + phi * rts_p[t-1, ] + theta * (rts_p[t-1, ] - mu_p[t-1,]) ; 102 | } 103 | 104 | for(d in 1:nt){ 105 | vd_p[d] = 0.0; 106 | ma_d_p[d] = 0.0; 107 | ar_d_p[d] = 0.0; 108 | // GARCH MA component 109 | for (q in 1:min( t-1, Q) ) { 110 | rr_p[t-q, d] = square( rts_p[t-q, d] - mu_p[t-q, d] ); 111 | ma_d_p[d] = ma_d_p[d] + a_h[q, d] * rr_p[t-q, d] ; 112 | } 113 | // GARCH AR component 114 | for (p in 1:min( t-1, P) ) { 115 | ar_d_p[d] = ar_d_p[d] + b_h[p, d] * D_p[t-p, d]^2; 116 | } 117 | 118 | // Predictor on diag (given in xC) 119 | if ( xC_marker >= 1) { 120 | vd_p[d] = exp( c_h[d] + beta[d] * xC_c[t, d] ) + ma_d_p[d] + ar_d_p[d]; 121 | } else if ( xC_marker == 0) { 122 | vd_p[d] = exp( c_h[d] ) + ma_d_p[d] + ar_d_p[d]; 123 | } 124 | 125 | D_p[t, d] = sqrt( vd_p[d] ); 126 | } 127 | u_p[t - 1,] = diag_matrix(D_p[t - 1,]) \ (rts_p[t - 1,]- mu_p[t - 1,]); 128 | Qr_p[t, ] = (1 - a_q - b_q) * S + a_q * (u_p[t-1,] * u_p[t-1,]') + b_q * Qr_p[t-1,]; 129 | Qr_sdi_p[t,] = 1 ./ sqrt(diagonal(Qr_p[t,])); 130 | R_p[t,] = quad_form_diag(Qr_p[t,], Qr_sdi_p[t,]); 131 | 132 | // H_p[t,] = quad_form_diag(R_p[t,], D_p[t,]); 133 | H_p[t,] = diag_matrix(D_p[t,]) * R_p[t,] * diag_matrix(D_p[t,]); 134 | 135 | /* sampling distributions */ 136 | #include /generated/forecast_sampling.stan 137 | /* if ( distribution == 0 ) { */ 138 | /* rts_p[t,] = multi_normal_rng( mu_p[t,], H_p[t,]); */ 139 | /* if( compute_log_lik ) { */ 140 | /* for( i in 1:ahead ){ */ 141 | /* log_lik[i] = multi_normal_lpdf( future_rts[i] | mu_p[t,], H_p[t,] ); */ 142 | /* } */ 143 | /* } */ 144 | /* } else if ( distribution == 1 ) { */ 145 | /* rts_p[t,] = multi_student_t_rng( nu, mu_p[t,], H_p[t,]); */ 146 | /* if( compute_log_lik ) { */ 147 | /* for( i in 1:ahead ){ */ 148 | /* log_lik[i] = multi_student_t_lpdf( future_rts[i] | nu, mu_p[t,], H_p[t,] ); */ 149 | /* } */ 150 | /* } */ 151 | /* } */ 152 | } 153 | rts_forecasted = rts_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 154 | H_forecasted = H_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 155 | R_forecasted = R_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 156 | mu_forecasted = mu_p[max(Q, P) + 1 : (max(Q, P) + ahead)]; 157 | #include /generated/forecast_log_lik.stan 158 | } 159 | -------------------------------------------------------------------------------- /inst/stan/functions/cov2cor.stan: -------------------------------------------------------------------------------- 1 | matrix cov2cor(matrix C){ 2 | int dm = rows(C); 3 | matrix[dm,dm] s; 4 | matrix[dm,dm] R; 5 | s = diag_matrix( 1 ./ sqrt(diagonal(C)) ); 6 | R = s*C*s ; //quad_form_diag(C, s); 7 | return R; 8 | } 9 | -------------------------------------------------------------------------------- /inst/stan/functions/jacobian.stan: -------------------------------------------------------------------------------- 1 | /* 2 | Computes jacobian for the a_b_scale transform. 3 | @param a Lower limit. 4 | @param b Upper limit. 5 | @param value The unconstrained value to be transformed. 6 | @return log jacobian contribution. 7 | */ 8 | real a_b_scale_jacobian(real a, real b, real value) { 9 | real invlogit_value = inv_logit(value); 10 | real out = log(b - a) + log(invlogit_value) + log1m(invlogit_value); 11 | return(out); 12 | } 13 | 14 | /* 15 | Takes unconstrained R value, transforms to be between a and b. 16 | @param a Lower limit. 17 | @param b Upper limit. 18 | @param value The unconstrained value to transform 19 | @return real value between a and b. 20 | */ 21 | real a_b_scale(real a, real b, real value) { 22 | return(a + (b - a) * inv_logit(value)); 23 | } 24 | 25 | /* 26 | Compute the upper limit of b_h from a_h, given that sum(a_h) + sum(b_h) < 1 27 | This works for b_h given a_h, or a_h given b_h. They yield identical models, assuming a dual constraint, such that 0 < sum(a_h) < 1 and 0 < sum(b_h) < 1 - sum(a_h), or vice-versa. 28 | @param a_h Array of vectors [nt, Q]. 29 | @return vector[nt] Upper limits such that sum(b_h{k}) < UpperLimit{k} = 1 - sum(a_h{k}) 30 | */ 31 | vector upper_limits(array[] vector a_h) { 32 | int nt = num_elements(a_h[1]); 33 | int Q = size(a_h); 34 | vector[nt] a_h_sums; 35 | vector[nt] out; 36 | for(k in 1:nt) { 37 | a_h_sums[k] = sum(a_h[1:Q, k]); 38 | out[k] = 1 - a_h_sums[k]; 39 | if(out[k] <= 0) {out[k] = .00001;} 40 | } 41 | 42 | return(out); 43 | } 44 | 45 | /* 46 | Transform unconstrained sums to (0, upperLimits). 47 | @param b_h_sum_s A vector [nt] of unconstrained sums. 48 | @param upperLimits A vector [nt] of the upper limits. 49 | @return vector[nt] of values between [0, upperLimits]. 50 | */ 51 | vector raw_sum_to_b_h_sum(vector b_h_sum_s, vector upperLimits) { 52 | int nt = num_elements(upperLimits); 53 | vector[nt] out; 54 | for(k in 1:nt) { 55 | out[k] = a_b_scale(0, upperLimits[k], b_h_sum_s[k]); 56 | } 57 | return(out); 58 | } 59 | /* 60 | Transform the array of b_h simplexes to b_h. 61 | 62 | The dual constraint is such that 0 < sum(a_h) + sum(b_h) < 1, for each timeseries. 63 | We assume sum(a_h) is [0,1], then sum(b_h) is [0, 1 - sum(a_h)]. 64 | The sums are estimated for a_h and b_h. 65 | Then the a_h and b_h simplexes are scaled by the sums to produce a_h and b_h. 66 | 67 | @param b_h_simplex Array [nt] of simplexes [P]. 68 | @param b_h_sum vector [nt] of the value to which the b_h's should be summed. 69 | @return An array [P] of vectors [nt]. 70 | */ 71 | array[] vector simplex_to_bh(array[] vector b_h_simplex, vector b_h_sum) { 72 | int nt = size(b_h_simplex); 73 | int P = num_elements(b_h_simplex[1]); 74 | array[P] vector[nt] b_h; 75 | for(k in 1:nt) { 76 | b_h[1:P, k] = to_array_1d(b_h_simplex[k] * b_h_sum[k]); 77 | } 78 | return(b_h); 79 | } 80 | -------------------------------------------------------------------------------- /inst/stan/generated/forecast_log_lik.stan: -------------------------------------------------------------------------------- 1 | if( compute_log_lik ) { 2 | if (distribution == 0 ) { 3 | for(i in 1:ahead) { 4 | log_lik[i] = multi_normal_lpdf( future_rts[i] | mu_forecasted[i], H_forecasted[i]); 5 | } 6 | } else if (distribution == 1 ) { 7 | for(i in 1:ahead) { 8 | log_lik[i] = multi_student_t_lpdf( future_rts[i] | nu, mu_forecasted[i], H_forecasted[i]); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /inst/stan/generated/forecast_sampling.stan: -------------------------------------------------------------------------------- 1 | if ( distribution == 0 ) { 2 | rts_p[t,] = multi_normal_rng( mu_p[t,], H_p[t,]); 3 | } else if ( distribution == 1 ) { 4 | rts_p[t,] = multi_student_t_rng( nu, mu_p[t,], H_p[t,]); 5 | } 6 | -------------------------------------------------------------------------------- /inst/stan/generated/retrodict_H.stan: -------------------------------------------------------------------------------- 1 | // retrodict given distribution type 2 | if ( distribution == 0 ){ 3 | for (t in 1:T) { 4 | rts_out[,t] = multi_normal_rng(mu[t,], H[t,]); 5 | corH[t,] = cov2cor(H[t,]); 6 | log_lik[t] = multi_normal_lpdf(rts[t,] | mu[t,], H[t,]); 7 | } 8 | } else if ( distribution == 1 ) { 9 | for (t in 1:T) { 10 | rts_out[,t] = multi_student_t_rng(nu, mu[t,], H[t,]); 11 | corH[t,] = cov2cor(H[t,]); 12 | log_lik[t] = multi_student_t_lpdf(rts[t,] | nu, mu[t,], H[t,]); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /inst/stan/include/license.stan: -------------------------------------------------------------------------------- 1 | /* 2 | bmgarch is free software: you can redistribute it and/or modify 3 | it under the terms of the GNU General Public License as published by 4 | the Free Software Foundation, either version 3 of the License, or 5 | (at your option) any later version. 6 | 7 | bmgarch is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with bmgarch. If not, see . 14 | */ 15 | -------------------------------------------------------------------------------- /inst/stan/model_components/mu.stan: -------------------------------------------------------------------------------- 1 | if( meanstructure == 0 ){ 2 | // Constant 3 | mu[t, ] = phi0; 4 | } else if( meanstructure == 1 ){ 5 | // arma11 6 | mu[t, ] = phi0 + phi * rts[t-1, ] + theta * (rts[t-1, ] - mu[t-1,]) ; 7 | } else if( meanstructure == 2 ){ 8 | // VAR1 9 | mu[t, ] = phi0 + phi * rts[t-1, ]; 10 | } 11 | -------------------------------------------------------------------------------- /inst/stan/parameters/arma.stan: -------------------------------------------------------------------------------- 1 | vector[nt] phi0; 2 | // gqs() cant not deal with ? yet - as long as that's not fixed 3 | // estimate phi and theta anyways 4 | //matrix[meanstructure ? nt : 0, meanstructure ? nt : 0 ] phi; 5 | //matrix[meanstructure ? nt : 0, meanstructure ? nt : 0 ] theta; 6 | matrix[nt,nt] phi; 7 | matrix[nt,nt] theta; 8 | -------------------------------------------------------------------------------- /inst/stan/parameters/predH.stan: -------------------------------------------------------------------------------- 1 | // Predictors for H 2 | //cov_matrix[ xC_marker >= 1 ? nt : 0 ] beta; 3 | // gqs() cant currently handle ? opeartor do this instead: 4 | vector[nt] beta; 5 | -------------------------------------------------------------------------------- /inst/stan/pdBEKKMGARCH.stan: -------------------------------------------------------------------------------- 1 | // pdBEKK-Parameterization 2 | functions { 3 | #include /functions/cov2cor.stan 4 | } 5 | 6 | data { 7 | #include /data/data.stan 8 | } 9 | 10 | transformed data { 11 | // Obtain mean and sd ove TS for prior in arma process phi0 12 | vector[nt] rts_m; 13 | vector[nt] rts_sd; 14 | // off diagonal elements 15 | int od = ( nt*nt - nt ) %/% 2; 16 | #include /transformed_data/xh_marker.stan 17 | 18 | if( meanstructure == 0 ){ 19 | for ( i in 1:nt ){ 20 | rts_m[i] = mean(rts[,i]); 21 | rts_sd[i] = sd(rts[,i]); 22 | } 23 | } else if (meanstructure == 1 || meanstructure == 2 ){ 24 | // set rts_m to first element in ts 25 | for ( i in 1:nt ){ 26 | rts_m[i] = rts[1,i]; 27 | rts_sd[i] = sd(rts[,i]); 28 | } 29 | } 30 | } 31 | 32 | parameters { 33 | // ARMA parameters 34 | #include /parameters/arma.stan 35 | 36 | // predictor for H 37 | //cov_matrix[ xC_marker >= 1 ? nt : 0 ] beta; 38 | row_vector[nt] beta0; 39 | vector[nt] beta1; 40 | 41 | // Separate into C_sd*C_R*C_sd 42 | // C_sd is defined in tp, as function of betas 43 | corr_matrix[nt] C_R; 44 | 45 | array[Q] vector[nt] A_diag; 46 | array[P] vector[nt] B_diag; 47 | 48 | array[Q] vector[ od ] A_lower; 49 | array[P] vector[ od ] B_lower; 50 | array[Q] vector[ od ] A_upper; 51 | array[P] vector[ od ] B_upper; 52 | 53 | // H1 init 54 | cov_matrix[nt] H1_init; 55 | real< lower = 2 > nu; // nu for student_t 56 | 57 | } 58 | transformed parameters { 59 | array[T] cov_matrix[nt] H; 60 | array[T-1] matrix[nt,nt] rr; 61 | array[T] vector[nt] mu; 62 | 63 | matrix[nt, nt] A_part = diag_matrix( rep_vector(0.0, nt)); 64 | matrix[nt, nt] B_part = diag_matrix( rep_vector(0.0, nt)); 65 | 66 | matrix[nt+1, nt] beta = append_row( beta0, diag_matrix(beta1) ); 67 | row_vector[nt] C_sd; 68 | cov_matrix[nt] Cnst; // Const is symmetric, A, B, are not 69 | 70 | // Construct square matrices with positive diagonals 71 | array[Q] matrix[nt, nt] A_raw; 72 | array[P] matrix[nt, nt] B_raw; 73 | 74 | for(q in 1:Q) { 75 | int L = 0; 76 | int U = 0; 77 | for( i in 1:nt ){ 78 | for( j in 1:nt ){ 79 | if ( i < j ) { 80 | U = U + 1; 81 | A_raw[q, i, j] = A_upper[q, U]; 82 | } else if ( i > j ) { 83 | L = L + 1; 84 | A_raw[q, i, j] = A_lower[q, L]; 85 | } else if (i == j ){ 86 | A_raw[q, i, j] = A_diag[q, i]; 87 | } 88 | } 89 | } 90 | } 91 | 92 | 93 | for(p in 1:P) { 94 | int L = 0; 95 | int U = 0; 96 | for( i in 1:nt ){ 97 | for( j in 1:nt ){ 98 | if ( i < j ) { 99 | U = U + 1; 100 | B_raw[p, i, j] = B_upper[p, U]; 101 | } else if ( i > j ) { 102 | L = L + 1; 103 | B_raw[p, i, j] = B_lower[p, L]; 104 | } else if (i == j ){ 105 | B_raw[p, i, j] = B_diag[p, i]; 106 | } 107 | } 108 | } 109 | } 110 | 111 | // Initialize model parameters 112 | mu[1,] = phi0; 113 | H[1,] = H1_init; 114 | 115 | for (t in 2:T){ 116 | // Meanstructure model: 117 | #include /model_components/mu.stan 118 | 119 | // reset A_part and B_part to zero for each iteration t 120 | A_part = diag_matrix( rep_vector(0.0, nt)); 121 | B_part = diag_matrix( rep_vector(0.0, nt)); 122 | 123 | for (q in 1:min( t-1, Q) ) { 124 | rr[t-q,] = ( rts[t-q,] - mu[t-q,] )*( rts[t-q,] - mu[t-q,] )'; 125 | A_part = A_part + A_raw[q]' * rr[t-q,] * A_raw[q]; 126 | } 127 | for (p in 1:min( t-1, P) ) { 128 | B_part = B_part + B_raw[p]' * H[t-p,] * B_raw[p]; 129 | } 130 | if( xC_marker == 0 ) { 131 | C_sd = exp( beta0 ); 132 | Cnst = quad_form_diag(C_R, C_sd ); 133 | H[t,] = Cnst + A_part + B_part; 134 | } else if( xC_marker >= 1) { 135 | C_sd = exp( append_col( 1.0, xC[t]' ) * beta ); 136 | Cnst = quad_form_diag(C_R, C_sd ); 137 | H[t,] = Cnst + A_part + B_part; 138 | } 139 | } 140 | } 141 | model { 142 | // priors 143 | 144 | // Prior on nu for student_t 145 | nu ~ normal( nt, 50 ); 146 | 147 | // Prior for initial state 148 | H1_init ~ wishart(nt + 1.0, diag_matrix(rep_vector(1.0, nt)) ); 149 | 150 | to_vector(theta) ~ std_normal(); 151 | to_vector(phi) ~ std_normal(); 152 | phi0 ~ multi_normal(rts_m, diag_matrix( rts_sd ) ); 153 | 154 | to_vector(beta0) ~ std_normal(); 155 | to_vector(beta1) ~ std_normal(); 156 | C_R ~ lkj_corr( 1 ); 157 | 158 | for(q in 1:Q) { 159 | to_vector(A_upper[q]) ~ std_normal(); 160 | to_vector(A_lower[q]) ~ std_normal(); 161 | to_vector(A_diag[q]) ~ uniform( 0, 1 ); 162 | } 163 | 164 | 165 | for(p in 1:P) { 166 | to_vector(B_upper[p]) ~ std_normal(); 167 | to_vector(B_lower[p]) ~ std_normal(); 168 | to_vector(B_diag[p]) ~ uniform( 0, 1 ); 169 | } 170 | 171 | // likelihood 172 | if ( distribution == 0 ) { 173 | for(t in 1:T){ 174 | target += multi_normal_lpdf(rts[t, ]| mu[t,], H[t,]); 175 | } 176 | } else if ( distribution == 1 ) { 177 | for(t in 1:T){ 178 | target += multi_student_t_lpdf( rts[t, ] | nu, mu[t,], H[t,]); 179 | } 180 | } 181 | } 182 | // 183 | generated quantities { 184 | array[Q] matrix[nt, nt] A = A_raw; 185 | array[P] matrix[nt, nt] B = B_raw; 186 | matrix[nt,T] rts_out; 187 | array[T] real log_lik; 188 | corr_matrix[nt] corC; 189 | array[T] corr_matrix[nt] corH; 190 | row_vector[nt] C_var; 191 | 192 | 193 | //Const = multiply_lower_tri_self_transpose(Cnst); 194 | corC = C_R; 195 | C_var = exp(2*beta0 ); 196 | 197 | // retrodict 198 | #include /generated/retrodict_H.stan 199 | } 200 | -------------------------------------------------------------------------------- /inst/stan/transformed_data/xh_marker.stan: -------------------------------------------------------------------------------- 1 | // Check whether xC contains a predictor or not. 2 | array[T] matrix[nt, nt] xC_m; 3 | int xC_marker = 0; 4 | real cp; 5 | 6 | for( t in 1:T ){ 7 | xC_m[t] = diag_matrix( xC[t] ); 8 | // add a variable that notes if xC is null or actually a predictor 9 | cp = sum( xC_m[t]' * xC_m[t] ); 10 | if( cp != 0 ) 11 | xC_marker = xC_marker + 1; 12 | } 13 | -------------------------------------------------------------------------------- /man/as.data.frame.fitted.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{as.data.frame.fitted.bmgarch} 4 | \alias{as.data.frame.fitted.bmgarch} 5 | \title{as.data.frame method for fitted.bmgarch objects.} 6 | \usage{ 7 | \method{as.data.frame}{fitted.bmgarch}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{fitted.bmgarch object.} 11 | 12 | \item{...}{Not used.} 13 | } 14 | \value{ 15 | Data frame. 16 | } 17 | \description{ 18 | as.data.frame method for fitted.bmgarch objects. 19 | } 20 | \author{ 21 | Stephen R. Martin 22 | } 23 | -------------------------------------------------------------------------------- /man/as.data.frame.forecast.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{as.data.frame.forecast.bmgarch} 4 | \alias{as.data.frame.forecast.bmgarch} 5 | \title{as.data.frame method for forecast.bmgarch objects.} 6 | \usage{ 7 | \method{as.data.frame}{forecast.bmgarch}(x, ..., backcast = TRUE) 8 | } 9 | \arguments{ 10 | \item{x}{forecast.bmgarch object.} 11 | 12 | \item{...}{Not used.} 13 | 14 | \item{backcast}{Logical (Default: True). Whether to include "backcasted" values from \code{\link{fitted.bmgarch}} in data frame.} 15 | } 16 | \value{ 17 | Data frame. 18 | } 19 | \description{ 20 | as.data.frame method for forecast.bmgarch objects. 21 | } 22 | \author{ 23 | Stephen R. Martin 24 | } 25 | -------------------------------------------------------------------------------- /man/bmgarch-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bmgarch-package.R 3 | \docType{package} 4 | \name{bmgarch-package} 5 | \alias{bmgarch-package} 6 | \title{The 'bmgarch' package.} 7 | \description{ 8 | The *bmgarch* package fits Bayesian multivariate GARCH models specified via Stan, 9 | a C++ package providing HMC methods for full Bayesian inference (cf. [http://mc-stan.org]). The currently implemented parameterizations are DCC(Q,P), 10 | CCC(Q,P), and BEKK(Q,P) with arbitrary lags defined in Q, and P. The package provides summaries and plots for the estimates as well 11 | as forecasted series with corresponding plots. The fitted objects are rstan class objects that can be inspected and manipulated 12 | accordingly. 13 | } 14 | \references{ 15 | Stan Development Team (2018). RStan: the R interface to Stan. R package version 2.18.2. http://mc-stan.org 16 | } 17 | \seealso{ 18 | Useful links: 19 | \itemize{ 20 | \item Report bugs at \url{https://github.com/ph-rast/bmgarch/issues} 21 | } 22 | 23 | } 24 | \author{ 25 | Philippe Rast 26 | } 27 | \keyword{internal} 28 | -------------------------------------------------------------------------------- /man/bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bmgarch.R 3 | \name{bmgarch} 4 | \alias{bmgarch} 5 | \title{Estimate Bayesian Multivariate GARCH} 6 | \usage{ 7 | bmgarch( 8 | data, 9 | xC = NULL, 10 | parameterization = "CCC", 11 | P = 1, 12 | Q = 1, 13 | iterations = 2000, 14 | chains = 4, 15 | standardize_data = FALSE, 16 | distribution = "Student_t", 17 | meanstructure = "constant", 18 | sampling_algorithm = "MCMC", 19 | backend = "rstan", 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{data}{Time-series or matrix object. A time-series or matrix object containing observations at the same interval.} 25 | 26 | \item{xC}{Numeric vector or matrix. Covariates(s) for the constant variance terms in C, or c, used in a log-linear model on the constant variance terms \insertCite{Rast2020}{bmgarch}. If vector, then it acts as a covariate for all constant variance terms. If matrix, must have columns equal to number of time series, and each column acts as a covariate for the respective time series (e.g., column 1 predicts constant variance for time series 1).} 27 | 28 | \item{parameterization}{Character (Default: "CCC"). The type of of parameterization. Must be one of "CCC", "DCC", "BEKK", or "pdBEKK".} 29 | 30 | \item{P}{Integer. Dimension of GARCH component in MGARCH(P,Q).} 31 | 32 | \item{Q}{Integer. Dimension of ARCH component in MGARCH(P,Q).} 33 | 34 | \item{iterations}{Integer (Default: 2000). Number of iterations for each chain (including warmup).} 35 | 36 | \item{chains}{Integer (Default: 4). The number of Markov chains.} 37 | 38 | \item{standardize_data}{Logical (Default: FALSE). Whether data should be standardized to easy computations.} 39 | 40 | \item{distribution}{Character (Default: "Student_t"). Distribution of innovation: "Student_t" or "Gaussian"} 41 | 42 | \item{meanstructure}{Character (Default: "constant"). Defines model for means. Either 'constant' or 'ARMA'. Currently ARMA(1,1) only. OR 'VAR' (VAR1).} 43 | 44 | \item{sampling_algorithm}{Character (Default" "MCMC"). Define sampling algorithm. Either 'MCMC'for Hamiltonian Monte Carlo or 'VB' for variational Bayes. 'VB' is inherited from stan and is currently in heavy development -- do not trust estimates.} 45 | 46 | \item{backend}{Select backend. Defaults to 'rstan' or select 'cmdstanr' if installed.} 47 | 48 | \item{...}{Additional arguments can be ‘chain_id’, ‘init_r’, ‘test_grad’, ‘append_samples’, ‘refresh’, ‘enable_random_init’ etc. See the documentation in \code{\link[rstan]{stan}}.} 49 | } 50 | \value{ 51 | \code{bmgarch} object. 52 | } 53 | \description{ 54 | Draw samples from a specified multivariate GARCH model using 'Stan', given multivariate time-series. Currently supports CCC, DCC, BEKK, and pdBEKK model parameterizations. 55 | } 56 | \details{ 57 | Four types of paramerizations are implemented. The constant conditional correlation (CCC) and the dynamic conditional correlation \insertCite{@DCC; Engle2002,Engle2001a}{bmgarch}, as well as BEKK \insertCite{Engle1995}{bmgarch} and a BEKK model with positivity constraints on the diagonals of the ARCH and GARCH parameters "pdBEKK" \insertCite{Rast2020}{bmgarch}. 58 | 59 | The fitted models are 'rstan' objects and all posterior parameter estimates can be obtained and can be examined with either the 'rstan' toolbox, plotted and printed using generic functions or passed to 'bmgarch' functions to 'forecast' or compute 'model_weights' or compute fit statistics based on leave-future-out cross-validation. 60 | } 61 | \examples{ 62 | \dontrun{ 63 | data(panas) 64 | # Fit BEKK(1,1) mgarch model with a ARMA(1,1) meanstructure, 65 | # and student-t residual distribution 66 | fit <- bmgarch(panas, parameterization = "BEKK", 67 | P = 1, Q = 1, 68 | meanstructure = "arma", 69 | distribution = "Student_t") 70 | 71 | # Summarize the parameters 72 | summary(fit) 73 | 74 | # Forecast 5 ahead 75 | fit.fc <- forecast(fit, ahead = 5) 76 | print(fit.fc) 77 | 78 | # Plot mean forecasts 79 | plot(fit.fc, type = "mean") 80 | 81 | # Plot variance forecasts 82 | plot(fit.fc, type = "var") 83 | 84 | # Plot correlation forecasts 85 | plot(fit.fc, type = "cor") 86 | 87 | # Plot modeled data ("backcasted values"). 88 | plot(fit, type = "mean") 89 | 90 | # Save "backcasted" values 91 | fit.bc <- fitted(fit) 92 | 93 | # Save estimated and forecasted data as a data.frame 94 | df.fc <- as.data.frame(fit.fc) 95 | 96 | # Access rstan's model fit object 97 | mf <- fit$model_fit 98 | 99 | # Return diagnostics and a plot of the first 10 parameters 100 | rstan::check_hmc_diagnostics(mf) 101 | rstan::plot(mf) 102 | } 103 | } 104 | \references{ 105 | \insertAllCited() 106 | } 107 | \author{ 108 | Philippe Rast, Stephen R. Martin 109 | } 110 | -------------------------------------------------------------------------------- /man/bmgarch_list.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{bmgarch_list} 4 | \alias{bmgarch_list} 5 | \title{Collect bmgarch objects into list.} 6 | \usage{ 7 | bmgarch_list(...) 8 | } 9 | \arguments{ 10 | \item{...}{bmgarch objects.} 11 | } 12 | \value{ 13 | List of bmgarch objects. Class: bmgarch_list and bmgarch. 14 | } 15 | \description{ 16 | Collect bmgarch objects into list. 17 | } 18 | -------------------------------------------------------------------------------- /man/dot-colQTs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.colQTs} 4 | \alias{.colQTs} 5 | \title{Quantiles within lists} 6 | \usage{ 7 | .colQTs(x, probs) 8 | } 9 | \arguments{ 10 | \item{x}{} 11 | 12 | \item{probs}{Quantile(s). Inherits from \code{forecast} which defaults to \code{c(.025, .975)}.} 13 | } 14 | \value{ 15 | Quantiles at the column level within lists 16 | } 17 | \description{ 18 | Obtain quantiles over columns in lists 19 | } 20 | \author{ 21 | philippe 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/dot-cp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helper.R 3 | \name{.cp} 4 | \alias{.cp} 5 | \title{Internal function} 6 | \usage{ 7 | .cp(x) 8 | } 9 | \arguments{ 10 | \item{x}{stan objec} 11 | } 12 | \description{ 13 | Internal function 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/dot-f_MA.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helper.R 3 | \name{.f_MA} 4 | \alias{.f_MA} 5 | \title{Multiply matrices in array with a vector} 6 | \usage{ 7 | .f_MA(MA, theta, mu, rts, i) 8 | } 9 | \arguments{ 10 | \item{MA}{} 11 | 12 | \item{theta}{} 13 | 14 | \item{mu}{} 15 | 16 | \item{rts}{} 17 | 18 | \item{i}{} 19 | } 20 | \value{ 21 | matrix 22 | } 23 | \description{ 24 | Multiply matrices in array with a vector 25 | } 26 | \author{ 27 | Philippe Rast 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/dot-f_array_x_mat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helper.R 3 | \name{.f_array_x_mat} 4 | \alias{.f_array_x_mat} 5 | \title{Multiply matrices in array with a vector -- generic} 6 | \usage{ 7 | .f_array_x_mat(mat_out, array_obj, mat_obj, i) 8 | } 9 | \arguments{ 10 | \item{mat_out}{} 11 | 12 | \item{array_obj}{} 13 | 14 | \item{mat_obj}{} 15 | 16 | \item{i}{} 17 | } 18 | \value{ 19 | matrix 20 | } 21 | \description{ 22 | Multiply matrices in array with a vector -- generic 23 | } 24 | \author{ 25 | Philippe Rast 26 | } 27 | \keyword{internal} 28 | -------------------------------------------------------------------------------- /man/dot-get_stan_summary.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.get_stan_summary} 4 | \alias{.get_stan_summary} 5 | \title{Get stan summaries.} 6 | \usage{ 7 | .get_stan_summary(model_fit, params, CrI, weights = NULL, sampling_algorithm) 8 | } 9 | \arguments{ 10 | \item{model_fit}{stanfit object or list of stanfit objects.} 11 | 12 | \item{params}{Character vector. Names of params to pull from stan summary.} 13 | 14 | \item{CrI}{Numeric vector (length 2).} 15 | 16 | \item{weights}{Numeric vector. Weights for each model in model_fit, if list.} 17 | 18 | \item{sampling_algorithm}{Character vector for sampling method.} 19 | } 20 | \value{ 21 | Stan summary for parameters. Columns: mean, sd, mdn, and CrIs. 22 | } 23 | \description{ 24 | Get stan summaries. 25 | } 26 | \author{ 27 | Stephen R. Martin, Philippe Rast 28 | } 29 | \keyword{internal} 30 | -------------------------------------------------------------------------------- /man/dot-get_target_stan_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cmdstan_path.R 3 | \name{.get_target_stan_path} 4 | \alias{.get_target_stan_path} 5 | \title{Path to stan files} 6 | \usage{ 7 | .get_target_stan_path() 8 | } 9 | \value{ 10 | Full path to folder containing stan files 11 | } 12 | \description{ 13 | Internal function to obtain stan code paths 14 | } 15 | \author{ 16 | philippe 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/dot-newline.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.newline} 4 | \alias{.newline} 5 | \title{Print helper - Return new line(s).} 6 | \usage{ 7 | .newline(n = 1) 8 | } 9 | \arguments{ 10 | \item{n}{Integer (Default: 1). Number of new lines.} 11 | } 12 | \value{ 13 | Prints new lines. 14 | } 15 | \description{ 16 | Print helper - Return new line(s). 17 | } 18 | \author{ 19 | Stephen R. Martin 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-pred_array_to_df.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{.pred_array_to_df} 4 | \alias{.pred_array_to_df} 5 | \title{Convert predictive array to data.frame.} 6 | \usage{ 7 | .pred_array_to_df(arr, type = "backcast", param = "var") 8 | } 9 | \arguments{ 10 | \item{arr}{Array to convert into data frame.} 11 | 12 | \item{type}{String. "backcast" or "forecast".} 13 | 14 | \item{param}{String. "var", "mean", or "cor".} 15 | } 16 | \value{ 17 | data.frame. Columns: period, type (backcast, forecast), param (var, mean, cor), TS (which time series, or which correlation for param = cor), summary columns. 18 | } 19 | \description{ 20 | Helper function for as.data.frame.{fitted, forecast}. Converts predictive array to data.frame. 21 | } 22 | \author{ 23 | Stephen R. Martin 24 | } 25 | \keyword{internal} 26 | -------------------------------------------------------------------------------- /man/dot-print.config.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.config} 4 | \alias{.print.config} 5 | \title{Print helper for Sampling Config.} 6 | \usage{ 7 | .print.config(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for Sampling Config. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.bekk.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.bekk} 4 | \alias{.print.summary.bekk} 5 | \title{Print helper for BEKK/pdBEKK.} 6 | \usage{ 7 | .print.summary.bekk(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for BEKK/pdBEKK. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.beta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.beta} 4 | \alias{.print.summary.beta} 5 | \title{Print helper for beta component.} 6 | \usage{ 7 | .print.summary.beta(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for beta component. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.ccc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.ccc} 4 | \alias{.print.summary.ccc} 5 | \title{Print helper for CCC.} 6 | \usage{ 7 | .print.summary.ccc(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for CCC. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.dcc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.dcc} 4 | \alias{.print.summary.dcc} 5 | \title{Print helper for DCC.} 6 | \usage{ 7 | .print.summary.dcc(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for DCC. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.lp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.lp} 4 | \alias{.print.summary.lp} 5 | \title{Print helper for LP component.} 6 | \usage{ 7 | .print.summary.lp(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for LP component. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.means.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.means} 4 | \alias{.print.summary.means} 5 | \title{Print helper for means component.} 6 | \usage{ 7 | .print.summary.means(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for means component. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-print.summary.nu.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.print.summary.nu} 4 | \alias{.print.summary.nu} 5 | \title{Print helper for nu component.} 6 | \usage{ 7 | .print.summary.nu(bmsum) 8 | } 9 | \arguments{ 10 | \item{bmsum}{summary.bmgarch object.} 11 | } 12 | \value{ 13 | Void. 14 | } 15 | \description{ 16 | Print helper for nu component. 17 | } 18 | \author{ 19 | Stephen R. Martin, Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-qtile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helper.R 3 | \name{.qtile} 4 | \alias{.qtile} 5 | \title{Internal function to be used} 6 | \usage{ 7 | .qtile(x, CrI = c(0.025, 0.975)) 8 | } 9 | \arguments{ 10 | \item{x}{} 11 | } 12 | \description{ 13 | Internal function to be used 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/dot-refit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lfocv.R 3 | \name{.refit} 4 | \alias{.refit} 5 | \title{Refit model} 6 | \usage{ 7 | .refit(object, data, xC_data) 8 | } 9 | \arguments{ 10 | \item{object}{bmgarch model object} 11 | 12 | \item{data}{new data} 13 | 14 | \item{xC_data}{new predictor} 15 | } 16 | \description{ 17 | Refit model 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /man/dot-sep.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.sep} 4 | \alias{.sep} 5 | \title{Print helper - Separator, new line} 6 | \usage{ 7 | .sep() 8 | } 9 | \value{ 10 | Prints "---" and a new line. 11 | } 12 | \description{ 13 | Print helper - Separator, new line 14 | } 15 | \author{ 16 | Stephen R. Martin 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/dot-sim.bekk.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simulate.R 3 | \name{.sim.bekk} 4 | \alias{.sim.bekk} 5 | \title{Simulate BEKK data.} 6 | \usage{ 7 | .sim.bekk(N, C, A, B, phi = NULL, theta = NULL) 8 | } 9 | \arguments{ 10 | \item{N}{Integer. Length of time series.} 11 | 12 | \item{C}{Numeric square matrix. Constant covariance matrix (C). Must be symmetric.} 13 | 14 | \item{A}{Numeric square matrix. Moving average GARCH matrix (A).} 15 | 16 | \item{B}{Numeric square matrix. Autoregressive ARCH matrix (B).} 17 | 18 | \item{phi}{Numeric square matrix (Optional). Autoregressive coefficients (Phi).} 19 | 20 | \item{theta}{Numeric square matrix (Optional). Moving average coefficients (Theta).} 21 | } 22 | \value{ 23 | Matrix of observations. 24 | } 25 | \description{ 26 | Simulates time series data from specified BEKK model. 27 | } 28 | \details{ 29 | Simulates timeseries data from specified BEKK model. 30 | Number of time series computed from the number of columns in C. 31 | All matrices must be of the same dimension. 32 | If ARMA parameters (phi, theta) unspecified (NULL), then assumes a constant mean of zero. 33 | } 34 | \author{ 35 | Stephen R. Martin 36 | } 37 | \keyword{internal} 38 | -------------------------------------------------------------------------------- /man/dot-square.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helper.R 3 | \name{.square} 4 | \alias{.square} 5 | \title{Internal function to be used in sweep()} 6 | \usage{ 7 | .square(x) 8 | } 9 | \arguments{ 10 | \item{x}{Value to be squared} 11 | } 12 | \value{ 13 | Squared value 14 | } 15 | \description{ 16 | Internal function to be used in sweep() 17 | } 18 | \author{ 19 | Philippe Rast 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-tab.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{.tab} 4 | \alias{.tab} 5 | \title{Print helper - tab} 6 | \usage{ 7 | .tab() 8 | } 9 | \value{ 10 | Prints tab. 11 | } 12 | \description{ 13 | Print helper - tab 14 | } 15 | \author{ 16 | Stephen R. Martin 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/figures/README-fit3ForecastPlot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-fit3ForecastPlot-1.png -------------------------------------------------------------------------------- /man/figures/README-fit3ForecastPlot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-fit3ForecastPlot-2.png -------------------------------------------------------------------------------- /man/figures/README-fit3ForecastPlot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-fit3ForecastPlot-3.png -------------------------------------------------------------------------------- /man/figures/README-forecastPlot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-forecastPlot-1.png -------------------------------------------------------------------------------- /man/figures/README-forecastPlot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-forecastPlot-2.png -------------------------------------------------------------------------------- /man/figures/README-forecastPlot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-forecastPlot-3.png -------------------------------------------------------------------------------- /man/figures/README-stockForecastPlot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-stockForecastPlot-1.png -------------------------------------------------------------------------------- /man/figures/README-stockForecastPlot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-stockForecastPlot-2.png -------------------------------------------------------------------------------- /man/figures/README-stockForecastPlot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-stockForecastPlot-3.png -------------------------------------------------------------------------------- /man/figures/README-weightedForecastPlot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-weightedForecastPlot-1.png -------------------------------------------------------------------------------- /man/figures/README-weightedForecastPlot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-weightedForecastPlot-2.png -------------------------------------------------------------------------------- /man/figures/README-weightedForecastPlot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-weightedForecastPlot-3.png -------------------------------------------------------------------------------- /man/figures/README-weightedForecastPlot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ph-rast/bmgarch/c6f81d8867527fe246accb6624878d2ebf04563b/man/figures/README-weightedForecastPlot-4.png -------------------------------------------------------------------------------- /man/fitted.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{fitted.bmgarch} 4 | \alias{fitted.bmgarch} 5 | \title{Fitted (backcasting) method for bmgarch objects.} 6 | \usage{ 7 | \method{fitted}{bmgarch}( 8 | object, 9 | CrI = c(0.025, 0.975), 10 | digits = 2, 11 | weights = NULL, 12 | inc_samples = FALSE, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{object}{bmgarch object.} 18 | 19 | \item{CrI}{Numeric vector (Default: \code{c(.025, .975)}). Lower and upper bound of predictive credible interval.} 20 | 21 | \item{digits}{Integer (Default: 2, optional). Number of digits to round to when printing.} 22 | 23 | \item{weights}{Takes weights from model_weight function. Defaults to 1 -- this parameter is not typically set by user.} 24 | 25 | \item{inc_samples}{Logical (Default: FALSE). Whether to return the MCMC samples for the fitted values.} 26 | 27 | \item{...}{Not used.} 28 | } 29 | \value{ 30 | fitted.bmgarch object. List containing \code{meta}data and the \code{backcast}. Backcast is a list containing three elements: 31 | \describe{ 32 | \item{mean}{\code{[N, 7, TS]} array of mean backcasts, where N is the timeseries length, and TS is the number of time series. E.g., \code{bc$backcast$mean[3,,"tsA"]} is the mean backcast for the third observation in time series "tsA".} 33 | \item{var}{\code{[N, 7, TS]} array of variance backcasts, where N is the timeseries length, and TS is the number of time series. E.g., \code{bc$backcast$var[3,,"tsA"]} is the variance backcast for the third observation in time series "tsA".} 34 | \item{cor}{\code{[N, 7, TS(TS - 1)/2]} array of correlation backcasts, where N is the timeseries length, and \code{TS(TS - 1)/2} is the number of correlations. E.g., \code{bc$backcast$cor[3,, "tsB_tsA"]} is the backcast for the correlation between "tsB" and "tsA" on the third observation. Lower triangular correlations are saved.} 35 | \item{samples}{List}. If inc_samples is \code{TRUE}, then a list of arrays of MCMC samples for means, vars, and cors. Each array is [Iteration, Period, ..., ...]. 36 | } 37 | } 38 | \description{ 39 | Extracts the model-predicted means, variances, and correlations for the fitted data. 40 | } 41 | \details{ 42 | Whereas \code{\link{forecast.bmgarch}} computes the \emph{forecasted} values for future time periods, \code{fitted.bmgarch} computes the \emph{backcasted} (model-predicted) values for the observed time periods. 43 | } 44 | \examples{ 45 | \dontrun{ 46 | data(panas) 47 | # Fit CCC(1,1) and constant meanstructure. 48 | fit <- bmgarch(panas, parameterization = "CCC", meanstructure = "constant") 49 | 50 | # Obtain fitted values 51 | fit.bc <- fitted(fit) 52 | 53 | # Print fitted values 54 | print(fit.bc) 55 | 56 | # Plot fitted values (plot.bmgarch calls fitted internally) 57 | plot(fit, type = "var") 58 | 59 | # Save fitted values as data frame 60 | fit.bc.df <- as.data.frame(fit.bc) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /man/forecast.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{forecast.bmgarch} 4 | \alias{forecast.bmgarch} 5 | \alias{forecast} 6 | \title{Forecast method for bmgarch objects.} 7 | \usage{ 8 | \method{forecast}{bmgarch}( 9 | object, 10 | ahead = 1, 11 | xC = NULL, 12 | newdata = NULL, 13 | CrI = c(0.025, 0.975), 14 | seed = NA, 15 | digits = 2, 16 | weights = NULL, 17 | L = NA, 18 | method = "stacking", 19 | inc_samples = FALSE, 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{object}{bmgarch object.} 25 | 26 | \item{ahead}{Integer (Default: 1). Periods to be forecasted ahead.} 27 | 28 | \item{xC}{Numeric vector or matrix. Covariates(s) for the constant variance terms in C, or c. Used in a log-linear model on the constant variance terms. If vector, then it acts as a covariate for all constant variance terms. If matrix, must have columns equal to number of time series, and each column acts as a covariate for the respective time series (e.g., column 1 predicts constant variance for time series 1).} 29 | 30 | \item{newdata}{Future datapoints for LFO-CV computation} 31 | 32 | \item{CrI}{Numeric vector (Default: \code{c(.025, .975)}). Lower and upper bound of predictive credible interval.} 33 | 34 | \item{seed}{Integer (Optional). Specify seed for \code{\link[rstan]{sampling}}.} 35 | 36 | \item{digits}{Integer (Default: 2, optional). Number of digits to round to when printing.} 37 | 38 | \item{weights}{Takes weights from model_weight function. Defaults to 1 -- this parameter is not typically set by user.} 39 | 40 | \item{L}{Minimal length of time series before engaging in lfocv} 41 | 42 | \item{method}{Ensemble methods, 'stacking' (default) or 'pseudobma'} 43 | 44 | \item{inc_samples}{Logical (Default: FALSE). Whether to return the MCMC samples for the fitted values.} 45 | 46 | \item{...}{Not used} 47 | } 48 | \value{ 49 | forecast.bmgarch object. List containing \code{forecast}, \code{backcast}, and \code{meta}data. 50 | See \code{\link{fitted.bmgarch}} for information on \code{backcast}. 51 | \code{forecast} is a list of four components: 52 | \describe{ 53 | \item{mean}{\code{[N, 7, TS]} array of mean forecasts, where N is the timeseries length, and TS is the number of time series. E.g., \code{fc$forecast$mean[3,,"tsA"]} is the 3-ahead mean forecast for time series "tsA".} 54 | \item{var}{\code{[N, 7, TS]} array of variance forecasts, where N is the timeseries length, and TS is the number of time series. E.g., \code{fc$forecast$var[3,,"tsA"]} is the 3-ahead variance forecast for time series "tsA".} 55 | \item{cor}{\code{[N, 7, TS(TS - 1)/2]} array of correlation forecasts, where N is the timeseries length, and \code{TS(TS - 1)/2} is the number of correlations. E.g., \code{fc$forecast$cor[3,, "tsB_tsA"]} is the 3-ahead forecast for the correlation between "tsB" and "tsA". Lower triangular correlations are saved.} 56 | \item{meta}{Meta-data specific to the forecast. I.e., TS_length (number ahead) and xC.} 57 | \item{samples}{List}. If inc_samples is \code{TRUE}, then a list of arrays of MCMC samples for means, vars, and cors. Each array is [Iteration, Period, ..., ...]. 58 | } 59 | } 60 | \description{ 61 | Estimates (weighted) forecasted means, variances, and correlations from a fitted bmgarch model. 62 | } 63 | \examples{ 64 | \dontrun{ 65 | data(panas) 66 | # Fit DCC(2,2) with constant mean structure. 67 | fit <- bmgarch(panas, parameterization = "DCC", P = 2, Q = 2, meanstructure = "constant") 68 | 69 | # Forecast 8 ahead 70 | fit.fc <- forecast(fit, ahead = 8) 71 | 72 | # Print forecasts 73 | fit.fc 74 | print(fit.fc) 75 | 76 | # Plot variance forecasts 77 | plot(fit.fc, type = "var") 78 | 79 | # Plot correlation forecasts 80 | plot(fit.fc, type = "cor") 81 | 82 | # Save backcasted and forecasted values as data frame. 83 | fit.fc.df <- as.data.frame(fit.fc) 84 | 85 | # Save only forecasted values as data frame. 86 | fit.fc.df <- as.data.frame(fit.fc, backcast = FALSE) 87 | 88 | # Add another model, compute model weights and perform a model weighted forecast 89 | 90 | # Fit a DCC(1,1) model 91 | fit1 <- bmgarch(panas, parameterization = "DCC", P = 1, Q = 1, meanstructure = "constant") 92 | 93 | # Compute model stacking weights based on the last 19 time points (with L = 80) 94 | blist <- bmgarch_list( fit1, fit ) 95 | mw <- model_weights(blist, L = 80) 96 | 97 | # Weighted forecasts: 98 | w.fc <- forecast(object = blist, ahead = 8, weights = mw) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /man/loo.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lfocv.R 3 | \name{loo.bmgarch} 4 | \alias{loo.bmgarch} 5 | \alias{loo} 6 | \title{Leave-Future-Out Cross Validation (LFO-CV)} 7 | \usage{ 8 | \method{loo}{bmgarch}(x, ..., type = "lfo", L = NULL, M = 1, mode = "backward") 9 | } 10 | \arguments{ 11 | \item{x}{Fitted bmgarch model. \code{lfocv} inherits all attributes 12 | from the bmgarch object} 13 | 14 | \item{...}{Not used} 15 | 16 | \item{type}{Takes \code{lfo} (default) or \code{loo}. LFO-CV is recommended 17 | for time-series but LOO-CV may be obtained to assess the structural part of the model.} 18 | 19 | \item{L}{Minimal length of times series before computing LFO} 20 | 21 | \item{M}{M step head predictions. Defines to what period the LFO-CV should be tuned to. Defaults to M=1.} 22 | 23 | \item{mode}{backward elpd_lfo approximation, or exact elpd-lfo; 24 | Takes 'backward', and 'exact'. 'exact' fits N-L models and may 25 | take a \emph{very} long time to complete. \code{forward} works too but is not 26 | complete yet.} 27 | } 28 | \value{ 29 | Approximate LFO-CV value and log-likelihood values across (L+1):N 30 | timepoints 31 | } 32 | \description{ 33 | \code{lfocv} returns the LFO-CV ELPD by either computing the exact ELDP or 34 | by approximating it via 35 | forward or backward approximation strategies based on Pareto smoothed 36 | importance sampling 37 | described in \insertCite{Buerkner2019}{bmgarch}. 38 | } 39 | \examples{ 40 | \dontrun{ 41 | data(stocks) 42 | # Fit a DCC model 43 | fit <- bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 44 | parameterization = "DCC", standardize_data = TRUE, 45 | iterations = 500) 46 | 47 | # Compute expected log-predictive density (elpd) using the backward mode 48 | # L is the upper boundary of the time-series before we engage in LFO-CV 49 | lfob <- loo(fit, mode = 'backward', L = 50 ) 50 | print(lfob) 51 | } 52 | } 53 | \references{ 54 | \insertAllCited{} 55 | } 56 | -------------------------------------------------------------------------------- /man/model_weights.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/model_weights.R 3 | \name{model_weights} 4 | \alias{model_weights} 5 | \title{Model weights} 6 | \usage{ 7 | model_weights( 8 | bmgarch_objects = NULL, 9 | L = NULL, 10 | M = 1, 11 | method = "stacking", 12 | mode = "backward" 13 | ) 14 | } 15 | \arguments{ 16 | \item{bmgarch_objects}{list of bmgarch model objects in \code{bmgarch_object}} 17 | 18 | \item{L}{Minimal length of time series before engaging in lfocv} 19 | 20 | \item{M}{M step head predictions. Defines to what period the LFO-CV should be tuned to. Defaults to M=1.} 21 | 22 | \item{method}{Ensemble methods, 'stacking' (default) or 'pseudobma'} 23 | 24 | \item{mode}{Either 'backward' (default) or 'exact'} 25 | } 26 | \value{ 27 | Model weights 28 | } 29 | \description{ 30 | Compute model weights for a list of candidate models based on leave-future-out 31 | cross validation (lfocv) expected log-predictive density (elpd). 32 | elpd can be approximated via the 'backward' mode described in \insertCite{Buerkner2019;textual}{bmgarch} or via exact cross-validation. 33 | The obtained weights can be passed to the forecast function to obtain weighted forecasts. 34 | \code{bmgarch_objects} takes a \code{bmgarch_object} lists. 35 | } 36 | \details{ 37 | `model_weights()` is a wrapper around the leave-future-out 'lfo' type in `loo.bmgarch()`. 38 | The weights can be either obtained from an approximate or exact leave-future-out cross-validation 39 | to compute expected log predictive density (ELPD). 40 | 41 | We can either obtain stacking weights or pseudo-BMA+ weigths as described in \insertCite{Yao2018}{bmgarch}. 42 | } 43 | \examples{ 44 | \dontrun{ 45 | data(stocks) 46 | # Fit at least two models on a subset of the stocks data 47 | # to compute model weights 48 | fit <- bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 49 | parameterization = "DCC", standardize_data = TRUE, 50 | iterations = 500) 51 | 52 | fit2 <- bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 53 | P = 2, Q = 2, 54 | parameterization = "DCC", standardize_data = TRUE, 55 | iterations = 500) 56 | # create a bmgarch_list object 57 | blist <- bmgarch_list(fit, fit2 ) 58 | 59 | # Compute model weights with the default stacking metod 60 | # L is the upper boundary of the time-series before we engage in LFO-CV 61 | mw <- model_weights( blist, L = 50, method = 'stacking', order = 'backwards' ) 62 | 63 | # Print model weights in the ordert of the bmgarch_list() 64 | print(mw) 65 | } 66 | } 67 | \references{ 68 | \insertAllCited{} 69 | } 70 | -------------------------------------------------------------------------------- /man/panas.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/panas.R 3 | \docType{data} 4 | \name{panas} 5 | \alias{panas} 6 | \title{Positive and Negative Affect Scores.} 7 | \format{ 8 | Data frame with 200 rows and 2 variables: 9 | \describe{ 10 | \item{Pos}{Positive Affect score} 11 | \item{Neg}{Negative Affect score} 12 | } 13 | } 14 | \usage{ 15 | panas 16 | } 17 | \description{ 18 | A dataset containing simulated values for Positive and Negative Affect scores across 200 measurement occasions for a single individual. 19 | } 20 | \keyword{datasets} 21 | -------------------------------------------------------------------------------- /man/plot.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot.R 3 | \name{plot.bmgarch} 4 | \alias{plot.bmgarch} 5 | \title{Plot method for bmgarch objects.} 6 | \usage{ 7 | \method{plot}{bmgarch}(x, type = "mean", askNewPage = TRUE, CrI = c(0.025, 0.975), ...) 8 | } 9 | \arguments{ 10 | \item{x}{bmgarch object.} 11 | 12 | \item{type}{String (Default: "mean"). Whether to plot conditional means ("mean"), variance ("var"), or correlations ("cor").} 13 | 14 | \item{askNewPage}{askNewPage Logical (Default: True). Whether to ask for new plotting page.} 15 | 16 | \item{CrI}{CrI Numeric vector (Default: \code{c(.025, .975)}). Lower and upper bound of predictive credible interval.} 17 | 18 | \item{...}{Not used} 19 | } 20 | \value{ 21 | List of ggplot objects (one per time series). 22 | } 23 | \description{ 24 | Plot method for bmgarch objects. 25 | } 26 | \author{ 27 | Stephen R. Martin 28 | } 29 | -------------------------------------------------------------------------------- /man/plot.forecast.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/plot.R 3 | \name{plot.forecast.bmgarch} 4 | \alias{plot.forecast.bmgarch} 5 | \title{Plot method for forecast.bmgarch objects.} 6 | \usage{ 7 | \method{plot}{forecast.bmgarch}(x, type = "mean", askNewPage = TRUE, last_t = 100, ...) 8 | } 9 | \arguments{ 10 | \item{x}{forecast.bmgarch object. See \code{\link{forecast.bmgarch}}.} 11 | 12 | \item{type}{String (Default: "mean"). Whether to plot conditional means ("mean"), variance ("var"), or correlations ("cor").} 13 | 14 | \item{askNewPage}{Logical (Default: True). Whether to ask for new plotting page.} 15 | 16 | \item{last_t}{Integer (Default: 100). Only show \code{last_t} observations in plot.} 17 | 18 | \item{...}{Not used} 19 | } 20 | \value{ 21 | List of ggplot objects (one per time series). 22 | } 23 | \description{ 24 | Plot method for forecast.bmgarch objects. 25 | } 26 | \author{ 27 | Stephen R. Martin 28 | } 29 | -------------------------------------------------------------------------------- /man/print.fitted.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{print.fitted.bmgarch} 4 | \alias{print.fitted.bmgarch} 5 | \title{Print method for fitted.bmgarch objects.} 6 | \usage{ 7 | \method{print}{fitted.bmgarch}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{fitted.bmgarch object.} 11 | 12 | \item{...}{Not used.} 13 | } 14 | \value{ 15 | object (invisible). 16 | } 17 | \description{ 18 | Print method for fitted.bmgarch objects. 19 | } 20 | \author{ 21 | Stephen R. Martin 22 | } 23 | -------------------------------------------------------------------------------- /man/print.forecast.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/forecasting_gq.R 3 | \name{print.forecast.bmgarch} 4 | \alias{print.forecast.bmgarch} 5 | \title{Print method for forecast.bmgarch objects.} 6 | \usage{ 7 | \method{print}{forecast.bmgarch}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{forecast.bmgarch object. See \code{\link{forecast.bmgarch}}} 11 | 12 | \item{...}{Not used.} 13 | } 14 | \value{ 15 | x (invisible). 16 | } 17 | \description{ 18 | Print method for forecast.bmgarch objects. 19 | } 20 | \author{ 21 | Stephen R. Martin 22 | } 23 | -------------------------------------------------------------------------------- /man/print.loo.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/lfocv.R 3 | \name{print.loo.bmgarch} 4 | \alias{print.loo.bmgarch} 5 | \title{print method for lfocv} 6 | \usage{ 7 | \method{print}{loo.bmgarch}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{lfo object} 11 | 12 | \item{...}{Not used.} 13 | } 14 | \value{ 15 | Invisible lfocv object 16 | } 17 | \description{ 18 | print method for lfocv 19 | } 20 | \author{ 21 | philippe 22 | } 23 | -------------------------------------------------------------------------------- /man/print.model_weights.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/model_weights.R 3 | \name{print.model_weights} 4 | \alias{print.model_weights} 5 | \title{Print method for model_weights} 6 | \usage{ 7 | \method{print}{model_weights}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{Model weights object} 11 | 12 | \item{...}{Not used.} 13 | } 14 | \value{ 15 | model_weights objects with weights, list of log-likelihoods, and r_eff_list 16 | } 17 | \description{ 18 | Print method for model_weights 19 | } 20 | \author{ 21 | philippe 22 | } 23 | -------------------------------------------------------------------------------- /man/print.summary.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{print.summary.bmgarch} 4 | \alias{print.summary.bmgarch} 5 | \title{Print method for bmgarch.summary objects.} 6 | \usage{ 7 | \method{print}{summary.bmgarch}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{summary.bmgarch object.} 11 | 12 | \item{...}{Not used.} 13 | } 14 | \value{ 15 | x (invisible). 16 | } 17 | \description{ 18 | Print method for bmgarch.summary objects. 19 | } 20 | \author{ 21 | Philippe Rast, Stephen R. Martin 22 | } 23 | -------------------------------------------------------------------------------- /man/standat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bmgarch.R 3 | \name{standat} 4 | \alias{standat} 5 | \title{Standardize input data to facilitate computation} 6 | \usage{ 7 | standat(data, xC, P, Q, standardize_data, distribution, meanstructure) 8 | } 9 | \arguments{ 10 | \item{data}{Time-series data} 11 | 12 | \item{xC}{Numeric vector or matrix.} 13 | 14 | \item{P}{Numeric.} 15 | 16 | \item{Q}{Numeric.} 17 | 18 | \item{standardize_data}{Logical.} 19 | 20 | \item{distribution}{Character.} 21 | 22 | \item{meanstructure}{Character.} 23 | } 24 | \value{ 25 | bmgarch stan data list. 26 | } 27 | \description{ 28 | Standardize input data to facilitate computation 29 | } 30 | \keyword{internal} 31 | -------------------------------------------------------------------------------- /man/stocks.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/stocks.R 3 | \docType{data} 4 | \name{stocks} 5 | \alias{stocks} 6 | \title{Daily data on returns of Toyota, Nissan, and Honda stocks.} 7 | \format{ 8 | Data frame with 2015 rows and 5 variables: 9 | \describe{ 10 | \item{date}{Date} 11 | \item{t}{Sequential time index} 12 | \item{toyota}{Daily returns for Toyota stock} 13 | \item{nissan}{Daily returns for Nissan stock} 14 | \item{honda}{Daily returns for Honda stock} 15 | } 16 | } 17 | \usage{ 18 | stocks 19 | } 20 | \description{ 21 | A dataset used by Stata to illustrate MGARCH models containing daily data on returns of Toyota, Nissan, and Honda stocks. 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/summary.bmgarch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{summary.bmgarch} 4 | \alias{summary.bmgarch} 5 | \title{Summary method for bmgarch objects.} 6 | \usage{ 7 | \method{summary}{bmgarch}(object, CrI = c(0.025, 0.975), digits = 2, ...) 8 | } 9 | \arguments{ 10 | \item{object}{bmgarch object.} 11 | 12 | \item{CrI}{Numeric vector (Default: \code{c(.025, .975)}). Lower and upper bound of predictive credible interval.} 13 | 14 | \item{digits}{Integer (Default: 2, optional). Number of digits to round to when printing.} 15 | 16 | \item{...}{Not used.} 17 | } 18 | \value{ 19 | summary.bmgarch object. A named list containing "meta" and "model_summary". \code{model_summary} contains summary table for all model parameters. 20 | } 21 | \description{ 22 | Computes posterior summaries for all parameters of interest for bmgarch objects. 23 | } 24 | \author{ 25 | Stephen R. Martin, Philippe Rast 26 | } 27 | -------------------------------------------------------------------------------- /man/supported_models.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bmgarch.R 3 | \docType{data} 4 | \name{supported_models} 5 | \alias{supported_models} 6 | \title{Models supported by bmgarch} 7 | \format{ 8 | An object of class \code{character} of length 4. 9 | } 10 | \usage{ 11 | supported_models 12 | } 13 | \description{ 14 | To be used when checking whether a parameterization or object type is a supported type. 15 | May facilitate more parameterizations, as we only have to update these, and the switch statements. 16 | } 17 | \author{ 18 | Philippe Rast and Stephen R. Martin 19 | } 20 | \keyword{internal} 21 | -------------------------------------------------------------------------------- /src/Makevars: -------------------------------------------------------------------------------- 1 | # Generated by rstantools. Do not edit by hand. 2 | 3 | STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") 4 | 5 | STANC_FLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "cat(ifelse(utils::packageVersion('rstan') >= '2.26', '-DUSE_STANC3',''))") 6 | PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error $(STANC_FLAGS) -D_HAS_AUTO_PTR_ETC=0 7 | PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()") 8 | PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()") 9 | 10 | CXX_STD = CXX17 11 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | # Generated by rstantools. Do not edit by hand. 2 | 3 | STANHEADERS_SRC = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "message()" -e "cat(system.file('include', 'src', package = 'StanHeaders', mustWork = TRUE))" -e "message()" | grep "StanHeaders") 4 | 5 | PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DRCPP_PARALLEL_USE_TBB=1 6 | PKG_CXXFLAGS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::CxxFlags()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::CxxFlags()") 7 | PKG_LIBS = $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "RcppParallel::RcppParallelLibs()") $(shell "$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" -e "StanHeaders:::LdFlags()") 8 | 9 | CXX_STD = CXX14 10 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | #include 6 | 7 | using namespace Rcpp; 8 | 9 | #ifdef RCPP_USE_GLOBAL_ROSTREAM 10 | Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); 11 | Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); 12 | #endif 13 | 14 | 15 | RcppExport SEXP _rcpp_module_boot_stan_fit4BEKKMGARCH_mod(); 16 | RcppExport SEXP _rcpp_module_boot_stan_fit4CCCMGARCH_mod(); 17 | RcppExport SEXP _rcpp_module_boot_stan_fit4DCCMGARCH_mod(); 18 | RcppExport SEXP _rcpp_module_boot_stan_fit4forecastBEKK_mod(); 19 | RcppExport SEXP _rcpp_module_boot_stan_fit4forecastCCC_mod(); 20 | RcppExport SEXP _rcpp_module_boot_stan_fit4forecastDCC_mod(); 21 | RcppExport SEXP _rcpp_module_boot_stan_fit4pdBEKKMGARCH_mod(); 22 | 23 | static const R_CallMethodDef CallEntries[] = { 24 | {"_rcpp_module_boot_stan_fit4BEKKMGARCH_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4BEKKMGARCH_mod, 0}, 25 | {"_rcpp_module_boot_stan_fit4CCCMGARCH_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4CCCMGARCH_mod, 0}, 26 | {"_rcpp_module_boot_stan_fit4DCCMGARCH_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4DCCMGARCH_mod, 0}, 27 | {"_rcpp_module_boot_stan_fit4forecastBEKK_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4forecastBEKK_mod, 0}, 28 | {"_rcpp_module_boot_stan_fit4forecastCCC_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4forecastCCC_mod, 0}, 29 | {"_rcpp_module_boot_stan_fit4forecastDCC_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4forecastDCC_mod, 0}, 30 | {"_rcpp_module_boot_stan_fit4pdBEKKMGARCH_mod", (DL_FUNC) &_rcpp_module_boot_stan_fit4pdBEKKMGARCH_mod, 0}, 31 | {NULL, NULL, 0} 32 | }; 33 | 34 | RcppExport void R_init_bmgarch(DllInfo *dll) { 35 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); 36 | R_useDynamicSymbols(dll, FALSE); 37 | } 38 | -------------------------------------------------------------------------------- /tests/stocks.R: -------------------------------------------------------------------------------- 1 | library(bmgarch ) 2 | options(mc.cores=2) 3 | 4 | ## Fit at least two models to compute model weights 5 | x1 <- x2 <- 0 6 | for( i in 2:100 ) { 7 | x1[i] <- x1[i-1] + rnorm(1, 0, 1 ) 8 | x2[i] <- x2[i-1] + rnorm(1, 0, 1 ) 9 | } 10 | 11 | devtools::load_all() 12 | 13 | .get_target_stan_path( ) 14 | 15 | 16 | out <- standat(data = stocks[1:100, c("toyota", "nissan" )], 17 | P = 1, Q = 1, meanstructure = 0, xC = NULL, 18 | standardize_data = 1, distribution = 0) 19 | 20 | stan_data <- out[ c("T", "xC", "rts", "nt", "distribution", "P", "Q", "meanstructure")] 21 | stan_data$rts[100] 22 | stan_data$T 23 | 24 | fit <- bmgarch(data = stocks[1:100, c("toyota", "nissan", "honda")], 25 | Q = 1, 26 | standardize_data = TRUE, 27 | parameterization = "CCC", 28 | iterations = 500, sampling_algorithm = 'VB', 29 | backend = "cmdstanr", 30 | threads = 1, 31 | seed = 123, 32 | refresh = 0, 33 | init = 0, 34 | save_latent_dynamics = FALSE, 35 | output_dir = NULL) 36 | 37 | ## Stuck at this error: 38 | ## Error in as.vector(x, "character") : 39 | ## cannot coerce type 'environment' to vector of type 'character' 40 | 41 | 42 | summary(fit ) 43 | plot(fit ) 44 | forecast(fit, ahead = 10 ) 45 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(bmgarch) 3 | options(mc.cores = 2 ) 4 | 5 | test_check("bmgarch") 6 | -------------------------------------------------------------------------------- /tests/testthat/test-meanstr.R: -------------------------------------------------------------------------------- 1 | library(bmgarch ) 2 | library(testthat ) 3 | options(mc.cores=2) 4 | 5 | 6 | fitVar <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 7 | parameterization = 'CCC', 8 | meanstructure = 'VAR', 9 | standardize_data = TRUE, 10 | iterations = 10)) 11 | 12 | test_that("meanstructure returns VAR", { 13 | expect_equal(fitVar$meanstructure, 2 ) 14 | }) 15 | 16 | fitArma <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 17 | parameterization = 'CCC', 18 | meanstructure = 'arma', 19 | standardize_data = TRUE, 20 | iterations = 10)) 21 | 22 | test_that("meanstructure returns VAR", { 23 | expect_equal(fitArma$meanstructure, 1 ) 24 | }) 25 | 26 | fit <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 27 | parameterization = 'CCC', 28 | standardize_data = TRUE, 29 | iterations = 10)) 30 | 31 | test_that("meanstructure returns VAR", { 32 | expect_equal(fit$meanstructure, 0 ) 33 | }) 34 | 35 | -------------------------------------------------------------------------------- /tests/testthat/test-models.R: -------------------------------------------------------------------------------- 1 | library(bmgarch ) 2 | library(testthat ) 3 | options(mc.cores=2) 4 | 5 | params <- c('CCC', 'DCC', 'BEKK', 'pdBEKK') 6 | 7 | for(i in params ) { 8 | 9 | fit <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 10 | parameterization = i, 11 | standardize_data = TRUE, 12 | iterations = 10)) 13 | 14 | fit2 <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 15 | P = 2, Q = 2, 16 | parameterization = i, 17 | standardize_data = TRUE, 18 | iterations = 10)) 19 | 20 | test_that(paste0("basic model ", i), { 21 | expect_is( fit, "bmgarch" ) 22 | }) 23 | 24 | ## test_that("basic model", { 25 | ## for(i in 1:4 ) { 26 | ## expect_is( fit[[i]], "bmgarch" ) 27 | ## } 28 | ## }) 29 | 30 | test_that(paste0("forecast model",i), { 31 | fc <- forecast( fit, ahead = 3 ) 32 | expect_is( fc, "forecast.bmgarch" ) 33 | }) 34 | ## test_that("forecast model", { 35 | ## for( i in 1:4 ) { 36 | ## fc <- forecast( fit[[i]], ahead = 3 ) 37 | ## expect_is( fc, "forecast.bmgarch" ) 38 | ## } 39 | ## }) 40 | 41 | test_that(paste0("lfo without refits",i), { 42 | lfob <- suppressWarnings( loo(fit, mode = 'backward', L = 99 ) ) 43 | expect_is(lfob, "loo.bmgarch" ) 44 | }) 45 | 46 | test_that(paste0("bmgarch model list",i), { 47 | mlist <- bmgarch_list( fit, fit2 ) 48 | expect_is( mlist,"bmgarch_list") 49 | }) 50 | 51 | test_that(paste0("model weights",i), { 52 | mlist <- bmgarch_list( fit, fit2 ) 53 | mw <- suppressWarnings( model_weights( mlist, L = 98 ) ) 54 | expect_is( mw, "model_weights") 55 | }) 56 | 57 | test_that( paste0(i, "generates non-null output" ), { 58 | expect_true( !is.null( summary( fit )$model_summary ) ) 59 | }) 60 | 61 | test_that( paste0(i, "is bmgarch object" ), { 62 | expect_is( print( fit )$RTS_full, "array" ) 63 | }) 64 | 65 | test_that( paste0(i, "generates list of ggplots" ), { 66 | out <- plot(fit, askNewPage = FALSE ) 67 | expect_is( out, "list" ) 68 | }) 69 | } 70 | 71 | ## Simulation of BEKK data: 72 | test_that("Data gets simulated", { 73 | simdat <- .sim.bekk(N = 100, 74 | C = matrix(c(1,0.5,0.5,1), ncol = 2), 75 | A = matrix(c(.5,-0.25,0.1,.2), ncol = 2), 76 | B = matrix(c(.3,0.1,0.2,.2), ncol = 2), 77 | phi = matrix(c(.2,0,0,.2), ncol = 2), 78 | theta = matrix(c(.2,0.1,0.1,.2), ncol = 2)) 79 | expect_equal( dim( simdat ) , c(100, 2) ) 80 | }) 81 | 82 | 83 | fitvb <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 84 | sampling_algorithm = 'VB', 85 | parameterization = 'CCC', 86 | standardize_data = TRUE, 87 | iterations = 100)) 88 | 89 | test_that( "VB returns a VB algo", { 90 | expect_match( fitvb$sampling_algorithm, "VB" ) 91 | }) 92 | 93 | fit <- suppressWarnings( bmgarch(data = stocks[1:100, c("toyota", "nissan" )], 94 | parameterization = 'CCC', 95 | standardize_data = TRUE, 96 | iterations = 10)) 97 | 98 | test_that( "model weights return error if sampling algo does not match", { 99 | expect_error( model_weights( bmgarch_objects = bmgarch_list(fit, fitvb), L = 90) ) 100 | }) 101 | -------------------------------------------------------------------------------- /tests/testthat/testdata.R: -------------------------------------------------------------------------------- 1 | library(bmgarch ) 2 | library(testthat ) 3 | options(mc.cores=2) 4 | 5 | context("Data structures of outcomes and predictors" ) 6 | 7 | test_that("Data vector is not constant", { 8 | expect_error( 9 | bmgarch:::standat(data = matrix(c(1, 1, 1, 1, 2, 3 ), ncol = 2 ), 10 | xC = NULL, P = 1, Q = 1, 11 | standardize_data = FALSE, distribution = 1, meanstructure = 1), 12 | "Datavector") 13 | }) 14 | 15 | 16 | --------------------------------------------------------------------------------