Home > Backtesting, R, Strategy, Trading Strategies > Intraday Backtest

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.

  1. December 29, 2012 at 3:13 pm

    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.

  2. Mark
    April 23, 2014 at 5:10 am

    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).

  3. Mark
    April 29, 2014 at 8:26 am

    …and open position at begining of the day (9:30).

  4. Karlton Hoskins
    May 14, 2014 at 5:51 pm

    Great Work. What is the time zone for the imported historical data?

  1. April 23, 2012 at 9:20 am
  2. January 14, 2014 at 3:13 am
  3. March 10, 2014 at 2:44 am

Leave a comment