1

I have an intraday dataset with closing prices that I want to adjust stock prices for stock splits. I have found the adjustOHLC() from the quantmod package to work almost effectively.

Here is one of the many UNADJUSTED tickers in my dataset called: AGII

datset <- structure(c(52.15, 52.17, 52.135, 52.155, 52.1, 52.1, 52.23, 
52.145, 52.185, 52.15, 52.215, 52.185, 52.15, 52.32, 52.415, 
52.4, 52.41, 52.42, 52.51, 52.39, 52.42, 52.02, 52, 52.12, 52.12, 
52.15, 52.06, 52.13, 52.13, 52.02, 52.02, 52.12, 52.06, 52.06, 
52, 52.025, 51.97, 51.96, 52.02, 52, 52.005, 52, 52.09, 52.17, 
52.15, 52.47, 52.51, 52.76, 52.58, 52.73, 52.65, 52.75, 52.7295, 
52.56, 52.5, 52.5, 52.46, 52.43, 52.3, 52.467, 52.48, 52.48, 
52.53, 52.657, 52.633, 52.55, 52.565, 52.56, 52.57, 52.735, 52.71, 
52.72, 52.55, 52.55, 52.34, 52.54, 52.46, 52.54, 52.45, 52.74, 
52.67, 52.8, 52.61, 52.63, 52.74, 52.78, 52.78, 52.59, 52.79, 
52.81, 52.81, 52.725, 52.69, 52.6, 52.675, 52.58, 52.67, 52.67, 
47.63, 47.57, 47.59, 47.57, 47.73, 47.64, 47.64, 47.64, 47.75, 
47.74, 47.78, 47.78, 47.83, 47.86, 47.99, 47.94, 47.94, 48, 47.97, 
47.97, 48.01, 47.88, 47.86, 47.96, 47.93, 47.98, 47.98, 48.06, 
48.01, 47.96, 47.93, 47.93, 48.02, 48.01, 48.04, 48.06, 48.12, 
48.1599, 48.1599, 48.18, 48.15, 48.19, 48.16, 48.11, 48.115, 
48.1, 48.08, 48.07, 48.04, 48.02, 47.995, 47.91), .indexTZ = "", class = c("xts", 
"zoo"), .indexCLASS = c("POSIXct", "POSIXt"), tclass = c("POSIXct", 
"POSIXt"), tzone = "", index = structure(c(1424481300, 1424482200, 
1424483100, 1424484000, 1424484900, 1424485800, 1424486700, 1424487600, 
1424488500, 1424489400, 1424490300, 1424491200, 1424492100, 1424493000, 
1424493900, 1424494800, 1424495700, 1424496600, 1424497500, 1424498400, 
1424735100, 1424736000, 1424736900, 1424737800, 1424738700, 1424739600, 
1424740500, 1424741400, 1424742300, 1424743200, 1424744100, 1424745000, 
1424745900, 1424746800, 1424747700, 1424748600, 1424749500, 1424750400, 
1424751300, 1424752200, 1424753100, 1424754000, 1424754900, 1424755800, 
1424756700, 1424757600, 1424821500, 1424822400, 1424823300, 1424824200, 
1424825100, 1424826000, 1424826900, 1424827800, 1424828700, 1424829600, 
1424830500, 1424831400, 1424832300, 1424833200, 1424834100, 1424835000, 
1424835900, 1424836800, 1424837700, 1424838600, 1424839500, 1424840400, 
1424841300, 1424842200, 1424843100, 1424844000, 1424907900, 1424908800, 
1424909700, 1424910600, 1424911500, 1424912400, 1424913300, 1424914200, 
1424915100, 1424916000, 1424916900, 1424917800, 1424918700, 1424919600, 
1424920500, 1424921400, 1424922300, 1424923200, 1424924100, 1424925000, 
1424925900, 1424926800, 1424927700, 1424928600, 1424929500, 1424930400, 
1424994300, 1424995200, 1424996100, 1424997000, 1424997900, 1424998800, 
1424999700, 1425000600, 1425001500, 1425002400, 1425003300, 1425004200, 
1425005100, 1425006000, 1425006900, 1425007800, 1425008700, 1425009600, 
1425010500, 1425011400, 1425012300, 1425013200, 1425014100, 1425015000, 
1425015900, 1425016800, 1425080700, 1425081600, 1425082500, 1425083400, 
1425084300, 1425085200, 1425086100, 1425087000, 1425087900, 1425088800, 
1425089700, 1425090600, 1425091500, 1425092400, 1425093300, 1425094200, 
1425095100, 1425096000, 1425096900, 1425097800, 1425098700, 1425099600, 
1425100500, 1425101400, 1425102300, 1425103200), tzone = "", tclass = c("POSIXct", 
"POSIXt")), .Dim = c(150L, 1L), .Dimnames = list(NULL, "AGII"))

