# Load Required Libraries
library(xts)
library(quantmod)
library(zoo)
library(ghyp)
# Create the Data Files
start.date <- "2014-04-01"
end.date   <- "2019-04-01"

getSymbols("NVDA", from = start.date, to = end.date, src = "yahoo", auto.assign = TRUE)
## [1] "NVDA"
getSymbols("BAC",  from = start.date, to = end.date, src = "yahoo", auto.assign = TRUE)
## [1] "BAC"
data.NVDA <- NVDA
data.BAC  <- BAC

names(data.NVDA) <- paste0("NVDA.", c("Open","High","Low","Close","Volume","Adjusted"))
names(data.BAC)  <- paste0("BAC.",  c("Open","High","Low","Close","Volume","Adjusted"))

# Subset to Fourth Year
hw3.start <- "2017-04-01"
hw3.end   <- "2018-03-31"

NVDA.hw3 <- window(data.NVDA, start = hw3.start, end = hw3.end)
BAC.hw3  <- window(data.BAC,  start = hw3.start, end = hw3.end)
# Part A - Variance-Covariance Matrix

# Daily log returns
NVDA.ret <- na.omit(diff(log(NVDA.hw3$NVDA.Adjusted)))
BAC.ret  <- na.omit(diff(log(BAC.hw3$BAC.Adjusted)))

# Merge on common dates
ret.merged <- merge(NVDA.ret, BAC.ret, join = "inner")
colnames(ret.merged) <- c("NVDA", "BAC")

ret.matrix <- as.matrix(ret.merged)

# Variance-Covariance Matrix
vcov.matrix <- cov(ret.matrix)

cat("=== Variance-Covariance Matrix (Daily Log Returns, Year 4) ===\n")
## === Variance-Covariance Matrix (Daily Log Returns, Year 4) ===
print(round(vcov.matrix, 8))
##            NVDA        BAC
## NVDA 0.00071228 0.00013230
## BAC  0.00013230 0.00019919
cat("\nVariance of NVDA:", round(vcov.matrix["NVDA","NVDA"], 8), "\n")
## 
## Variance of NVDA: 0.00071228
cat("Variance of BAC: ", round(vcov.matrix["BAC","BAC"],   8), "\n")
## Variance of BAC:  0.00019919
cat("Covariance:      ", round(vcov.matrix["NVDA","BAC"],  8), "\n")
## Covariance:       0.0001323
cat("Correlation:     ", round(vcov.matrix["NVDA","BAC"] /
      sqrt(vcov.matrix["NVDA","NVDA"] * vcov.matrix["BAC","BAC"]), 4), "\n")
## Correlation:      0.3512
cat("\n=== Annualized Variance-Covariance Matrix ===\n")
## 
## === Annualized Variance-Covariance Matrix ===
print(round(vcov.matrix * 252, 6))
##          NVDA      BAC
## NVDA 0.179495 0.033339
## BAC  0.033339 0.050196
cat("\nAnnualized Std Dev NVDA:", round(sqrt(vcov.matrix["NVDA","NVDA"] * 252) * 100, 2), "%\n")
## 
## Annualized Std Dev NVDA: 42.37 %
cat("Annualized Std Dev BAC: ", round(sqrt(vcov.matrix["BAC","BAC"]   * 252) * 100, 2), "%\n")
## Annualized Std Dev BAC:  22.4 %
# Part B - Section 1: Fit GHD, HYP, and NIG

nvda.vec <- as.numeric(ret.merged[, "NVDA"])

fit.ghd <- fit.ghypuv(nvda.vec, symmetric = FALSE, silent = TRUE)
fit.hyp <- fit.hypuv(nvda.vec,  symmetric = FALSE, silent = TRUE)
fit.nig <- fit.NIGuv(nvda.vec,  symmetric = FALSE, silent = TRUE)

cat("--- GHD Parameters ---\n"); print(fit.ghd)
## --- GHD Parameters ---
## Asymmetric Generalized Hyperbolic Distribution:
## 
## Parameters:
##        lambda     alpha.bar            mu         sigma         gamma 
## -0.1925642112  0.4663137226  0.0034417053  0.0265777097 -0.0003814184 
## 
## log-likelihood:
## 577.2492
## 
## 
## Call:
## fit.ghypuv(data = nvda.vec, symmetric = FALSE, silent = TRUE)
cat("\n--- HYP Parameters ---\n"); print(fit.hyp)
## 
## --- HYP Parameters ---
## Asymmetric Hyperbolic Distribution:
## 
## Parameters:
##    alpha.bar           mu        sigma        gamma 
## 0.0001313448 0.0024083411 0.0256551425 0.0006571446 
## 
## log-likelihood:
## 576.6797
## 
## 
## Call:
## fit.hypuv(data = nvda.vec, symmetric = FALSE, silent = TRUE)
cat("\n--- NIG Parameters ---\n"); print(fit.nig)
## 
## --- NIG Parameters ---
## Asymmetric Normal Inverse Gaussian Distribution:
## 
## Parameters:
##     alpha.bar            mu         sigma         gamma 
##  0.4618002457  0.0035731862  0.0267362868 -0.0005072733 
## 
## log-likelihood:
## 577.2038
## 
## 
## Call:
## fit.NIGuv(data = nvda.vec, symmetric = FALSE, silent = TRUE)
# Part B - Section 2: Combined Density Plot

