Tuesday, May 31, 2011

Overoptimizing Chicago Fed

THIS SHOULD BE OBVIOUS THROUGHOUT THE POST BUT THIS IS NOT INVESTMENT ADVICE.  PLEASE DO NOT FOLLOW THIS SYSTEM AS IT COULD RESULT IN SERIOUS LOSSES.

One of the perils of system-building is the tendency to unintentionally overoptimize by playing/refining the parameters to fit history.  It starts with some harmless data playing but very possibly a system appears with some potential like that shown in More St. Louis Fred Fun with National Financial Conditions.  Then through some form of iterative adjusting something seemingly magical occurs.

From TimelyPortfolio
From TimelyPortfolio
From TimelyPortfolio

However, after this subtle adjusting, I have no more data to test what might be something worthwhile, so I’m left with something to watch but not something on which I would risk my assets.

Play away but be careful.  It is much better to start with an idea, test this idea with a limited dataset, and then extend the test to a much more encompassing out-of-sample dataset in terms of timeframes, other countries, or other asset classes.

 

R code:

#this bit of code will show a system after significant
#optimization and hindsight bias
#without any out-of-sample testing
#explore how SP500 behaves in different ranges of Financial Conditions
#see previous posts for more discussion  
require(quantmod)
require(PerformanceAnalytics)
require(ggplot2)   #get data from St. Louis Federal Reserve (FRED)
getSymbols("SP500",src="FRED") #load SP500
getSymbols("ANFCI",src="FRED") #load Adjusted Chicago Financial
getSymbols("CFNAI",src="FRED") #load Chicago National Activity
#do not use this but here in case you want to play
getSymbols("PANDI",src="FRED") #load Chicago Fed Production and Income    
#do a little manipulation to get the data lined up on weekly basis
SP500 <- to.monthly(SP500)[,4]
ANFCI <- to.monthly(ANFCI)[,4]
CFNAI <- to.monthly(CFNAI)[,4]
PANDI <- to.monthly(PANDI)[,4]
index(SP500) <- as.Date(index(SP500))
index(ANFCI) <- as.Date(index(ANFCI))
index(CFNAI) <- as.Date(index(CFNAI))
index(PANDI) <- as.Date(index(PANDI))    
SP500_ANFCI <- na.omit(merge(ROC(SP500,n=1,type="discrete"),
ANFCI,CFNAI,PANDI))        
#and just for fun an enhanced very basic system
signal <- runSum(-0.25*SP500_ANFCI[,2]-SP500_ANFCI[,3],n=4)
chartSeries(signal, name="Chicago Fed Signal")
signal <- lag(signal,k=1)
#go long if extremely negative (signal>10)
#or good but not too good (signal between -.25 and -2)
ret <- ifelse(signal>10 | (signal <= -0.25 & signal > -2.25) , 1, 0) * SP500_ANFCI[,1]
ret <- merge(ret, SP500_ANFCI[,1])
colnames(ret) <- c("ChicagoFed_LongOnlySystem","SP500")
charts.PerformanceSummary(ret, ylog=TRUE, main="Over-optimized Chicago Fed S&P 500 System",
colorset=c("cadetblue","darkolivegreen3"))    
#I really like the boxplot by range, so let's do the same here
df <- na.omit(merge(round(signal,0),ROC(SP500,n=1,type="discrete")))
df <- as.data.frame(cbind(index(df),
coredata(df)))
colnames(df) <- c("date","ChiFedSignal","SP500return")
ggplot(df,aes(factor(ChiFedSignal),SP500return)) +
geom_boxplot(aes(colour = factor(ChiFedSignal))) +
opts(title="Box Plot of SP500 Monthly Change by Chicago Fed Signal")

Created by Pretty R at inside-R.org

Monday, May 30, 2011

More St. Louis Fred Fun with National Financial Conditions

I owe someone at the Fed a beer for all the recent additions at http://research.stlouisfed.org/fred2/.  I have covered some in Spreads and Stress and Gifts from BAC ML and the Federal Reserve.  The newest addition 8 Chicago Fed Indexes Added to FRED contains a nice weekly series on US National Financial Conditions that I’m sure we can use.

From TimelyPortfolio

How does the S&P 500 look against the Chicago Fed Adjusted National Financial Conditions (ANFCI) index?  I did not look at the nonadjusted FCI, but I’m sure it offers potentially useful information also.

From TimelyPortfolio
From TimelyPortfolio