If you plot it, you will see the big drop in price i need to adjust for:

library(quantmod)
chartSeries(datset$AGII)

Since this is part of a larger dataset & I need to adjust many tickers I have written the following loop:

library(quantmod)
dataset <- xts()
NOMS <- names(datset)

for(i in 1:length(NOMS)) {
  NOMS[i]-> symbol
  # Symbol might not be found so I try "skip" the ticker with "try()"
  tryit <- try(adjustOHLC(to.period(datset[,symbol],"minutes",15), adjust=c("split"), symbol.name=symbol))
  if(inherits(tryit, "try-error")){
    ADJ = datset[,symbol]
    colnames(ADJ)<- symbol
    dataset <- merge.xts(dataset,ADJ)
  } else {
    # If ticker is found, then adjust it
    ADJ = adjustOHLC(to.period(datset[,symbol],"minutes",15), adjust=c("split"), symbol.name=symbol)
    ADJ <- Cl(ADJ)
    colnames(ADJ)<- symbol
    dataset <- merge.xts(dataset,ADJ)
  }
}

Now if you plot it: chartSeries(dataset) ... it is overstated February 24. The actual stock split occurs February 26 (if that helps)

   # To see split factor & when it occured
    getSplits("AGII",from="2015-02-20")

How do I get the appropriate split without it being overstated?

Rime
  • 912
  • 2
  • 11
  • 39
  • 1
    Here's a function that does a yahoo-style dividend/split adjustment on intraday data: https://r-forge.r-project.org/scm/viewvc.php/pkg/qmao/R/adjustIntraday.yahoo.R?view=markup&root=twsinstrument – GSee Mar 11 '15 at 19:53
  • @GSee thanks the function is excellent! – Rime Mar 11 '15 at 22:22
  • @GSee Is the `qmao` package compatible with mac osx Yosemite & the R version 3.1.2 ? I have tried `install.packages("qmao")` & also `install.packages("~/Desktop/R/qmao_1.6.10.tar.gz", repos = NULL, type="source") ` with no luck... :( – Rime Mar 13 '15 at 03:54
  • 1
    Yes, but it's not on CRAN, so you'd need to use `install.packages("qmao", repos="http://r-forge.r-project.org")` or `devtools::install_github("gsee/qmao")` or you could [checkout/build/install from source](http://stackoverflow.com/questions/11105131/cannot-install-r-forge-package-using-install-packages/11105132#11105132). (qmao has quite a few dependencies that you need to install first) – GSee Mar 13 '15 at 13:15
  • @GSee thanks I was now able to install `qmao` but I needed to load gdata, shiny, and pander first... qmao is awesome! – Rime Mar 13 '15 at 22:20

1 Answers1

0

First, these functions were designed to work on daily data, not intraday data.

Second, the problem is that Date objects are considered to be at midnight UTC, and your datset object has no timezone. So the adjustment algorithm thinks the split occurred at whatever midnight UTC happens to be in your system's timezone.

The work-around is to do this yourself, after adjusting the timezone of the split data to be the same as your local timezone.

s <- getSplits(symbol)
indexTZ(s) <- indexTZ(x)       # ensure the objects have the same timezone
index(s) <- index(s)           # force an index recalculation
indexClass(s) <- "POSIXct"     # convert index to POSIXct
r <- adjRatios(s, NA, datset)  # calculate adjustment ratios
y <- adjustOHLC(x, ratio=r$Split, symbol.name=symbol)
chartSeries(Cl(y))

Notice that you still see a spike in the adjusted data, because the split likely did not apply at midnight on 2015-02-26. You can work around that by lagging the adjustment ratios.

r2 <- na.locf(lag(r), fromLast=TRUE)
y2 <- adjustOHLC(x, ratio=r2$Split, symbol.name=symbol)
chartSeries(Cl(y2))
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418