Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a technical indicator in quantmod package

Tags:

r

quantmod

I'm a newbie to R and I am facing some problems with the creation of a technical indicator. More specifically, I want to create an indicator, Fibonacci, which will be added to the chartSeries and will consist of 5 horizontal lines. The data I am working with are the closing prices of a stock. So the graph I want to create will have one horizontal line in the point of the max closing price, one horizontal line in the point of the min closing price and three horizontal lines between the previous two. The code I wrote in order to take the five values of a time series of closing prices of a stock is the following:

Fibonacci <- function(x) {
x <- try.xts(x, error = as.matrix)
n <- nrow(x)
min <- runMin(x,n=n)
max <- runMax(x,n=n)
high <- 0.62*(max-min) + min
middle <- 0.5*(max-min) + min
low <- 0.38*(max-min) + min
res <-cbind(na.spline(min),na.spline(max),na.spline(high),
            na.spline(middle),na.spline(low))
colnames(res)<- c("min","max","high","middle","low") 
reclass (res, x)
}

I also wrote the following code in order to add the technical indicator to the existing chartSeries plot of quantmod package :

addFibonacci<- function(col = "red",overlay = TRUE){
stopifnot("package:TTR" %in% search() || require("TTR", quietly = TRUE))
lchob <- quantmod:::get.current.chob() 
x <- as.matrix(lchob@xdata)
chobTA <- new("chobTA")
chobTA@new <- !overlay
if (!is.OHLC(x)) 
    stop("Fibonacci requires HL series")
else {
fibon <- Fibonacci(Cl(x))
}
[email protected] <- fibon[lchob@xsubset]
chobTA@call <- match.call()
chobTA@on <- 1
chobTA@params <- list(xrange = lchob@xrange, colors = lchob@colors, 
    color.vol = [email protected], multi.col = [email protected], 
    spacing = lchob@spacing, width = lchob@width, bp = lchob@bp, 
    x.labels = [email protected], time.scale = [email protected], 
    col = col)
if (is.null(sys.call(-1))) {
    TA <- [email protected]$TA
    [email protected]$TA <- c(TA, chobTA)
    lchob@windows <- lchob@windows + ifelse(chobTA@new, 1, 
        0)
    chartSeries.chob <- quantmod:::chartSeries.chob
    do.call(chartSeries.chob, list(lchob))
    invisible(chobTA)
}
else {
    return(chobTA)
}
}

The problem is that the indicator is not getting added to the chart and I am also getting the following error message:

Error in do.call([email protected]$TA[[j]]@name, list([email protected]$TA[[j]])) :
  'what' must be a character string or a function

Any ideas for what I am doing wrong?

like image 298
user3017291 Avatar asked Nov 25 '13 12:11

user3017291


1 Answers

Rather than writing the add* function from scratch, you could just use newTA:

> library(quantmod)
> getSymbols("AAPL")
[1] "AAPL"
> addFibonacci <- newTA(Fibonacci,on=1)
> chartSeries(AAPL, TA="addFibonacci()")
Error in addFibonacci() : could not find function "get.current.chob"

Hmm, apparently get.current.chob isn't exported... that's okay, we can just change the function ourselves. After calling addFibonacci <- newTA(Fibonacci,on=1), addFibonacci is defined as:

addFibonacci <- function (..., on = 1, legend = "auto") 
{
    #lchob <- get.current.chob()
    lchob <- quantmod:::get.current.chob()
    x <- as.matrix(lchob@xdata)
    x <- Fibonacci(x = x)
    yrange <- NULL
    chobTA <- new("chobTA")
    if (NCOL(x) == 1) {
        [email protected] <- x[lchob@xsubset]
    }
    else [email protected] <- x[lchob@xsubset, ]
    chobTA@name <- "chartTA"
    if (any(is.na(on))) {
        chobTA@new <- TRUE
    }
    else {
        chobTA@new <- FALSE
        chobTA@on <- on
    }
    chobTA@call <- match.call()
    legend.name <- gsub("^add", "", deparse(match.call()))
    gpars <- c(list(...), list())[unique(names(c(list(), list(...))))]
    chobTA@params <- list(xrange = lchob@xrange, yrange = yrange, 
        colors = lchob@colors, color.vol = [email protected], multi.col = [email protected], 
        spacing = lchob@spacing, width = lchob@width, bp = lchob@bp, 
        x.labels = [email protected], time.scale = [email protected], 
        isLogical = is.logical(x), legend = legend, legend.name = legend.name, 
        pars = list(gpars))
    if (is.null(sys.call(-1))) {
        TA <- [email protected]$TA
        [email protected]$TA <- c(TA, chobTA)
        lchob@windows <- lchob@windows + ifelse(chobTA@new, 1, 
            0)
        chartSeries.chob <- chartSeries.chob
        do.call("chartSeries.chob", list(lchob))
        invisible(chobTA)
    }
    else {
        return(chobTA)
    }
}

And you can see where I replaced the call to get.current.chob() with quantmod:::get.current.chob(). Now it should work.

chartSeries(AAPL, TA="addFibonacci()")

Success!

enter image description here

like image 82
Joshua Ulrich Avatar answered Sep 20 '22 12:09

Joshua Ulrich