Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generalized function to substitute all variables in the quote()d expression, if they exist in an environment [duplicate]

Tags:

r

Having similar problem, I am looking for a more generalized solution than the one provided for this question: How do I substitute symbols in a language object?

I have an unevaluated expression foo <- quote(bar + baz), which is a variable inside other expression: qux <- quote(bla + foo).

We can check that:

exists("foo", envir=.GlobalEnv) & class(foo)=="call"
[1] TRUE
exists("qux", envir=.GlobalEnv) & class(qux)=="call"
[1] TRUE

Now I would like to write a generalized function that decomposes (parses?) qux into the component expressions and replaces the ones that exist in the .GlobalEnv and that are of class call with their values:

replaceFUN <- function(x) {
  # do something
}

Running replaceFUN(qux) should return:

bla + (bar + baz)  

Background on the actual problem:

I am building a quant trading rules backtesting engine. My aim is to delay evaluation of the quote()d expressions, such as rules and indicator calculations later after their definition.

require(data.table)
require(TTR) # for the `SMA` function

DT <- data.table(Instrument=rep("SPX",3),Date=1:3, Close=c(1050, 1052, 1051))

# define parameters
nSMA <-2
t <- 2

# define indicators
time.filter <- quote( Date==t )
moving.average <- quote( SMA(Close, nSMA) )    
buy <- quote( Close > moving.average & time.filter )


AddColumn <- function(x, colname) {
  DT[,eval(substitute(colname)):=eval(x, envir=.SD)]
}

AddColumn(time.filter, "filter")

    Instrument Date Close filter
 1:        SPX    1  1050  FALSE
 2:        SPX    2  1052   TRUE
 3:        SPX    3  1051  FALSE

AddColumn(moving.average, "MA")

   Instrument Date Close filter     MA
1:        SPX    1  1050  FALSE     NA
2:        SPX    2  1052   TRUE 1051.0
3:        SPX    3  1051  FALSE 1051.5

AddColumn(buy, "Buy")

Error in Close > moving.average & time.filter : 
operations are possible only for numeric, logical or complex types

This obviously raises an error because AddColumn function lacks the mechanism to parse the nested moving.average and time.filter variables (plus and any other that user defines and nests). The nesting of rules inside buy is done for readability and is indeed a syntactic sugar.

like image 510
Daniel Krizian Avatar asked Dec 20 '25 10:12

Daniel Krizian


1 Answers

I was solving a very similar problem to this a little while ago. Check out the source code of [.data.table and look at the deconstruct_and_eval and construct functions there. It should give you enough info to go on.

like image 186
eddi Avatar answered Dec 22 '25 22:12

eddi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!