I am experimenting to try to find better ways to hedge some of our equity portfolios. It's easy enough to use R to get a PCA breakdown of exposure for a portfolio but I can't figure out how to then use that to actually hedge something.

In the example below I'm just using four securities. In real life we would use more, but the small set it to keep this example manageable. Here's the R code:

# Get publicly available data
px.spy=getYahooData("SPY", 20130101, 20160101)$Close
px.iwm=getYahooData("IWM", 20130101, 20160101)$Close
px.tlt=getYahooData("TLT", 20130101, 20160101)$Close
px.gld=getYahooData("GLD", 20130101, 20160101)$Close


px=merge( px.spy  , px.iwm )
px=merge( px  , px.tlt )
px=merge( px , px.gld )

# turn it into something that we can put into princomp
pxList=as.data.frame(px) %>% mutate( SPYr = (lag(SPY,1) - SPY )/SPY , IWMr = (lag(IWM,1) - IWM )/IWM  ,
 TLTr = (lag(TLT,1) - TLT )/TLT , GLDr= (lag(GLD,1) - GLD )/GLD) %>% filter( complete.cases(.)) %>% select(SPYr,IWMr,TLTr,GLDr )


Now we the loadings in pc$loadings. Now, say we wanted to take a portfolio of $100mm of SPY and hedge it with IWM,TLT,GLD based on the PCA exposures. What's the right way to extract that simply and to create a frame with the weightings?

Thanks, Josh

  • $\begingroup$ Note that you can simplify the whole naming & merging business into just by using px = merge(px.spy, px.iwm, px.tlt, px.gld) and the adding the names as colnames(px) <- c("SPY", "IWM", "TLT", "GLD") $\endgroup$ May 27 '16 at 17:27
  • $\begingroup$ Yeah, good pt. Was doing this quick and dirty. $\endgroup$
    – JoshK
    May 27 '16 at 17:37
  • $\begingroup$ It depends. What is the goal? Do you want to minimize variance/risk, or minimize some combination of risk and return? PCA is just a decomposition for covariance matrices. $\endgroup$
    – Taylor
    May 27 '16 at 20:28
  • 1
    $\begingroup$ If you already know that you are going to hedge SPY with IWM, TLT, GLD it seems to me you do not need a PCA but just a multiple regression with SPY returns as dependent variable and the other 3 as independent variables. $\endgroup$
    – Alex C
    May 27 '16 at 23:04
  • 1
    $\begingroup$ Also, if PCA works well it might be more convenient when doing portfolios with large numbers of stocks. Say you wanted to construct a portfolio of 50 names a side. It doesn't seem as easy to optimize the hedges then with 100 different regression equations. But with PCA we would just have to run an optimizer to reduce the factor weights. $\endgroup$
    – JoshK
    May 27 '16 at 23:34

Just a heads up, I'm not going to go through all the mathematical caveats of using this approach.

Let $\Sigma$ be your covariance matrix, and $X$ a random vector of daily returns. So

$$\text{Var}(X) = \Sigma.$$ You have a bug in your code. In your code you call it pxCov, but you probably meant to use cov() insted of cor(). Check out the documentation to princomp(). It expects the covariance matrix by default. This will change things.

Also, princomp() is interpreting your covariance matrix as a data frame. You should run the following commands instead of your last two lines:


Now the math stuff. All the stuff you want to do, that you mentioned in the comments, can be done by taking expectations, variances, or covariances of linear combinations of your random return vector. The weights will be constructed from the loadings or eigenvectors, and calculation of variances will be simplified using the eigenvalues or standard deviation terms corresponding to the loadings.

Let $w$ be a weight (column) vector. Assume for now that the sum of its entires is $1$. Each element denotes the share of your portfolio sitting in that stock. Basic properties tell us that $$\text{Var}(w'X) = w'\Sigma w,$$ where the apostrophe denotes the transpose.

We can take the spectral decomposition of covariance matrices (positive definite and symmetric): $$\Sigma = \sum_{i=1}^4 \lambda_i v_i v_i'$$ with the set of loadings or eigenvectors, $\{v_i\}$ being orthonormal. In your code, these are pc$loadings. The lambdas that correspond with these are pc$sdev^2. This function orders everything in decreasing order, so $\lambda_1 > \cdots > \lambda_4$.

When you say PCA, you are probably trying to use the $v_i$s to construct a ''good'' $w$. There is no single way to do this. If you want to minimize your volatility without paying any mind to your expected returns, you would set $w = v_4$. Then your portfolio variance/risk would be

$$\text{Var}(wX) = v_4' \left[ \sum_{i=1}^4 \lambda_i v_i v_i'\right] v_4 = \lambda_4 v_4'v_4 v_4'v_4 = \lambda_4,$$ because of the orthonormality of the loading vectors.

