[prev in list] [next in list] [prev in thread] [next in thread] 

List:       r-sig-finance
Subject:    [R-SIG-Finance] perTradeStats in quantstrat messed up
From:       Ilya Kipnis <ilya.kipnis () gmail ! com>
Date:       2013-10-10 21:03:14
Message-ID: CA+oJuEFvhv3oX2G+6K8zr9s2zaTUbUDpNs6Ri_sUOjEPFiL=sw () mail ! gmail ! com
[Download RAW message or body]

So I've been playing around with my Connors RSI demo and when I ran it for
a 30 long entry 70 long exit (and inverse for short), my perTradeStats
essentially registered two trades that were basically more than my entire
P&L as plotted by chart.Posn. Not to mention, losses of such magnitude
would have definitely shown up in the chart.Posn plots, and they didn't,
and the two huge losses didn't show up in tradeStats either.

Since the Maximum Excursion (ME) charts use the data from perTradeStats,
this means that they are also unreliable.

In any case, here are the functions the demo is dependent on, and the demo
itself:


########################### CONNORS RSI ##############################

# compute Connor's RSI, depends on RSI TTR function
connorsRSI <- function(HLC, nRSI=3, nStreak=2, nPercentLookBack=100){
  price=Cl(HLC)
  priceRSI <- RSI(price, nRSI)
  streakRSI <- RSI(computeStreak(price), nStreak)
  percents <- rollapply(price, nPercentLookBack, lastPercentRank)
  ret <- (priceRSI+streakRSI+percents)/3
  ret <- xts(c(rep(NA,nPercentLookBack-1),ret), order.by=index(HLC))
  return(ret)
}

# computes a running streak of positives and negatives of price changes
computeStreak <- function(priceSeries){
  signs <- sign(diff(priceSeries))
  posDiffs <- negDiffs <- rep(0,length(signs))
  posDiffs[signs==1] <- 1
  negDiffs[signs==-1] <- -1

  #create vector of cumulative sums and cum sums not incremented during
streaks
  #zero out any leading NAs after na.locf
  posCum <- cumsum(posDiffs)
  posNAcum <- posCum
  posNAcum[posDiffs==1] <- NA
  posNAcum <- na.locf(posNAcum, na.rm=FALSE)
  posNAcum[is.na(posNAcum)] <- 0
  posStreak <- posCum - posNAcum

  #repeat for negative cumulative sums
  negCum <- cumsum(negDiffs)
  negNAcum <- negCum
  negNAcum[negDiffs==-1] <- NA
  negNAcum <- na.locf(negNAcum, na.rm=FALSE)
  negNAcum[is.na(negNAcum)] <- 0
  negStreak <- negCum - negNAcum

  streak <- posStreak + negStreak
  return (streak)
}

# ranks percentage returns from one point to the next
lastPercentRank <- function(priceSeries) {
  ranks <- rank(as.numeric(diff(log(priceSeries)))[-1])
  percentRanks <- ranks/length(ranks)
  lastVal <- round(percentRanks[length(percentRanks)]*100)
  return (lastVal)
}

##################### CHECK BLOTTER UPDATE ##########################

checkBlotterUpdate <- function(port.st,account.st,verbose=TRUE)
{
  ok <- TRUE
  p <- getPortfolio(port.st)
  a <- getAccount(account.st)
  syms <- names(p$symbols)
  port.tot <- sum(sapply(syms,FUN = function(x) eval(parse(
    text=paste("sum(p$symbols",x,"posPL.USD$Net.Trading.PL)",sep="$")))))
  initEq <- as.numeric(first(a$summary$End.Eq))
  endEq <- as.numeric(last(a$summary$End.Eq))
  if( !isTRUE(all.equal(port.tot,endEq-initEq)) ) {
    ok <- FALSE
    if( verbose )
      print("portfolio P&L doesn't match account P&L")
  }
  if( sum(duplicated(index(p$summary))) ) {
    ok <- FALSE
    if( verbose )
      print("duplicate timestamps in portfolio summary")
  }
  if( sum(duplicated(index(a$summary))) ) {
    ok <- FALSE
    if( verbose )
      print("duplicate timestamps in account summary")
  }
  return(ok)
}

############################# DEMO ###############################

require(quantstrat)

currency("USD")

symbols <- c("SPY","QQQ")
getSymbols(symbols,
           index.class=c("POSIXt","POSIXct"),
           from = startDate, to = endDate, adjust=TRUE)

stock(symbols, currency='USD', multiplier=1)

myTheme <- chart_theme()
myTheme$col$dn.col <- 'lightblue'
myTheme$col$dn.border <- 'lightgray'
myTheme$col$up.border <- 'lightgray'

initDate <- '2006-12-31'
startDate <- '2007-01-01'
endDate <- '2011-08-31'
initEq = 100000
Sys.setenv(TZ="UTC") #Brian, why is this needed?


