Skip to content
Prev 13021 / 15274 Next

Bug in ruleOrderProc - txnfees is not a numeric?

I ran into this same problem and have a proposed patch. As Ivan proposed,
it appears to be related to the splitting transactions to cross position
values over 0. Any strategy with rules that create orders crossing
positions through 0 will fail on its eventual call to addTxn, even if you
define TxnFees = 0 on the ruleSignal (because it is carried around
internally as.character to support txnFUNs)

It looks like the problem lies in blotter::addTxn rather than
quantstrat::ruleOrderProc. If we move the txnfee evaluation before
splitting the transactions we will have a valid numeric rather than a
character in the '/' operation. I made this change in my dev version and it
looks like it works.

addTxn <- function(Portfolio, Symbol, TxnDate, TxnQty, TxnPrice, ...,
TxnFees=0, allowRebates=FALSE, ConMult=NULL, verbose=TRUE, eps=1e-06)

<snip>

    # FUNCTION
    # Coerce the transaction fees to a function if a string was supplied

    if(is.character(TxnFees)) {
        TF <- try(match.fun(TxnFees), silent=TRUE)
        if (!inherits(TF,"try-error")) TxnFees<-TF
    }
    # Compute transaction fees if a function was supplied
    if (is.function(TxnFees)) {
      txnfees <- TxnFees(TxnQty, TxnPrice, Symbol)
    } else {
      txnfees<- as.numeric(TxnFees)
    }

    if(is.null(txnfees) | is.na(txnfees)) txnfees = 0
    if(txnfees>0 && !isTRUE(allowRebates)) stop('Positive Transaction
Fees should only be used in the case of broker/exchange rebates for
TxnFees ',TxnFees,'. See Documentation.')

addTxn has a block of code that evaluates the transaction fees if a
function was passed in, or casts it as as.numeric. Quantstrat will pass in
argument TxnFees as an xts of characters. Before TxnFees can be evaluated,
an attempt to split the transaction into two pieces is made.

   # split transactions that would cross through zero
    if(PrevPosQty!=0 && sign(PrevPosQty+TxnQty)!=sign(PrevPosQty) &&
PrevPosQty!=-TxnQty){*        txnFeeQty=TxnFees/abs(TxnQty) #
calculate fees pro-rata by quantity*
        addTxn(Portfolio=pname, Symbol=Symbol, TxnDate=TxnDate,
TxnQty=-PrevPosQty, TxnPrice=TxnPrice, ...,
                TxnFees = txnFeeQty*abs(PrevPosQty), ConMult =
ConMult, verbose = verbose, eps=eps)
        TxnDate=TxnDate+2*eps #transactions need unique timestamps, so
increment a bit
        TxnQty=TxnQty+PrevPosQty
        PrevPosQty=0
        TxnFees=txnFeeQty*abs(TxnQty+PrevPosQty)
    }

At this stage TxnFees is still a character. This / operator is what is
creating the error:

Error in `/.default`(TxnFees, abs(TxnQty)) :
  non-numeric argument to binary operator

Switching the order of these two blocks of code and changing

*txnFeeQty=TxnFees/abs(TxnQty)*

To

*txnFeeQty=txnfees/abs(TxnQty)*

should fix it.

2014-01-14 10:45 GMT-05:00 Brian G. Peterson <brian at braverock.com>: