@@ -206,10 +206,10 @@ Now we can compute their empirical quantiles, and those of the data.
206206
207207``` r
208208
209- quants <- c(0.01 , 0.05 , 0.25 , 0.4 , 0.5 , 0.6 , 0.75 , 0.95 , 0.99 )
210- q_normal <- quantile(yf_normal , quants )
211- q_t <- quantile(yf_t , quants )
212- q_y <- quantile(y , quants )
209+ thesequants <- c(0.01 , 0.05 , 0.25 , 0.4 , 0.5 , 0.6 , 0.75 , 0.95 , 0.99 )
210+ q_normal <- quantile(yf_normal , thesequants )
211+ q_t <- quantile(yf_t , thesequants )
212+ q_y <- quantile(y , thesequants )
213213
214214knitr :: kable(round(t(cbind(" Data" = q_y , " Student t" = q_t ,
215215 " Gaussian" = q_normal )), 3 ))
@@ -732,7 +732,7 @@ abline(h = 0, lty = 3)
732732
733733![ ] ( Chapter09_files/figure-html/unnamed-chunk-34-1.png )
734734
735- ### Section 2 .5.3: Forecasting Volatility via GARCH(1,1) Models
735+ ### Section 10 .5.3: Forecasting Volatility via GARCH(1,1) Models
736736
737737We start by defining the parameter transformation.
738738
@@ -757,7 +757,7 @@ loglik <- function(y, theta) {
757757 pars <- unrestricted2restricted(theta )
758758 sigma2 <- rep(NA_real_ , length(y ))
759759
760- # initialize at unconditional variance
760+ # Initialize at unconditional variance
761761 sigma2 [1 ] <- pars [1 ] / (1 - pars [2 ] - pars [3 ])
762762
763763 for (i in 2 : length(y )) {
@@ -783,28 +783,32 @@ Finally, we define our random walk MH posterior sampler.
783783``` r
784784
785785sampler <- function (y , M = 20000L , nburn = 2000L , propsds = rep(0.15 , 3 )) {
786- # allocate storage
786+ # Allocate storage
787787 thetas <- matrix (NA_real_ , M , 3 )
788788 sigma2s <- matrix (NA_real_ , M , length(y ))
789789
790- # starting values
790+ # Starting values
791791 theta <- rep(0 , 3 )
792792 currentlogpost <- loglik(y , theta ) + logprior(theta )
793793
794794 naccepts <- 0L
795795 for (m in seq_len(nburn + M )) {
796- if (m > nburn ) sigma2s [m - nburn , ] <- attr(currentlogpost , " sigma2" )
797796 prop <- rnorm(3 , theta , propsds )
798797 proplogpost <- loglik(y , prop ) + logprior(prop )
799798 logR <- proplogpost - currentlogpost
800799
800+ # Accept / reject
801801 if (log(runif(1 )) < logR ) {
802802 theta <- prop
803803 currentlogpost <- proplogpost
804804 if (m > nburn ) naccepts <- naccepts + 1L
805805 }
806806
807- if (m > nburn ) thetas [m - nburn , ] <- theta
807+ # Store
808+ if (m > nburn ) {
809+ thetas [m - nburn , ] <- theta
810+ sigma2s [m - nburn , ] <- attr(currentlogpost , " sigma2" )
811+ }
808812 }
809813
810814 # Transform back to the usual parameterization
@@ -852,10 +856,10 @@ myhist <- function(dat, breaks = 30, freq = FALSE, ...) {
852856 main = " " , ylab = " " , ... )
853857}
854858
855- layout(matrix (c(1 , 1 , 1 , 2 , 3 , 4 ), nrow = 2 , byrow = TRUE ))
856- ts.plot(y , col = " gray" )
859+ ts.plot(y , col = " gray" , ylab = " " )
857860lines(colMeans(sqrt(res $ sigma2 )))
858- lines(- colMeans(sqrt(res $ sigma2 )))
861+ legend(" topright" , legend = c(" Data" , bquote(E(sigma [t ] ~ " |" ~ bold(y )))),
862+ lty = 1 , col = c(" gray" , 1 ))
859863myhist(res $ para $ alpha0 , xlab = expression(alpha [0 ]))
860864myhist(res $ para $ alpha1 , xlab = expression(alpha [1 ]))
861865myhist(res $ para $ gamma1 , xlab = expression(gamma [1 ]))
@@ -868,25 +872,88 @@ a function that predicts a number of steps ahead.
868872
869873``` r
870874
871- prediction <- function (obj , nahead = 1L ) {
872- sigma2f <- yf <- matrix (NA_real_ , obj $ ndraws , nahead )
873- sigma2f [, 1 ] <- obj $ para $ alpha0 + obj $ para $ alpha1 * tail(obj $ y , 1 )^ 2 +
874- obj $ para $ gamma1 * obj $ sigma2 [, ncol(obj $ sigma2 )]
875- yf [, 1 ] <- rnorm(obj $ ndraws , 0 , sqrt(sigma2f [, 1 ]))
875+ prediction <- function (obj , nahead = 1L , drawsmult = 1L ) {
876+ # Allocate storage space
877+ sigma2f <- yf <- matrix (NA_real_ , obj $ ndraws * drawsmult , nahead )
878+
879+ # Predict one step ahead
880+ sigma2f [, 1 ] <- rep(obj $ para $ alpha0 + obj $ para $ alpha1 * tail(obj $ y , 1 )^ 2 +
881+ obj $ para $ gamma1 * obj $ sigma2 [, ncol(obj $ sigma2 )], drawsmult )
882+ yf [, 1 ] <- rnorm(obj $ ndraws * drawsmult , 0 , sqrt(sigma2f [, 1 ]))
883+
884+ # Predict two and more steps ahead
876885 if (nahead > 1L ) {
877886 for (i in 2 : nahead ) {
878887 sigma2f [, i ] <- obj $ para $ alpha0 + obj $ para $ alpha1 * yf [, i - 1 ]^ 2 +
879888 obj $ para $ gamma1 * sigma2f [, i - 1 ]
880- yf [, i ] <- rnorm(obj $ ndraws , 0 , sqrt(sigma2f [, i ]))
889+ yf [, i ] <- rnorm(obj $ ndraws * drawsmult , 0 , sqrt(sigma2f [, i ]))
881890 }
882891 }
892+
893+ # Return
883894 list (y = yf , sigma2 = sigma2f )
884895}
885896```
886897
887- Let’s try it out.
898+ Let’s try it out. We cut the data a some point, re-estimate and predict.
899+
900+ ``` r
901+
902+ cutoff <- 2990
903+ nahead <- 50
904+ ytrain <- head(y , cutoff )
905+ restrain <- sampler(ytrain )
906+ predstatic <- prediction(restrain , nahead , drawsmult = 10 )
907+ predstaticquants <- apply(predstatic $ y , 2 , quantile , thesequants )
908+ ```
909+
910+ Alternatively, we might want to do sequential one-step-ahead
911+ predictions. Note that this amounts to re-estimating the model very
912+ often, thus we reduce the number of posterior draws.
888913
889914``` r
890915
891- pred <- prediction(res , 2 )
916+ predquants <- matrix (NA_real_ , nrow = length(thesequants ), nahead )
917+ predsigmamean <- rep(NA_real_ , nahead )
918+ longrunsdmean <- rep(NA_real_ , nahead )
919+ for (i in seq_len(nahead )) {
920+ y1 <- head(y , cutoff - 1 + i )
921+ res1 <- sampler(y1 , M = 2000 )
922+ longrunsdmean [i ] <- mean(sqrt(res1 $ para $ alpha0 /
923+ (1 - res1 $ para $ alpha1 - res1 $ para $ gamma1 )))
924+ pred1 <- prediction(res1 , 1 , drawsmult = 100 )
925+ predsigmamean [i ] <- mean(sqrt(pred1 $ sigma2 [, 1 ]))
926+ predquants [, i ] <- quantile(pred1 $ y [, 1 ], thesequants )
927+ }
892928```
929+
930+ And visualize.
931+
932+ ``` r
933+
934+ plotwindow <- (cutoff - nahead ): (cutoff + nahead )
935+ plot(plotwindow , y [plotwindow ], xlab = " " , ylab = " " , col = " gray" , type = " l" ,
936+ main = " Static predictions" , ylim = range(predstaticquants , y [plotwindow ]))
937+ abline(h = 0 , lty = 3 , col = " gray" )
938+ abline(v = cutoff , lty = 3 )
939+ lines((cutoff - nahead ): cutoff , colMeans(sqrt(restrain $ sigma2 [, (cutoff - nahead ): cutoff ])))
940+ lines(cutoff + 1 : nahead , colMeans(sqrt(predstatic $ sigma2 )))
941+ abline(h = mean(sqrt(restrain $ para $ alpha0 / (1 - restrain $ para $ alpha1 - restrain $ para $ gamma1 ))),
942+ lty = 2 )
943+ for (i in seq_along(thesequants )) {
944+ lines(cutoff + 1 : nahead , predstaticquants [i , ], col = 2 )
945+ }
946+
947+ plot(plotwindow , y [plotwindow ], xlab = " " , ylab = " " , col = " gray" , type = " l" ,
948+ main = " Dynamic predictions" , ylim = range(predstaticquants , y [plotwindow ]))
949+ abline(h = 0 , lty = 3 , col = " gray" )
950+ abline(v = cutoff , lty = 3 )
951+ lines((cutoff - nahead ): cutoff , colMeans(sqrt(restrain $ sigma2 [, (cutoff - nahead ): cutoff ])))
952+ lines(cutoff + 1 : nahead , predsigmamean )
953+ lines(cutoff + 1 : nahead , longrunsdmean , lty = 2 )
954+ for (i in seq_along(thesequants )) {
955+ lines(cutoff + 1 : nahead , predquants [i , ], col = 2 )
956+ }
957+ ```
958+
959+ ![ ] ( Chapter09_files/figure-html/unnamed-chunk-43-1.png )
0 commit comments