Home > Factors, Portfolio Construction, R > Factor Attribution 2

Factor Attribution 2

I want to continue with Factor Attribution theme that I presented in the Factor Attribution post. I have re-organized the code logic into the following 4 functions:

  • factor.rolling.regression – Factor Attribution over given rolling window
  • factor.rolling.regression.detail.plot – detail time-series plot and histogram for each factor
  • factor.rolling.regression.style.plot – historical style plot for selected 2 factors
  • factor.rolling.regression.bt.plot – compare fund’s performance with portfolios implied by Factor Attribution

Let’s first replicate style and performance charts from the Three Factor Rolling Regression Viewer at the mas financial tools web site.

###############################################################################
# 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')	
	tickers = 'VISVX'

	periodicity = 'months'
		
	data <- new.env()
	getSymbols(tickers, src = 'yahoo', from = '1980-01-01', env = data, auto.assign = T)
	for(i in ls(data)) {
		temp = adjustOHLC(data[[i]], use.Adjusted=T)							
		
		period.ends = endpoints(temp, periodicity)
			period.ends = period.ends[period.ends > 0]

		if(periodicity == 'months') {
			# reformat date to match Fama French Data
			monthly.dates = as.Date(paste(format(index(temp)[period.ends], '%Y%m'),'01',sep=''), '%Y%m%d')
			data[[i]] = make.xts(coredata(temp[period.ends,]), monthly.dates)
		} else
			data[[i]] = temp[period.ends,]
	}
	data.fund = data[[tickers]]
	
	#*****************************************************************
	# Fama/French factors
	#****************************************************************** 
	factors = get.fama.french.data('F-F_Research_Data_Factors', periodicity = periodicity,download = T, clean = F)

	# add factors and align
	data <- new.env()
		data[[tickers]] = data.fund
	data$factors = factors$data / 100
	bt.prep(data, align='remove.na', dates='1994::')

	#*****************************************************************
	# Facto Loadings Regression
	#****************************************************************** 
	obj = factor.rolling.regression(data, tickers, 36)

	#*****************************************************************
	# Reports
	#****************************************************************** 
	factor.rolling.regression.detail.plot(obj)

	factor.rolling.regression.style.plot(obj)

	factor.rolling.regression.bt.plot(obj)

Next let’s add the Momentum factor from the Kenneth R French: Data Library and run Factor Attribution one more time.

	#*****************************************************************
	# Fama/French factors + Momentum
	#****************************************************************** 
	factors = get.fama.french.data('F-F_Research_Data_Factors', periodicity = periodicity,download = T, clean = F)

	factors.extra = get.fama.french.data('F-F_Momentum_Factor', periodicity = periodicity,download = T, clean = F)	
		factors$data = merge(factors$data, factors.extra$data) 
	
	# add factors and align
	data <- new.env()
		data[[tickers]] = data.fund
	data$factors = factors$data / 100
	bt.prep(data, align='remove.na', dates='1994::')

	#*****************************************************************
	# Facto Loadings Regression
	#****************************************************************** 
	obj = factor.rolling.regression(data, tickers, 36)

	#*****************************************************************
	# Reports
	#****************************************************************** 
	factor.rolling.regression.detail.plot(obj)

	factor.rolling.regression.style.plot(obj)

	factor.rolling.regression.bt.plot(obj)


To visualize style from the Momentum point of view, let’s create a style chart that shows fund’s attribution in the HML / Momentum space.

	factor.rolling.regression.style.plot(obj, xfactor='HML', yfactor='Mom')

I designed the Factor Attribution functions to take any user specified factors. This way you can easily run Factor Attribution on any combination of the historical factor returns from the Kenneth R French: Data Library Or use your own historical factor returns data.

To view the complete source code for this example, please have a look at the three.factor.rolling.regression() function in bt.test.r at github.

