joshuaulrich / quantmod

Quantitative Financial Modelling Framework
http://www.quantmod.com/
GNU General Public License v3.0
823 stars 224 forks source link

want OpCl to work on merged frames #187

Open isomorphisms opened 7 years ago

isomorphisms commented 7 years ago

Description

OpCl nor sapply(OpCl) don’t work on cbinded xxts data.frames the way I expect

Expected behavior

xts.thing %>% merge.xts %>% OpCl should go through each symbol and OpCl it.

Minimal, reproducible example

require(quantmod)
require(magrittr)
getSymbols( c('^GDAXI','GLD') )
merge.xts( GDAXI, GLD, join='inner') %>% {function(x) cbind(Op(x),Cl(x))}() %>% {function(x) Cl(x) - Op(x) }() %>% head
           GDAXI.Close GLD.Close
2007-01-03   10.089824 -1.300001
2007-01-04   12.159902 -0.419998
2007-01-05  -68.810156 -0.580002
2007-01-08    4.039844  0.100000
2007-01-09  -10.909883  0.709998
2007-01-10  -12.199941  0.130000

but if I subbed OpCl for {function(x) cbind(Op(x),Cl(x))}() I would get

merge.xts( GDAXI, GLD, join='inner') %>% OpCl %>% head
Error in xts(new.x, x.index) : NROW(x) must match length(order.by)

Session Info

> sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: i686-pc-linux-gnu (32-bit)
Running under: Ubuntu 16.04.3 LTS

Matrix products: default
BLAS: /usr/lib/atlas-base/libf77blas.so.3.0
LAPACK: /opt/R-3.4.1/lib/libRlapack.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] quantmod_0.4-10 TTR_0.23-2      xts_0.10-0      zoo_1.8-0       magrittr_1.5    colorout_1.1-2 

loaded via a namespace (and not attached):
 [1] compiler_3.4.1   pryr_0.1.2       tools_3.4.1      curl_2.7         Rcpp_0.12.12     stringi_1.1.5   
 [7] codetools_0.2-15 grid_3.4.1       stringr_1.2.0    lattice_0.20-35
joshuaulrich commented 7 years ago

Can you please provide an example that doesn't depend on an external package? I don't understand the %>% logic here, and I think it may be leading to your difficulty/misunderstanding.

It's also unclear what behavior you're expecting. "xts.thing %>% merge.xts %>% OpCl should go through each symbol and OpCl it." I don't understand why you would call merge() on a single object. And I don't understand what you mean by (essentially OpCl(xts_object)) "should go through each symbol".

isomorphisms commented 7 years ago
require(quantmod)
getSymbols( c('^GDAXI','GLD') )
merge.xts( GDAXI, GLD, join='inner') -> gld.gdaxi
cbind(Op(gld.gdaxi),Cl(gld.gdaxi)) -> gld.gdaxi.opcl
OpCl(gld.gdaxi.opcl)

Here is the error message:

> OpCl(gld.gdaxi.opcl)
Error in xts(new.x, x.index) : NROW(x) must match length(order.by)
In addition: Warning message:
In `dim<-.zoo`(`*tmp*`, value = NULL) :
  setting this dimension may lead to an invalid zoo object

Looking around in the code for quantmod::Delt there is a line that sets dim(x2) <- NULL. In my limited debugging attempts I think that line may be operative here.

isomorphisms commented 7 years ago

By "go through each symbol" I mean that I would like to add something like an xtApply or apply.xts (even just as an alias for existing functionality) which, when given something like a cbind( GDAXI, GLD, SPY ) (properly classed and structured), can OpCl( cbind( GDAXI, GLD, SPY ) ) and return three Delts, cbinded together.

isomorphisms commented 7 years ago

Here is a related problem (maybe needs separate issue, maybe not).

require(quantmod)
getSymbols( '^GDAXI', 'GLD' )
merge.xts(GDAXI,GLD, join='inner') -> gdaxi.gld
apply(gdaxi.gld.opcl,2,OpCl)

This raises an error of:

Error in Op(x) : 
  subscript out of bounds: no column name containing "Open"

Now, whether I’m using the correctly *ply or not, it is the case that the column names contain Open, as seen by:

> names(gdaxi.gld.opcl)
[1] "GDAXI.Open"  "GLD.Open"    "GDAXI.Close" "GLD.Close" 

Running lapply instead of apply(..., 2, ...) gives a similar (wrong) error about no columns having Close in the name.