Calendar Strategy: Fed Days
UPDATE: I was pointed out a problem with original post due to look ahead bias introduced by prices > SMA(prices,100) statement. In the calendar strategy logic I did not use a usual lag of one day because important days are known before hand. However, the prices > SMA(prices,100) statement should be lagged by one day. I updated plots and source code.
Today, I want to follow up with the Calendar Strategy: Option Expiry post. Let’s examine the importance of the FED meeting days as presented in the Fed Days And Intermediate-Term Highs post.
Let’s dive in and examine historical perfromance of SPY during FED meeting days:
############################################################################### # Load Systematic Investor Toolbox (SIT) # https://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') tickers = spl('SPY') data <- new.env() getSymbols.extra(tickers, src = 'yahoo', from = '1980-01-01', env = data, set.symbolnames = T, auto.assign = T) for(i in data$symbolnames) data[[i]] = adjustOHLC(data[[i]], use.Adjusted=T) bt.prep(data, align='keep.all', fill.gaps = T) #***************************************************************** # Setup #***************************************************************** prices = data$prices n = ncol(prices) dates = data$dates models = list() universe = prices > 0 # 100 day SMA filter universe = universe & prices > SMA(prices,100) # Find Fed Days info = get.FOMC.dates(F) key.date.index = na.omit(match(info$day, dates)) key.date = NA * prices key.date[key.date.index,] = T #***************************************************************** # Strategy #***************************************************************** signals = list(T0=0) for(i in 1:15) signals[[paste0('N',i)]] = 0:i signals = calendar.signal(key.date, signals) models = calendar.strategy(data, signals, universe = universe) strategy.performance.snapshoot(models, T, sort.performance=F)
Please note 100 day moving average filter above. If we take it out, the performance deteriorates significantly.
# custom stats out = sapply(models, function(x) list( CAGR = 100*compute.cagr(x$equity), MD = 100*compute.max.drawdown(x$equity), Win = x$trade.summary$stats['win.prob', 'All'], Profit = x$trade.summary$stats['profitfactor', 'All'] )) performance.barchart.helper(out, sort.performance = F) strategy.performance.snapshoot(models$N15, control=list(main=T)) last.trades(models$N15) trades = models$N15$trade.summary$trades trades = make.xts(parse.number(trades[,'return']), as.Date(trades[,'entry.date'])) layout(1:2) par(mar = c(4,3,3,1), cex = 0.8) barplot(trades, main='N15 Trades', las=1) plot(cumprod(1+trades/100), type='b', main='N15 Trades', las=1)
N15 Strategy:
With this post I wanted to show how easily we can study calendar strategy performance using the Systematic Investor Toolbox.
Next, I will look at the importance of the Dividend days.
To view the complete source code for this example, please have a look at the bt.calendar.strategy.fed.days.test() function in bt.test.r at github.
Thanks, very interesting. Could you explain why some trade in the N15 example are held for only a couple of days e.g. the trade entered on 2012-06-18? Doesn’t the N 15 mean hold for 15 days from the Fed day?
Please note the 100 day moving average filter. If during 15 days, SPY drops below its 100 day moving average, we exit position until SPY is above its 100 day moving average and 15 days has not yet passed since Fed meeting day.
Could you clarify what N15 means? Are you buying on the evening before a Fed day and holding for 15 days? Your entry/exit dates suggest that, except the entry on 6/18/12 exited 2 days later, so it is not clear what this strategy is doing. These are interesting studies.
N15 – enter at the close a day before Fed meeting and exit 15 days later. If during that period SPY drops below its 100 day moving average, we exit and only re-enter if SPY is above its 100 day moving average and 15 days has not yet passed since Fed meeting day.
Dear,
As always, very interesting.
Could you please show a way to test whether the return during any N day period after a FED meeting is statistically different from any N day period where there is not a FED meeting?
On the same subject of calendar strategies could you show how to recreate using R the Day of the month graph from marketsci: http://marketsci.wordpress.com/2014/01/30/day-of-month-seasonality-for-february-2/ ?
Thanks in advance and keep up the great blogging!