You can use the rollapply() function from the zoo package, providing you with a series of zoos:
TimeSeries <- cumsum(rnorm(1000)) ZooSeries <- as.zoo(TimeSeries) BollLines <- rollapply(ZooSeries,9,function(x){ M <- mean(x) SD <- sd(x) c(M,M+SD*2,M-SD*2) })
Now you must remember that rollapply uses a centered frame, that is, it takes values ββto the left and right of the current day. This is also more convenient and more true for determining the Bollinger band than your assumption of accepting x previous values.
If you do not want to convert to a zoo, you can also use vectors and write your own function. I added an S3-based build function, which also makes it easy to build calculations. Using these functions, you can do something like:
TimeSeries <- cumsum(rnorm(1000)) X <- BollingerBands(TimeSeries,80) plot(X,TimeSeries,type="l",main="An Example")
To obtain:

Function Codes:
BollingerBands <- function(x,width){ Start <- width +1 Stop <- length(x) Trail <- rep(NA,ceiling(width/2)) Tail <- rep(NA,floor(width/2)) Lines <- sapply(Start:Stop,function(i){ M <- mean(x[(i-width):i]) SD <- sd(x[(i-width):i]) c(M,M+2*SD,M-2*SD) }) Lines <- apply(Lines,1,function(i)c(Trail,i,Tail)) Out <- data.frame(Lines) names(Out) <- c("Mean","Upper","Lower") class(Out) <- c("BollingerBands",class(Out)) Out } plot.BollingerBands <- function(x,data,lcol=c("red","blue","blue"),...){ plot(data,...) for(i in 1:3){ lines(x[,i],col=lcol[i]) } }