dailyReturn with xts object - r

I am having difficulty using dailyReturn function on an xts object with multiple return series.
a<-Cl(getSymbols("INTC",auto.assign=FALSE))
b<-Cl(getSymbols("IBM",auto.assign=FALSE))
a<-merge(a,b)
dailyReturn(a[,1]) #This works!
dailyReturn(a) #Only return the result for first series
apply(a,2, dailyReturn)
#Error in array(ans, c(len.a%/%d2, d.ans), if (!all(vapply(dn.ans, is.null, :
length of 'dimnames' [1] not equal to array extent
How do I get dailyReturn to return the daily returns for multiple series in xts object?

I prefer ROC also, but if you must use dailyReturn, you can lapply over the columns and cbind them back together.
> head(do.call(cbind, lapply(a, dailyReturn)))
daily.returns daily.returns.1
2007-01-03 0.0000000000 0.000000000
2007-01-04 0.0402948403 0.010691889
2007-01-05 -0.0033065659 -0.009052996
2007-01-08 -0.0042654028 0.015191952
2007-01-09 0.0009519277 0.011830131
2007-01-10 0.0233000476 -0.011791746
I used do.call so that it will work with any number of columns.

I would just use TTR::ROC instead.
> head(r <- ROC(a, type="discrete"))
INTC.Close IBM.Close
2007-01-03 NA NA
2007-01-04 0.0402948403 0.010691889
2007-01-05 -0.0033065659 -0.009052996
2007-01-08 -0.0042654028 0.015191952
2007-01-09 0.0009519277 0.011830131
2007-01-10 0.0233000476 -0.011791746

Related

Merging many lists of different XTS objects in R

I have 3 lists of large XTS objects: "SMA"; "L", "Marubozu". Quick look how it looks:
> names(Marubozu)
[1] "TSLA" "AAPL" "NTES" "GOOGL" "ASML" "GOOG" "NFLX" "ADBE" "AMZN" "MSFT" "ADI" "FB"
> names(SMA)
[1] "TSLA" "AAPL" "NTES" "GOOGL" "ASML" "GOOG" "NFLX" "ADBE" "AMZN" "MSFT" "ADI" "FB"
> names(L)
[1] "TSLA" "AAPL" "NTES" "GOOGL" "ASML" "GOOG" "NFLX" "ADBE" "AMZN" "MSFT" "ADI" "FB"
> head(Marubozu$AAPL, n = 2)
WhiteMarubozu BlackMarubozu
2000-01-03 FALSE FALSE
2000-01-04 FALSE FALSE
> head(SMA$AAPL, n = 2)
UpTrend NoTrend DownTrend Trend
2000-01-03 NA NA NA NA
2000-01-04 NA NA NA NA
> head(L$AAPL, n =2)
AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted
2000-01-03 0.936384 1.004464 0.907924 0.999442 535796800 0.856887
2000-01-04 0.966518 0.987723 0.903460 0.915179 512377600 0.784643
I want to merge corresponding XTS objects in that lists so that it creates one big lig list. For example, the output for New_List$AAPL would be:
AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted WhiteMarubozu BlackMarubozu UpTrend NoTrend DownTrend Trend
2000-01-03 0.936384 1.004464 0.907924 0.999442 535796800 0.856887 0 0 NA NA NA NA
2000-01-04 0.966518 0.987723 0.903460 0.915179 512377600 0.784643 0 0 NA NA NA NA
I tried to create a list of lists and merging it, but it didnt work. Here you can see:
#That works for a single ticker AAPL
full <- merge.xts(L$AAPL, Marubozu$AAPL, SMA$AAPL)
#This doesn't work
out3 <- Map(function(x) {full$x <- merge.xts(lista[[1]]$x, lista[[2]]$x)}, lista)
I guess it is just some simple 2-lines thing but can't really find the solution, thanks for any responses!
We could do this with Map - as the list of xts elements have the same tickers in the same order, just use Map instead of creating a list of lists
library(xts)
out <- Map(merge.xts, L, Marubozu, SMA)
Here's a small function u() that binds the xts-index to an xts object and converts to 'data.frame'.
u <- function(x) cbind.data.frame(index=index(x), unclass(x))
To test it, we create some data using sample_matrix which comes with xts. We split first two and last two columns into two separate xts objects with same index.
library(xts)
data(sample_matrix)
sample.xts <- as.xts(sample_matrix, descr='my new xts object')
S1 <- as.xts(sample_matrix[,1:2]) ##
S2 <- as.xts(sample_matrix[,3:4])
Now we may easily apply merge and create a new xts object out of it.
res <- merge(u(S1), u(S2)) |>
(\(x) xts(x[-1], x$index, descr='my new xts object'))()
class(res)
# [1] "xts" "zoo"
stopifnot(all.equal(res, sample.xts)) ## proof