Can we build a silly system with the S&P 500 and ANFCI?  THIS IS MERELY AN ILLUSTRATION AND DOES NOT CONSTITUTE FINANCIAL ADVICE.  YOUR GAINS AND LOSSES ARE YOUR OWN RESPONSIBILITY.

From TimelyPortfolio

Nothing particularly special system-wise, but 1998-2004 is a very abnormal circumstance.

R code:

#explore how SP500 behaves in different ranges of Financial Conditions   
require(quantmod)
require(PerformanceAnalytics)
require(ggplot2)   #get data from St. Louis Federal Reserve (FRED)
getSymbols("SP500",src="FRED") #load SP500
getSymbols("ANFCI",src="FRED") #load Adjusted Chicago Financial  
#show a chart of ANFCI
chartSeries(ANFCI,theme="white",name="Adjusted National Financial Conditions (ANFCI)")
#do a little manipulation to get the data lined up on weekly basis
SP500 <- to.weekly(SP500)[,4]
ANFCI <- to.weekly(ANFCI)[,4]
#get weekly format to yyyy-mm-dd with the first day of the week
index(SP500) <- as.Date(index(SP500))
index(ANFCI) <- as.Date(index(ANFCI))  
#use floor to get ranges for ANFCI so we can run boxplots
ANFCI <- floor(ANFCI)
#lag ANFCI signal
ANFCI <- lag(ANFCI,k=1)   #merge sp500 returns and ANFCI
SP500_ANFCI <- na.omit(merge(ROC(SP500,n=1,type="discrete"),ANFCI))
colnames(SP500_ANFCI) <- c("SP500","ANFCI")  
#convert xts to data frame for ggplot boxplot exploration
df <- as.data.frame(cbind(index(SP500_ANFCI),
coredata(SP500_ANFCI[,1:2])))
ggplot(df,aes(factor(ANFCI),SP500)) +
geom_boxplot(aes(colour = factor(ANFCI))) +
opts(title="Box Plot of SP500 Weekly Change by Adjusted Financial Conditions")      
#show linked returns based on Adjusted Financial Conditions
ret_eq_neg3 <- ifelse(SP500_ANFCI[,2] == -3, SP500_ANFCI[,1], 0)
ret_eq_neg2 <- ifelse(SP500_ANFCI[,2] == -2, SP500_ANFCI[,1], 0)
ret_eq_neg1 <- ifelse(SP500_ANFCI[,2] == -1, SP500_ANFCI[,1], 0)
ret_eq_0 <- ifelse(SP500_ANFCI[,2] == 0, SP500_ANFCI[,1], 0)
ret_eq_pos1 <- ifelse(SP500_ANFCI[,2] == 1, SP500_ANFCI[,1], 0)
ret_eq_pos2 <- ifelse(SP500_ANFCI[,2] == 2, SP500_ANFCI[,1], 0)
ret_eq_pos3 <- ifelse(SP500_ANFCI[,2] == 3, SP500_ANFCI[,1], 0)
ret_eq_pos4 <- ifelse(SP500_ANFCI[,2] == 4, SP500_ANFCI[,1], 0)
ret_eq_pos5 <- ifelse(SP500_ANFCI[,2] == 5, SP500_ANFCI[,1], 0)  
#merge series for PerformanceSummary chart
ret_comp <- merge(ret_eq_neg3, ret_eq_neg2, ret_eq_neg1, ret_eq_0,
ret_eq_pos1,ret_eq_pos2,ret_eq_pos3,ret_eq_pos4,ret_eq_pos5)
#name columns for the legend
colnames(ret_comp) <- c("ANFCI=-3","ANFCI=-2","ANFCI=-1","ANFCI=0",
"ANFCI=1","ANFCI=2","ANFCI=3","ANFCI=4","ANFCI=5")  
charts.PerformanceSummary(ret_comp, main="SP500 Linked Returns by Financial Conditions")       
#and just for fun a very basic system
signal <- runMax(SP500_ANFCI[,2] , n=10)
#go long if Max of ANFCI over last ten weeks is 0; already lagged earlier
ret <- ifelse(signal <= 0, 1, 0) * SP500_ANFCI[,1]
ret <- merge(ret, SP500_ANFCI[,1])
colnames(ret) <- c("ANFCI_LongOnlySystem","SP500")
charts.PerformanceSummary(ret, ylog=TRUE, main="Very Simple ANFCI S&P 500 System",
colorset=c("cadetblue","darkolivegreen3"))

Created by Pretty R at inside-R.org

Thursday, May 26, 2011

Clustering with Currencies and Fidelity Funds

