# Load necessary libraries
library(quantmod) # For fetching financial data
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(ggplot2) # For creating informative plots
library(rugarch) # For GARCH modeling
## Loading required package: parallel
##
## Attaching package: 'rugarch'
## The following object is masked from 'package:stats':
##
## sigma
# 1. Plot the returns and check for volatility clustering.
# First, I'll fetch the daily adjusted closing prices for Apple (AAPL) from Yahoo Finance.
getSymbols("AAPL", from = "2020-01-01", to = Sys.Date())
## [1] "AAPL"
aapl_prices <- Ad(AAPL)
# Next, I'll calculate the daily returns from the adjusted closing prices.
aapl_returns <- diff(log(aapl_prices))[-1]
# Now, I'll create a plot of these daily returns to visually inspect for volatility clustering.
# Volatility clustering is characterized by periods of high volatility followed by periods of low volatility.
return_plot <- ggplot(data.frame(Date = index(aapl_returns), Return = as.numeric(aapl_returns)), aes(x = Date, y = Return)) +
geom_line() +
labs(title = "Daily Returns of AAPL Stock", y = "Return", x = "Date") +
theme_minimal()
print(return_plot)

# By examining this plot, I'll look for sections where the magnitude of the returns (both positive and negative) is larger for a period, and other sections where they are smaller. This visual inspection helps in identifying volatility clustering.
# 2. Apply function to check for ARCH effect.
# To formally test for ARCH effects without the FinTS package, I will implement Engle's ARCH test.
# This involves regressing the squared returns on a number of its lags.
# I'll square the returns.
squared_returns <- aapl_returns^2
# I'll create lagged values of the squared returns (up to a certain number of lags, e.g., 5).
num_lags <- 5
lagged_squared_returns <- embed(squared_returns, dimension = num_lags + 1)[, -1]
# Now, I'll fit a linear regression of the squared returns on these lags.
arch_test_model <- lm(squared_returns[(num_lags + 1):length(squared_returns)] ~ lagged_squared_returns)
summary_arch_test <- summary(arch_test_model)
# The R-squared from this regression and the overall F-statistic can be used to test for ARCH effects.
# A significant F-statistic (low p-value) suggests the presence of ARCH effects.
print("Engle's ARCH Test Results:")
## [1] "Engle's ARCH Test Results:"
print(summary_arch_test)
##
## Call:
## lm(formula = squared_returns[(num_lags + 1):length(squared_returns)] ~
## lagged_squared_returns)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0047603 -0.0002882 -0.0001929 0.0000264 0.0176931
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.786e-04 3.502e-05 5.099 3.90e-07 ***
## lagged_squared_returns1 2.148e-01 2.731e-02 7.867 7.42e-15 ***
## lagged_squared_returns2 1.255e-01 2.756e-02 4.554 5.74e-06 ***
## lagged_squared_returns3 3.021e-02 2.776e-02 1.088 0.2767
## lagged_squared_returns4 1.655e-01 2.756e-02 6.005 2.46e-09 ***
## lagged_squared_returns5 4.532e-02 2.740e-02 1.654 0.0984 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.001126 on 1339 degrees of freedom
## Multiple R-squared: 0.1528, Adjusted R-squared: 0.1496
## F-statistic: 48.3 on 5 and 1339 DF, p-value: < 2.2e-16
# 3. Fit a GARCH(1,1) model using the rugarch package.
# Now that we've (potentially) identified ARCH effects, I'll proceed to fit a GARCH(1,1) model.
# The GARCH(1,1) model is a common and relatively simple model that captures the conditional volatility
# based on the previous period's squared error and the previous period's variance.
# First, I'll define the GARCH(1,1) model specification using the ugarchspec function.
garch11_spec <- ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(1, 1)),
mean.model = list(armaOrder = c(0, 0)), # Assuming a simple mean model with no ARMA components
distribution.model = "norm" # Assuming a normal distribution for the errors
)
# Next, I'll fit this specification to our AAPL returns data using the ugarchfit function.
garch11_fit <- ugarchfit(spec = garch11_spec, data = aapl_returns)
print(summary(garch11_fit))
## Length Class Mode
## 1 uGARCHfit S4
# The summary of the fitted model will provide estimates for the coefficients of the GARCH(1,1) model
# (omega, alpha1, beta1), as well as diagnostic information about the model fit.
# 4. Plot the conditional volatility.
# After fitting the GARCH model, I can extract and plot the conditional volatility, which represents
# the time-varying standard deviation of the returns predicted by the model.
# I'll extract the conditional volatility using the sigma function.
conditional_volatility <- sigma(garch11_fit)
# Now, I'll create a plot of this conditional volatility over time.
volatility_plot <- ggplot(data.frame(Date = index(conditional_volatility), Volatility = as.numeric(conditional_volatility)), aes(x = Date, y = Volatility)) +
geom_line() +
labs(title = "Conditional Volatility of AAPL Returns (GARCH(1,1))", y = "Conditional Volatility", x = "Date") +
theme_minimal()
print(volatility_plot)

