Friday, February 10, 2012

Simplified Example of Systematic Investor’s Fine Work

THIS IS ONLY AN EXAMPLE AND IS NOT INVESTMENT ADVICE. ACTING ON THIS WILL LOSE LOTS OF MONEY.

Systematic Investor Blog (be sure to check out the site) offers extremely good examples of how to use R in finance.  Since I firmly believe more examples are always better, I wanted to provide an additional very simple example of how to use his Systematic Investor Toolbox (SIT) for systems development.  This will provide a building block for a series of posts similar to my A Quantstrat to Build On Part 6.  We’ll use our good old count up/down (CUD) indicator on the S&P 500 Index and compare it to Mebane Faber’s 10 month moving average.

I know this is not pretty, but I wanted to start with as simple a base as possible.  Any loyal readers will already have known that CUD is not so great at making money.

From TimelyPortfolio
R code in GIST:
#highlight the very fine work of http://systematicinvestor.wordpress.com/
#adapted some of his code to provide an addtional example for
#those that might be interested
###############################################################################
# Load Systematic Investor Toolbox (SIT)
# http://systematicinvestor.wordpress.com/systematic-investor-toolbox/
###############################################################################
con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb'))
    source(con)
close(con)
###############################################################################
require(quantmod)
#*****************************************************************
# Load historical data
#******************************************************************
tickers = spl('^GSPC')
data <- new.env()
getSymbols(tickers, src = 'yahoo', from = '1896-01-01', env = data, auto.assign = T)
bt.prep(data, align='keep.all', dates='1896::2011')
#*****************************************************************
# Code Strategies
#******************************************************************
prices = data$prices
# Buy & Hold
data$weight[] = 1
buy.hold = bt.run(data)
# MA Cross
#Meban Faber 10 month or approximately 200 day moving average entry
sma = bt.apply(data, function(x) { SMA(Cl(x), 200) } )
data$weight[] = NA
#when price crosses 200 day moving average enter
data$weight[] = iif(prices >= sma, 1, 0)
sma.cross = bt.run(data, trade.summary=T)
# just do the cud function with ttrTests optimized value of 110 days
cud = bt.apply(data, function(x) {runSum(ifelse(ROC(x,1,type="discrete") > 0,1,-1),n=110)})
data$weight[] = NA
# buy an 100% if cud greater than 10
# buy 50% if cud between 0 and 10
# exit below 0
# this is not advice and is a bad system
# please do not use for real money
data$weight[] = iif(cud >= 10, 1, iif(cud >= 0 & cud <10, 0.5, 0))
cud.plus = bt.run(data, trade.summary=T)
#*****************************************************************
# Create Report
#******************************************************************
plotbt.custom.report(cud.plus, sma.cross)
#to compare to buy hold then
plotbt.custom.report(cud.plus, buy.hold)

Monday, February 6, 2012

More Beautiful Growth of $1 Chart

With all my recent focus on reporting and visualization, you might think that I have the investments all figured out.  Unfortunately, that is not the case, and I will resume more standard investment and systems posts soon.  I did want to share what I think are two more beautiful Growth of a $1 visualizations.  Although my lattice code is far from tight, I think the result is fairly good using and modifying some of the Economist style graphs offered in latticeExtra.

From TimelyPortfolio

With a little modification, the chart.CumReturns from PerformanceAnalytics can also look very similar.  I will let you choose your favorite.  However, the lattice version will much more likely appear in my reports.

From TimelyPortfolio

Get code from GIST:

#trying to get a better growth of a $1 chart
#using lattice or PerformanceAnalytics
require(quantmod)
require(reshape)
require(lattice)
require(latticeExtra)
#get Vanguard US Total Bond Fund vbmfx
getSymbols("VBMFX",from="1990-01-01",to=Sys.Date(),adjust=TRUE)
#get Vanguard SP500 Fund vfinx
getSymbols("VFINX",from="1990-01-01",to=Sys.Date(),adjust=TRUE)
perf <- na.omit(merge(monthlyReturn(VBMFX[,4]),monthlyReturn(VFINX[,4])))
colnames(perf) <- c("VBMFX","VFINX")
perf.cumul <- rbind(c(index(perf)[1]-30,1,1),as.data.frame(cbind(index(perf),apply(1+perf[,1:2],MARGIN=2,FUN=cumprod))))
perf.cumul[,1] <- as.Date(perf.cumul[,1])
perf.cumul.melt <- melt(perf.cumul,id.vars=1)
colnames(perf.cumul.melt) <- c("date","index","growth1")
mycolors <- c("indianred4","deepskyblue3","deepskyblue4")
#add alpha to colors
addalpha <- function(cols,alpha=180) {
rgbcomp <- col2rgb(cols)
rgbcomp[4] <- alpha
return(rgb(rgbcomp[1],rgbcomp[2],rgbcomp[3],rgbcomp[4],maxColorValue=255))
}
mycolors.alpha <- apply(as.matrix(mycolors),MARGIN=1,FUN=addalpha,alpha=220)
ylimits<-c(pretty(c(min(perf.cumul.melt$growth1),
max(perf.cumul.melt$growth1))),as.numeric(round(last(perf.cumul[order(last(perf.cumul)[2:3])+1]),2)))
ylabels<-c(ylimits[1:(length(ylimits)-2)],colnames(perf.cumul)[order(last(perf.cumul)[2:3])+1])
#p1<-
xyplot(growth1~date,groups=index,data=perf.cumul.melt,
type="l",lwd=4, col=mycolors.alpha,
#function to customize the axes
#would like a bottom axis for the dates
#then a left axis for numeric labels
#no top axis
#and a right axis that labels the end points with the instrument/asset
axis=function (side = c("top", "bottom", "left", "right"), scales,
components, ..., labels = c("default", "yes", "no"), ticks = c("default",
"yes", "no"), line.col){
side <- match.arg(side)
labels <- match.arg(labels)
ticks <- match.arg(ticks)
axis.text <- trellis.par.get("axis.text")
#for debugging
#print(side)
#for debugging
#print(components)
if(side == "top") return() #no top axis
if(side %in% c("bottom","right")){
if (side == "right") { #want just the last 2 components of the y
components[["right"]]<-components[["left"]]
n<-length(components[["right"]]$ticks$at)
components[["right"]]$ticks$at <- components[["right"]]$ticks$at[(n-1):n]
components[["right"]]$labels$at <- components[["right"]]$labels$at[(n-1):n]
components[["right"]]$labels$labels <- components[["right"]]$labels$labels[(n-1):n]
#for some reason need to draw the horizontal grid lines in the r side section
comp.list <- components[["left"]]
#draw a horizontal grid line at each of the y numeric labels
panel.refline(h = comp.list$ticks$at[1:(n-2)])
#draw a solid horizontal line for the x axis
lims <- current.panel.limits()
panel.abline(h = lims$y[1], col = axis.text$col)
}
#draw the axis ticks and labels for bottom and right
axis.default(side, scales = scales, components = components,
..., labels = labels, ticks = ticks, line.col = axis.text$col)
}
#due to the use of y(left) components to specify right
#will need a separate function to draw the left y with just numeric labels
if(side =="left"){
#numeric labels in this instance are all y except for the last 2
comp.list<-components
n<-length(comp.list[["left"]]$ticks$at)
comp.list[["left"]]$ticks$at <- comp.list[["left"]]$ticks$at[1:(n-2)]
comp.list[["left"]]$labels$at <- comp.list[["left"]]$labels$at[1:(n-2)]
comp.list[["left"]]$labels$labels <- comp.list[["left"]]$labels$labels[1:(n-2)]
axis.default(side, scales = scales, components = comp.list,
..., labels = labels, ticks = ticks, line.col = axis.text$col)
}
},
par.settings=theEconomist.theme(box="transparent"),
#specify y to be both numbers and the text labels so y axis width is automated
#this is helpful to make sure the right axis has room to label the end points
scales=list(y=list(alternating=3,at=ylimits,labels=ylabels)),
xlab=NULL,
ylab=NULL,
main=paste("Cumulative Growth Since ",format(index(perf)[1],"%B %Y"),sep=""))
require(PerformanceAnalytics)
par(oma=c(0,2,0,0))
par(mar=c(4,2,4,6))
chart.CumReturns(perf,colorset=mycolors.alpha,lwd=4,
main=NA,xlab=NA,ylab=NA,wealth.index=TRUE,xaxis=FALSE)
#add left justified title
title(main=paste("Cumulative Growth Since ",format(index(perf)[1],"%B %Y"),sep=""),
adj=0,outer=TRUE,line=-2,font.main=1)
#add bottom x axis with dates formatted as years
axis(side=1,
at=c(1,which(format(index(perf),"%Y-%m")%in%format(pretty(index(perf)),"%Y-%m"))),
labels=c(format(index(perf)[1],"%Y"),format(pretty(index(perf)),"%Y")),tick=FALSE,cex.axis=0.9)
#add labels for endpoints on right axis
axis(side=4,
at=Return.cumulative(perf)+1,
labels=colnames(perf),tick=FALSE,cex.axis=0.85,line=-1.5,las=1)
#add points for endpoints
points(x=rep(NROW(perf),2),y=as.numeric(Return.cumulative(perf)+1),
pch=19,cex=1.2,col=mycolors.alpha)

Wednesday, February 1, 2012

Jim Rogers at CFA Society of Alabama Dinner

I am extremely excited to share the announcement that Jim Rogers will present at the CFA Society of Alabama Annual Dinner February 29 at Barber Motorsports Museum in Birmingham.  I believe there is still room for anyone who might like to attend.  Barron’s senior editor Jack Willoughby will moderate.  Congratulations to the CFA Society of Alabama on a high-powered event.

image