Great news came yesterday with the release of the R In Finance 2011 Presentations.  I must attend next year after seeing all that I missed.  The Iacus: Statistical Analysis of Financial Time Series and Option Pricing in R (pdf) presentation offered a different method of clustering than that shown in yesterday’s post Eigen-who? How Can I Write About Eigen-anything and Expect You to Read?, so I thought it would be fun to quickly run his Markov Operator Distance example on the currency data from yesterday. As always, please comment liberally and point out any errors.  Mr. Iacus does not use the change but rather price in his analysis.  Knowing far less about these methods, I think using percentage change makes more sense.  I’ll use price first and then show results using percentage change.

From TimelyPortfolio
From TimelyPortfolio

As I said above, price is used, but I thought I should run on price change also.  These results make more sense to me since I know that the Chinese Yuan has been closely pegged to the US Dollar over the analysis period.

From TimelyPortfolio

A very good friend of mine has a 401k with various Fidelity mutual funds, so let’s run the same techniques on his set of Fidelity Fund options.  To avoid repetition, I will only run on price change rather than price.  I only included the equity fund options, so FPURX Fidelity Puritan with only 60% equities makes sense that it is all alone.

From TimelyPortfolio
From TimelyPortfolio
From TimelyPortfolio

R code:

#extends post on principal component analysis with MODist
#using example from http://www.rinfinance.com/agenda/2011/StefanoIacus.pdf
#on currency data and fidelity mutual fund data   require(quantmod)   #get currency data from the FED FRED data series
Korea <- getSymbols("DEXKOUS",src="FRED",auto.assign=FALSE) #load Korea
Malaysia <- getSymbols("DEXMAUS",src="FRED",auto.assign=FALSE) #load Malaysia
Singapore <- getSymbols("DEXSIUS",src="FRED",auto.assign=FALSE) #load Singapore
Taiwan <- getSymbols("DEXTAUS",src="FRED",auto.assign=FALSE) #load Taiwan
China <- getSymbols("DEXCHUS",src="FRED",auto.assign=FALSE) #load China
Japan <- getSymbols("DEXJPUS",src="FRED",auto.assign=FALSE) #load Japan
Thailand <- getSymbols("DEXTHUS",src="FRED",auto.assign=FALSE) #load Thailand
Brazil <- getSymbols("DEXBZUS",src="FRED",auto.assign=FALSE) #load Brazil
Mexico <- getSymbols("DEXMXUS",src="FRED",auto.assign=FALSE) #load Mexico
India <- getSymbols("DEXINUS",src="FRED",auto.assign=FALSE) #load India
USDOther <- getSymbols("DTWEXO",src="FRED",auto.assign=FALSE) #load US Dollar Other Trading Partners
USDBroad <- getSymbols("DTWEXB",src="FRED",auto.assign=FALSE) #load US Dollar Broad       #combine all the currencies into one big currency xts
currencies <- merge(Korea, Malaysia, Singapore, Taiwan,
China, Japan, Thailand, Brazil, Mexico, India,
USDOther, USDBroad)
currencies <- na.omit(currencies)
colnames(currencies) <- c("Korea", "Malaysia", "Singapore", "Taiwan",
"China", "Japan", "Thailand", "Brazil", "Mexico", "India",
"USDOther", "USDBroad")       #use MODist package as described in the fine presentation
#http://www.rinfinance.com/agenda/2011/StefanoIacus.pdf
require(sde)   currencies <- as.zoo(currencies)
d <- MOdist(currencies)
cl <- hclust( d )
groups <- cutree(cl, k=4)
plot(currencies, col=groups, main="Various Asian and American Currencies
1995-Current"
)
cmd <- cmdscale(d)
colnames(cmd) <- c("first coordinate","second coordinate")
plot( cmd, col=groups, main="MODist of Various Asian and American Currencies
1995-Current"
)
text( cmd, labels(d) , col=groups)   #struggling with whether price or percent change works better
#run again with percentage change
currencies <- ROC(currencies,1,type="discrete")
currencies[1,1:NCOL(currencies)] <- 0
currencies <- as.zoo(currencies)
d <- MOdist(currencies)
cl <- hclust( d )
groups <- cutree(cl, k=4)
cmd <- cmdscale(d)
colnames(cmd) <- c("first coordinate","second coordinate")
plot( cmd, col=groups, main="MODist of Various Asian and American Currencies
Percentage Change 1995-Current"
)
text( cmd, labels(d) , col=groups)     #do the same MODist for some Fidelity Funds
#except just use price change rather than price
tckr<-c("FBGRX","FCNTX","FDGFX","FEQIX","FEXPX",
"FFTYX","FFIDX","FDGRX","FDEGX","FLCSX",
"FMCSX","FOCPX","FDVLX","FSLSX","FIVFX",
"FOSFX","FRESX","FSEMX","FSTMX","FPURX")
start<-"1990-01-01"
end<- format(Sys.Date(),"%Y-%m-%d") # yyyy-mm-dd   # Pull tckr index data from Yahoo! Finance
getSymbols(tckr, from=start, to=end, adjust=TRUE)   fidelity<-na.omit(merge(to.weekly(FBGRX)[,4],to.weekly(FCNTX)[,4],
to.weekly(FDGFX)[,4] ,to.weekly(FEQIX)[,4],
to.weekly(FEXPX)[,4] , to.weekly(FFTYX)[,4],
to.weekly(FFIDX)[,4] , to.weekly(FDGRX)[,4],
to.weekly(FDEGX)[,4] , to.weekly(FLCSX)[,4],
to.weekly(FMCSX)[,4] , to.weekly(FOCPX)[,4],
to.weekly(FDVLX)[,4] , to.weekly(FSLSX)[,4],
to.weekly(FIVFX)[,4] , to.weekly(FOSFX)[,4],
to.weekly(FRESX)[,4] , to.weekly(FSEMX)[,4],
to.weekly(FSTMX)[,4] , to.weekly(FPURX)[,4]))   colnames(fidelity) <- substr(colnames(fidelity),1,5)   fidelity <- ROC(fidelity,1,type="discrete")
fidelity[1,1:NCOL(fidelity)] <- 0
fidelity <- as.zoo(fidelity)   d <- MOdist(fidelity)
cl <- hclust( d )
groups <- cutree(cl, k=5)
plot(fidelity, col=groups, main="Various Fidelity Mutual Funds
1998-Current"
)
cmd <- cmdscale(d)
colnames(cmd) <- c("first coordinate","second coordinate")
plot( cmd, col=groups, main="MODist of Various Fidelity Mutual Funds
1995-Current"
)
text( cmd, labels(d) , col=groups)   #get plot of eigenvalues since we have not done in any
#previous posts
#using techniques from corrgram package documentation
#get correlation matrix
(fidelity.cor <- cor(fidelity,use="pair"))
#get two largest eigenvectors
(fidelity.eig <- eigen(fidelity.cor)$vectors[,1:2])
e1 <- fidelity.eig[,1]
e2 <- fidelity.eig[,2]
#make the chart
plot(e1,e2,col='white', xlim=range(e1,e2), ylim=range(e1,e2),
main="Plot of 2 Largest Eigenvectors for Various Fidelity Funds")
arrows(0, 0, e1, e2, cex=0.5, col=groups, length=0.1)
text(e1,e2, rownames(fidelity.cor), cex=0.75, col=groups)