About these ads
  1. John Mach
    June 28, 2012 at 9:47 am | #1

    Thanks for you blog, I always find it very informative. I was wondering how would you use your own factor models. could you give me an example of one factor that is loaded from a saved .txt file in same format as the FF factors are. eg. one factor I use is Emerging Market over US Market i.e. MSCI EM vs S&P 500.

    • June 30, 2012 at 3:41 am | #2

      John,

      Let’s say you store the EEM/SPY factor in the “EEM_SPY.csv” file. For this example, I created some sample weekly data for EEM/SPY factor using following code:

      	#*****************************************************************
      	# Load historical data
      	#****************************************************************** 
      	load.packages('quantmod')	
      	tickers = spl('EEM,SPY')
      	
      	data <- new.env()
      	getSymbols(tickers, src = 'yahoo', from = '1970-01-01', env = data, auto.assign = T)
      		for(i in ls(data)) data[[i]] = adjustOHLC(data[[i]], use.Adjusted=T)		
      	bt.prep(data, align='remove.na')
      	
      	#*****************************************************************
      	# Create weekly factor
      	#****************************************************************** 
      	prices = data$prices
      	
      	periodicity = 'weeks'
      	period.ends = endpoints(prices, periodicity)
      		period.ends = period.ends[period.ends > 0]
      	
      	hist.returns = ROC(prices[period.ends,], type = 'discrete')	
      		hist.returns = na.omit(hist.returns)
      	
      	#Emerging Market over US Market i.e. MSCI EM vs S&P 500 = EEM - SPY	
      	EEM_SPY = hist.returns$EEM - hist.returns$SPY
      		colnames(EEM_SPY) = 'EEM_SPY'
      	
      	write.xts(EEM_SPY, 'EEM_SPY.csv')
      

      Now let’s add the EEM/SPY factor to the Fama/French 3 factor model:

      	#*****************************************************************
      	# Load historical data
      	#****************************************************************** 
      	load.packages('quantmod')	
      	tickers = 'VISVX'
      		
      	data <- new.env()
      	getSymbols(tickers, src = 'yahoo', from = '1980-01-01', env = data, auto.assign = T)
      	for(i in ls(data)) {
      		temp = adjustOHLC(data[[i]], use.Adjusted=T)							
      		
      		period.ends = endpoints(temp, periodicity)
      			period.ends = period.ends[period.ends > 0]
      
      		data[[i]] = temp[period.ends,]
      	}
      	data.fund = data[[tickers]]
      		
      	#*****************************************************************
      	# Fama/French factors
      	#****************************************************************** 
      	factors = get.fama.french.data('F-F_Research_Data_Factors', periodicity = periodicity,download = F, clean = F)
      
      	factors.extra = 100 * read.xts('EEM_SPY.csv')
      		factors$data = merge(factors$data, factors.extra, join='inner')
      	# add factors and align
      	data <- new.env()
      		data[[tickers]] = data.fund
      	data$factors = factors$data / 100
      	bt.prep(data, align='remove.na')
      	
      	#*****************************************************************
      	# Check Correlations, make sure the EEM/SPY factor is NOT highly correlated
      	#****************************************************************** 	
      	load.packages('psych')
      	pairs.panels(coredata(data$factors))	
      	
      	#*****************************************************************
      	# Facto Loadings Regression
      	#****************************************************************** 
      	obj = factor.rolling.regression(data, tickers, 36)
      
      	#*****************************************************************
      	# Reports
      	#****************************************************************** 
      	factor.rolling.regression.detail.plot(obj)
      
      	factor.rolling.regression.style.plot(obj)
      
      	factor.rolling.regression.style.plot(obj, xfactor='HML', yfactor='EEM_SPY')
      
      	factor.rolling.regression.bt.plot(obj)
      

  2. John Mach
    July 3, 2012 at 4:05 pm | #3

    Thank for your detailed reply. Much appreciate it.
    best wishes,
    John

  1. July 4, 2012 at 3:34 am | #1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 207 other followers

%d bloggers like this: