Tuesday, May 12, 2009

Packages featured with Inference for R

quantmod, TTR, and xts were (not so) recently featured on the Inference for R Blog. Inference for R is a Integrated Development Environment (IDE) designed specifically for R.

The post gives an example of how to easily perform advanced financial stock analysis using Inference in Excel.

I appreciate how they're making R more accessible to a general audience, even though I like a command line interface and my preferred development environment is vim. :-)

Monday, May 4, 2009

R/Finance 2009 Presentations Online

Posted to the R-SIG-Finance mailing list today:

For those who missed it, the slides for the R/Finance 2009 tutorials
and presentations are now available on RinFinance.com

http://www.RinFinance.com/presentations

We want to thank everyone who traveled to Chicago to make this happen. With nearly 200 attendees, coming from 8 countries and 20+ states in the US, the conference exceeded all of our expectations. A very big thank you to our presenters for taking the time to join us, UIC's International Center for Futures and Derivatives for hosting the event, and our sponsors REvolution Computing and Microsoft for their support.

We look forward to doing it again in the future. Stay tuned...

On behalf of the committee and sponsors.

Friday, May 1, 2009

RSI(2) with Position Sizing

Though it's more than two weeks later, here's the second post in the series that will demonstrate how to build, test, and implement a trading strategy with R. You can find the first post here.

The first post replicated this simple RSI(2) strategy from the MarketSci Blog. This second post will demonstrate how to replicate this strategy that scales in/out of RSI(2).

A couple notes before moving to the code:
  1. The rsi2pos() function isn't necessary, but it provides an example of how to define a function. Plus, it enables us to test several ideas with much greater speed and flexibility.

  2. The ifelse() function works on entire vectors at once, avoiding costly loops (loops are costly in R because it's an interpreted language). Since we can potentially modify the entire 'size' vector, we must be mindful of the order of the tests.

On to the code!
# Attach the quantmod and TTR packages.
# You can install packages via:
# install.packages(c("quantmod","TTR"))
library(quantmod)
library(TTR)

# Pull S&P500 index data from Yahoo! Finance
getSymbols("^GSPC", from="2000-01-01", to="2008-12-07")

# Calculate the RSI indicator
rsi <- RSI(Cl(GSPC),2)

# Calculate Close-to-Close returns
# (this assumes we open/close our positions
# at each day's close)
ret <- ROC(Cl(GSPC))
ret[1] <- 0

# Define our position-sizing function
rsi2pos <- function(ind, indIncr=5, posIncr=0.25) {
# Inputs:
# ind : indicator vector
# indIncr : indicator value increments/breakpoints
# posIncr : position value increments/breakpoints

# Initialize result vector
size <- rep(0,NROW(ind))

# Long
size <- ifelse(ind < 4*indIncr, (1-posIncr*3), size)
size <- ifelse(ind < 3*indIncr, (1-posIncr*2), size)
size <- ifelse(ind < 2*indIncr, (1-posIncr*1), size)
size <- ifelse(ind < 1*indIncr, (1-posIncr*0), size)

# Short
size <- ifelse(ind > 100-4*indIncr, 3*posIncr-1, size)
size <- ifelse(ind > 100-3*indIncr, 2*posIncr-1, size)
size <- ifelse(ind > 100-2*indIncr, 1*posIncr-1, size)
size <- ifelse(ind > 100-1*indIncr, 0*posIncr-1, size)

# Today's position ('size') is based on today's
# indicator, but we need to apply today's position
# to the Close-to-Close return at tomorrow's close.
size <- lag(size)

# Replace missing signals with no position
# (generally just at beginning of series)
size[is.na(size)] <- 0

# Return results
return(size)
}

# Calculate signals using the 'rsi2pos()' function
sig <- rsi2pos(rsi, 5, 0.25)

# Break out the long (up) and short (dn) signals
sigup <- ifelse(sig > 0, sig, 0)
sigdn <- ifelse(sig < 0, sig, 0)

# Calculate equity curves
eq_up <- exp(cumsum(ret*sigup)
)
eq_dn <- exp(cumsum(ret*sigdn))
eq_all <- exp(cumsum(ret*sig))

# Replicate Michael's nice chart (again)
png(filename="20090430_rsi2_replication.png")
plot.zoo( cbind(eq_up, eq_dn), plot.type="single",
ylab=c("Long","Short"), col=c("green","red"),
main="RSI(2) Strategy, with Position Scaling:\n 2000-01-03 through 2008-12-07" )
dev.off()


# Calculate signals using the 'rsi2pos()' function
# with new values
sig <- rsi2pos(rsi, 10, 0.3)

# Break out the long (up) and short (dn) signals
sigup <- ifelse(sig > 0, sig, 0)
sigdn <- ifelse(sig < 0, sig, 0)

# Calculate equity curves
eq_up <- exp(cumsum(ret*sigup)
)
eq_dn <- exp(cumsum(ret*sigdn))
eq_all <- exp(cumsum(ret*sig))

# Re-plot equity curves using updated values
png(filename="20090501_rsi2_updated.png")
plot.zoo( cbind(eq_up, eq_dn), plot.type="single",
ylab=c("Long","Short"), col=c("green","red"),
main="Updated RSI(2) Strategy, with Position Scaling:\n 2000-01-03 through 2008-12-07" )
dev.off()


Visual inspection of the charts seems to indicate the updated RSI(2) strategy has slightly higher returns, but more volatility and larger drawdowns. The next post will use the PerformanceAnalytics package to evaluate the volatility, drawdowns, and related metrics associated with these strategies. I will do my best to post it less than two weeks from now!