Created by Pretty R at inside-R.org

Wednesday, May 25, 2011

Eigen-who? How Can I Write About Eigen-anything and Expect You to Read?

After the very nice Convore reply

@timelyportfolio some of your posts include "eigenvalue ratio plots" -- kindly tell us what they show and how they might be useful in constructing a portfolio.

I felt like I should at least attempt to offer a little more detail on eigenvectors, which allow us to visually see similarity between variables (in my mind, time series of asset classes, indexes, stocks, or other financial prices).  In other posts, I have used the fAssets package function assetsCorEigenPlot for Long XLU Short SPY and  Russell Napier, ASIP in FT Says Emerging Market CurrenciesMichael Friendly’s wonderful paper does a very fine job of explaining eigenvalues and their use in sorting for helpful visualizations of correlation.  Wikipedia also gives a decent introduction in these two articles http://en.wikipedia.org/wiki/Principal_component_analysis and http://en.wikipedia.org/wiki/Eigenvector.  Also, I’m anxious to read the following book whose authors run http://factominer.free.fr/classical-methods/index.html

Really, the closer the variables in distance and angle, the more closely they are related.  I thought some currency data from the St. Louis Fed would provide a nice example.  Similar to milktrader’s Chop, Slice and Dice Your Returns in R, I also wanted to show multiple ways in R of achieving a plot of eigenvalues with fAssets, SciViews, and corrgram.  This analysis does not yield any real surprises—Mexican Peso and Brazilian Real are closely related, but both are least related to the Japanese Yen.

From TimelyPortfolio
From TimelyPortfolio
From TimelyPortfolio

Since I used Michael Friendly’s paper so much in writing this article, I wanted to show a corrgram of the currency data.  The corrgram package offers lots of potentially useful variations of this visualization.