nvda.vec <- as.numeric(ret.merged[, "NVDA"])

x.seq    <- seq(min(nvda.vec) - 0.01, max(nvda.vec) + 0.01, length.out = 500)
dens.ghd <- dghyp(x.seq, fit.ghd)
dens.hyp <- dghyp(x.seq, fit.hyp)
dens.nig <- dghyp(x.seq, fit.nig)

# Remove NAs and Inf before calculating y.max
all.dens <- c(dens.ghd, dens.hyp, dens.nig, density(nvda.vec)$y)
all.dens <- all.dens[is.finite(all.dens)]
y.max    <- max(all.dens, na.rm = TRUE) * 1.05

hist(nvda.vec, breaks = 50, freq = FALSE,
     col    = "gray90",
     border = "white",
     xlab   = "Daily Log Return",
     main   = "NVDA Daily Log Returns: GHD, HYP, and NIG Density Fits\nYear 4 (April 2017 - March 2018)",
     ylim   = c(0, y.max))

lines(x.seq, dens.ghd, col = "steelblue", lwd = 2)
lines(x.seq, dens.hyp, col = "firebrick", lwd = 2, lty = 2)
lines(x.seq, dens.nig, col = "darkgreen", lwd = 2, lty = 3)
lines(density(nvda.vec), col = "black",   lwd = 1.5, lty = 4)

legend("topright",
       legend = c("GHD", "HYP", "NIG", "Empirical Density"),
       col    = c("steelblue","firebrick","darkgreen","black"),
       lwd    = 2, lty = c(1,2,3,4), cex = 0.85)

# Part B - Section 3: Q-Q Plots

par(mfrow = c(1, 3), mar = c(4, 4, 3, 1))

qqghyp(fit.ghd, plot.it = TRUE,
       main = "Q-Q Plot: GHD\nNVDA Year 4",
       ghyp.col = "steelblue", line = TRUE)

qqghyp(fit.hyp, plot.it = TRUE,
       main = "Q-Q Plot: HYP\nNVDA Year 4",
       ghyp.col = "firebrick", line = TRUE)

qqghyp(fit.nig, plot.it = TRUE,
       main = "Q-Q Plot: NIG\nNVDA Year 4",
       ghyp.col = "darkgreen", line = TRUE)

par(mfrow = c(1, 1))
# Part B - Section 4: Likelihood Ratio Test

lrt.ghd.hyp <- lik.ratio.test(fit.ghd, fit.hyp)
lrt.ghd.nig <- lik.ratio.test(fit.ghd, fit.nig)

cat("GHD vs HYP:\n"); print(lrt.ghd.hyp)
## GHD vs HYP:
## $statistic
##         L 
## 0.5657949 
## 
## $p.value
## [1] 0.2858537
## 
## $df
## [1] 1
## 
## $H0
## [1] TRUE
cat("\nGHD vs NIG:\n"); print(lrt.ghd.nig)
## 
## GHD vs NIG:
## $statistic
##         L 
## 0.9555958 
## 
## $p.value
## [1] 0.7631114
## 
## $df
## [1] 1
## 
## $H0
## [1] TRUE
cat("\n=== Log-Likelihoods ===\n")
## 
## === Log-Likelihoods ===
cat("GHD:", round(logLik(fit.ghd), 4), "\n")
## GHD: 577.2492
cat("HYP:", round(logLik(fit.hyp), 4), "\n")
## HYP: 576.6797
cat("NIG:", round(logLik(fit.nig), 4), "\n")
## NIG: 577.2038
cat("\n=== AIC (lower is better) ===\n")
## 
## === AIC (lower is better) ===
cat("GHD:", round(AIC(fit.ghd), 4), "\n")
## GHD: -1144.498
cat("HYP:", round(AIC(fit.hyp), 4), "\n")
## HYP: -1145.359
cat("NIG:", round(AIC(fit.nig), 4), "\n")
## NIG: -1146.408
# Part B - Section 5: VaR Calculation and Plot

var.ghd.95  <- qghyp(0.05, fit.ghd)
var.ghd.99  <- qghyp(0.01, fit.ghd)
var.hyp.95  <- qghyp(0.05, fit.hyp)
var.hyp.99  <- qghyp(0.01, fit.hyp)
var.nig.95  <- qghyp(0.05, fit.nig)
var.nig.99  <- qghyp(0.01, fit.nig)
var.hist.95 <- as.numeric(quantile(nvda.vec, 0.05))
var.hist.99 <- as.numeric(quantile(nvda.vec, 0.01))

