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