I have an R portfolio construction code that uses daily adjusted close price data from yahoo. I've had some problems with NA values, but the code has been working for some time. Until this weekend (e.g., Feb 28, 2015).
Right now the yahoo data source seems to be completely broken when I use the tseries function get.hist.quote(). By broken I mean that it will not correctly return data for VTV and a number of other ETFs. I don't know if the Yahoo time series source is down or what.
There was a post (https://stackoverflow.com/a/3507948/2341077) which suggested that changing the URL in get.hist.quote() from chart.yahoo.com to ichart.yahoo.com would fix the problem. But this didn't change anything for me. I also made sure that I have the latest version of tseries installed.
Has anyone else been having problems with the close price time series from Yahoo? I've been wondering if I should change my code to use the quantmod function getSymbols, which, apparently, can use Google finance as a data source.
The code below is written to read hundreds of ETF symbols and return a matrix containing the ETF time series data. An attempt is made to align the data by date.
Even when Yahoo seemed to be providing data, there were still missing values, which is what the fillHoles() function is meant to address.
<pre>
#
# Fill "NA" holes in the time series.
#
fillHoles = function(ts.zoo) {
v_approx = na.approx(ts.zoo, maxgap=4, na.rm=FALSE)
v_fill = na.fill(v_approx, fill="extend")
return( v_fill)
}
<i>
#
# The yahoo market data has problems (at least when it's fetched with get.hist.quote()) when the compression
# argument is used to fetch weekly adjusted close data.
#
# Two time series are shown below, for VXF and MINT. The weekly boundaries appear on different dates.
#
# VXF
# 2007-04-04 48.55
# 2007-04-09 48.98
# 2007-04-16 49.52 <==
# 2007-04-23 49.70
# 2007-04-30 50.03
# 2007-05-07 50.04 <==
#
# MINT
# 2007-04-04 8.03
# 2007-04-09 8.03
# 2007-04-17 7.88 <==
# 2007-04-23 8.11
# 2007-04-30 8.92
# 2007-05-08 9.14 <==
#
# If the two time series are merged via a cbind NA values
# end up being inserted where the time series don't line up:'
#
# VXF MINT
# 2007-04-04 48.55 8.03
# 2007-04-09 48.98 8.03
# 2007-04-16 49.52 NA
# 2007-04-23 49.70 8.11
# 2007-04-30 50.03 8.92
# 2007-05-07 50.04 NA
#
# To avoid this problem of data alignment, the function fetches daily adjusted close that can then be converted
# into weekly adjusted close.
#
# Given a vector of symbols, this function will fetch the daily adjusted close price data from
# Yahoo. The data is aligned since not all time series will have exactly the same start and end
# dates (although with daily data, as noted above, this should be less of an issue)
#
</i>
getDailyCloseData = function(symbols, startDate, endDate )
{
closeData.z = c()
firstTime = TRUE
minDate = c()
maxDate = c()
fetchedSyms = c()
startDate.ch = as.character( findMarketDate(as.Date(startDate)))
endDate.ch = as.character( findMarketDate(as.Date(endDate)))
for (i in 1:length(symbols)) {
sym = symbols[i]
print(sym)
symClose.z = NULL
timeOut = 1
tsEndDate.ch = endDate.ch
while ((timeOut < 7) && is.null(symClose.z)) {
try(
(symClose.z = get.hist.quote(instrument=sym, start=startDate.ch, end=tsEndDate.ch, quote="AdjClose",
provider="yahoo", compression="d", retclass="zoo", quiet=T)),
silent = TRUE)
tsEndDate.ch = as.character( findMarketDate( (as.Date(tsEndDate.ch) - 1)))
timeOut = timeOut + 1
}
if (! is.null(symClose.z)) {
fetchedSyms = c(fetchedSyms, sym)
dateIx = index(symClose.z)
if (firstTime) {
closeData.z = symClose.z
firstTime = FALSE
minDate = min(dateIx)
maxDate = max(dateIx)
} else {
minDate = max(minDate, min(dateIx))
maxDate = min(maxDate, max(dateIx))
matIx = index(closeData.z)
repeat {
startIx = which(matIx == minDate)
if (length(startIx) > 0 && startIx > 0) {
break()
} else {
minDate = minDate + 1
}
} # repeat
repeat {
endIx = which(matIx == maxDate)
if (length(endIx) > 0 && endIx > 0) {
break()
} else {
maxDate = maxDate - 1
}
}
matIxAdj = matIx[startIx:endIx]
closeData.z = cbind(closeData.z[matIxAdj,], symClose.z[matIxAdj])
}
} # if (! is.null(symClose.z))
} # for
if (length(closeData.z) > 0) {
dateIx = index(closeData.z)
# fill any NA "holes" created by daily date alignment
closeData.mat = apply(closeData.z, 2, FUN=fillHoles)
rownames(closeData.mat) = as.character(dateIx)
colnames(closeData.mat) = fetchedSyms
}
return( closeData.mat )
} # getDailyCloseData
</pre>