From TimelyPortfolio

The second part of the Convore question is how can we use eigenvalues to construct a portfolio.  Maybe I can answer that in one of my next posts…

R code:

#explain basics of principal component analysis
#by showing the various methods of charting eigenvalues
#of currency data   #give specific credit to Michael Friendly
#and his paper http://www.math.yorku.ca/SCS/Papers/corrgram.pdf
#another example of similar techniques used for both
#baseball and finance   #for additional information on principal component analysis (PCA)
#see http://en.wikipedia.org/wiki/Principal_component_analysis   require(quantmod)   #get currency data from the FED FRED data series
Korea <- getSymbols("DEXKOUS",src="FRED",auto.assign=FALSE) #load Korea
Malaysia <- getSymbols("DEXMAUS",src="FRED",auto.assign=FALSE) #load Malaysia
Singapore <- getSymbols("DEXSIUS",src="FRED",auto.assign=FALSE) #load Singapore
Taiwan <- getSymbols("DEXTAUS",src="FRED",auto.assign=FALSE) #load Taiwan
China <- getSymbols("DEXCHUS",src="FRED",auto.assign=FALSE) #load China
Japan <- getSymbols("DEXJPUS",src="FRED",auto.assign=FALSE) #load Japan
Thailand <- getSymbols("DEXTHUS",src="FRED",auto.assign=FALSE) #load Thailand
Brazil <- getSymbols("DEXBZUS",src="FRED",auto.assign=FALSE) #load Brazil
Mexico <- getSymbols("DEXMXUS",src="FRED",auto.assign=FALSE) #load Mexico
India <- getSymbols("DEXINUS",src="FRED",auto.assign=FALSE) #load India
USDOther <- getSymbols("DTWEXO",src="FRED",auto.assign=FALSE) #load US Dollar Other Trading Partners
USDBroad <- getSymbols("DTWEXB",src="FRED",auto.assign=FALSE) #load US Dollar Broad   #combine all the currencies into one big currency xts
currencies<-merge(Korea, Malaysia, Singapore, Taiwan,
China, Japan, Thailand, Brazil, Mexico, India,
USDOther, USDBroad)
currencies<-na.omit(currencies)
colnames(currencies)<-c("Korea", "Malaysia", "Singapore", "Taiwan",
"China", "Japan", "Thailand", "Brazil", "Mexico", "India",
"USDOther", "USDBroad")
#get daily percent changes
currencies<-currencies/lag(currencies)-1       #using fAssets
require(fAssets)
assetsCorEigenPlot(as.timeSeries(currencies))       #using techniques from corrgram package documentation
#get correlation matrix
(currencies.cor <- cor(currencies,use="pair"))
#get two largest eigenvectors
(currencies.eig<-eigen(currencies.cor)$vectors[,1:2])
e1 <- currencies.eig[,1]
e2 <- currencies.eig[,2]
#make the chart
plot(e1,e2,col='white', xlim=range(e1,e2), ylim=range(e1,e2),
main="Plot of 2 Largest Eigenvectors for Various Asian
and American Currencies (corrgram)"
)
arrows(0, 0, e1, e2, cex=0.5, col="red", length=0.1)
text(e1,e2, rownames(currencies.cor), cex=0.75)
#run an interesting corrgram chart
require(corrgram) #do not need for previous eigenvector plot
df1 <- data.frame(cbind(index(currencies),coredata(currencies)))
corrgram(df1, order=TRUE,
main="Currency data PC2/PC1 order",
lower.panel=panel.shade, upper.panel=panel.pie,
text.panel=panel.txt)       #using techniques from SciViews package
#do principal component analysis
require(SciViews)
(currencies.pca <- pcomp(~Korea + Malaysia + Singapore + Taiwan +
China + Japan + Thailand + Brazil + Mexico + India +
USDOther + USDBroad,
data = currencies))
#make the chart
plot(currencies.pca, which = "correlations",
main="Plot of 2 Largest Eigenvectors for Various Asian
and American Currencies (SciViews)"
)
#more SciViews fun
#summary(currencies.pca)
#screeplot(currencies.pca)
#currencies.ldg<-loadings(currencies.pca)
#(currencies.cor <- correlation(currencies.pca))
#plot(currencies.pca, which = "scores", cex = 0.8)
#pairs(currencies.pca)         #compare 2 largest eigenvectors from the sciview and corrgram
cbind(loadings(currencies.pca)[,1],e1,loadings(currencies.pca)[,2],e2)

Created by Pretty R at inside-R.org