.orderqty=100
.txnFees=-30

# I thought you could specify these in the parameters...
# tells me object not found when I try that
# can I do the quote trick with threshold?
longEntryRSI <- 30
longExitRSI <- 70


rm.strat("ConnorRSI")
rm.strat("ConnRSI")
initPortf(name="ConnorRSI",symbols=symbols,initDate=initDate)
initAcct(name="ConnorRSI",portfolios="ConnorRSI",initDate=initDate,initEq=initEq)
initOrders(portfolio="ConnorRSI",symbols=symbols,initDate=initDate)

strategy(name="ConnRSI",store=TRUE)

#indicator MUST be the same length as time series, or else we get a cryptic
error
add.indicator(strategy="ConnRSI", name="connorsRSI",
              arguments=list(HLC=quote(HLC(mktdata))),
              label="conRSI")

#entry signals
add.signal(strategy="ConnRSI",name="sigThreshold",
           arguments=list(threshold=longEntryRSI, column="conRSI",
relationship="lt", cross=TRUE),
           label="RSI.lt.lower")

add.signal(strategy="ConnRSI",name="sigThreshold",
           arguments=list(threshold=(100-longEntryRSI), column="conRSI",
relationship="gt", cross=TRUE),
           label="RSI.gt.upper")

#exit signals
add.signal(strategy="ConnRSI",name="sigThreshold",
           arguments=list(threshold=longExitRSI, column="conRSI",
relationship="gt", cross=TRUE),
           label="RSI.gt.exit.long")

add.signal(strategy="ConnRSI",name="sigThreshold",
           arguments=list(threshold=(100-longExitRSI), column="conRSI",
relationship="lt", cross=TRUE),
           label="RSI.lt.exit.short")


#long rules
add.rule(strategy="ConnRSI",name="ruleSignal",
         arguments=list(
           sigcol="RSI.lt.lower",
           sigval=TRUE,
           orderside='long',
           ordertype="stoplimit",
           prefer="Low",
           orderqty=.orderqty,
           replace=FALSE
           ),
         type='enter',
         label='enter.long'
)

add.rule(strategy="ConnRSI",name='ruleSignal',
         arguments=list(
           sigcol="RSI.gt.exit.long",
           sigval=TRUE,
           orderside='long',
           ordertype='market',
           orderqty='all',
           TxnFees=.txnFees,
           replace=FALSE),
         type='exit',
         label='exit.long'
)

#short rules
add.rule(strategy='ConnRSI',name='ruleSignal',
         arguments=list(
           sigcol="RSI.gt.upper",
           sigval=TRUE,
           orderside='short',
           ordertype='stoplimit',
           prefer="High",
           orderqty=-.orderqty,
           replace=FALSE
           ),
         type='enter',
         label='enter.short'
)

add.rule(strategy='ConnRSI',name='ruleSignal',
         arguments=list(
           sigcol="RSI.lt.exit.short",
           sigval=TRUE,
           orderside='short',
           ordertype='market',
           orderqty='all',
           TxnFees=.txnFees,
           replace=FALSE),
         type='exit',
         label='exit.short'
)

out <- applyStrategy(strategy='ConnRSI',portfolios="ConnorRSI",
                     parameters=list(
                       nPrice=3,
                       nStreak=2,
                       nPercentLookBack=100,
                       longEntryRSI=10,
                       longExitRSI=80),
                     verbose=TRUE)

updatePortf(Portfolio="ConnorRSI",Dates=paste(startDate,endDate,sep="::"))
dateRange <- time(getPortfolio("ConnorRSI")$summary)[-1]
updateAcct(name="ConnorRSI",Dates=dateRange)
updateEndEq("ConnorRSI")

checkBlotterUpdate("ConnorRSI","ConnorRSI")

acct <- getAccount(Account="ConnorRSI")
EndEq <- getEndEq(Account="ConnorRSI",endDate)
maxEq <- max(acct$summary$End.Eq)
(tStats <- tradeStats(Portfolios="ConnorRSI"))

####################### ME charts (SPY's is beyond unbelievable)

chart.ME(Portfolio="ConnorRSI",Symbol="SPY",type="MAE", scale='percent')
chart.ME(Portfolio="ConnorRSI",Symbol="SPY",type="MFE", scale='percent')
chart.ME(Portfolio="ConnorRSI",Symbol="QQQ",type="MAE", scale='percent')
chart.ME(Portfolio="ConnorRSI",Symbol="QQQ",type="MFE", scale='percent')

####################### Comparison position and cumulative PL charts

chart.Posn("ConnorRSI","SPY")
chart.Posn("ConnorRSI","QQQ")

	[[alternative HTML version deleted]]

_______________________________________________
R-SIG-Finance@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-sig-finance
-- Subscriber-posting only. If you want to post, subscribe first.
-- Also note that this is not the r-help list where general R questions should go.
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic