--- title: "Moving from bvartools 0.3.0 to 1.0.0" author: "Franz X. Mohr" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Moving from bvartools 0.3.0 to 1.0.0} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ## What this release is for Version 0.3.0 is a transition release. It is the functionality of bvartools as it has been on CRAN, with a small number of correctness fixes, and it is the last version before 1.0.0 reorganises the package around a different set of functions. Nothing in this release stops working. What it adds is a message: the first time in a session that you use a function which 1.0.0 does not have any more, bvartools says so and names what takes its place. Upgrading to this release is therefore a way to find out what a later upgrade to 1.0.0 will cost you, while everything still runs. The messages are shown once per function per session. To switch them off: ```{r} options(bvartools.transition.messages = FALSE) ``` ## Renamed functions These do the same thing under a new name. The arguments are unchanged. | 0.3.0 | 1.0.0 | |---|---| | `gen_var()` | `create_bvarmodel()` | | `gen_vec()` | `create_bvecmodel()` | | `bvec_to_bvar()` | `vec_to_var()` | | `kalman_dk()` | `kalman_durbin_koopman_2002()` | | `stochvol_ksc1998()` | `stochvol_ksc_1998()` | | `stochvol_ocsn2007()` | `stochvol_ocsn_2007()` | | `stoch_vol()` | `stochvol_ksc_1998()` | | `bvs()` | `post_bvs()` | `stoch_vol()` was a wrapper for the algorithm of Kim, Shephard and Chib (1998), which `stochvol_ksc_1998()` implements directly, so the wrapper has no separate successor. ## A changed workflow for posterior simulation `draw_posterior()`, `bvarpost()` and `bvecpost()` are replaced by a sequence of functions, each of which adds one thing to the model object. Where 0.3.0 has ```{r} object <- gen_var(data, p = 2, deterministic = "const") object <- add_priors(object) object <- draw_posterior(object) ``` 1.0.0 has ```{r} object <- create_bvarmodel(data, p = 2, deterministic = "const") object <- add_priors(object) object <- add_initial_values(object) object <- add_posterior_coefficients(object) ``` with `add_posterior_forecasts()` and `add_posterior_loglik()` producing the forecasts and the log likelihood that `draw_posterior()` used to produce in the same call. Splitting them apart is what lets a model be estimated once and then have forecasts added, or the log likelihood recomputed, without repeating the simulation. ## Removed without a successor Dynamic factor models are removed from bvartools in 1.0.0 entirely. That covers `dfm()`, `dfmpost()` and `gen_dfm()`, the `add_priors()`, `plot()`, `summary()` and `thin()` methods for objects of class `dfm`, and the example data set `bem_dfmdata`. A data set cannot announce itself, so this is the only notice `bem_dfmdata` gets. `post_normal_covar_const()` and `post_normal_covar_tvp()` are also removed with nothing taking their place. ## Renamed classes, and the methods that follow them The model classes are renamed in 1.0.0. The generics are the same, so code that calls `plot()`, `summary()`, `predict()` or `thin()` on a model object keeps working; what changes is the name of the class those methods are written for, which matters if you dispatch on it yourself or test for it with `inherits()`. | 0.3.0 | 1.0.0 | |---|---| | `bvar` | `bvarmodel` | | `bvec` | `bvecmodel` | | `bvarlist` | `modellist` | These do not produce a message, because the function you call is unchanged. ## Same name, different input These functions exist in 1.0.0 under the same name but do not take the same input, because they take the reorganised model object. They produce no message either, for the same reason: the name is still there. Read their documentation before assuming a call carries over. `add_priors()`, `bvar()`, `bvec()`, `irf()`, `fevd()`, `inclusion_prior()`, `minnesota_prior()`, `ssvs_prior()`. ## Fixes in this release Five defects in the CRAN sources are fixed here. Three of them change results. * **Stochastic volatility with an observation far out in the tails.** `stochvol_ksc1998()` and `stochvol_ocsn2007()` sampled the mixture indicator from weights formed as densities and normalised by their sum. Where an observation lies far enough out in the tails of every component, each density underflows to zero, the row sums to zero, the weights become `NaN`, and the indicator runs one past the last component -- which ends the call with `Mat::elem(): index out of bounds`. The weights are now formed in logs and shifted by their row maximum before they are exponentiated. This is algebraically the same calculation, and draws from a given seed are unchanged: verified bit for bit against the previous implementation. Only the case that used to fail behaves differently, and it now returns a draw. * **Argument checking in the same two functions.** `sigma`, `h_init` and `constant` were indexed on trust, so a vector of the wrong length surfaced as `Mat::elem(): index out of bounds` rather than as a statement about the argument. Each is now checked against the number of columns of `y` and named in the error. * **Impulse responses and variance decompositions of structural models.** A structural model keeps its contemporaneous block separately, so its coefficient draws are the structural `A_i` and its covariance draws the covariance of the structural errors. The forecast error, orthogonalised and generalised recursions want the reduced form. Given the structural quantities they returned numbers that belong to no model at all -- and the same numbers for all three types, since the structural error covariance makes the orthogonalisation degenerate. `irf()` with `type` of `"feir"`, `"oir"` or `"gir"`, and `fevd()` with `"oir"` or `"gir"`, now refuse a structural model and say why. Use `"sir"` or `"sgir"`, which are what a structural model is for and are unchanged, or estimate the model with `structural = FALSE`. * **The structural variance decomposition ignored the variances of the structural shocks.** `fevd()` with `type = "sir"` used `A_0^-1` as the impulse matrix and `A_0^-1 A_0^-1'` as the forecast error covariance, leaving the covariance of the structural errors out of both. Every structural shock was then decomposed as if it had unit variance, which moves weight to whichever shock loads most heavily in `A_0`. Because the shares are normalised they still summed to one, so nothing in the output showed that anything was wrong. `"sgir"` already carried the covariance and is unchanged, as is every reduced form type. * **Seasonal terms for data of frequency one.** `gen_vec()` warned that no seasonal dummies are generated for a series of frequency one and then added them anyway, stopping with `object 'seas' not found`. It now does what the warning says. `gen_var()` was never affected. ## Getting the messages out of a script Beyond the option above, the messages are ordinary conditions, so `suppressMessages()` works on any single call: ```{r} object <- suppressMessages(gen_var(data, p = 2, deterministic = "const")) ``` They are messages rather than warnings deliberately: they will not become errors under `options(warn = 2)`, and they will not fail a check that treats warnings as failures.