R: do.call with merge and eapply

I am merging two xts objects with join="left" i.e. (all rows in the left object, and those that match in the right). I loaded these objectd in myEnv.
library(quantmod)
myEnv <- new.env()
getSymbols("AAPL;FB", env=myEnv)
[1] "AAPL" "FB"
MainXTS <- do.call(merge, c(eapply(myEnv, Cl), join = "left"))
head(MainXTS)
AAPL.Close FB.Close
2007-01-03 2.992857 NA
2007-01-04 3.059286 NA
2007-01-05 3.037500 NA
2007-01-08 3.052500 NA
2007-01-09 3.306072 NA
2007-01-10 3.464286 NA
range(index(myEnv$AAPL))
[1] "2007-01-03" "2020-10-27"
range(index(myEnv$FB))
[1] "2012-05-18" "2020-10-27"
So far it is working as expected since the time index in above merged object is being picked up from APPL. The issue is that when I change the order of the tickers so that FB comes first, the merged object still picks up time indexes from AAPL.
myEnv <- new.env()
getSymbols("FB;AAPL", env=myEnv)
[1] "FB" "AAPL"
MainXTS <- do.call(merge, c(eapply(myEnv, Cl), join = "left"))
head(MainXTS)
AAPL.Close FB.Close
2007-01-03 2.992857 NA
2007-01-04 3.059286 NA
2007-01-05 3.037500 NA
2007-01-08 3.052500 NA
2007-01-09 3.306072 NA
2007-01-10 3.464286 NA
I was expecting the time index to be picked up from FB. Does any one know what I am missing?
I think this has something to do with the fact that the order of objects being loaded is the same and in both cases above it is:
ls(myEnv)
[1] "AAPL" "FB"
We can change the order with match
out <- do.call(merge, c(lapply(mget(ls(myEnv)[match(ls(myEnv),
c("FB", "AAPL"))], myEnv), Cl), join = "left"))
-output
head(out)
# FB.Close AAPL.Close
#2012-05-18 38.23 18.94214
#2012-05-21 34.03 20.04571
#2012-05-22 31.00 19.89179
#2012-05-23 32.00 20.37714
#2012-05-24 33.03 20.19000
#2012-05-25 31.91 20.08178

Trying to find daily difference for field in a dataframe

I have this.
head(df2)
Close Group
2007-01-03 17.625 S
2007-01-04 17.645 B
2007-01-05 17.570 B
2007-01-08 17.505 B
2007-01-09 17.430 B
2007-01-10 17.375 S
I am trying to find the daily change of 'Close'.
I tried this: dailychange <- diff(df2$Close)
That didn't work because 'non-numeric argument to binary operator'. This is a time series, but I don't think that matters at all.
str(df2)
‘zoo’ series from 2007-01-03 to 2018-07-27
Data: chr [1:2913, 1:2] "17.625" "17.645" "17.570" "17.505" "17.430" "17.375" "17.905" "17.950" "18.110" "18.145" ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:2913] "2007-01-03" "2007-01-04" "2007-01-05" "2007-01-08" ...
..$ : chr [1:2] "Close" "Group"
Index: Date[1:2913], format: "2007-01-03" "2007-01-04" "2007-01-05" "2007-01-08" "2007-01-09" "2007-01-10" "2007-01-11" "2007-01-12" ...
From the documentation of ts:
a vector or matrix of the observed time-series values. A data frame
will be coerced to a numeric matrix via data.matrix
But, a timeseries with a character column will transform all columns into character. The same behaviour can be seen in a matrix with a character value.
Either keep your data in as a data.frame, or use as.numeric inside your diff statement.
dailychange <- diff(as.numeric(df2$Close))
dailychange
[1] 0.020 -0.075 -0.065 -0.075 -0.055
The error message arises because some data is not numerical. Only numerical data can be used in diff(). Check your data in the close column to check if the data is numerical.

How to save data column of zoo object to matrix?

