0% found this document useful (0 votes)
6 views11 pages

Module 3

The document outlines a process for analyzing TCS stock prices using R, including downloading data, calculating daily log returns, and performing stationarity tests. It employs the GARCH model to estimate volatility, showing results from both ARCH(1) and GARCH(1,1) models. The analysis includes various statistical tests and plots to assess the model fit and residuals.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views11 pages

Module 3

The document outlines a process for analyzing TCS stock prices using R, including downloading data, calculating daily log returns, and performing stationarity tests. It employs the GARCH model to estimate volatility, showing results from both ARCH(1) and GARCH(1,1) models. The analysis includes various statistical tests and plots to assess the model fit and residuals.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

> library(quantmod) # for downloading stock data

> library(tseries) # for stationarity tests (ADF)


> library(rugarch) # for ARCH/GARCH estimation
> library(FinTS) # for ARCH-LM test
> # Download daily TCS stock prices from Yahoo Finance
> getSymbols("[Link]", from = "2015-01-01", src = "yahoo")
[1] "[Link]"

Warning message:
[Link] contains missing values. Some functions will not work if objects
contain missing values in the middle of the series. Consider using [Link](),
[Link](), [Link](), etc to remove or replace them.
> # Extract Adjusted Closing Price (preferred for returns)
> price <- Ad([Link])
> # Compute daily log returns: r_t = log(P_t) - log(P_{t-1})
> returns <- diff(log(price))
> # Remove first NA observation
> returns <- [Link](returns)
> plot(
+ returns,
+ main = "TCS Daily Log Returns",
+ ylab = "Returns",
+ xlab = "Time",
+ col = "steelblue"
+ )
> abline(h = 0, col = "red", lty = 2)
> plot(
+ returns^2,
+ main = "Squared Log Returns of TCS",
+ ylab = "Squared Returns",
+ xlab = "Time",
+ col = "darkorange"
+ )
> [Link]([Link](price))

​ Augmented Dickey-Fuller Test

data: [Link](price)
Dickey-Fuller = -1.2924, Lag order
= 14, p-value = 0.8779
alternative hypothesis: stationary

> [Link](returns)

​ Augmented Dickey-Fuller Test

data: returns
Dickey-Fuller = -13.808, Lag order
= 14, p-value = 0.01
alternative hypothesis: stationary

Warning message:
In [Link](returns) : p-value smaller than printed p-value
> acf(
+ returns,
+ main = "ACF of Returns (Check Mean Structure)"
+ )
> acf(
+ returns^2,
+ main = "ACF of Squared Returns (Volatility Clustering)"
+ )
> # Engle's ARCH-LM test on raw returns
> ArchTest(returns, lags = 5)

​ ARCH LM-test; Null hypothesis: no


​ ARCH effects

data: returns
Chi-squared = 133.49, df = 5,
p-value < 2.2e-16

> spec_arch1 <- ugarchspec(


+
+ [Link] = list(
+
+ # "sGARCH" refers to the standard GARCH framework in rugarch.
+ # Even when we want a pure ARCH model, rugarch still requires "sGARCH"
+ # because ARCH is implemented as a special case of GARCH.
+ model = "sGARCH",
+
+ # garchOrder = c(p, q)
+ # p = number of GARCH terms (lags of past conditional variance h_{t-1},
h_{t-2}, ...)
+ # q = number of ARCH terms (lags of past squared shocks ε_{t-1}^2,
ε_{t-2}^2, ...)
+ #
+ # Here we use c(1, 0):
+ # p = 1, q = 0
+ # Since q = 0, the GARCH part drops out in practice.
+ # This effectively gives:
+ # h_t = α0 + α1 * ε_{t-1}^2
+ # which is an ARCH(1) model.
+ #
+ # you could later change this to:
+ # c(2,0) -> ARCH(2)
+ # c(1,1) -> GARCH(1,1)
+ # c(2,1) -> GARCH(2,1)
+ garchOrder = c(1, 0)
+ ),
+
+ [Link] = list(
+
+ # armaOrder = c(p, q) specifies the mean equation for returns.
+ # p = number of AR terms, q = number of MA terms.
+ #
+ # c(0,0) means no AR and no MA terms, so the mean equation is simply:
+ # r_t = μ + ε_t
+ #
+ # If you wanted to allow predictability in returns, they could use:
+ # c(1,0) for AR(1)
+ # c(0,1) for MA(1)
+ armaOrder = c(0, 0),
+
+ # [Link] = TRUE means we estimate a constant mean μ.
+ # If this were FALSE, the model would force μ = 0.
+ [Link] = TRUE
+ ),
+
+ # [Link] specifies the assumed distribution of ε_t given past
information.
+ #
+ # "norm" means:
+ # ε_t | F_{t-1} ~ Normal(0, h_t)
+ #
+ # if you want you could later change this to:
+ # "std" for Student-t (if returns have fat tails)
+ # "sstd" for skewed Student-t
+ [Link] = "norm"
+ )
> fit_arch1 <- ugarchfit(
+
+ # 'spec' tells rugarch which model structure to estimate
+ spec = spec_arch1,
+
+ # 'data' is the series to which the model is fitted.
+ # This must be returns, not prices.
+ data = returns
+ )
> # Show results
> show(fit_arch1)