# This plot will show how the predicted volatility of Apple's stock returns has changed over the period,
# ideally reflecting the volatility clustering we might have observed in the initial return plot.
# 5. Produce forecast for 12 months.
# Finally, I'll generate a forecast of the conditional volatility for the next 12 months (approximately 252 trading days).
n_ahead <- 252
garch11_forecast <- ugarchforecast(garch11_fit, n.ahead = n_ahead)
print(garch11_forecast)
##
## *------------------------------------*
## * GARCH Model Forecast *
## *------------------------------------*
## Model: sGARCH
## Horizon: 252
## Roll Steps: 0
## Out of Sample: 0
##
## 0-roll forecast [T0=2025-05-16]:
## Series Sigma
## T+1 0.00126 0.02310
## T+2 0.00126 0.02302
## T+3 0.00126 0.02295
## T+4 0.00126 0.02287
## T+5 0.00126 0.02280
## T+6 0.00126 0.02273
## T+7 0.00126 0.02266
## T+8 0.00126 0.02259
## T+9 0.00126 0.02252
## T+10 0.00126 0.02246
## T+11 0.00126 0.02240
## T+12 0.00126 0.02234
## T+13 0.00126 0.02228
## T+14 0.00126 0.02222
## T+15 0.00126 0.02217
## T+16 0.00126 0.02211
## T+17 0.00126 0.02206
## T+18 0.00126 0.02201
## T+19 0.00126 0.02196
## T+20 0.00126 0.02191
## T+21 0.00126 0.02187
## T+22 0.00126 0.02182
## T+23 0.00126 0.02178
## T+24 0.00126 0.02174
## T+25 0.00126 0.02170
## T+26 0.00126 0.02166
## T+27 0.00126 0.02162
## T+28 0.00126 0.02158
## T+29 0.00126 0.02154
## T+30 0.00126 0.02151
## T+31 0.00126 0.02147
## T+32 0.00126 0.02144
## T+33 0.00126 0.02141
## T+34 0.00126 0.02138
## T+35 0.00126 0.02135
## T+36 0.00126 0.02132
## T+37 0.00126 0.02129
## T+38 0.00126 0.02126
## T+39 0.00126 0.02123
## T+40 0.00126 0.02121
## T+41 0.00126 0.02118
## T+42 0.00126 0.02116
## T+43 0.00126 0.02113
## T+44 0.00126 0.02111
## T+45 0.00126 0.02109
## T+46 0.00126 0.02106
## T+47 0.00126 0.02104
## T+48 0.00126 0.02102
## T+49 0.00126 0.02100
## T+50 0.00126 0.02098
## T+51 0.00126 0.02097
## T+52 0.00126 0.02095
## T+53 0.00126 0.02093
## T+54 0.00126 0.02091
## T+55 0.00126 0.02090
## T+56 0.00126 0.02088
## T+57 0.00126 0.02086
## T+58 0.00126 0.02085
## T+59 0.00126 0.02083
## T+60 0.00126 0.02082
## T+61 0.00126 0.02081
## T+62 0.00126 0.02079
## T+63 0.00126 0.02078
## T+64 0.00126 0.02077
## T+65 0.00126 0.02076
## T+66 0.00126 0.02074
## T+67 0.00126 0.02073
## T+68 0.00126 0.02072
## T+69 0.00126 0.02071
## T+70 0.00126 0.02070
## T+71 0.00126 0.02069
## T+72 0.00126 0.02068
## T+73 0.00126 0.02067
## T+74 0.00126 0.02066
## T+75 0.00126 0.02065
## T+76 0.00126 0.02064
## T+77 0.00126 0.02064
## T+78 0.00126 0.02063
## T+79 0.00126 0.02062
## T+80 0.00126 0.02061
## T+81 0.00126 0.02061
## T+82 0.00126 0.02060
## T+83 0.00126 0.02059
## T+84 0.00126 0.02058
## T+85 0.00126 0.02058
## T+86 0.00126 0.02057
## T+87 0.00126 0.02057
## T+88 0.00126 0.02056
## T+89 0.00126 0.02055
## T+90 0.00126 0.02055
## T+91 0.00126 0.02054
## T+92 0.00126 0.02054
## T+93 0.00126 0.02053
## T+94 0.00126 0.02053
## T+95 0.00126 0.02052
## T+96 0.00126 0.02052
## T+97 0.00126 0.02051
## T+98 0.00126 0.02051
## T+99 0.00126 0.02051
## T+100 0.00126 0.02050
## T+101 0.00126 0.02050
## T+102 0.00126 0.02049
## T+103 0.00126 0.02049
## T+104 0.00126 0.02049
## T+105 0.00126 0.02048
## T+106 0.00126 0.02048
## T+107 0.00126 0.02048
## T+108 0.00126 0.02047
## T+109 0.00126 0.02047
## T+110 0.00126 0.02047
## T+111 0.00126 0.02046
## T+112 0.00126 0.02046
## T+113 0.00126 0.02046
## T+114 0.00126 0.02046
## T+115 0.00126 0.02045
## T+116 0.00126 0.02045
## T+117 0.00126 0.02045
## T+118 0.00126 0.02045
## T+119 0.00126 0.02044
## T+120 0.00126 0.02044
## T+121 0.00126 0.02044
## T+122 0.00126 0.02044
## T+123 0.00126 0.02044
## T+124 0.00126 0.02043
## T+125 0.00126 0.02043
## T+126 0.00126 0.02043
## T+127 0.00126 0.02043
## T+128 0.00126 0.02043
## T+129 0.00126 0.02043
## T+130 0.00126 0.02042
## T+131 0.00126 0.02042
## T+132 0.00126 0.02042
## T+133 0.00126 0.02042
## T+134 0.00126 0.02042
## T+135 0.00126 0.02042
## T+136 0.00126 0.02041
## T+137 0.00126 0.02041
## T+138 0.00126 0.02041
## T+139 0.00126 0.02041
## T+140 0.00126 0.02041
## T+141 0.00126 0.02041
## T+142 0.00126 0.02041
## T+143 0.00126 0.02041
## T+144 0.00126 0.02041
## T+145 0.00126 0.02040
## T+146 0.00126 0.02040
## T+147 0.00126 0.02040
## T+148 0.00126 0.02040
## T+149 0.00126 0.02040
## T+150 0.00126 0.02040
## T+151 0.00126 0.02040
## T+152 0.00126 0.02040
## T+153 0.00126 0.02040
## T+154 0.00126 0.02040
## T+155 0.00126 0.02040
## T+156 0.00126 0.02040
## T+157 0.00126 0.02040
## T+158 0.00126 0.02039
## T+159 0.00126 0.02039
## T+160 0.00126 0.02039
## T+161 0.00126 0.02039
## T+162 0.00126 0.02039
## T+163 0.00126 0.02039
## T+164 0.00126 0.02039
## T+165 0.00126 0.02039
## T+166 0.00126 0.02039
## T+167 0.00126 0.02039
## T+168 0.00126 0.02039
## T+169 0.00126 0.02039
## T+170 0.00126 0.02039
## T+171 0.00126 0.02039
## T+172 0.00126 0.02039
## T+173 0.00126 0.02039
## T+174 0.00126 0.02039
## T+175 0.00126 0.02039
## T+176 0.00126 0.02039
## T+177 0.00126 0.02039
## T+178 0.00126 0.02039
## T+179 0.00126 0.02038
## T+180 0.00126 0.02038
## T+181 0.00126 0.02038
## T+182 0.00126 0.02038
## T+183 0.00126 0.02038
## T+184 0.00126 0.02038
## T+185 0.00126 0.02038
## T+186 0.00126 0.02038
## T+187 0.00126 0.02038
## T+188 0.00126 0.02038
## T+189 0.00126 0.02038
## T+190 0.00126 0.02038
## T+191 0.00126 0.02038
## T+192 0.00126 0.02038
## T+193 0.00126 0.02038
## T+194 0.00126 0.02038
## T+195 0.00126 0.02038
## T+196 0.00126 0.02038
## T+197 0.00126 0.02038
## T+198 0.00126 0.02038
## T+199 0.00126 0.02038
## T+200 0.00126 0.02038
## T+201 0.00126 0.02038
## T+202 0.00126 0.02038
## T+203 0.00126 0.02038
## T+204 0.00126 0.02038
## T+205 0.00126 0.02038
## T+206 0.00126 0.02038
## T+207 0.00126 0.02038
## T+208 0.00126 0.02038
## T+209 0.00126 0.02038
## T+210 0.00126 0.02038
## T+211 0.00126 0.02038
## T+212 0.00126 0.02038
## T+213 0.00126 0.02038
## T+214 0.00126 0.02038
## T+215 0.00126 0.02038
## T+216 0.00126 0.02038
## T+217 0.00126 0.02038
## T+218 0.00126 0.02038
## T+219 0.00126 0.02038
## T+220 0.00126 0.02038
## T+221 0.00126 0.02038
## T+222 0.00126 0.02038
## T+223 0.00126 0.02038
## T+224 0.00126 0.02038
## T+225 0.00126 0.02038
## T+226 0.00126 0.02038
## T+227 0.00126 0.02038
## T+228 0.00126 0.02038
## T+229 0.00126 0.02038
## T+230 0.00126 0.02038
## T+231 0.00126 0.02038
## T+232 0.00126 0.02038
## T+233 0.00126 0.02038
## T+234 0.00126 0.02038
## T+235 0.00126 0.02038
## T+236 0.00126 0.02038
## T+237 0.00126 0.02038
## T+238 0.00126 0.02038
## T+239 0.00126 0.02038
## T+240 0.00126 0.02038
## T+241 0.00126 0.02038
## T+242 0.00126 0.02038
## T+243 0.00126 0.02038
## T+244 0.00126 0.02038
## T+245 0.00126 0.02038
## T+246 0.00126 0.02038
## T+247 0.00126 0.02038
## T+248 0.00126 0.02038
## T+249 0.00126 0.02038
## T+250 0.00126 0.02038
## T+251 0.00126 0.02038
## T+252 0.00126 0.02038
# The ugarchforecast function will provide a forecast of the conditional volatility for the specified number of steps ahead.
# The output will include the forecasted volatility values.
# I can also plot this forecast to visualize the expected future volatility.
forecast_volatility <- data.frame(Volatility = fitted(garch11_forecast)[,1]) # Extract the first column of fitted values and name it "Volatility"
# Generate a sequence of dates starting from the day after the last return date
start_date <- tail(index(aapl_returns), 1) + 1
all_forecast_dates <- seq(from = start_date, length.out = n_ahead * 2, by = "day") # Generate more dates to ensure we get enough weekdays
# Filter for weekdays and take the first n_ahead dates
forecast_dates <- all_forecast_dates[weekdays(all_forecast_dates) %in% c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")]
forecast_dates <- head(forecast_dates, n_ahead)
forecast_volatility$Date <- forecast_dates
forecast_plot <- ggplot(forecast_volatility, aes(x = Date, y = Volatility)) +
geom_line() +
labs(title = "Forecasted Conditional Volatility (12 Months)", y = "Forecasted Volatility", x = "Date") +
theme_minimal()
print(forecast_plot)

# This final plot shows the predicted trend of Apple's stock return volatility for the upcoming year, based on the fitted GARCH(1,1) model.