3
$\begingroup$

Here is a few references about OBV calculations:

  1. http://ta.mql4.com/indicators/volumes/on_balance_volume
  2. http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:on_balance_volume_obv
  3. http://en.wikipedia.org/wiki/On-balance_volume

When I navigate to the source code of OBV function in TTR package, I see this:

"OBV" <-
function(price, volume) {
    # On Balance Volume
    price <- try.xts(price, error=as.matrix)
    volume <- try.xts(volume, error=as.matrix)

    if(!(is.xts(price) && is.xts(volume))) {
        price <- as.vector(price)
        volume <- as.vector(volume)
    }
    obv <- c( volume[1], ifelse( ROC(price) > 0, volume, -volume )[-1] )
    obv <- cumsum( obv )
    if(is.xts(obv)) {
        obv <- xts(obv,index(price))
        colnames(obv) <- 'obv'
    }
    reclass( obv, price )
}

I see that the equality case (I mean the case occurs when today’s close is equal to yesterday’s close) in the reference web pages does not exist in OBV function implementation.

Is it a bug or an acceptance of the package? If it is a bug, where can I report the issue?

$\endgroup$
2
$\begingroup$

Yes, the function does not consider cases when the price is flat. The solution is very simple. Look at the OBV2 function below. The series from OBV and OBV2 are highly correlated, but the strict definition would be higher (smaller) depending on the market evolution. In the QQQ case that difference is about 50% 1. You could find the maintainer here: http://cran.r-project.org/web/packages/TTR/index.html

    OBV2 <-  function(price, volume) { #
    # On Balance Volume 2
    price <- try.xts(price, error=as.matrix)
    volume <- try.xts(volume, error=as.matrix)

    if(!(is.xts(price) && is.xts(volume))) {
       price <- as.vector(price)
      volume <- as.vector(volume)
   }
   obv <- c( volume[1], ifelse(ROC(price) > 0, volume, -volume)[-1] )
   obv[ROC(price)==0]<-0
   obv <- cumsum( obv )
   if(is.xts(obv)) {
     obv <- xts(obv,index(price))
     colnames(obv) <- 'obv2'
   }
   reclass( obv, price )
   }

   require("quantmod")  

   getSymbols('QQQ', src='yahoo',from='2012-01-01')
   chartSeries(QQQ,TA = NULL)
   addOBV()
   sobv=OBV(QQQ[,4],QQQ[,5])
   #addTA(sobv,on=3)
   head(cbind(QQQ,sobv))
   table(ROC(QQQ[,4])==0)

   sobv2=OBV2(QQQ[,4],QQQ[,5])
   addTA(sobv2,on=2,col="red")
   cor(sobv,sobv2)
   tail(cbind(sobv,sobv2,sobv2/sobv-1))
   chartSeries(sobv2,TA = NULL)
   addTA(sobv,on=1,col="red")
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.