cat("=== Value at Risk ===\n")
## === Value at Risk ===
cat(sprintf("%-12s %10s %10s\n", "Model",      "VaR 95%",    "VaR 99%"))
## Model           VaR 95%    VaR 99%
cat(sprintf("%-12s %10.4f %10.4f\n", "GHD",        var.ghd.95,  var.ghd.99))
## GHD             -0.0386    -0.0742
cat(sprintf("%-12s %10.4f %10.4f\n", "HYP",        var.hyp.95,  var.hyp.99))
## HYP             -0.0383    -0.0670
cat(sprintf("%-12s %10.4f %10.4f\n", "NIG",        var.nig.95,  var.nig.99))
## NIG             -0.0383    -0.0752
cat(sprintf("%-12s %10.4f %10.4f\n", "Historical", var.hist.95, var.hist.99))
## Historical      -0.0381    -0.0715
var.data <- matrix(c(abs(var.ghd.95),  abs(var.ghd.99),
                     abs(var.hyp.95),  abs(var.hyp.99),
                     abs(var.nig.95),  abs(var.nig.99),
                     abs(var.hist.95), abs(var.hist.99)),
                   nrow = 2, byrow = FALSE)
colnames(var.data) <- c("GHD", "HYP", "NIG", "Historical")
rownames(var.data) <- c("95%", "99%")

bp <- barplot(var.data, beside = TRUE,
        col     = c("steelblue","firebrick"),
        ylim    = c(0, max(var.data) * 1.4),
        main    = "VaR Comparison by Model\nNVDA Year 4 (April 2017 - March 2018)",
        ylab    = "VaR (Absolute Daily Log Return)",
        xlab    = "Model")

legend("topright",
       legend = c("95% VaR", "99% VaR"),
       fill   = c("steelblue","firebrick"),
       cex    = 0.85)

text(bp, var.data + 0.001,
     labels = round(var.data, 4),
     cex = 0.7, pos = 3)

# Part B - Section 6: ES Calculation and Plot

es.ghd.95  <- ESghyp(0.05, fit.ghd)
es.ghd.99  <- ESghyp(0.01, fit.ghd)
es.hyp.95  <- ESghyp(0.05, fit.hyp)
es.hyp.99  <- ESghyp(0.01, fit.hyp)
es.nig.95  <- ESghyp(0.05, fit.nig)
es.nig.99  <- ESghyp(0.01, fit.nig)
es.hist.95 <- mean(nvda.vec[nvda.vec <= var.hist.95])
es.hist.99 <- mean(nvda.vec[nvda.vec <= var.hist.99])

cat("=== Expected Shortfall ===\n")
## === Expected Shortfall ===
cat(sprintf("%-12s %10s %10s\n", "Model",      "ES 95%",     "ES 99%"))
## Model            ES 95%     ES 99%
cat(sprintf("%-12s %10.4f %10.4f\n", "GHD",        es.ghd.95,  es.ghd.99))
## GHD             -0.0609    -0.0991
cat(sprintf("%-12s %10.4f %10.4f\n", "HYP",        es.hyp.95,  es.hyp.99))
## HYP             -0.0561    -0.0848
cat(sprintf("%-12s %10.4f %10.4f\n", "NIG",        es.nig.95,  es.nig.99))
## NIG             -0.0616    -0.1024
cat(sprintf("%-12s %10.4f %10.4f\n", "Historical", es.hist.95, es.hist.99))
## Historical      -0.0600    -0.0807
es.data <- matrix(c(abs(es.ghd.95),  abs(es.ghd.99),
                    abs(es.hyp.95),  abs(es.hyp.99),
                    abs(es.nig.95),  abs(es.nig.99),
                    abs(es.hist.95), abs(es.hist.99)),
                  nrow = 2, byrow = FALSE)
colnames(es.data) <- c("GHD", "HYP", "NIG", "Historical")
rownames(es.data) <- c("95%", "99%")

bp2 <- barplot(es.data, beside = TRUE,
        col     = c("steelblue","firebrick"),
        ylim    = c(0, max(es.data) * 1.4),
        main    = "Expected Shortfall (ES) Comparison by Model\nNVDA Year 4 (April 2017 - March 2018)",
        ylab    = "ES (Absolute Daily Log Return)",
        xlab    = "Model")

legend("topright",
       legend = c("95% ES", "99% ES"),
       fill   = c("steelblue","firebrick"),
       cex    = 0.85)

text(bp2, es.data + 0.001,
     labels = round(es.data, 4),
     cex = 0.7, pos = 3)