Search code examples
rdplyrsubsetquantmod

Applying function to a subset of xts quantmod


I'm trying to get the standard deviation of a stock price by year, but I'm getting the same value for every year.

I tried with dplyr (group_by, summarise) and also with a function, but had no luck in any of them, both return the same value of 67.0.

It is probably passing the whole dataframe without subsetting it, how can this issue be fixed?

library(quantmod)
library(tidyr)
library(dplyr)

#initial parameters
initialDate = as.Date('2010-01-01')
finalDate = Sys.Date()

ybeg = format(initialDate,"%Y")
yend = format(finalDate,"%Y")

ticker = "AAPL"

#getting stock prices
stock = getSymbols.yahoo(ticker, from=initialDate, auto.assign = FALSE)
stock = stock[,4] #working only with closing prices

With dplyr:

#Attempt 1 with dplyr - not working, all values by year return the same

stock = stock %>% zoo::fortify.zoo()
stock$Date = stock$Index
separate(stock, Date, c("year","month","day"), sep="-") %>% 
   group_by(year) %>%
   summarise(stdev= sd(stock[,2]))

# A tibble: 11 x 2
#   year  stdev
#   <chr> <dbl>
# 1 2010   67.0
# 2 2011   67.0
#....
#10 2019   67.0
#11 2020   67.0

And with function:

#Attempt 2 with function - not working - returns only one value instead of multiple

#getting stock prices
stock = getSymbols.yahoo(ticker, from=initialDate, auto.assign = FALSE)
stock = stock[,4] #working only with closing prices

#subsetting
years = as.character(seq(ybeg,yend,by=1))
years

calculate_stdev = function(series,years) {
  series[years] #subsetting by years, to be equivalent as stock["2010"], stock["2011"] e.g.
  sd(series[years][,1]) #calculate stdev on closing prices of the current subset
}

yearly.stdev = calculate_stdev(stock,years)

> yearly.stdev
[1] 67.04185

Solution

  • Use apply.yearly() (a convenience wrapper around the more general period.apply()) to call a function on yearly subsets of the xts object returned by getSymbols().

    You can use the Cl() function to extract the close column from objects returned by getSymbols().

    stock = getSymbols("AAPL", from = "2010-01-01", auto.assign = FALSE)
    apply.yearly(Cl(stock), sd)
    ##            AAPL.Close
    ## 2010-12-31   5.365208
    ## 2011-12-30   3.703407
    ## 2012-12-31   9.568127
    ## 2013-12-31   6.412542
    ## 2014-12-31  13.371293
    ## 2015-12-31   7.683550
    ## 2016-12-30   7.640743
    ## 2017-12-29  14.621191
    ## 2018-12-31  20.593861
    ## 2019-12-31  34.538978
    ## 2020-06-19  29.577157