*---------------------------------*
* GARCH Model Fit *
*---------------------------------*

Conditional Variance Dynamics ​


-----------------------------------
GARCH Model​ : sGARCH(1,0)
Mean Model​ : ARFIMA(0,0,0)
Distribution​: norm

Optimal Parameters
------------------------------------
Estimate Std. Error t value
mu 0.035495 0.000017 2130.6344
omega 0.000000 0.000000 2.0498
alpha1 0.991403 0.007112 139.4066
Pr(>|t|)
mu 0.000000
omega 0.040381
alpha1 0.000000

Robust Standard Errors:


Estimate Std. Error t value
mu 0.035495 0.000329 107.947337
omega 0.000000 0.000027 0.014584
alpha1 0.991403 0.322599 3.073174
Pr(>|t|)
mu 0.000000
omega 0.988364
alpha1 0.002118

LogLikelihood : -278.2397

Information Criteria
------------------------------------

Akaike 0.20424
Bayes 0.21069
Shibata 0.20424
Hannan-Quinn 0.20657

Weighted Ljung-Box Test on Standardized Residuals


------------------------------------
statistic
Lag[1] 13.24
Lag[2*(p+q)+(p+q)-1][2] 13.25
Lag[4*(p+q)+(p+q)-1][5] 13.63
p-value
Lag[1] 0.0002734
Lag[2*(p+q)+(p+q)-1][2] 0.0002647
Lag[4*(p+q)+(p+q)-1][5] 0.0010300
d.o.f=0
H0 : No serial correlation

Weighted Ljung-Box Test on Standardized Squared Residuals


------------------------------------
statistic
Lag[1] 0.06352
Lag[2*(p+q)+(p+q)-1][2] 0.08312
Lag[4*(p+q)+(p+q)-1][5] 0.13340
p-value
Lag[1] 0.8010
Lag[2*(p+q)+(p+q)-1][2] 0.9316
Lag[4*(p+q)+(p+q)-1][5] 0.9967
d.o.f=1

Weighted ARCH LM Tests


------------------------------------
Statistic Shape Scale
ARCH Lag[2] 0.03914 0.500 2.000
ARCH Lag[4] 0.08355 1.397 1.611
ARCH Lag[6] 0.10564 2.222 1.500
P-Value
ARCH Lag[2] 0.8432
ARCH Lag[4] 0.9874
ARCH Lag[6] 0.9989

Nyblom stability test


------------------------------------
Joint Statistic: 18.2009
Individual Statistics:
mu 0.1332
omega 4.3687
alpha1 15.1708

Asymptotic Critical Values (10% 5% 1%)


Joint Statistic: ​ 0.846 1.01 1.35
Individual Statistic:​ 0.35 0.47 0.75

Sign Bias Test


------------------------------------
t-value prob
Sign Bias 6.109 1.147e-09
Negative Sign Bias 7.166 9.864e-13
Positive Sign Bias 5.494 4.290e-08
Joint Effect 111.428 5.407e-24
sig
Sign Bias ***
Negative Sign Bias ***
Positive Sign Bias ***
Joint Effect ***

