Search code examples
rquantmod

Plot function outside the candlestick pattern in R


I have two xts objects: stock and base. I calculate the relative strength (which is simply the ratio of closing price of stock and of the base index) and I want to plot the weekly relative strength outside the candlestick pattern. The links for the data are here and here.

library(quantmod)
library(xts)

read_stock = function(fichier){ #read and preprocess data
  stock = read.csv(fichier, header = T)
  stock$DATE = as.Date(stock$DATE, format = "%d/%m/%Y") #standardize time format
  stock = stock[! duplicated(index(stock), fromLast = T),] # Remove rows with a duplicated timestamp, 
                                                      # but keep the latest one
  stock$CLOSE = as.numeric(stock$CLOSE) #current numeric columns are of type character
  stock$OPEN = as.numeric(stock$OPEN)   #so need to convert into double
  stock$HIGH = as.numeric(stock$HIGH)   #otherwise quantmod functions won't work
  stock$LOW = as.numeric(stock$LOW)
  stock$VOLUME = as.numeric(stock$VOLUME)
  stock = xts(x = stock[,-1], order.by = stock[,1]) # convert to xts class
  return(stock)
}

relative.strength = function(stock, base = read_stock("vni.csv")){
  rs = Cl(stock) / Cl(base)
  rs = apply.weekly(rs, FUN = mean)
}
stock = read_stock("aaa.csv")

candleChart(stock, theme='white')
addRS = newTA(FUN=relative.strength,col='red', legend='RS')
addRS()

However R returns me this error:

 Error in `/.default`(Cl(stock), Cl(base)) : non-numeric argument to binary operator

How can I fix this?


Solution

  • One problem is that "vni.csv" contains a "Ticker" column. Since xts objects are a matrix at their core, you can't have columns of different types. So the first thing you need to do is ensure that you only keep the OHLC and volume columns of the "vni.csv" file. I've refactored your read_stock function to be:

    read_stock = function(fichier) {
      # read and preprocess data
      stock <- read.csv(fichier, header = TRUE, as.is = TRUE)
      stock$DATE = as.Date(stock$DATE, format = "%d/%m/%Y")
      stock = stock[!duplicated(index(stock), fromLast = TRUE),]
      # convert to xts class
      stock = xts(OHLCV(stock), order.by = stock$DATE)
      return(stock)
    }
    

    Next, it looks like the the first argument to relative.strength inside the addRS function is passed as a matrix, not an xts object. So you need to convert to xts, but take care that the index class of the stock object is the same as the index class of the base object.

    Then you need to make sure your weekly rs object has an observation for each day in stock. You can do that by merging your weekly data with an empty xts object that has all the index values for the stock object.

    So I refactored your relative.strength function to:

    relative.strength = function(stock, base) {
      # convert to xts
      sxts <- as.xts(stock)
      # ensure 'stock' index class is the same as 'base' index class
      indexClass(sxts) <- indexClass(base)
      index(sxts) <- index(sxts)
      # calculate relative strength
      rs = Cl(sxts) / Cl(base)
      # weekly mean relative strength
      rs = apply.weekly(rs, FUN = mean)
      # merge 'rs' with empty xts object contain the same index values as 'stock'
      merge(rs, xts(,index(sxts)), fill = na.locf)
    }
    

    Now, this code:

    stock = read_stock("aaa.csv")
    base = read_stock("vni.csv")
    addRS = newTA(FUN=relative.strength, col='red', legend='RS')
    candleChart(stock, theme='white')
    addRS(base)
    

    Produces this chart:

    enter image description here