Search code examples
rxtstibble

R tibble dataframe slice and rollapply function


I am writing a script to calculate the standard deviation of S&P500 and want to compare the rolling standard deviation to the long term average of the SD.

I can make my codes work but seems kind of clumsy. I want to ask two questions to make my code easier to understand.

  1. Suppose I have two indices. Can I use one line of code to find the annualised SD for both tickers? Now I have to do it ticker by ticker
GSPC.new <- merge(GSPC.new,rollapply(GSPC.new$GSPC.adj.ret, 252, sd)) 
  1. It is easier to slice a xts object. Can I do the same in tibble dataframe?
gspc.avg10yr <- mean(na.omit(GSPC.new$GSPC.adj.std.annualised["2011/2022"]))

All code below can be executed directly in RStudio directly.

library(tidyverse)
library(quantmod)
library(ggplot2)

tickers <- c("^HSI","^GSPC")
getSymbols(Symbols = tickers,
           src = "yahoo",
           index.class = "POSIXct",
           from = "1997-01-01")

GSPC.new <- na.omit(GSPC)
GSPC.new <- merge(GSPC.new, dailyReturn(GSPC.new$GSPC.Adjusted))
colnames(GSPC.new)[7] <- "GSPC.adj.ret"
GSPC.new <- merge(GSPC.new,rollapply(GSPC.new$GSPC.adj.ret, 252, sd)) # how to annualised both tickers in one line
colnames(GSPC.new)[8] <- "GSPC.adj.std"
GSPC.new <- merge(GSPC.new, GSPC.new$GSPC.adj.std*sqrt(252))
colnames(GSPC.new)[9] <- "GSPC.adj.std.annualised"
GSPC.new.tbl <- as_tibble(fortify(GSPC.new))
p.gspc <- ggplot(GSPC.new.tbl, aes(x=Index,y=GSPC.adj.std.annualised))
p.gspc + geom_line()
gspc.avg10yr <- mean(na.omit(GSPC.new$GSPC.adj.std.annualised["2011/2022"])) # is it possible to do in tibble way?
gspc.avg15yr <- mean(na.omit(GSPC.new$GSPC.adj.std.annualised["2006/2022"]))
gspc.avg20yr <- mean(na.omit(GSPC.new$GSPC.adj.std.annualised["2001/2022"]))
gspc.avg25yr <- mean(na.omit(GSPC.new$GSPC.adj.std.annualised["1997/2022"]))
p.gspc + geom_line()+
  geom_hline(yintercept = gspc.avg10yr, color = "red")+
  geom_hline(yintercept = gspc.avg15yr, color = "blue")+
  geom_hline(yintercept = gspc.avg20yr, color = "green")+
  geom_hline(yintercept = gspc.avg25yr, color = "black")

Solution

  • Place the ticker data in environment, e, iterate over the ticker names calculating the returns in a list, ret.list, and then form that into an xts object, ret. From that calculate the standardized returns annualized, std_ann, as an xts object.

    To create the plot create a grid data frame g and from it data frame Means with columns Series, col (colors) and means to be used in geom_hline. autoplot will use Series to refer to the facets and geom_hline will use the Series column in Means to match each horizontal line to the appropriate facet.

    Only the packages listed below (and the packages they depend on) are used.

    library(quantmod)
    library(ggplot2)
    
    tickers <- c("^HSI","^GSPC")
    yrs <- c(red = 10, green = 15, blue = 20, black = 25)
    
    getSymbols(Symbols = tickers, env = e <- new.env(), from = "1997-01-01")
    
    ret.list <- Map(function(nm) dailyReturn(na.omit(Ad(e[[nm]]))), ls(e))
    ret <- setNames(do.call("merge", ret.list), names(ret.list))
    std_ann <- rollapplyr(ret, 252, function(x) sqrt(252) * sd(x, na.rm = TRUE))
    
    g <- expand.grid(Series = names(std_ann), col = names(yrs), 
      stringsAsFactors = FALSE)
    meansfun <- function(Series, col) {
        st <- as.Date(as.yearqtr(2022-yrs[[col]]-1))
        mean(window(std_ann[, Series], start = st), na.rm = TRUE)
    }
    Means <- transform(g, means = mapply(meansfun, Series, col))
    
    autoplot(std_ann) +
      geom_hline(aes(yintercept = means), Means, col = Means$col) +
      xlab("")
    

    screenshot