Beating Kenneth French Small – High
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
With 148 pageviews over the last 24 hours, my post Kenneth French Gift to the Finance World has been popular relative to most of my other posts. I think the popularity is due to Kenneth French’s notoriety and the amazing outperformance of Small Size and High Momentum stocks since 1927. 18% annualized returns are hard to beat, but I thought I should give it a try. My first line of attack will be reducing the drawdown with some two popular and one not so popular price-based systems.
Great success was unfortunately not achieved, but I was able to reduce the drawdown to 50% from 79%. If anybody has better ideas, please let me know. I would love to see them and share them.
From TimelyPortfolio |
From TimelyPortfolio |
Try a very subtle change by using the average return price series of all Small Size to determine the rank-based signal. Performance is improved slightly.
From TimelyPortfolio |
#the real challenge now is how to beat the best #small momentum with a system #get very helpful Ken French data #for this project we will look at Momentum Portfolios #http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_Prior_12_2.zip require(PerformanceAnalytics) require(quantmod) require(ggplot2) my.url="http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/6_Portfolios_ME_Prior_12_2.zip" my.tempfile<-paste(tempdir(),"\\frenchmomentum.zip",sep="") my.usefile<-paste(tempdir(),"\\6_Portfolios_ME_Prior_12_2.txt",sep="") download.file(my.url, my.tempfile, method="auto", quiet = FALSE, mode = "wb",cacheOK = TRUE) unzip(my.tempfile,exdir=tempdir(),junkpath=TRUE) #read space delimited text file extracted from zip french_momentum <- read.table(file=my.usefile, header = TRUE, sep = "", as.is = TRUE, skip = 12, nrows=1013) colnames(french_momentum) <- c(paste("Small", colnames(french_momentum)[1:3],sep="."), paste("Large",colnames(french_momentum)[1:3],sep=".")) #get dates ready for xts index datestoformat <- rownames(french_momentum) datestoformat <- paste(substr(datestoformat,1,4), substr(datestoformat,5,7),"01",sep="-") #get xts for analysis french_momentum_xts <- as.xts(french_momentum[,1:6], order.by=as.Date(datestoformat)) french_momentum_xts <- french_momentum_xts/100 charts.PerformanceSummary(french_momentum_xts[,1:3],ylog=TRUE, main="Performance by Kenneth French Size and Momentum Monthly Since 1927", colorset=c("cadetblue3","cadetblue","cadetblue4", "darkolivegreen3","darkolivegreen","darkolivegreen4")) mtext("Source: http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html", side=1,adj=0,cex=0.75) #dev.off() #get price series of small cap high momentum for system building french_momentum_price <- cumprod(1+french_momentum_xts[,3]) #speedy solution for ranking from Charles Berry # http://r.789695.n4.nabble.com/efficient-rolling-rank-td2013535.html #rolling rank of price over last 12 months (12 means max price for last 12) #pad first 11 with NA nper <- 10 x.rank <- c(rep(NA,nper-1),rowSums(coredata(french_momentum_price)[ -(1:(nper-1)) ] >= embed(french_momentum_price,nper))) x.rank <- as.xts(x.rank,order.by=index(french_momentum_price)) signalRank <- ifelse(x.rank[,1] > 3 | french_momentum_price >= runMax(french_momentum_price,2),1,0) retRank <- lag(signalRank,k=1)*french_momentum_xts[,3] #try rolling 10 month moving average popularized by Mebane Faber signalAvg <- ifelse(french_momentum_price > runMean(french_momentum_price,n=10),1,0) retAvg <- lag(signalAvg,k=1)*french_momentum_xts[,3] #try RSI signalRSI <- ifelse(RSI(french_momentum_price,n=4) > 45,1,0) retRSI <- lag(signalRSI,k=1)*french_momentum_xts[,3] retCompare <- merge(retRank,retAvg,retRSI,french_momentum_xts[,3]) colnames(retCompare) <- c("Small.High.Rank", "Small.High.Avg","Small.High.RSI","Small.High.Benchmark") #jpeg(filename="performance of small-high with systems.jpg",quality=100,width=6.25, height = 8, units="in",res=96) charts.PerformanceSummary(retCompare,ylog=TRUE,cex.legend=1.2, colorset = c("cadetblue","darkolivegreen3","purple","gray70"), main="Kenneth French Small Size and High Momentum Stocks Compared To Various Price Systems") #dev.off() #jpeg(filename="capture of small-high with systems.jpg",quality=100,width=6.25, height = 8, units="in",res=96) chart.CaptureRatios(retCompare[,1:3],retCompare[,4], main="Kenneth French Small Size and High Momentum Stocks Compared To Various Price Systems") #dev.off() #get average of small size for additional system testing french_momentum_avg <- cumprod(1+apply(coredata(french_momentum_xts[,c(1:3)]),MARGIN=1,FUN=mean)) french_momentum_avg <- as.xts(french_momentum_avg,order.by=index(french_momentum_price)) nper <- 10 x.rank <- c(rep(NA,nper-1),rowSums(coredata(french_momentum_avg)[ -(1:(nper-1)) ] >= embed(french_momentum_avg,nper))) x.rank <- as.xts(x.rank,order.by=index(french_momentum_avg)) signalRankAvg <- ifelse(x.rank[,1] > 3 | french_momentum_price >= runMax(french_momentum_price,2),1,0) retRankAvg <- lag(signalRankAvg,k=1)*french_momentum_xts[,3] retCompare <- merge(retRank,retRankAvg,french_momentum_xts[,3]) colnames(retCompare) <- c("Small.High.Rank", "Small.High.RankOnAvg","Small.High.Benchmark") #jpeg(filename="performance of small-high with 2 rank systems.jpg",quality=100,width=6.25, height = 8, units="in",res=96) charts.PerformanceSummary(retCompare,ylog=TRUE,cex.legend=1.2, colorset = c("cadetblue","darkolivegreen3","gray70"), main="Kenneth French Small Size and High Momentum Stocks Compared To Rank-based Price Systems") #dev.off()
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.