I am trying to download stock prices from yahoo of several shares at once using R loops. I tried the following code, and it produces results but I would like the results to be presented in column per share.
options(digits=4, width=70)
library("PerformanceAnalytics")
library("tseries")
library("zoo")
ticker<-c('AAPL','MSFT','AMZN','TSLA','GOOGL','GOOG','BRK-B','NVDA','UNH','FB')
n <- length(ticker)
cours_bours<- function(){
for (i in 1:n){
prices <- get.hist.quote(instrument=ticker[i], start="2009-12-01",
end="2020-02-01", quote="AdjClose",
provider="yahoo", origin="2000-09-01",
compression="m", ret)
dimnames(prices)[[2]] <- as.character(ticker[i])
index(prices) <- as.yearmon(index(prices))
print(prices)
}
}
cours_bours()
What I get as a result is a column with all time series of the 3 shares. I would like to have them all in 3 columns as:
Date AAPL MSFT GOOG ....
2015-xx-xx xx.xx xx.xx xx.xx ....
CodePudding user response:
First let's redefine your function and avoid the for
-loop:
func_cb <- function(ticker) {
my_list <- lapply(ticker,
function(i)
tseries::get.hist.quote(
instrument = i,
start = "2009-12-01",
end = "2020-02-01",
quote = "AdjClose",
provider = "yahoo",
origin = "2000-09-01",
compression = "m",
retclass = "zoo"
)
)
names(my_list) <- ticker
return(my_list)
}
Now this function takes a ticker
vector as input and returns a list.
ticker <- c('AAPL','MSFT','AMZN','TSLA','GOOGL','GOOG','BRK-B','NVDA','UNH','FB')
my_ts_list <- func_cb(ticker)
Next we use tidyverse
to reshape the list into your expected output:
library(tidyverse)
my_ts_list %>%
map_dfr(~.x %>%
as.data.frame() %>%
rownames_to_column(var = "date"),
.id = "name") %>%
pivot_wider(names_from = "name", values_from = "Adjusted")
This returns
# A tibble: 122 x 11
date AAPL MSFT AMZN TSLA GOOGL GOOG `BRK-B` NVDA UNH FB
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2009-12-01 6.44 23.5 135. NA 310. 309. 65.7 4.29 25.4 NA
2 2010-01-01 5.87 21.7 125. NA 265. 264. 76.4 3.53 27.5 NA
3 2010-02-01 6.26 22.1 118. NA 264. 262. 80.1 3.72 28.2 NA
4 2010-03-01 7.19 22.7 136. NA 284. 283. 81.3 4.00 27.2 NA
5 2010-04-01 7.98 23.6 137. NA 263. 262. 77 3.61 25.2 NA
6 2010-05-01 7.86 20.0 125. NA 243. 242. 70.6 3.02 24.2 NA
7 2010-06-01 7.69 17.9 109. NA 223. 222. 79.7 2.34 23.7 NA
8 2010-07-01 7.87 20.1 118. 3.99 243. 242. 78.1 2.11 25.5 NA
9 2010-08-01 7.43 18.3 125. 3.90 225. 224. 78.8 2.14 26.5 NA
10 2010-09-01 8.68 19.2 157. 4.08 263. 262. 82.7 2.68 29.4 NA
# ... with 112 more rows
CodePudding user response:
Use Map to create the list L of zoo objects and then use merge.zoo to merge them into a single zoo object. Finally convert the index to yearmon giving the z.ym zoo object. Optionally use fortify.zoo(z.ym) if you need a data frame.
library(tseries)
library(zoo)
ticker<-c('AAPL','MSFT','AMZN')
L <- Map(get.hist.quote, ticker, start="2009-12-01", end="2020-02-01",
quote="AdjClose", provider="yahoo", origin="2000-09-01", compression="m",
ret)
z <- setNames(do.call("merge", L), ticker)
z.ym <- aggregate(z, as.yearmon, c)
head(z.ym)
## AAPL MSFT AMZN
## Dec 2009 6.444381 23.49339 134.52
## Jan 2010 5.873429 21.72060 125.41
## Feb 2010 6.257530 22.09828 118.40
## Mar 2010 7.186586 22.68174 135.77
## Apr 2010 7.984454 23.64972 137.10
## May 2010 7.855704 19.97913 125.46
Alternately express this as a pipeline:
clean_names <- function(x) setNames(x, sub("Adjusted.", "", names(x)))
out <- ticker |>
Map(f = get.hist.quote, start="2009-12-01", end="2020-02-01", quote="AdjClose",
provider="yahoo", origin="2000-09-01", compression="m", ret) |>
do.call(what = "merge") |>
clean_names() |>
aggregate(as.yearmon, c)