As we saw earlier, ARIMA models are used to model the conditional expectation of a process, given its past. For such a process, the conditional variance is constant. Real-world financial time series exhibit, among other characteristics, volatility clustering; that is, periods of relative calm are interrupted by bursts of volatility.

In this section we look at GARCH time series models that can take this stylized fact of real-world (financial) time series into account and apply these models to VaR forecasting.

Financial institutions measure the risk of their activities using a Value-at-Risk (VaR), usually calculated at the 99% confidence level over a 10 business day horizon. This is the loss that is expected to be exceeded only 1% of the time.

We load the `zoo`

library and import monthly return data for Intel Corporation from January 1973 to December 2008.

> library("zoo")> intc <- read.zoo("intc.csv", header = TRUE,+ sep = ",", format = "%Y-%m", FUN = as.yearmon)

A plot of the returns indicates that ARCH effects might exist in the monthly return data.

**> plot(intc, main = "Monthly returns of Intel Corporation",+ xlab = "Date", ylab = "Return in percent")**

The output of the preceding commands is as shown in the following figure:

We can use statistical hypothesis tests to verify our inkling. Two commonly used tests are as follows:

First, we perform the Ljung-Box test on the first 12 lags of the squared returns using the following command:

> Box.test(coredata(intc^2), type = "Ljung-Box", lag = 12)Box-Ljung testdata: coredata(intc^2)X-squared = 79.3451, df = 12, p-value = 5.502e-12

We can reject the null hypothesis of no autocorrelations in the squared returns at the 1% significance level. Alternatively, we could employ the LM test from the `FinTS`

package, which gives the same result.

> install.packages("FinTS")> library("FinTS")> ArchTest(coredata(intc))ARCH LM-test; Null hypothesis: no ARCH effectsdata: coredata(intc)Chi-squared = 59.3647, df = 12, p-value = 2.946e-08

Both tests confirm that ARCH effects exist in the monthly Intel returns; hence, an ARCH or GARCH model should be employed in modeling the return time series.

The most commonly used GARCH model, and one that is usually appropriate for financial time series as well, is a GARCH(1,1) model. We use the functions provided by the `rugarch`

library for model specification, parameter estimation, backtesting, and forecasting. If you haven't installed the package, use the following command:

**> install.packages("rugarch")**

Afterwards, we can load the library using the following command:

**> library("rugarch")**

First, we need to specify the model using the function `ugarchspec`

. For a GARCH(1,1) model, we need to set the `garchOrder`

to `c(1,1)`

and the model for the mean (`mean.model`

) should be a white noise process and hence equal to `armaOrder =`

`c(0,0)`

.

**> intc_garch11_spec <- ugarchspec(variance.model = list(+ garchOrder = c(1, 1)),+ mean.model = list(armaOrder = c(0, 0)))**

The actual fitting of the coefficients by the method of maximum likelihood is done by the function `ugarchfit`

using the model specification and the return data as inputs.

**> intc_garch11_fit <- ugarchfit(spec = intc_garch11_spec,+ data = intc)**

For additional arguments, see the Help on `ugarchfit`

. The output of the fitted model (use the command `intc_garch11_fit`

) reveals useful information, such as the values of the optimal parameters, the value of the log-likelihood function, and the information criteria.

A useful test for checking the model performance is to do a historical backtest. In a risk model backtest, we compare the estimated VaR with the actual return over the period. If the return is more negative than the VaR, we have a VaR exceedance. In our case, a VaR exceedance should only occur in 1% of the cases (since we specified a 99% confidence level).

The function `ugarchroll`

performs a historical backtest on the specified GARCH model (here the model is `intc_garch11_spec`

). We specify the backtest as follows:

The return data to be used is stored in the

`zoo`

object`intc`

The start period of the backtest (

`n.start`

) shall be 120 months after the beginning of the series (that is, January 1983)The model should be reestimated every month (

`refit.every = 1`

)We use a

`moving`

window for the estimationWe use a

`hybrid`

solverWe'd like to calculate the VaR (

