Search code examples
rxtsquantmodstockquotes

Adjusting for Stock Splits in R Error?


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?


Solution

  • 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))