Historical stock data - r

I want to get the closing prices for all S&P 500 stocks for specific dates.
I've trawled SO for answers and they fall into the following:
Download specific stocks for S&P with start and end dates - returns more than closing price which would require a line to concatenate all stocks and slows it right down
Download all stocks for S&P with start and end dates - always gets "Error in download"
For instance:
library(BatchGetSymbols)
first.date <- Sys.Date() - 160
last.date <- Sys.Date() - 1
all_stocks <- GetSP500Stocks()
tickers <- all_stocks$tickers
show <- BatchGetSymbols(tickers = tickers,
first.date = first.date,
last.date = last.date)
This always returns:
"Adobe Systems Inc | yahoo (7|505) | Not Cached
- Error in download..
and so on.
I merely want three columns - ticker, first.date and last.date
Appreciate any help!

Use tickers as all_stocks$company instead of all_stocks$tickers
library(BatchGetSymbols)
tickers <- all_stocks$company
show <- BatchGetSymbols(tickers = tickers,
first.date = first.date,last.date = last.date)
It seems unconventional to me though that column with ticker information is given column name as company and column with company names is given name as tickers.

You can find constituents of the S&P 500 here.
https://en.wikipedia.org/wiki/List_of_S%26P_500_companies
library(quantmod)
e <- new.env()
getSymbols("MMM;ABT;ABBV;ABMD;ACN;
ATVI;ADBE;AMD;AAP;AES;AMG;AFL;A;APD;
AKAM;ALK;ALB;ARE;ALXN;ALGN;ALLE;AGN;ADS;
LNT;ALL;GOOGL", env = e)
pframe <- do.call(merge, as.list(e))
head(pframe)
Try this too.
library(quantmod)
Nasdaq100_Symbols <- c('GE','PG','MSFT','AAPL','PFE','AMD','DELL')
# put all stocks in one list object
stocks <- lapply(Nasdaq100_Symbols, getSymbols, auto.assign = FALSE)
# following is not needed but if you want to use the list for other purposes
# it is a good practice to name all the different list objects.
# names(stocks) <- Nasdaq100_Symbols
# merge all stocks into 1 xts object
nasdaq100 <- Reduce(merge, stocks)
# fill NA's with 0
nasdaq100 <- na.fill(nasdaq100, 0)
outcomeSymbol <- "GE.Volume" # <-- used GE as that data is available in the downloaded data set
# merge outcome to data
nasdaq100 <- merge(nasdaq100, lm1 = lag(nasdaq[, outcomeSymbol], -1))
# turn into data.frame
nasdaq100_df <- data.frame(date = index(nasdaq100), coredata(nasdaq100))
Finally, try this to get the tickers.
library(rvest)
url <- "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies"
SP500 <- url %>%
html() %>%
html_nodes(xpath='//*[#id="mw-content-text"]/div/table[1]') %>%
html_table()
SP500 <- SP500[[1]]
SP500
As an alternative, see the links below for more ideas of how to do this.
https://www.r-bloggers.com/downloading-sp-500-stock-data-from-googlequandl-with-r-command-line-script/
https://www.business-science.io/investments/2016/10/23/SP500_Analysis.html
https://www.business-science.io/investments/2016/11/30/Russell2000_Analysis.html

Related

How to extract only closing prices with Quantmod

I am new to quantmod
I am using quantmod to extract stock prices, however, I want to restrict my extraction only to closing prices. I am wondering if there is a way to do it instead of downloading all default columns.
This is the code I am using
tickers <- c("1COV.DE","ADS.DE","ALV.DE","BAS.DE")
from <- "2014-10-01"
to = "2021-07-29"
getSymbols(tickers,
src = "yahoo",
from = from,
to = to,
adjust = TRUE,
periodicity = "daily")
You can do it with this pattern:
tickers <- c("1COV.DE", "ADS.DE", "ALV.DE", "BAS.DE")
# Store all data in a new environment
e <- new.env()
getSymbols(tickers, from = "2014-10-01", adjust = TRUE, env = e)
# Combine close prices
prices <- do.call(merge, lapply(e, Cl))
# remove leading "X" created by make.names()
colnames(prices) <- gsub("^X", "", colnames(prices))
# remove ".Close" suffix
colnames(prices) <- gsub(".Close", "", colnames(prices), fixed = TRUE)
# reorder columns to match 'tickers'
prices <- prices[, tickers]
One way is to use tidyquant library and put all four stocks in one data frame. Then you can group by the symbol. In that way, you don't have problems with different lengths of symbols.
library(tidyquant)
tickers <- c("1COV.DE","ADS.DE","ALV.DE","BAS.DE")
from <- "2014-10-01"
to = "2021-07-29"
closed <- tq_get(tickers,
from = from,
to = to) %>%
select(symbol, date, close) %>%
arrange(date)

Downloading Yahoo stock prices in R - date setting

I am downloading data on stocks from yahoo finance with tseries package. The issue is that I am not getting the most recent date - last price is always for 2 days ago.
Below is my code, can you please advise what I should correct to get all the available prices?
Thank you!
`dir <- "D:/Yahoo stock prices" #location
setwd(dir)
# Packages needed
require(tseries)
require(zoo)
YH <- read.csv2(file="SBI.csv",header=T, sep=";", dec=".")
date <- "2012-09-20"
penny_stocks <- c("SMDS.L", "MNDI.L", "SKG.L")
prices <- NULL
for(i in 1:length(YH[,1])){
prices <- try(get.hist.quote(as.character(YH[i,1]),
start=date,
quote='Open'
)
,silent=TRUE
)
if(!is.character(prices)){
if(as.character(YH[i,1]) %in% penny_stocks) prices <- prices / 100
prices <- as.data.frame(prices)
prices <- cbind(rownames(prices),prices)
colnames(prices) <- c("date",as.character(YH[i,1]))
if(length(prices) > 1){
if(i == 1){
allprices <- prices
names <- c("date",as.character(YH[i,1]))
} else {
names <- append(colnames(allprices),as.character(YH[i,1]))
allprices <- merge(allprices,prices,by ="date", all.x = TRUE)
colnames(allprices) <- names
}
}
}
}
write.csv2(allprices,"Prices 200511.csv")
warnings()
`
At the moment of writing, the data available on the yahoo site is until the 2020-05-12. You need to specify the end date as by default in tseries, the end is defined as Sys.Date() - 1. So using tseries::get.hist.quote("SMDS.L", end = Sys.Date(), quote = "Open") will return the data until 2020-05-12. Now you would expect that the default would be good enough, but there are a lot of issues with the yahoo data and getting the correct last records if the data is not located in the US. There probably is a process in place that loads the data a day after closing.
Note that the default settings of tseries::get.hist.quote are slightly different than the defaults of underlying function call to quantmod::getSymbols. tseries uses the default Sys.Date() - 1, quantmod uses Sys.Date(). Also the start dates are different. tseries uses "1991-01-02" as the start date, quantmod uses "2007-01-01".

Trying to match stock tickers to adjusted.price

I have the script below which pulls in historical stock prices just fine, but I can't seem to get a list of tickers, by date, with adjusted prices. I'm getting 25 stocks, and headers that look like this: $df.tickers, price.open, price.high, price.low, price.close, volume price.adjusted
One thing that I can't figure out is that when I type 'out' I get the data set, but when I type dim(out) I get a null. That's doesn't make any sense. Anyway, I'm trying to run the code from the link below.
http://programmingforfinance.com/2017/10/portfolio-optimization-with-r/
Here is the code that I'm working with.
library(BatchGetSymbols)
library(sqldf)
library(dplyr)
# set dates
first.date <- Sys.Date() - 360
last.date <- Sys.Date()
# set tickers
tickers <- c('MMM','ABT','ABBV','ABMD',
'ACN','ATVI','AYI','ADBE','AMD','AAP',
'AES','AET','AMG','AFL','A','APD','AKAM',
'ALK','ALB','ARE','ALXN','ALGN','ALLE','AGN','ADS')
out <- BatchGetSymbols(tickers = tickers,
first.date = first.date,
last.date = last.date,
cache.folder = file.path(tempdir(),
'BGS_Cache') ) # cache in tempdir()
# dim(out$df.tickers)
# 6175 10
# After downloading the data, we can check the success of the process for each ticker.
# Notice that the last ticker does not exist in yahoo finance or google and therefore
# results in an error. All information regarding the download process is provided in the dataframe df.control:
# print(out$df.control)
price_adjusted <- as.data.frame(out)
price_final <- subset(price_adjusted, select = c(df.control.ticker, df.tickers.price.adjusted, df.tickers.ref.date))
# df_final <- subset(price_final, df.control.ticker == 'MMM', select = c("df.control.ticker","df.tickers.price.adjusted","df.tickers.ref.date"))
I believe the Google API was turned off last year, and as such, you can't get historical stock prices from Google anymore. Any thoughts on how to make this work? Thanks!
The tutorial is using data in the 'xts' time series format. To convert your data as such,
library(BatchGetSymbols)
library(tidyr)
library(quantmod)
# set dates
first.date <- Sys.Date() - 360
last.date <- Sys.Date()
# set tickers
tickers <- c('MMM','ABT','ABBV','ABMD',
'ACN','ATVI','AYI','ADBE','AMD','AAP',
'AES','AET','AMG','AFL','A','APD','AKAM',
'ALK','ALB','ARE','ALXN','ALGN','ALLE','AGN','ADS')
out <- BatchGetSymbols(tickers = tickers,
first.date = first.date,
last.date = last.date,
cache.folder = file.path(tempdir(),
'BGS_Cache') )
out<-out$df.tickers
out<-out[,c("ref.date","ticker", "price.adjusted")]
q <- spread(out, ticker, price.adjusted)
portfolioPrices <- xts(q[,-1], order.by=q[,1])

in quantmod: how to get all stocks that meet specific criteria

I would like to retrieve stocks OHLC data based on a specific criterion, for example only s&p 500 that are above their own MA5. Is there a way to do it using quantmod? For example, can I enter an if function in the getSymbols function?
Attached is the code that I use without the criterion:
require(quantmod)
options(scipen=999)
spy <- getSymbols(c('SPY', 'IBM') , src = 'yahoo', from = '2007-01-01', auto.assign = T)
tail(cbind(SPY, IBM))
I don't think that this is possible. You have to get all symbols, compute the indicators of interest and then filter for the ones meeting your conditions.
Here is a way to retrieve all S&P500 symbols (takes approx 10 minutes because there is a pause of 1 second between the requests) and compute the 200-day sma for each of them.
library(rvest)
library(quantmod)
library(TTR)
tbl <- read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies') %>% html_nodes(css = 'table')
tbl <- tbl[1] %>% html_table() %>% as.data.frame()
tbl$Ticker.symbol <- gsub(pattern = '\\.', '-', tbl$Ticker.symbol) # BRK.B -> BRK-B (yahoo uses '-')
head(tbl$Ticker.symbol)
[1] "MMM" "ABT" "ABBV" "ACN" "ATVI" "AYI"
quotes <- new.env()
getSymbols(tbl$Ticker.symbol, src = 'yahoo', from = '2007-01-01', env = quotes)
sma_200 <- lapply(quotes, function(x) {
SMA(x[, 4], n = 200)
})

Downloading Yahoo stock prices in R

This is a newbie question in R. I am downloading yahoo finance monthly stock price data using R where the ticker names are read from a text file. I am using a loop to read the ticker names to download the data and putting them in a list. My problem is some ticker names may not be correct thus my code stops when it encounters this case. I want the following.
skip the ticker name if it is not correct.
Each element in the list is a dataframe. I want the ticker names to be appended to variable names in element dataframes.
I need an efficient way to create a dataframe that has the closing prices as variables.
Here is the sample code for the simplified version of my problem.
library(tseries)
tckk <- c("MSFT", "C", "VIA/B", "MMM") # ticker names defined
numtk <- length(tckk);
ustart <- "2000-12-30";
uend <- "2007-12-30" # start and end date
all_dat <- list(); # empty list to fill in the data
for(i in 1:numtk)
{
all_dat[[i]] <- xxx <- get.hist.quote(instrument = tckk[i], start=ustart, end=uend, quote = c("Open", "High", "Low", "Close"), provider = "yahoo", compression = "m")
}
The code stops at the third entry but I want to skip this ticker and move on to "MMM". I have heard about Trycatch() function but do not know how to use it.
As per question 2, I want the variable names for the first element of the list to be "MSFTopen", "MSFThigh", "MSFTlow", and "MSFTclose". Is there a better to way to do it apart from using a combination of loop and paste() function.
Finally, for question 3, I need a dataframe with three columns corresponding to closing prices. Again, I am trying to avoid a loop here.
Thank you.
Your best bet is to use quantmod and store the results as a time series (in this case, it will be xts):
library(quantmod)
library(plyr)
symbols <- c("MSFT","C","VIA/B","MMM")
#1
l_ply(symbols, function(sym) try(getSymbols(sym)))
symbols <- symbols[symbols %in% ls()]
#2
sym.list <- llply(symbols, get)
#3
data <- xts()
for(i in seq_along(symbols)) {
symbol <- symbols[i]
data <- merge(data, get(symbol)[,paste(symbol, "Close", sep=".")])
}
This also a little late...If you want to grab data with just R's base functions without dealing with any add-on packages, just use the function read.csv(URL), where the URL is a string pointing to the right place at Yahoo. The data will be pulled in as a dataframe, and you will need to convert the 'Date' from a string to a Date type in order for any plots to look nice. Simple code snippet is below.
URL <- "http://ichart.finance.yahoo.com/table.csv?s=SPY"
dat <- read.csv(URL)
dat$Date <- as.Date(dat$Date, "%Y-%m-%d")
Using R's base functions may give you more control over the data manipulation.
I'm a little late to the party, but I think this will be very helpful to other late comers.
The stockSymbols function in TTR fetches instrument symbols from nasdaq.com, and adjusts the symbols to be compatible with Yahoo! Finance. It currently returns ~6,500 symbols for AMEX, NYSE, and NASDAQ. You could also take a look at the code in stockSymbols that adjusts tickers to be compatible with Yahoo! Finance to possibly adjust some of the tickers in your file.
NOTE: stockSymbols in the version of TTR on CRAN is broken due to a change on nasdaq.com, but it is fixed in the R-forge version of TTR.
I do it like this, because I need to have the historic pricelist and a daily update file in order to run other packages:
library(fImport)
fecha1<-"03/01/2009"
fecha2<-"02/02/2010"
Sys.time()
y <- format(Sys.time(), "%y")
m <- format(Sys.time(), "%m")
d <- format(Sys.time(), "%d")
fecha3 <- paste(c(m,"/",d,"/","20",y), collapse="")
write.table(yahooSeries("GCI", from=fecha1, to=fecha2), file = "GCI.txt", sep="\t", quote = FALSE, eol="\r\n", row.names = TRUE)
write.table(yahooSeries("GCI", from=fecha2, to=fecha3), file = "GCIupdate.txt", sep="\t", quote = FALSE, eol="\r\n", row.names = TRUE)
GCI <- read.table("GCI.txt")
GCI1 <- read.table("GCIupdate.txt")
GCI <- rbind(GCI1, GCI)
GCI <- unique(GCI)
write.table(GCI, file = "GCI.txt", sep="\t", quote = FALSE, eol="\r\n", row.names = TRUE)
If your ultimate goal is to get the data.frame of three columns of closing prices, then the new package tidyquant may be better suited for this.
library(tidyquant)
symbols <- c("MSFT", "C", "VIA/B", "MMM")
# Download data in tidy format.
# Will remove VIA/B and warn you.
data <- tq_get(symbols)
# Ticker symbols as column names for closing prices
data %>%
select(.symbol, date, close) %>%
spread(key = .symbol, value = close)
This will scale to any number of stocks, so the file of 1000 tickers should work just fine!
Slightly modified from the above solutions... (thanks Shane and Stotastic)
symbols <- c("MSFT", "C", "MMM")
# 1. retrieve data
for(i in seq_along(symbols)) {
URL <- paste0("http://ichart.finance.yahoo.com/table.csv?s=", symbols[i])
dat <- read.csv(URL)
dat$Date <- as.Date(dat$Date, "%Y-%m-%d")
assign(paste0(symbols[i]," _data"), dat)
dat <- NULL
}
Unfortunately, URL "ichart.finance.yahoo.com" is dead and not working now. As I know, Yahoo closed it and it seems it will not be opened.
Several days ago I found nice alternative (https://eodhistoricaldata.com/) with an API very similar to Yahoo Finance.
Basically, for R-script described above you just need to change this part:
URL <- paste0("ichart.finance.yahoo.com/table.csv?s=", symbols[i])
to this:
URL <- paste0("eodhistoricaldata.com/api/table.csv?s=", symbols[i])
Then add an API key and it will work in the same way as before. I saved a lot of time for my R-scripts on it.
Maybe give the BatchGetSymbols library a try. What I like about it over quantmod is that you can specify a time period for your data.
library(BatchGetSymbols)
# set dates
first.date <- Sys.Date() - 60
last.date <- Sys.Date()
freq.data <- 'daily'
# set tickers
tickers <- c('FB','MMM','PETR4.SA','abcdef')
l.out <- BatchGetSymbols(tickers = tickers,
first.date = first.date,
last.date = last.date,
freq.data = freq.data,
cache.folder = file.path(tempdir(),
'BGS_Cache') ) # cache in tempdir()

Resources