If you want to minimize some other objective function, then you can do that too. For example, if your expected return is $w'\mu$, then you might want to minimize $w'\Sigma w - m w'\mu$. I have no idea what's commonly done in practice, though.

If you want to see how much each variance each loading explains, run plot(pc$sdev^2/sum(pc$sdev^2)). If you want 90\% you need some mix of the first two loadings. So we need to find some $0 < \alpha < 1$ such that $w = \alpha v_1 + (1-\alpha)v_2$. Using stuff like orthogonality that I showed you earlier, you can get

$$\text{Var}(wX) = \alpha^2\lambda_1 + (1-\alpha)^2\lambda_2 \overset{\text{set}}{=} .9$$

So you have to use the quadratic formula to find $\alpha$ in order to get your $w$. You could also do a mix of the last three loadings, too. I'm not sure what's done commonly in practice here, either.

If you want to find the "exposure" of your new portfolio, $w'X$, to the returns of the SPY, $e_1'X$, which I take to mean as covariance, then you can use the bilinearity of $\text{Cov}(\cdot,\cdot)$

$$\text{Cov}(w'X, e_1'X) = w'\Sigma e_1$$

where $e_1' = (1, 0, 0, 0)$.

  • $\begingroup$ Hi, thanks for the reply. As far as` cov()` vs cor(), I have been playing with both. I've read arguments for each and wanted to see if there are practical differences. My question isn't really about the theory. I just wanted to figure out how to take pc$loadings and figure out how to practically apply it. Say I wanted to use just the vectors that explain 90% of variance. I just am not sure how to twiddle around with R to get those out and to use it to generate the hedge basket. Does that make sense? $\endgroup$
    – JoshK
    May 29 '16 at 15:36
  • $\begingroup$ If I remember correctly, the function that gives you the principal components is expecting a different matrix by default, namely the covariance matrix versus the correlation matrix. So, practically, everything is wrong. $\endgroup$
    – Taylor
    May 29 '16 at 15:58
  • $\begingroup$ Regarding the other stuff, see the edit that I'm about to do. $\endgroup$
    – Taylor
    May 29 '16 at 16:00
  • $\begingroup$ Fwiw the results don't change that much between cov() and cor(). Maybe my understanding is wrong but I thought that a PCA breakdown will extract orthogonal vectors that express whatever you pass it and that cor essentially takes care of scaling issues since it's just 1 to -1 and cov is the total covariance and can give additional color by specifically not reducing the scale? Looking at the princomp funciton in more detail now it looks like princomp does it's own cov or cor depending on what you pass in for the "cor" parameter. Does that sound right? $\endgroup$
    – JoshK
    May 30 '16 at 4:33
  • $\begingroup$ Ty for the edit above, that makes sense. If I just wanted to take the first two loadings and: 1. see what the exposure for SPY is to each of those two loadings and then 2. Get the exposure to the first two loadings for the other stocks, how would be the right way to extract that? I am confused by how to use the $loadings matrix. Once I have those I can use optim() to figure out something that is at least test-worthy. And I really appreciate your help above, ty. $\endgroup$
    – JoshK
    May 30 '16 at 4:37

Several issues arise no matter which approach you choose (as a reference for my claims you can go through this:

  • the covariance matrix of many assets can become instable (the more assets the more instable). Then your PCA will be based on noise. Therefore first get a good stimator of covariance. Using data of something like a year of observations worked good for me. Shrinkage is a good method to estimate the covariance matrix.
  • Then you could use PCA ... but why should you? PCA with long and short loadings will be instable.
  • For me the place to go would be to set-up an optimization problem (and solve it):
  • minimize the tracking error (based on the stable covariance matrix)
  • subject to: long only weights (this will make the thing more robust)
  • and subject to:a cardinality constraint: you want to use $N$ assets for the basket
  • and subject to: sector constraints: if all fails then you will have stocks with enough weight from every sector.

The above will give you a basked with only positive weights, controlled sector deviations and a control over the number of assets in the basket and finally a TE estimate.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.