`calculate.VaR = TRUE`

) at the 99% VaR tail level (`VaR.alpha = 0.01`

)We would like to keep the estimated coefficients (

`keep.coef = TRUE)`

The following command shows all the preceding points for a backtest:

**> intc_garch11_roll <- ugarchroll(intc_garch11_spec, intc,+ n.start = 120, refit.every = 1, refit.window = "moving",+ solver = "hybrid", calculate.VaR = TRUE, VaR.alpha = 0.01,+ keep.coef = TRUE)**

We can examine the backtesting report using the `report`

function. By specifying the `type`

argument as `VaR`

, the function executes the unconditional and conditional coverage tests for exceedances. `VaR.alpha`

is the tail probability and `conf.level`

is the conﬁdence level on which the conditional coverage hypothesis test will be based.

> report(intc_garch11_roll, type = "VaR", VaR.alpha = 0.01,+ conf.level = 0.99)VaR Backtest Report===========================================Model: sGARCH-normBacktest Length: 312Data:==========================================alpha: 1%Expected Exceed: 3.1Actual VaR Exceed: 5 Actual %: 1.6%Unconditional Coverage (Kupiec)Null-Hypothesis: Correct ExceedancesLR.uc Statistic: 0.968LR.uc Critical: 6.635LR.uc p-value: 0.325Reject Null: NOConditional Coverage (Christoffersen)Null-Hypothesis: Correct Exceedances andIndependence of FailuresLR.cc Statistic: 1.131LR.cc Critical: 9.21LR.cc p-value: 0.568Reject Null: O

Kupiec's unconditional coverage compares the number of expected versus actual exceedances given the tail probability of VaR, while the Christoffersen test is a joint test of the unconditional coverage and the independence of the exceedances. In our case, despite the actual five exceedances versus an expectation of three, we can't reject the null hypothesis that the exceedances are correct and independent.

A plot of the backtesting performance can also be generated easily. First, create a `zoo`

object using the extracted forecasted VaR from the `ugarchroll`

object.

**> intc_VaR <- zoo(intc_garch11_roll@forecast$VaR[, 1])**

We overwrite the `index`

property of the `zoo`

object with `rownames`

(year and month) from this object as well.

**> index(intc_VaR) <- as.yearmon(rownames(intc_garch11_roll@forecast$VaR))**

We do the same for the actual returns that are also stored in the `ugarchroll`

object.

> intc_actual <- zoo(intc_garch11_roll@forecast$VaR[, 2])> index(intc_actual) <- as.yearmon(rownames(intc_garch11_roll@forecast$VaR))

Now, we are able to plot the VaR versus the actual returns of Intel using the following commands:

> plot(intc_actual, type = "b", main = "99% 1 Month VaR Backtesting",+ xlab = "Date", ylab = "Return/VaR in percent")> lines(intc_VaR, col = "red")> legend("topright", inset=.05, c("Intel return","VaR"), col = c("black","red"), lty = c(1,1))

The following figure shows the output of the preceding command lines:

Now that we can be reasonably sure that our risk model works properly, we can produce VaR forecasts as well. The function `ugarchforecast`

takes as arguments the fitted GARCH model (`intc_garch11_fit`

) and the number of periods for which a forecast should be produced (`n.ahead = 12`

; that is, twelve months).

**> intc_garch11_fcst <- ugarchforecast(intc_garch11_fit, n.ahead = 12)**

The resulting forecast can be expected by querying the forecast object as shown in the following command lines:

> intc_garch11_fcst*------------------------------------** GARCH Model Forecast **------------------------------------*Model: sGARCHHorizon: 12Roll Steps: 0Out of Sample: 00-roll forecast [T0=Dec 2008]:Series SigmaT+1 0.01911 0.1168T+2 0.01911 0.1172T+3 0.01911 0.1177T+4 0.01911 0.1181T+5 0.01911 0.1184T+6 0.01911 0.1188T+7 0.01911 0.1191T+8 0.01911 0.1194T+9 0.01911 0.1197T+10 0.01911 0.1200T+11 0.01911 0.1202T+12 0.01911 0.1204

The one-period ahead forecast for the volatility (sigma) is 0.1168. Since we assume a normal distribution, the 99% VaR can be calculated using the 99% quantile (type in `qnorm(0.99)`

) of the standard normal distribution. The one-month 99% VaR estimate for the next period is hence `qnorm(0.99)*0.1168 = 0.2717`

. Hence, with 99% probability the monthly return is above -27%.