Probabilistic Momentum with Intraday data
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
I want to follow up the Intraday data post with testing the Probabilistic Momentum strategy on Intraday data. I will use Intraday data for SPY and GLD from the Bonnot Gang to test the strategy.
##############################################################################
# Load Systematic Investor Toolbox (SIT)
# http://systematicinvestor.wordpress.com/systematic-investor-toolbox/
###############################################################################
setInternet2(TRUE)
con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb'))
source(con)
close(con)
#*****************************************************************
# Load historical data
#******************************************************************
load.packages('quantmod')
# data from http://thebonnotgang.com/tbg/historical-data/
# please save SPY and GLD 1 min data at the given path
spath = 'c:/Desktop/'
data = bt.load.thebonnotgang.data('SPY,GLD', spath)
data1 <- new.env()
data1$FI = data$GLD
data1$EQ = data$SPY
data = data1
bt.prep(data, align='keep.all', fill.gaps = T)
lookback.len = 120
confidence.level = 60/100
prices = data$prices
ret = prices / mlag(prices) - 1
models = list()
#*****************************************************************
# Simple Momentum
#******************************************************************
momentum = prices / mlag(prices, lookback.len)
data$weight[] = NA
data$weight$EQ[] = momentum$EQ > momentum$FI
data$weight$FI[] = momentum$EQ <= momentum$FI
models$Simple = bt.run.share(data, clean.signal=T)
#*****************************************************************
# Probabilistic Momentum + Confidence Level
# http://cssanalytics.wordpress.com/2014/01/28/are-simple-momentum-strategies-too-dumb-introducing-probabilistic-momentum/
# http://cssanalytics.wordpress.com/2014/02/12/probabilistic-momentum-spreadsheet/
#******************************************************************
ir = sqrt(lookback.len) * runMean(ret$EQ - ret$FI, lookback.len) / runSD(ret$EQ - ret$FI, lookback.len)
momentum.p = pt(ir, lookback.len - 1)
data$weight[] = NA
data$weight$EQ[] = iif(cross.up(momentum.p, confidence.level), 1, iif(cross.dn(momentum.p, (1 - confidence.level)), 0,NA))
data$weight$FI[] = iif(cross.dn(momentum.p, (1 - confidence.level)), 1, iif(cross.up(momentum.p, confidence.level), 0,NA))
models$Probabilistic = bt.run.share(data, clean.signal=T)
data$weight[] = NA
data$weight$EQ[] = iif(cross.up(momentum.p, confidence.level), 1, iif(cross.up(momentum.p, (1 - confidence.level)), 0,NA))
data$weight$FI[] = iif(cross.dn(momentum.p, (1 - confidence.level)), 1, iif(cross.up(momentum.p, confidence.level), 0,NA))
models$Probabilistic.Leverage = bt.run.share(data, clean.signal=T)
#*****************************************************************
# Create Report
#******************************************************************
strategy.performance.snapshoot(models, T)
Next, let’s examine the hourly perfromance of the strategy.
#*****************************************************************
# Hourly Performance
#******************************************************************
strategy.name = 'Probabilistic.Leverage'
ret = models[[strategy.name]]$ret
ret.number = 100*as.double(ret)
dates = index(ret)
factor = format(dates, '%H')
layout(1:2)
par(mar=c(4,4,1,1))
boxplot(tapply(ret.number, factor, function(x) x),outline=T, main=paste(strategy.name, 'Distribution of Returns'), las=1)
barplot(tapply(ret.number, factor, function(x) sum(x)), main=paste(strategy.name, 'P&L by Hour'), las=1)
There are lots of abnormal returns in the 9:30-10:00am box due to big overnight returns. I.e. a return from today’s open to prior’s day close. If we exclude this observation every day, the distribution each hour is more consistent.
#***************************************************************** # Hourly Performance: Remove first return of the day (i.e. overnight) #****************************************************************** day.stat = bt.intraday.day(dates) ret.number[day.stat$day.start] = 0 layout(1:2) par(mar=c(4,4,1,1)) boxplot(tapply(ret.number, factor, function(x) x),outline=T, main=paste(strategy.name, 'Distribution of Returns'), las=1) barplot(tapply(ret.number, factor, function(x) sum(x)), main=paste(strategy.name, 'P&L by Hour'), las=1)
The strategy performs best in the morning and dwindles down in the afternoon and overnight.
These hourly seasonality plots are just a different way to analyze performance of the strategy based on Intraday data.
To view the complete source code for this example, please have a look at the bt.strategy.intraday.thebonnotgang.test() function in bt.test.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.