I am downloading some data using R package tseries,
require('tseries')
tickers<- c('JPM','AAPL','MSFT','FB','GE');
prices = matrix(NA,nrow=40,ncol=6)
startdate<-'2015-02-02'
enddate<-'2015-03-30'# 40 rows dim()
for(i in 1:5){
prices[,i]<-get.hist.quote(
instrument=tickers[i],
start=startdate,
end=enddate,
quote='AdjClose',
provider='yahoo')
}
colnames(prices)<-c('JPM','AAPL','MSFT','FB','GE');
I want to construct a matrix saving the adjclose price and date information, but I don't know how to access the zoo date column, say when I construct a zoo object using get.hist.quote(), I can view the object like this
But when I save them to matrix, the date column is missing
Here Map applied to get.hist.quote will create a zoo object for each ticker. Then we use zoo's multiway merge.zoo to merge them all together creating a final zoo object prices:
prices <- do.call(merge,
Map(get.hist.quote, tickers,
start=startdate,
end=enddate,
quote='AdjClose',
provider='yahoo')
)
I would probably keep all the series in a zoo object. This can be done like in the following code, thereby also avoiding your for-loop etc. You can always convert this object to a matrix by as.matrix() afterwards.
prices <-lapply(tickers, get.hist.quote, start=startdate, end=enddate, quote='AdjClose')
prices <- Reduce(cbind, prices)
names(prices) <- tickers
prices <- as.matrix(prices)
head(prices)
JPM AAPL MSFT FB GE
2015-02-02 55.10 118.16 40.99 74.99 23.99
2015-02-03 56.35 118.18 41.31 75.40 24.25
2015-02-04 56.01 119.09 41.54 75.63 23.94
2015-02-05 56.40 119.94 42.15 75.61 24.28
2015-02-06 57.51 118.93 42.11 74.47 24.30
2015-02-09 57.44 119.72 42.06 74.44 24.42

What R function sends output to a new vector?

Suppose I have a data.frame named TLT whose last line is this:
TLT.Open TLT.Close
2010-12-14 92.4 92.14
And I want to add an extra vector called TLT.BarColor so it looks like this:
TLT.Open TLT.Close TLT.BarColor
2010-12-14 92.4 92.14 "Green"
Here is a function that "prints" whether it was a green or red bar day.
bar_color <- function(ticker) {
require("quantmod")
x <- getSymbols(ticker, auto.assign=FALSE)
open <- x[,1]
close <- x[,2]
last_open <- tail(open, n=1)
last_close <- tail(close, n=1)
if (last_open > last_close)
{print("Red Bar")}
else if (last_open < last_close)
{print("Green Bar")}
else {print("Doji Bar")}
Instead of using the print() R function (which only prints to console), what R function would you use to send the output to populate a new vector?
super_dataframe <- cbind(TLT, apply(TLT, 1, valid_function))
The sample function does not work in this solution. But if the function were valid, it's output could be attached in this manner.
ticker can't be a dataframe, but has to be a character. So with the apply you use to create your super data frame, you'll have a problem. THe following function gives the labels for different tickers.
bar_color <- function(ticker){
x <- getSymbols(ticker,auto.assign=FALSE)
n <- nrow(x)
switch(
sign(x[n,1]-x[n,4])+2,
"Green Bar",
"Doji Bar",
"Red Bar")
}
> TLT <- c("F","QQQQ")
> cbind(TLT,sapply(TLT,bar_color))
TLT
F "F" "Green Bar"
QQQQ "QQQQ" "Red Bar"
If you want the labels for one ticker but different dates, then this is what you're looking for :
bar_color <- function(ticker){
x <- as.data.frame(getSymbols(ticker,auto.assign=FALSE))
x$barcolor <- sapply(
as.numeric(sign(x[,1]-x[,4])+2),
function(j) switch(j,"Green Bar","Doji Bar","Red Bar")
)
return(x)
}
> head(bar_color("F"))
F.Open F.High F.Low F.Close F.Volume F.Adjusted barcolor
2007-01-03 7.56 7.67 7.44 7.51 78652200 7.51 Red Bar
2007-01-04 7.56 7.72 7.43 7.70 63454900 7.70 Green Bar
2007-01-05 7.72 7.75 7.57 7.62 40562100 7.62 Red Bar
2007-01-08 7.63 7.75 7.62 7.73 48938500 7.73 Green Bar
2007-01-09 7.75 7.86 7.73 7.79 56732200 7.79 Green Bar
2007-01-10 7.79 7.79 7.67 7.73 42397100 7.73 Red Bar
The problem you -likely- face is the fact that getSymbols does not return you a dataframe, but an xts object. For xts there are specific methods to access and add data, and one should not expect this to behave like a data frame.
> X <- getSymbols("F",auto.assign=FALSE)
> class(X)
[1] "xts" "zoo"
If you changed the print statements to simply the character vector itself, e.g."Red Bar", you can add that to an existing vector such as the last row. It might be clearer code if you substituted return() for the print()'s. The only problem is that a vector needs to be of all the same mode so you would need to accept a character vector or use a one line data.frame.
vec <- c(TLT[NROW(TLT), ] , bar.color( "TLT") ) # a character vector
onerowdf <- cbind( TLT[NROW(TLT), ], bar.color( "TLT")) )
# a data.frame (aka list)

Resources