Adjusted Pearson Goodness-of-Fit Test:


------------------------------------
group statistic p-value(g-1)
1 20 4779 0
2 30 4899 0
3 40 4874 0
4 50 5018 0
Elapsed time : 0.435992

> # pplot estimated ARCH volatility


> plot(fit_arch1, which = 2)

please wait...calculating quantiles...


> res_arch <- residuals(fit_arch1, standardize = TRUE)
> # ACF of squared standardized residuals
> acf(res_arch^2, main = "ACF of Squared Residuals (ARCH)")
> # Formal ARCH-LM test on residuals
> ArchTest(res_arch, lags = 5)

​ ARCH LM-test; Null hypothesis: no


​ ARCH effects

data: res_arch
Chi-squared = 0.20167, df = 5,
p-value = 0.9991

> spec_garch11 <- ugarchspec(


+ [Link] = list(model = "sGARCH", garchOrder = c(1, 1)), #
GARCH(1,1)
+ [Link] = list(armaOrder = c(0, 0), [Link] = TRUE),
+ [Link] = "norm"
+ )
> fit_garch11 <- ugarchfit(
+ spec = spec_garch11,
+ data = returns
+ )
> ##expalined code in deatil for the same thing you ran aboce
> spec_garch11 <- ugarchspec(
+
+ [Link] = list(
+
+ # "sGARCH" is the standard GARCH framework in rugarch.
+ # This is the usual specification for most basic GARCH models.
+ model = "sGARCH",
+
+ # garchOrder = c(p, q)
+ # p = number of GARCH terms (lags of past conditional variance h_{t-1},
h_{t-2}, ...)
+ # q = number of ARCH terms (lags of past squared shocks ε_{t-1}^2,
ε_{t-2}^2, ...)
+ #
+ # Here we use c(1, 1), which means:
+ # p = 1 (one lag of past variance)
+ # q = 1 (one lag of past squared shock)
+ #
+ # This gives the standard GARCH(1,1) variance equation:
+ # h_t = α0 + α1 * ε_{t-1}^2 + β1 * h_{t-1}
+ #
+ # you could later experiment with:
+ # c(2,1) -> GARCH(2,1)
+ # c(1,2) -> GARCH(1,2)
+ # c(2,2) -> GARCH(2,2)
+ garchOrder = c(1, 1)
+ ),
+
+ [Link] = list(
+
+ # armaOrder = c(p, q) specifies the mean equation for returns.
+ # p = number of AR terms, q = number of MA terms.
+ #
+ # c(0,0) means no AR and no MA terms, so the mean equation is simply:
+ # r_t = μ + ε_t
+ #
+ # If you wanted to model predictability in returns, they could use:
+ # c(1,0) for AR(1)
+ # c(0,1) for MA(1)
+ armaOrder = c(0, 0),
+
+ # [Link] = TRUE means we estimate a constant mean μ.
+ # If this were FALSE, the model would force μ = 0.
+ [Link] = TRUE
+ ),
+
+ # [Link] specifies the assumed conditional distribution of
ε_t.
+ #
+ # "norm" means:
+ # ε_t | F_{t-1} ~ Normal(0, h_t)
+ #
+ # you could later change this to:
+ # "std" for Student-t (if returns have fat tails)
+ # "sstd" for skewed Student-t
+ [Link] = "norm"
+ )
> fit_garch11 <- ugarchfit(
+
+ # 'spec' tells rugarch which model structure to estimate
+ spec = spec_garch11,
+
+ # 'data' is the series to which the model is fitted.
+ # This must be returns, not prices.
+ data = returns
+ )
> # Show results
> show(fit_garch11)

*---------------------------------*
* 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
mu 0.000369 0.000263 1.4048
omega 0.000014 0.000000 53.0211
alpha1 0.056348 0.003396 16.5923
beta1 0.875992 0.006766 129.4654
Pr(>|t|)
mu 0.16009
omega 0.00000
alpha1 0.00000
beta1 0.00000

Robust Standard Errors:


Estimate Std. Error t value
mu 0.000369 0.000261 1.4127
omega 0.000014 0.000001 27.1900
alpha1 0.056348 0.004003 14.0779
beta1 0.875992 0.008311 105.4006
Pr(>|t|)
mu 0.15776
omega 0.00000
alpha1 0.00000
beta1 0.00000

