Intraday Backtest
I came across a free source of Intraday Forex data while reading Forex Trading with R : Part 1 post. You can download either Daily or Hourly historical Forex data from the FXHISTORICALDATA.COM.
The outline of this post:
- Download and Import Forex data
- Reference and Plot Intraday data
- Daily Backtest
- Intraday Backtest
First,I created a getSymbols.fxhistoricaldata() function in data.r at github to download Forex data from the FXHISTORICALDATA.COM. Following code loads ‘EURUSD’ hourly data and creates a candle chart for 2012:03:06 from 10 to 21 hours using the Systematic Investor Toolbox:
############################################################################### # Load Systematic Investor Toolbox (SIT) # https://systematicinvestor.wordpress.com/systematic-investor-toolbox/ ############################################################################### con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb')) source(con) close(con) #***************************************************************** # Load historical data #****************************************************************** load.packages('quantmod') EURUSD = getSymbols.fxhistoricaldata('EURUSD', 'hour', auto.assign = F, download=T) SPY = getSymbols('SPY', src = 'yahoo', from = '1980-01-01', auto.assign = F) #***************************************************************** # Reference intraday period #****************************************************************** plota(EURUSD['2012:03:06 10::2012:03:06 21'], type='candle', main='EURUSD on 2012:03:06 from 10 to 21')
We can reference Intraday data by specifying hours, minutes, and seconds in addition to year, month, and day. I.e. YYYY:MM:DD HH:MM:SS
Next, let’s combine Daily price for SPY and Intraday quotes for EURUSD in one chart.
#***************************************************************** # Plot hourly and daily prices on the same chart #****************************************************************** # two Y axis plot dates= '2012:01:01::2012:01:11' y = SPY[dates] plota(y, type = 'candle', LeftMargin=3) y = EURUSD[dates] plota2Y(y, ylim = range(OHLC(y), na.rm=T), las=1, col='red', col.axis = 'red') plota.ohlc(y, col=plota.candle.col(y)) plota.legend('SPY(rhs),EURUSD(lhs)', 'black,red', list(SPY[dates],EURUSD[dates]))
Next, let’s create a Daily Backtest by investing into Currency Majors: EUR/USD, USD/JPY, GBP/USD, AUD/USD, USD/CHF and USD/CAD. I will investigate an Equal Weight portfolio and Timing portfolio as explained in the A Quantitative Approach to Tactical Asset Allocation by M. Faber (2006) paper.
#***************************************************************** # Universe: Currency Majors # http://en.wikipedia.org/wiki/Currency_pair #****************************************************************** tickers = spl('EURUSD,USDJPY,GBPUSD,AUDUSD,USDCHF,USDCAD') #***************************************************************** # Daily Backtest #****************************************************************** data <- new.env() getSymbols.fxhistoricaldata(tickers, 'day', data, download=T) bt.prep(data, align='remove.na', dates='1990::') prices = data$prices n = len(tickers) models = list() # Equal Weight data$weight[] = NA data$weight[] = ntop(prices, n) models$equal.weight = bt.run.share(data, clean.signal=F) # Timing by M. Faber sma = bt.apply.matrix(prices, SMA, 200) data$weight[] = NA data$weight[] = ntop(prices, n) * (prices > sma) models$timing = bt.run.share(data, clean.signal=F) # Report models = rev(models) plotbt.custom.report.part1(models) plotbt.custom.report.part2(models)
Next, let’s create an Intraday Backtest using the same strategies.
#***************************************************************** # Intraday Backtest #****************************************************************** data <- new.env() getSymbols.fxhistoricaldata(tickers, 'hour', data, download=T) bt.prep(data, align='remove.na', dates='1990::') prices = data$prices n = len(tickers) models = list() # Equal Weight data$weight[] = NA data$weight[] = ntop(prices, n) models$equal.weight = bt.run.share(data, clean.signal=F) # Timing by M. Faber sma = bt.apply.matrix(prices, SMA, 200) data$weight[] = NA data$weight[] = ntop(prices, n) * (prices > sma) models$timing = bt.run.share(data, clean.signal=F) # Report models = rev(models) plotbt.custom.report.part1(models) plotbt.custom.report.part2(models)
Please note that the code for the Daily Backtest and Intraday Backtest is identical except for the line where we download the data:
- Daily Backtest:
getSymbols.fxhistoricaldata(tickers, 'day', data, download=T)
- Intraday Backtest:
getSymbols.fxhistoricaldata(tickers, 'hour', data, download=T)
It is easy to work with Intraday data and it is easy to create Intraday Backtest, right?
To view the complete source code for this example, please have a look at the bt.intraday.test() function in bt.test.r at github.
T and F are not reserved words in R. This is a sneaky gotcha. They can be stock symbols (ATT and Ford), or true/false or the opposite of true/false if someone were so devious as to set them that way.
The term intraday is occasionally used to describe securities that trade on the markets during regular business hour (9:30-16:00 EST). If you have time please explain how to build a strategy with closing position on the market at the end of the day (5 min before RTH Close).
…and open position at begining of the day (9:30).
Great Work. What is the time zone for the imported historical data?