Backtesting Classical Technical Patterns
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
In the last post, Classical Technical Patterns, I discussed the algorithm and pattern definitions presented in the Foundations of Technical Analysis by A. Lo, H. Mamaysky, J. Wang (2000) paper. Today, I want to check how different patterns performed historically using SPY.
I will follow the rolling window procedure discussed on pages 14-15 of the paper. Let’s begin by loading the historical data for the SPY and running a rolling window pattern search algorithm.
############################################################################### # Load Systematic Investor Toolbox (SIT) ############################################################################### con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb')) source(con) close(con) #***************************************************************** # Load historical data #****************************************************************** load.packages('quantmod') ticker = 'SPY' data = getSymbols(ticker, src = 'yahoo', from = '1970-01-01', auto.assign = F) data = adjustOHLC(data, use.Adjusted=T) #***************************************************************** # Search for all patterns over a rolling window #****************************************************************** load.packages('sm') history = as.vector(coredata(Cl(data))) window.L = 35 window.d = 3 window.len = window.L + window.d patterns = pattern.db() found.patterns = c() for(t in window.len : (len(history)-1)) { ret = history[(t+1)]/history[t]-1 sample = history[(t - window.len + 1):t] obj = find.extrema( sample ) if(len(obj$data.extrema.loc) > 0) { out = find.patterns(obj, patterns = patterns, silent=F, plot=F) if(len(out)>0) found.patterns = rbind(found.patterns,cbind(t,out,t-window.len+out, ret)) } if( t %% 10 == 0) cat(t, 'out of', len(history), '\n') } colnames(found.patterns) = spl('t,start,end,tstart,tend,ret')
There are many patterns that are found multiple times. Let’s remove the entries that refer to the same pattern and keep only the first occurrence.
#***************************************************************** # Clean found patterns #****************************************************************** # remove patterns that finished after window.L found.patterns = found.patterns[found.patterns[,'end'] <= window.L,] # remove the patterns found multiple times, only keep first one pattern.names = unique(rownames(found.patterns)) all.patterns = c() for(name in pattern.names) { index = which(rownames(found.patterns) == name) temp = NA * found.patterns[index,] i.count = 0 i.start = 1 while(i.start < len(index)) { i.count = i.count + 1 temp[i.count,] = found.patterns[index[i.start],] subindex = which(found.patterns[index,'tstart'] > temp[i.count,'tend']) if(len(subindex) > 0) { i.start = subindex[1] } else break } all.patterns = rbind(all.patterns, temp[1:i.count,]) }
Now we can visualize the performance of each pattern using the charts from my presentation about Seasonality Analysis and Pattern Matching at the R/Finance conference.
#***************************************************************** # Plot #****************************************************************** # Frequency for each Pattern frequency = tapply(rep(1,nrow(all.patterns)), rownames(all.patterns), sum) layout(1) barplot.with.labels(frequency/100, 'Frequency for each Pattern') # Summary for each Pattern all.patterns[,'ret'] = history[(all.patterns[,'t']+20)] / history[all.patterns[,'t']] - 1 data_list = tapply(all.patterns[,'ret'], rownames(all.patterns), list) group.seasonality(data_list, '20 days after Pattern') # Details for BBOT pattern layout(1) name = 'BBOT' index = which(rownames(all.patterns) == name) time.seasonality(data, all.patterns[index,'t'], 20, name)
The Broadening bottoms (BBOT) and Rectangle tops (RTOP) worked historically well for SPY.
To view the complete source code for this example, please have a look at the bt.patterns.test() function in rfinance2012.r at github.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.