I am currently working my way through the Stanford Machine Learning course as well as trying to get a bit more familiar with the statistical language R.
I am also interested in using tools to help make better trading decisions. I am not particularly sold on pure systematic/algorithmic trading systems, and have spent a reasonable chunk of the last few years investigating them. Price tells an important story, and one that is easily absorbed by looking at a chart. It's not so easy to quantify that into an algorithm, and there are some structural and practical issues that bother me about systematic trading.
But hey, it's fun to play with, and you never know when it might come in handy.
The base system is for now going long when price is above the 200 day moving average. Mebane Faber at Cambria Investment Management has some solid research around moving average systems available in his paper A Quantitative Approach to Tactical Asset Allocation. It's usually worth watching what everyone else is watching, if only because that's what everyone else is watching, and for equities at least the 200 day moving average is not uncommon.
Why long only? Well that is what the political economy wants, and who am I to argue.
A table of performance stats, with and without the moving average is as follows:
So, we objectively reduced drawdowns (some very large, hairy drawdowns), and increased the average annual return. But in absolute terms nothing at all to write home about.
I'm using numbers like the Sharpe ratio not because I believe its particularly great, but it is fairly common and well understood. I am looking to use it as a relative measure to determine if modifications lead to improvements, namely by higher risk adjusted return, which Sharpe reflects at least on some level.
Charts of the two equity curves and the code are below. The code is based off the version published by Joshua Ulrich in this post which I am very greatful for.
Next we'll take a look at adding a simple volatility filter using VIX.
require(quantmod)
require(PerformanceAnalytics)
#get the data and fill out the MA
getSymbols('SPY', from='1999-01-01')
SPY$ma200 <- SMA(Cl(SPY), 200)
#lets look at it from 2000 to 2011
spy <- SPY['2000/2011']
#our baseline, unfiltered results
ret <- ROC(Cl(spy))
eq <- exp(cumsum(na.omit(ret)))
#our comparision, filtered result
ma_sig <- Lag(ifelse(Cl(spy) > spy$ma200, 1, 0))
ma_ret <- ROC(Cl(spy)) * ma_sig
ma_eq <- exp(cumsum(na.omit(ma_ret)))
maxDrawdown(ret)
maxDrawdown(ma_ret)
table.AnnualizedReturns(ret)
table.AnnualizedReturns(ma_ret)