Using their daily close prices, I want to model the dependency among five major indices, the SP500, SSEC, HSI, TASI, and DAX. I need to align the three-time series with the common trading days among them and omit other days.
Here is my attempt which always results in an error:
library(quantmod)
# Fetch daily close prices
sp500 <- getSymbols("^GSPC", src = "yahoo", auto.assign = FALSE, from = "2017-10-09", to = "2022-09-29")
ssec <- getSymbols("000001.SS", src = "yahoo", auto.assign = FALSE, from = "2017-10-09", to = "2022-09-29")
hsi <- getSymbols("^HSI", src = "yahoo", auto.assign = FALSE, from = "2017-10-09", to = "2022-09-29")
tasi <- getSymbols("^TASI.SR", src = "yahoo", auto.assign = FALSE, from = "2017-10-09", to = "2022-09-29")
dax <- getSymbols("^GDAXI", src = "yahoo", auto.assign = FALSE, from = "2017-10-09", to = "2022-09-29")
# Align the data
all_dates <- Reduce(intersect, list(index(sp500), index(ssec), index(hsi), index(tasi), index(dax)))
sp500_aligned <- Cl(sp500)[all_dates]
ssec_aligned <- Cl(ssec)[all_dates]
hsi_aligned <- Cl(hsi)[all_dates]
Error
sp500_aligned <- Cl(sp500)[all_dates]
Error in[.xts
(Cl(sp500), all_dates) : subscript out of bounds
The problem with the code in the question is that intersect
strips the class from the dates. Although that is readily fixed we suggest a different approach based on merge.xts
which supports multiway merges.
1) Put the symbols' data in environment e
and then use eapply
to get a list of ticker data closes (or use Ad
to get adjusted closes).
Define and invoke mergeList
which takes a list of one column xts objects, merges them and sets the names of the output to the original list names. Finally remove any rows that have one or more NA's using na.omit
.
library(quantmod)
tickers <- c("^GSPC", "000001.SS", "^HSI", "^TASI.SR", "^GDAXI")
getSymbols(tickers, env = e <- new.env(),
from = "2017-10-09", to = "2022-09-29")
mergeList <- \(x) do.call("merge", x) |> setNames(names(x))
alldata <- e |>
eapply(Cl) |>
mergeList() |>
na.omit()
# rm(e) # optional
2) A variation of the above places the data in the global environment and then retrieves them. This has the advantage of being a single pipeline but does leave a bunch of loose objects hanging around in the global environment which is not as neat as keeping them all in a separate environment as in (1) although they could be deleted if unwanted as shown in the optional line below.
alldata <- tickers |>
getSymbols(from = "2017-10-09", to = "2022-09-29") |>
mget(envir = .GlobalEnv) |>
Map(f = Cl) |>
mergeList() |>
na.omit()
# rm(list = names(alldata), envir = .GlobalEnv) # optional
Simplified and fixed. Add (2).