I'm trying to import stock data (split), and I have a problem. There is no issue if all symbols contain split. When one of them does not have split, however, the matrix are shaped in different way and wrong.
Here are codes that I use:
library(quantmod)
Tick <- c("AA","ARGO")
split_test <- Reduce(merge, lapply(Tick, function(x) {
tryCatch({
getSplits(x, from= "2016-01-04", to="2017-03-09", src="yahoo")
}, error = function(e) {}
)
}))
and the outcome is fine:
AA.spl ARGO.spl
2016-05-27 N/A 0.9091
2016-10-06 3.000 N/A
2016-11-01 0.801 N/A
The problem is that if Tick includes "A" which does not have split , the outcome is quite different and wrong:
Tick <- c("A","AA","ARGO")
x AA.spl ARGO.spl
1 N/A 3.000 0.9091
2 N/A 0.801 0.9091
Dates are not shown up anymore, and the value is also wrong(same number repeats). How do I get outcome like first one even though a stock has no split? If it is possible I want "A" is just shown up as N/As like:
A.spl AA.spl ARGO.spl
2016-05-27 N/A N/A 0.9091
2016-10-06 N/A 3.000 N/A
2016-11-01 N/A 0.801 N/A
Tick <- c("A","AA","AADR","AAN","AAP","AAT")
Test <-
lapply(Tick,
function(x) {
try(getDividends(x, from= "2016-01-04", to="2016-03-15", src="yahoo"),
silent = TRUE)
})
names(Test) <- Tick
# convert NA to xts object with date < 1900
Test <-
lapply(Test,
function(x) {
if (identical(x, NA)) xts(NA, .Date(-4e4)) else x
})
# merge and remove pre-1900 date
Test <- Reduce(merge, Test)["1900/"]
getSplits()
just returns NA
for "A", not an xts object. And "A" is first in your Tick
vector, so the merge()
method for xts objects isn't being called (because of how S3 method dispatch works).
You could use cbind()
instead of merge()
because method dispatch for cbind()
works different. But I wouldn't suggest that solution, because you're not likely to remember that subtle difference between the two functions.
Instead, I would pre-process your list of splits before merging.
split_test <-
lapply(Tick,
function(x) {
try(getSplits(x, from= "2016-01-04", to="2017-03-09", src="yahoo"),
silent = TRUE)
})
names(split_test) <- Tick
# convert NA to xts object with date < 1900
split_test <-
lapply(split_test,
function(x) {
if (identical(x, NA)) xts(NA, .Date(-4e4)) else x
})
# merge and remove pre-1900 date
split_test <- Reduce(merge, split_test)["1900/"]
# set names
names(split_test) <- Tick
split_test
## AA A ARGO
## 2016-05-27 NA NA 0.9090909
## 2016-10-06 3.000 NA NA
## 2016-11-01 0.801 NA NA
The code checks for list elements that are only NA
, and replaces the NA
with an xts object that has a date index before 1900. That date will be easy to identify in the output.
Then we merge all the list elements together using Reduce()
, like you did. And we set the names to your Tick
vector, so the column that didn't have any data has the correct ticker name.
Update for getDividends()
, since it returns a zero-width xts object when there are no dividends, not NA like getSplits()
does. We can add another check to the function that adjusts the xts objects with NA.
Let's move this to a function, since you need it in more than one place. We can add another condition to the if
statement.
fill_missing <-
function(x)
{
y <- x
if (identical(x, NA) || length(x) < 1) {
y <- xts(NA, .Date(-4e4))
}
y
}
Now use this function in your lapply()
call and do the same Reduce()
call. Then you can set names again, if you need to.
Test <- lapply(Test, fill_missing)
out <- Reduce(merge, Test)["1900/"]
out <- out[,Tick]