LogLikelihood : 7808.871

Information Criteria
------------------------------------

Akaike -5.6680
Bayes -5.6594
Shibata -5.6680
Hannan-Quinn -5.6649

Weighted Ljung-Box Test on Standardized Residuals


------------------------------------
statistic
Lag[1] 1.717
Lag[2*(p+q)+(p+q)-1][2] 2.431
Lag[4*(p+q)+(p+q)-1][5] 3.073
p-value
Lag[1] 0.1901
Lag[2*(p+q)+(p+q)-1][2] 0.2003
Lag[4*(p+q)+(p+q)-1][5] 0.3939
d.o.f=0
H0 : No serial correlation

Weighted Ljung-Box Test on Standardized Squared Residuals


------------------------------------
statistic
Lag[1] 0.06734
Lag[2*(p+q)+(p+q)-1][5] 4.00015
Lag[4*(p+q)+(p+q)-1][9] 9.81989
p-value
Lag[1] 0.7952
Lag[2*(p+q)+(p+q)-1][5] 0.2541
Lag[4*(p+q)+(p+q)-1][9] 0.0548
d.o.f=2

Weighted ARCH LM Tests


------------------------------------
Statistic Shape Scale
ARCH Lag[3] 3.287 0.500 2.000
ARCH Lag[5] 4.595 1.440 1.667
ARCH Lag[7] 9.908 2.315 1.543
P-Value
ARCH Lag[3] 0.06984
ARCH Lag[5] 0.12735
ARCH Lag[7] 0.01933

Nyblom stability test


------------------------------------
Joint Statistic: 161.0661
Individual Statistics:
mu 0.1683
omega 9.9383
alpha1 0.2588
beta1 0.1155

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.1867 0.8519
Negative Sign Bias 1.0228 0.3065
Positive Sign Bias 0.1204 0.9041
Joint Effect 1.1880 0.7559
Adjusted Pearson Goodness-of-Fit Test:
------------------------------------
group statistic p-value(g-1)
1 20 127.6 4.147e-18
2 30 145.3 1.973e-17
3 40 152.6 2.338e-15
4 50 179.7 8.241e-17

Elapsed time : 0.4168251

> res_garch <- residuals(fit_garch11, standardize = TRUE)


> # Check autocorrelation in standardized residuals
> acf(res_garch, main = "ACF of Standardized Residuals (GARCH)")
> # Check remaining ARCH in squared residuals
> acf(res_garch^2, main = "ACF of Squared Standardized Residuals (GARCH)")
> # Test for autocorrelation in residuals (mean structure)
> [Link](res_garch, lag = 10, type = "Ljung")

​ Box-Ljung test

data: res_garch
X-squared = 9.1455, df = 10,
p-value = 0.5184

> # Test for remaining ARCH in squared residuals


> [Link](res_garch^2, lag = 10, type = "Ljung")

​ Box-Ljung test

data: res_garch^2
X-squared = 18.661, df = 10,
p-value = 0.04479

> # ARCH-LM test on GARCH residuals


> ArchTest(res_garch, lags = 5)

​ ARCH LM-test; Null hypothesis: no


​ ARCH effects

data: res_garch
Chi-squared = 6.9763, df = 5,
p-value = 0.2224

> plot(fit_arch1, which = 2) # ARCH volatility (spiky)

please wait...calculating quantiles...


> plot(fit_garch11, which = 2) # GARCH volatility (smoother, persistent)

please wait...calculating quantiles...


> infocriteria(fit_arch1)
Akaike 0.2042409
Bayes 0.2106906
Shibata 0.2042385
Hannan-Quinn 0.2065709
> infocriteria(fit_garch11)

Akaike -5.668025
Bayes -5.659426
Shibata -5.668029
Hannan-Quinn -5.664918
> acf(res_arch^2, main = "Squared Residuals: ARCH")
> acf(res_garch^2, main = "Squared Residuals: GARCH")
>
> # Typically:
> # Typically:
> # ARCH still shows some structure
> # Typically:
> # ARCH still shows some structure
> # GARCH cleans it up.

You might also like