# Simulate 100 random shocks
set.seed(123)
u_t <- rnorm(100, mean = 0, sd = 1)
#Compute squared shocks
u_t2 <- u_t^2
#Plot
par(mfrow = c(2,1), mar = c(3,4,2,1))
plot(u_t,
type = "h",
col = "steelblue",
main = "Raw shocks (u_t)",
ylab = "u_t")
plot(u_t2,
type = "h",
col = "firebrick",
main = "Squared shocks (u_t^2)",
ylab = "u_t^2")GARCH Notes
Background: Connecting ADL, ARIMA, and ARCH Models
Although ARIMA, ADL, and ARCH/GARCH models appear different,
they all belong to the same family of linear dynamic models —
each describes how a current value depends on past information.
1. ARIMA — Dynamics in the Mean
The ARIMA(p,d,q) model captures persistence in the mean of a time series.
\[ y_t = c + \phi_1 y_{t-1} + \dots + \phi_p y_{t-p} + \theta_1 \varepsilon_{t-1} + \dots + \theta_q \varepsilon_{t-q} + \varepsilon_t \]
- Focus: Expected value (trend, momentum)
- Dependence: current value on past values and shocks
- Example: forecasting GDP, prices, returns, etc.
2. ADL — Dynamics Across Variables
The Autoregressive Distributed Lag (ADL) model extends ARIMA to include other predictors.
\[ y_t = \beta_0 + \sum_{i=1}^{p}\beta_i y_{t-i} + \sum_{j=0}^{q}\gamma_j x_{t-j} + \varepsilon_t \]
- Focus: Mean relationship between multiple variables
- Dependence: current \(y_t\) on past \(y\)’s and past \(x\)’s
- Example: inflation as a function of past inflation and past money growth.
ADL is basically an ARIMA on \(y_t\), but with exogenous regressors \(x_t\).
3. ARCH/GARCH — Dynamics in the Variance
The ARCH(p) and GARCH(p,q) models apply the same dynamic logic to the variance of errors, not the mean.
\[ \sigma_t^2 = \alpha_0 + \sum_{i=1}^{p}\alpha_i u_{t-i}^2 + \sum_{j=1}^{q}\phi_j \sigma_{t-j}^2 \]
- Focus: Volatility dynamics (conditional variance)
- Dependence: today’s volatility on past squared shocks and past volatility
- Example: modeling stock return volatility.
In spirit, a GARCH model is an ADL applied to the error variance.
4. The Common Thread
| Model | Dependent variable | What it models | Dynamic structure |
|---|---|---|---|
| ARIMA | \(y_t\) | Mean of a single series | Past \(y_t\)’s and shocks |
| ADL | \(y_t\) | Mean with external drivers | Past \(y_t\)’s and past \(x_t\)’s |
| ARCH/GARCH | \(\sigma_t^2\) | Conditional variance | Past \(u_t^2\)’s and \(\sigma_t^2\)’s |
All three share the same recursive idea:
> “Today depends on yesterday.”
Only the object of interest (mean vs variance) changes.
5. Intuitive Hierarchy
| Level | Model | Focus |
|---|---|---|
| 1 | ADL / ARIMA | Predicting the expected level of a series |
| 2 | ARCH / GARCH | Predicting the expected variability of that series |
So, GARCH ≈ ARIMA logic applied to volatility,
and ADL ≈ ARIMA logic extended to multiple variables.
Key Insight
ARIMA → dynamics of the mean
ADL → dynamics between variables
GARCH → dynamics of the variance
All are linear-in-parameters models that explain persistence —
in levels (ARIMA), across variables (ADL), or in volatility (GARCH).
The Problem GARCH Solves
In ordinary regression or ARIMA models, we assume that the variance of the errors is constant:
\[u_t \sim N (0, \sigma^2)\]
That’s called homoskedasticity. But in real-world financial or economic data (returns, inflation, exchange rates, etc.), you often see volatility clustering — periods of calm and periods of turbulence.
Example:
- When markets are stable → small changes day after day
- When crises hit → large swings for many days
So the variance (volatility) is changing over time. That’s called heteroskedasticity.
From ARIMA to ARCH
Engle (1982) introduced the ARCH model (Autoregressive Conditional Heteroskedasticity).
Idea: Let’s model the variance itself as something that depends on past squared shocks.
\[\sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \alpha_2 u_{t-2}^2 + \dots + \alpha_p u_{t-p}^2\]
Here:
- \(u_t\) is the residual (shock) at time \(t\)
- \(u_t^2\) is the squared shock (proxy for magnitude of volatility)
- \(\sigma_t^2\) is the conditional variance — variance given past information
So volatility today depends on how big shocks were yesterday, the day before, etc.
In the ARCH model, we use squared shocks (\(u_{t-i}^2\)) instead of the raw shocks (\(u_{t-i}\)).
There are two main reasons:
Variance must be positive
Variance (\(\sigma_t^2\)) represents volatility — it cannot be negative.
Squaring ensures that each term contributes positively: \[ \sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \alpha_2 u_{t-2}^2 + \dots + \alpha_p u_{t-p}^2, \quad \text{where } \alpha_0 > 0, \; \alpha_i \ge 0. \]We care about the magnitude, not the direction, of shocks
Both large positive and large negative shocks increase volatility.
Squaring \(u_t\) removes the sign and keeps only the size of the movement.
Small Demonstration in R
But ARCH Has a Limitation
If volatility persists for a long time (as in financial data), ARCH needs many lags (\(p\)) to capture that persistence.
That means too many parameters → not efficient.
Enter GARCH — Generalized ARCH (Bollerslev, 1986)
GARCH solves that by adding lagged variances themselves:
\[\sigma_t^2 = \alpha_0 + \sum_{i=1}^{p}\alpha_i u_{t-i}^2 + \sum_{j=1}^{q}\phi_j \sigma_{t-j}^2\]
This means volatility depends both on:
- recent shocks (ARCH part), and
- its own past values (GARCH part)
Textbook (Theoretical) Notation
The GARCH(1,1) model is written as:
\[ R_t = \beta_0 + u_t, \quad u_t \sim N(0, \sigma_t^2) \]
\[ \sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \phi_1 \sigma_{t-1}^2 \]
where:
- \(R_t\) :return (e.g., percentage change in price)
- \(u_t\) : innovation or residual (shock) at time \(t\)
- \(\sigma_t^2\) : conditional variance (volatility at time \(t\) given information up to \(t-1\))
Parameter Definitions
| Symbol | Meaning | Expected Sign |
|---|---|---|
| \(\beta_0\) | Constant (mean of returns) | Any |
| \(\alpha_0\) | Long-run average variance | \(> 0\) |
| \(\alpha_1\) | Reaction to last period’s shock (ARCH effect) | \(\ge 0\) |
| \(\phi_1\) | Volatility persistence (GARCH effect) | \(\ge 0\) |
Interpretation
Mean (return) equation:
Describes the average return level — how returns behave on average over time.
- \(\beta_0\) represents the average return (constant mean component).
(Conditional) Variance equation:
Captures the time-varying volatility — how uncertainty evolves over time.
- \(\alpha_0\) is the long-run average variance, representing the baseline or steady-state risk level.
- \(\alpha_1\) measures how strongly volatility reacts to new shocks (the ARCH effect).
- \(\phi_1\) measures how persistent volatility is over time (the GARCH effect).
- The sum \(\alpha_1 + \phi_1\) reflects volatility persistence:
- If close to 1 → volatility decays slowly (long memory).
- If much less than 1 → volatility fades quickly (short memory).
- The model is stationary if \(\alpha_1 + \phi_1 < 1\).
Chapter 16.4 of Econometrics with R
This discussion focuses on modeling volatility clustering with ARCH and GARCH. These topics equip you with advanced tools for working with structured data and financial or economic series that exhibit time-varying variance.
Required Readings:
- Hanck, Arnold, Gerber, and Schmelzer, Econometrics with R, Chapter 16.4:
Volatility Clustering and ARCH.
Volatility Modeling with ARCH and GARCH (Required)
Exploring Volatility Clustering:
Read Chapter 16.4 of Econometrics with R for an introduction to volatility clustering and the motivation behind ARCH and GARCH models.
Select or simulate a time series where you suspect time-varying volatility, such as financial returns, commodity prices, or any series with fluctuating variance.
I select MSFT monthly returns and fit a GARCH model from fGarch library.
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
── Attaching core tidyquant packages ─────────────────────── tidyquant 1.0.11 ──
✔ PerformanceAnalytics 2.0.8 ✔ TTR 0.24.4
✔ quantmod 0.4.28 ✔ xts 0.14.1
── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
✖ zoo::as.Date() masks base::as.Date()
✖ zoo::as.Date.numeric() masks base::as.Date.numeric()
✖ PerformanceAnalytics::legend() masks graphics::legend()
✖ quantmod::summary() masks base::summary()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Warning: package 'ggplot2' was built under R version 4.5.2
Warning: package 'dplyr' was built under R version 4.5.2
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.0 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 4.0.2 ✔ tibble 3.3.0
✔ lubridate 1.9.4 ✔ tidyr 1.3.1
✔ purrr 1.1.0
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::first() masks xts::first()
✖ dplyr::lag() masks stats::lag()
✖ dplyr::last() masks xts::last()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
conflicted::conflicts_prefer(dplyr::lag)[conflicted] Will prefer dplyr::lag over any other package.
conflicted::conflicts_prefer(dplyr::last)[conflicted] Will prefer dplyr::last over any other package.
conflicted::conflicts_prefer(dplyr::filter)[conflicted] Will prefer dplyr::filter over any other package.
tibble [9,145 × 8] (S3: tbl_df/tbl/data.frame)
$ symbol : chr [1:9145] "MSFT" "MSFT" "MSFT" "MSFT" ...
$ date : Date[1:9145], format: "1990-01-02" "1990-01-03" ...
$ open : num [1:9145] 0.606 0.622 0.62 0.635 0.622 ...
$ high : num [1:9145] 0.616 0.627 0.639 0.639 0.632 ...
$ low : num [1:9145] 0.598 0.615 0.616 0.622 0.615 ...
$ close : num [1:9145] 0.616 0.62 0.638 0.622 0.632 ...
$ volume : num [1:9145] 5.30e+07 1.14e+08 1.26e+08 6.96e+07 5.90e+07 ...
$ adjusted: num [1:9145] 0.376 0.378 0.389 0.379 0.385 ...
# A tibble: 10 × 9
symbol date open high low close volume adjusted pct_change
<chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 MSFT 1990-01-02 0.606 0.616 0.598 0.616 53035200 0.376 NA
2 MSFT 1990-01-03 0.622 0.627 0.615 0.620 113774400 0.378 0.564
3 MSFT 1990-01-04 0.620 0.639 0.616 0.638 125740800 0.389 2.94
4 MSFT 1990-01-05 0.635 0.639 0.622 0.622 69566400 0.379 -2.45
5 MSFT 1990-01-08 0.622 0.632 0.615 0.632 58982400 0.385 1.53
6 MSFT 1990-01-09 0.632 0.639 0.627 0.630 70300800 0.384 -0.275
7 MSFT 1990-01-10 0.625 0.634 0.612 0.613 103766400 0.374 -2.75
8 MSFT 1990-01-11 0.616 0.622 0.590 0.601 95774400 0.366 -1.98
9 MSFT 1990-01-12 0.591 0.606 0.583 0.598 148910400 0.365 -0.433
10 MSFT 1990-01-15 0.595 0.604 0.592 0.598 62467200 0.365 0
# Plot closing prices over time
ggplot(data = df_ts,
mapping = aes(x = date,
y = pct_change)
) +
geom_line(color = "blue") +
labs(
title = "MSFT Daily Price Pct Change Over Time",
x = "Date",
y = "Closing Price (USD)"
) +
theme_minimal()Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).
# Convert to monthly and calculate % change
df_monthly <- df_ts %>%
group_by(year_month = floor_date(x = date, unit = "month")) %>%
summarise(close = last(close), .groups = "drop") %>%
mutate(
pct_change = (close - lag(close)) / lag(close) * 100
) %>% filter(!is.na(pct_change))
# Plot closing prices over time
ggplot(df_monthly, aes(x = year_month, y = pct_change)) +
geom_line(color = "blue") +
labs(
title = "MSFT Monthly Price Pct Change Over Time",
x = "Date",
y = "Closing Price (USD)"
)# plot sample autocorrelation of daily percentage changes
acf(df_monthly$pct_change,
main = "ACF"
)We see that autocorrelations are weak - so that it is difficult to predict future outcomes using, e.g., an AR model.
The tall bar at lag 0 = 1 is expected — every ACF plot has it.
The other bars (lags 1–25) hover near zero, meaning autocorrelation is weak. → The series behaves like white noise — difficult to predict using an AR model.
Estimation
Modeling Conditional Variance:
Fit an ARCH or GARCH model to your series using R (for example, the
fGarchorrugarchpackage).Plot the estimated conditional variance and compare it to the unconditional variance from simpler models.
Interpret the significance of the parameters and how volatility evolves over time.
I. fGarch
Univariate or multivariate GARCH time series fitting. Estimates the parameters of a univariate ARMA-GARCH/APARCH process.
NOTE: Packages 'fBasics', 'timeDate', and 'timeSeries' are no longer
attached to the search() path when 'fGarch' is attached.
If needed attach them yourself in your R script by e.g.,
require("timeSeries")
Title:
GARCH Modelling
Call:
garchFit(data = df_monthly$pct_change, trace = F)
Mean and Variance Equation:
data ~ garch(1, 1)
<environment: 0x15c5f3c48>
[data = df_monthly$pct_change]
Conditional Distribution:
norm
Coefficient(s):
mu omega alpha1 beta1
1.903408 3.001870 0.094128 0.861356
Std. Errors:
based on Hessian
Error Analysis:
Estimate Std. Error t value Pr(>|t|)
mu 1.90341 0.35333 5.387 7.16e-08 ***
omega 3.00187 1.28565 2.335 0.019548 *
alpha1 0.09413 0.02762 3.407 0.000656 ***
beta1 0.86136 0.03656 23.561 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Log Likelihood:
-1517.292 normalized: -3.488028
Description:
Sat Apr 25 06:33:49 2026 by user:
Standardised Residuals Tests:
Statistic p-Value
Jarque-Bera Test R Chi^2 31.1494600 1.721792e-07
Shapiro-Wilk Test R W 0.9843064 1.188851e-04
Ljung-Box Test R Q(10) 9.6067976 4.756403e-01
Ljung-Box Test R Q(15) 12.8346510 6.150678e-01
Ljung-Box Test R Q(20) 15.5665872 7.431222e-01
Ljung-Box Test R^2 Q(10) 8.6068224 5.697789e-01
Ljung-Box Test R^2 Q(15) 10.6720941 7.754739e-01
Ljung-Box Test R^2 Q(20) 16.5910105 6.793489e-01
LM Arch Test R TR^2 11.2992237 5.034642e-01
Information Criterion Statistics:
AIC BIC SIC HQIC
6.994446 7.031921 6.994279 7.009237
After running the GARCH model, you need to interpret two linked equations — the mean returns equation and the conditional heteroskedasticity equation (the two-equation system). Part 2, the heteroskedasticity component, can become more complex depending on the chosen GARCH(p, q) specification.
First, I write both equations using Greek symbols, and then replace the Greeks with the estimated coefficients from the model output. Be aware that different software packages use different notation, so it is important to interpret the parameters carefully.
I have adjusted some coefficient symbols from the textbook to match the notation used by the garchFit() command in R.
\[ R_t = 1.97218 + \mu_t, \quad \mu_t \sim N(0, \sigma_t^2) \]
Where:
- 1.97218 is the constant mean return per period. This is \(mu\) term in the
garcgFit, but called \(\beta_0\) in textbook system of equations 16.3 (see screenshot above). - \(\mu_t\) is the innovation (error term) at time \(t\), which is normally distributed with mean zero and conditional variance \(\sigma_t^2\).
- The conditional variance \(\sigma_t^2\) evolves according to the GARCH(1,1) specification:
\[ \sigma_t^2 = 3.03537 + 0.09266 \epsilon_{t-1}^2 + 0.86307 \sigma_{t-1}^2 \]
Where:
\(\omega\) = 2.91377: Long-run average variance (baseline risk level).
\(\alpha_1\) = 0.09266: Impact of the most recent shock. A large \(\mu_{t-1}^2\) will increase \(\sigma_t^2\) in the next period.
\(\beta_1\) = 0.86307: Persistence of volatility from the previous period. A high value indicates slow decay of volatility after shocks.
This formulation allows the volatility to change over time, capturing periods of high and low market turbulence.
The persistence parameter:
\[ \alpha_1 + \beta_1 = 0.95573 \]
is close to 1, indicating high volatility persistence — shocks to volatility tend to last for a long time.
# compute deviations of the percentage changes from their mean
dev_mean_MSFT <- df_monthly$pct_change - GARCH_MSFT@fit$coef[1]
# plot deviation of percentage changes from mean
plot(x = df_monthly$year_month, y = dev_mean_MSFT,
type = "l",
col = "steelblue",
ylab = "Percent",
xlab = "Date",
main = "Estimated Bands of +- One Conditional Standard Deviation",
cex.main=0.8,
lwd = 0.2)
# add horizontal line at y = 0
abline(0, 0)
# add GARCH(1,1) confidence bands (one standard deviation) to the plot
lines(x = df_monthly$year_month,
GARCH_MSFT@fit$coef[1] + GARCH_MSFT@sigma.t,
col = "darkred",
lwd = 0.5)
lines(x = df_monthly$year_month,
GARCH_MSFT@fit$coef[1] - GARCH_MSFT@sigma.t, ,
col = "darkred",
lwd = 0.5)The light blue line appears to be the actual returns or residuals from a financial time series (likely % deviations from a mean).
The two red lines represent the estimated bands of ± 1 conditional standard deviation from a volatility model (likely a GARCH-type model).
Conditional variance changes over time based on recent information. In GARCH models, this means periods of high volatility widen the bands, while quiet periods narrow them.
Unconditional variance assumes volatility is constant over time — from a simple model like historical variance. This would be a flat horizontal band (same width everywhere).
-
Comparison:
If you plotted the unconditional variance, it would likely underestimate volatility during high-stress periods (e.g., late 1990s, 2008) and overestimate during calm periods.
The GARCH conditional variance adapts to spikes in volatility and periods of calm, making it better for risk estimation.
Discussion Questions:
In your dataset, how did the ARCH/GARCH model improve the understanding of volatility compared to traditional constant-variance models?
How would you incorporate volatility modeling into forecasting workflows alongside ETS or ARIMA models?
How ARCH/GARCH Improved Understanding of Volatility
The GARCH(1,1) model:
-
Captured volatility clustering
The plot shows that conditional standard deviation bands widen during turbulent market periods (e.g., dot-com bubble, 2008 financial crisis, COVID-19 shock) and narrow during calm periods.
A constant-variance model would have used one average variance level for all periods, missing this dynamic.
-
Quantified persistence of volatility
α₁ (0.09266) → About 9% of last period’s shock size carries into today’s volatility.
β₁ (0.86307) → About 86% of yesterday’s volatility persists today.
Persistence α₁ + β₁ ≈ 0.956 → Shocks have long-lasting effects.
Constant-variance models cannot measure or use this persistence in risk estimates.
-
Improved risk measurement
Prediction intervals adapt to market conditions — wide when volatility is high, narrow when low — unlike ARIMA/ETS with fixed-width intervals.
This improves Value-at-Risk (VaR) and stress-testing accuracy.
-
Better model diagnostics
Ljung–Box and ARCH–LM tests show no remaining autocorrelation in squared residuals → volatility structure is well captured.
Constant-variance models leave significant autocorrelation in squared residuals, meaning they systematically miss volatility patterns.
Incorporating Volatility Modeling with ETS/ARIMA
ARIMA–GARCH Hybrid (Finance Standard)
Step 1: Fit ARIMA to model the conditional mean of returns.
Step 2: Fit GARCH to ARIMA residuals to model conditional variance.
-
Step 3: Forecast mean & volatility jointly.
ARIMA forecast → central path.
GARCH forecast → time-varying prediction intervals or VAR.
II. rugarch
Another popular way to implement the GARCH.
The rugarch package aims to provide a flexible and rich univariate GARCH modelling and testing environment. Modelling is a simple process of defining a specification and fitting the data.
- Mean equation parameters will be expressed as:
- Volatility equation parameters will be expressed as:
Loading required package: parallel
?rugarch
??ugarchspec
?fGarch::garchSpec
# Specify and fit a GARCH(1,1) model
spec <- ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(0, 0), include.mean = TRUE),
distribution.model = "norm" # standard normal distribution
)
fit <- ugarchfit(spec = spec,
data = df_monthly$pct_change
)
show(fit)
*---------------------------------*
* GARCH Model Fit *
*---------------------------------*
Conditional Variance Dynamics
-----------------------------------
GARCH Model : sGARCH(1,1)
Mean Model : ARFIMA(0,0,0)
Distribution : norm
Optimal Parameters
------------------------------------
Estimate Std. Error t value Pr(>|t|)
mu 1.903204 0.353323 5.3866 0.000000
omega 3.004190 1.288633 2.3313 0.019738
alpha1 0.093746 0.027526 3.4057 0.000660
beta1 0.861397 0.036658 23.4981 0.000000
Robust Standard Errors:
Estimate Std. Error t value Pr(>|t|)
mu 1.903204 0.334554 5.6888 0.000000
omega 3.004190 1.325636 2.2662 0.023438
alpha1 0.093746 0.024863 3.7705 0.000163
beta1 0.861397 0.031791 27.0955 0.000000
LogLikelihood : -1517.282
Information Criteria
------------------------------------
Akaike 6.9944
Bayes 7.0319
Shibata 6.9942
Hannan-Quinn 7.0092
Weighted Ljung-Box Test on Standardized Residuals
------------------------------------
statistic p-value
Lag[1] 1.800 0.1798
Lag[2*(p+q)+(p+q)-1][2] 1.839 0.2909
Lag[4*(p+q)+(p+q)-1][5] 3.178 0.3754
d.o.f=0
H0 : No serial correlation
Weighted Ljung-Box Test on Standardized Squared Residuals
------------------------------------
statistic p-value
Lag[1] 0.8623 0.3531
Lag[2*(p+q)+(p+q)-1][5] 3.6017 0.3081
Lag[4*(p+q)+(p+q)-1][9] 5.1747 0.4042
d.o.f=2
Weighted ARCH LM Tests
------------------------------------
Statistic Shape Scale P-Value
ARCH Lag[3] 4.042 0.500 2.000 0.04438
ARCH Lag[5] 4.794 1.440 1.667 0.11464
ARCH Lag[7] 5.255 2.315 1.543 0.20002
Nyblom stability test
------------------------------------
Joint Statistic: 0.7445
Individual Statistics:
mu 0.2689
omega 0.2169
alpha1 0.3561
beta1 0.3315
Asymptotic Critical Values (10% 5% 1%)
Joint Statistic: 1.07 1.24 1.6
Individual Statistic: 0.35 0.47 0.75
Sign Bias Test
------------------------------------
t-value prob sig
Sign Bias 0.8231 0.4109
Negative Sign Bias 0.9544 0.3404
Positive Sign Bias 0.9623 0.3364
Joint Effect 1.9077 0.5918
Adjusted Pearson Goodness-of-Fit Test:
------------------------------------
group statistic p-value(g-1)
1 20 21.87 0.2906
2 30 29.34 0.4472
3 40 42.70 0.3151
4 50 46.49 0.5753
Elapsed time : 0.1655369
Note sGARCH is standard GARCH, not seasonal GARCH.
There are lots of GARCH models - EGARCH, APARCH, TGARCH, QGARCH, GJRGARCH, IGARCH, AVGARCH, PGARCH, GARCH-M and the standard GARCH.
You can add refinement/structure to the mean model and variance model by changing the parameters.
1. Add an AR term in the mean equation
Try including an autoregressive (AR) term in the mean equation and observe how the estimated mean equation changes.
Because the residuals (\(u_t\)) are derived from the mean model, this change will also affect the variance equation indirectly.
# Specify and fit a GARCH(1,1) model with an AR(1) mean equation
spec2 <- ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(1, 0), include.mean = TRUE),
distribution.model = "norm" # standard normal innovations
)
fit2 <- ugarchfit(
spec = spec2,
data = df_monthly$pct_change
)
show(fit2)
*---------------------------------*
* GARCH Model Fit *
*---------------------------------*
Conditional Variance Dynamics
-----------------------------------
GARCH Model : sGARCH(1,1)
Mean Model : ARFIMA(1,0,0)
Distribution : norm
Optimal Parameters
------------------------------------
Estimate Std. Error t value Pr(>|t|)
mu 1.891334 0.331066 5.7129 0.000000
ar1 -0.074256 0.051786 -1.4339 0.151602
omega 2.904610 1.267033 2.2925 0.021880
alpha1 0.092093 0.027265 3.3777 0.000731
beta1 0.864348 0.036214 23.8678 0.000000
Robust Standard Errors:
Estimate Std. Error t value Pr(>|t|)
mu 1.891334 0.331378 5.7075 0.000000
ar1 -0.074256 0.046562 -1.5948 0.110760
omega 2.904610 1.264056 2.2978 0.021570
alpha1 0.092093 0.024303 3.7894 0.000151
beta1 0.864348 0.030277 28.5479 0.000000
LogLikelihood : -1516.261
Information Criteria
------------------------------------
Akaike 6.9943
Bayes 7.0411
Shibata 6.9940
Hannan-Quinn 7.0128
Weighted Ljung-Box Test on Standardized Residuals
------------------------------------
statistic p-value
Lag[1] 0.002757 0.9581
Lag[2*(p+q)+(p+q)-1][2] 0.031865 1.0000
Lag[4*(p+q)+(p+q)-1][5] 1.371195 0.8769
d.o.f=1
H0 : No serial correlation
Weighted Ljung-Box Test on Standardized Squared Residuals
------------------------------------
statistic p-value
Lag[1] 0.7962 0.3722
Lag[2*(p+q)+(p+q)-1][5] 3.0348 0.4007
Lag[4*(p+q)+(p+q)-1][9] 4.5334 0.5010
d.o.f=2
Weighted ARCH LM Tests
------------------------------------
Statistic Shape Scale P-Value
ARCH Lag[3] 3.061 0.500 2.000 0.08022
ARCH Lag[5] 3.972 1.440 1.667 0.17647
ARCH Lag[7] 4.433 2.315 1.543 0.28834
Nyblom stability test
------------------------------------
Joint Statistic: 0.8387
Individual Statistics:
mu 0.2992
ar1 0.1019
omega 0.2176
alpha1 0.3420
beta1 0.3202
Asymptotic Critical Values (10% 5% 1%)
Joint Statistic: 1.28 1.47 1.88
Individual Statistic: 0.35 0.47 0.75
Sign Bias Test
------------------------------------
t-value prob sig
Sign Bias 0.9006 0.3683
Negative Sign Bias 1.1876 0.2357
Positive Sign Bias 1.0064 0.3148
Joint Effect 2.5776 0.4614
Adjusted Pearson Goodness-of-Fit Test:
------------------------------------
group statistic p-value(g-1)
1 20 15.90 0.6642
2 30 27.28 0.5568
3 40 34.06 0.6945
4 50 46.72 0.5659
Elapsed time : 0.02385712
Estimated GARCH(1,1) Model
The estimated equations based on the optimal parameters are as follows:
Mean equation:
\[ r_t = 0.3006 + 0.0928\,r_{t-1} + u_t \]
Conditional variance equation:
\[ \sigma_t^2 = 0.2561 + 0.4093\,u_{t-1}^2 + 0.3689\,\sigma_{t-1}^2 \]
Interpretation
The mean equation includes both a constant term (\(\mu = 0.3006\)) and an autoregressive term (\(\text{AR}(1) = 0.0928\)).
This implies a small positive autocorrelation in returns — today’s return depends slightly on yesterday’s return.The ARCH term (\(\alpha_1 = 0.4093\)) shows how strongly volatility reacts to recent shocks (\(u_{t-1}^2\)).
Larger shocks yesterday lead to higher variance today.The GARCH term (\(\beta_1 = 0.3689\)) captures volatility persistence — how much of yesterday’s volatility carries forward to today.
The total persistence is: \[ \alpha_1 + \beta_1 = 0.7782 \] which is less than 1, meaning volatility is mean-reverting (it gradually returns to normal after shocks).
The long-run (unconditional) variance is: \[ \frac{\omega}{1 - \alpha_1 - \beta_1} = \frac{0.2561}{1 - 0.7782} \approx 1.15 \] giving a long-run volatility of \(\sqrt{1.15} \approx 1.07\).
Summary
| Term | Symbol | Value | Interpretation |
|---|---|---|---|
| Mean (intercept) | \(\mu\) | 0.3006 | Average return |
| AR(1) term | \(\phi_1\) | 0.0928 | Dependence on \(r_{t-1}\) |
| Constant (variance intercept) | \(\omega\) | 0.2561 | Baseline variance |
| ARCH(1) | \(\alpha_1\) | 0.4093 | Reaction to new shocks (\(u_{t-1}^2\)) |
| GARCH(1) | \(\beta_1\) | 0.3689 | Persistence of volatility (\(\sigma_{t-1}^2\)) |
In short:
The model suggests modest return autocorrelation and strong but decaying volatility persistence —
periods of high volatility subside gradually toward a long-run variance of about 1.15.
2. Experiment with higher-order volatility terms
Increase the lag orders in the variance equation to estimate a more complex GARCH(\(p\), \(q\)) model. This allows volatility to depend on multiple past shocks and lagged variances.
# Specify and fit a GARCH(3,2) model
spec2 <- ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(3, 2)),
mean.model = list(armaOrder = c(0, 0), include.mean = TRUE),
distribution.model = "norm" # standard normal distribution
)
fit2 <- ugarchfit(spec = spec2,
data = df_monthly$pct_change
)
show(fit2)
*---------------------------------*
* GARCH Model Fit *
*---------------------------------*
Conditional Variance Dynamics
-----------------------------------
GARCH Model : sGARCH(3,2)
Mean Model : ARFIMA(0,0,0)
Distribution : norm
Optimal Parameters
------------------------------------
Estimate Std. Error t value Pr(>|t|)
mu 1.848021 0.354857 5.20779 0.000000
omega 4.767716 2.538761 1.87797 0.060385
alpha1 0.023211 0.043637 0.53191 0.594790
alpha2 0.061486 0.057574 1.06794 0.285548
alpha3 0.068209 0.067514 1.01029 0.312356
beta1 0.467978 0.471725 0.99206 0.321170
beta2 0.308263 0.404023 0.76298 0.445473
Robust Standard Errors:
Estimate Std. Error t value Pr(>|t|)
mu 1.848021 0.324523 5.69457 0.000000
omega 4.767716 2.662384 1.79077 0.073330
alpha1 0.023211 0.036440 0.63696 0.524154
alpha2 0.061486 0.056787 1.08274 0.278924
alpha3 0.068209 0.056103 1.21579 0.224064
beta1 0.467978 0.229252 2.04133 0.041218
beta2 0.308263 0.180175 1.71091 0.087097
LogLikelihood : -1515.913
Information Criteria
------------------------------------
Akaike 7.0019
Bayes 7.0675
Shibata 7.0014
Hannan-Quinn 7.0278
Weighted Ljung-Box Test on Standardized Residuals
------------------------------------
statistic p-value
Lag[1] 2.152 0.1424
Lag[2*(p+q)+(p+q)-1][2] 2.179 0.2348
Lag[4*(p+q)+(p+q)-1][5] 3.538 0.3175
d.o.f=0
H0 : No serial correlation
Weighted Ljung-Box Test on Standardized Squared Residuals
------------------------------------
statistic p-value
Lag[1] 0.0008041 0.9774
Lag[2*(p+q)+(p+q)-1][14] 5.0864548 0.7587
Lag[4*(p+q)+(p+q)-1][24] 8.9539061 0.8009
d.o.f=5
Weighted ARCH LM Tests
------------------------------------
Statistic Shape Scale P-Value
ARCH Lag[6] 0.361 0.500 2.000 0.5479
ARCH Lag[8] 1.328 1.480 1.774 0.6758
ARCH Lag[10] 1.935 2.424 1.650 0.7831
Nyblom stability test
------------------------------------
Joint Statistic: 1.072
Individual Statistics:
mu 0.2592
omega 0.1856
alpha1 0.2865
alpha2 0.3782
alpha3 0.3206
beta1 0.3157
beta2 0.3177
Asymptotic Critical Values (10% 5% 1%)
Joint Statistic: 1.69 1.9 2.35
Individual Statistic: 0.35 0.47 0.75
Sign Bias Test
------------------------------------
t-value prob sig
Sign Bias 0.8727 0.3833
Negative Sign Bias 1.4511 0.1475
Positive Sign Bias 0.4502 0.6528
Joint Effect 2.3732 0.4986
Adjusted Pearson Goodness-of-Fit Test:
------------------------------------
group statistic p-value(g-1)
1 20 17.46 0.5587
2 30 22.31 0.8071
3 40 39.39 0.4524
4 50 47.87 0.5188
Elapsed time : 0.03780007
Estimated GARCH(3,2) Model
The estimated equations based on the optimal parameters are as follows:
Mean equation:
\[ r_t = 1.894470 + u_t \]
Conditional variance equation:
\[ \begin{aligned} \sigma_t^2 &= 4.514070 + 0.022001\,u_{t-1}^2 + 0.059165\,u_{t-2}^2 + 0.066420\,u_{t-3}^2 \\ &\quad + 0.485763\,\sigma_{t-1}^2 + 0.296979\,\sigma_{t-2}^2 \end{aligned} \]
Interpretation
The mean equation indicates an average return level of 1.894, with shocks captured by \(u_t\).
The ARCH terms (\(\alpha_1 = 0.022\), \(\alpha_2 = 0.059\), \(\alpha_3 = 0.066\)) measure how recent shocks affect current volatility.
Each squared residual \(u_{t-i}^2\) represents the impact of past return shocks on today’s variance.The GARCH terms (\(\beta_1 = 0.486\), \(\beta_2 = 0.297\)) measure the persistence of volatility — how much past volatility carries over into the current period.
The total persistence is: \[ \alpha_1 + \alpha_2 + \alpha_3 + \beta_1 + \beta_2 = 0.9303 \] which is less than 1, implying that volatility is mean-reverting but decays slowly.
The long-run (unconditional) variance is: \[ \frac{\omega}{1 - \sum \alpha_i - \sum \beta_j} = \frac{4.514070}{1 - 0.930328} \approx 64.79 \] giving a long-run volatility of \(\sqrt{64.79} \approx 8.05\).
| Term | Symbol | Value | Interpretation |
|---|---|---|---|
| Mean (intercept) | \(\mu\) | 1.894 | Average return |
| Constant (variance intercept) | \(\omega\) | 4.514 | Baseline variance |
| ARCH(1) | \(\alpha_1\) | 0.022 | Response to \(u_{t-1}^2\) |
| ARCH(2) | \(\alpha_2\) | 0.059 | Response to \(u_{t-2}^2\) |
| ARCH(3) | \(\alpha_3\) | 0.066 | Response to \(u_{t-3}^2\) |
| GARCH(1) | \(\beta_1\) | 0.486 | Persistence of \(\sigma_{t-1}^2\) |
| GARCH(2) | \(\beta_2\) | 0.297 | Persistence of \(\sigma_{t-2}^2\) |
In short:
The model captures moderate short-term shock effects and strong volatility persistence,
suggesting that periods of high volatility decay gradually toward a long-run average variance of about 64.8.
In GARCH models, we don’t assume that shocks are always normally distributed — financial data often show fat tails (extreme events more likely than under normality) and sometimes asymmetry (negative shocks having different effects from positive ones).
So we can specify how the conditional errors are distributed —
“norm”: simplest; if residuals’ histogram looks bell-shaped.
“std”: use if you see fat tails in residuals (high kurtosis, large outliers).
“sstd”: use if both fat tails and asymmetry appear (negative shocks produce larger volatility).
“ged”/“sged”: slightly less common but can fine-tune tail behavior.
Summary
The Problem
- Financial data shows volatility clustering: calm periods alternate with turbulent periods
- Traditional models assume constant variance (homoskedasticity)
- Reality: variance changes over time (heteroskedasticity)
- Need models that capture time-varying volatility
ARCH (1982)
Variance depends on past squared shocks:
\[ \sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \alpha_2 u_{t-2}^2 + \dots \]
Limitation: Needs many lags to capture persistent volatility
GARCH (1986)
Adds lagged variance terms to make it efficient:
\[ \sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \phi_1 \sigma_{t-1}^2 \]
Full GARCH Model Structure
Mean equation:
\[
r_t = \mu + u_t
\]
Shock structure:
\[
u_t = \sigma_t \cdot \varepsilon_t, \quad \varepsilon_t \sim N(0,1)
\]
Variance equation (GARCH):
\[
\sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \phi_1 \sigma_{t-1}^2
\]
Therefore:
\[
u_t \sim N(0, \sigma_t)
\]
where \(\sigma_t\) is time-varying and predicted by GARCH.
Two components:
-
ARCH part (\(\alpha_1 u_{t-1}^2\)): reacts to recent shocks
- GARCH part (\(\phi_1 \sigma_{t-1}^2\)): captures persistence/memory
GARCH(1,1) — Most Common
\[ \sigma_t^2 = \alpha_0 + \alpha_1 u_{t-1}^2 + \phi_1 \sigma_{t-1}^2 \]
| Term | What it does |
|---|---|
| \(\alpha_0\) | Baseline variance / minimum level of volatility that exists even when there are no shocks |
| \(\alpha_1\) | Reaction to new shocks Big shock yesterday → higher variance today |
| \(\phi_1\) | Persistence of volatility High variance yesterday → stays high today |
Condition for stability: \(\alpha_1 + \phi_1 < 1\).
Key Concepts
Volatility Clustering: Large changes follow large changes; small follow small
-
Persistence: \(\alpha_1 + \phi_1\) measures how long volatility stays elevated
- Close to 1 → long-lasting volatility clusters
- Must be < 1 for stability
- Close to 1 → long-lasting volatility clusters
Long-run variance:
\[ \frac{\alpha_0}{1 - \alpha_1 - \phi_1} \]
gives the average variance over time. It accounts for both the baseline level and the persistence of volatility.Mean reversion: After a shock, variance gradually returns to the long-run average
Wave Analogy
-
ARCH: Each shock creates a wave
- GARCH: The wave doesn’t vanish immediately — it rolls over and decays slowly
Two-Part Structure
Mean equation (ARIMA, AR, etc.): Models expected returns — gives residuals \(u_t\)
Variance equation (GARCH): Models expected volatility — uses those \(u_t\) to predict \(\sigma_t^2\)
Historical note:
The parameter nameomegaoriginates from Bollerslev’s (1986) original formulation of the GARCH model.
In his notation, the conditional variance equation was written as
\[ \sigma_t^2 = \omega + \alpha_1 u_{t-1}^2 + \beta_1 \sigma_{t-1}^2, \]
where \(\omega\) represents the constant term — the baseline or “intercept” in the variance equation.Later textbooks often replaced \(\omega\) with \(\alpha_0\) for consistency with the ARCH model notation,
but most software packages (includinggarchFit()andrugarch) retainedomegato stay true to Bollerslev’s original paper.