Compute the implied correlation of a Portfolio

This result is way off. You can see this intuitively as weighted component vol is .229.
For large baskets, as n -> inf, implied corr will converge on basket-vol / weighted-component-vol. This overstates corr for small baskets. Rule of thumb iv**3 / crossprod(w**3,v**3) yields a guess of .77/

Explicitly calculating it corr comes in around .75:

rho = (iv**2 - crossprod(w**2,v**2) / sum(outer(v,v) * outer(w,w) - eye(3) * diag(outer(v,v) * outer(w,w)))
Kevin im having a hard time getting this code to work (getting a strange number). Was there a typo somewhere?

I re-did this example with a 100 asset portfolio. I realized that if I take the square root of the output from the original formula I get the same output as iv/sum(v*w). Is that because we calculated in vars?

Here is the R code if you want to give it a run (should be 0 errors).

Code:
#create weights and vol vectors for a 100 asset portfolio
x<-runif(100)
w = x/sum(x)

v = rnorm(100, mean = .35, sd = .07)

vIndex = .21



#create vector and matrix for top and bottom summations
top.sum = vector()
bottom.sum = matrix(nrow = length(v), ncol = length(v))

#loop over inputs
for(i in 1:length(v)){
  top.sum[i] = w[i]^2 * v[i]^2
  for(j in 1:length(v)){
    bottom.sum[i,j] = w[i]*w[j]*v[i]*v[j]
  }
}

#get the upper right corner of our matrix
mat = bottom.sum[upper.tri(bottom.sum)]

#print implied correlation
ic = (vIndex^2 - sum(top.sum))/(2 * sum(mat))

#print difference between 2 formulas
vIndex/sum(v*w) - sqrt(ic)

there is very little difference
 
Attached is the SandP500 component ivols + weights.
ICJ is trading at 51% right now and SPY 30d ATM vol at 19%

Using the attached data:
vIndex/sum(w*v) = ~55%

Using original formula I posted you get only 38%
 

Attachments

Code:
rho <- 
(iv**2 - crossprod(w**2,v**2)) /  sum(outer(v,v) * outer(w,w) - diag(3) * diag(outer(v,v) * outer(w,w)))

Kevin im having a hard time getting this code to work (getting a strange number). Was there a typo somewhere?
The function eye is non-standard. I replaced it with diag(3) in the code above. With the correct v vector, v <- c(.25,.35,.18). it returns .3609, same number you got/

Your vIndex/sum(w*v) is the same as basket-vol over weighted-component-vol as mentioned in my post. For a 500 stock index or for your 100 stock random index, it is going to be pretty close.
 
hey guys I need a bit of math help. I am trying to compute the implied correlation of an ETF as i am trying to find expensive/cheap ivol. I was hoping someone could cross check my code or dummy example before I go and bet.

I am using the CBOE implied correlation formula to back out the IC from option prices.
View attachment 254026
Maybe I'm wrong, but I think that I notice a difference between the posted formula and the posted code. It is about the denominator portion. It states below the summation mark 1 <= i < j <= n. For n = 3 this would result in the [i,j] pairs [1,2],[1,3],[2,3]. In the software code I see a summation being done for both i and j from 1 to n, resulting in more [i,j] combinations. Am I misreading the formula?
 
Code:
rho <-
(iv**2 - crossprod(w**2,v**2)) /  sum(outer(v,v) * outer(w,w) - diag(3) * diag(outer(v,v) * outer(w,w)))


The function eye is non-standard. I replaced it with diag(3) in the code above. With the correct v vector, v <- c(.25,.35,.18). it returns .3609, same number you got/

Your vIndex/sum(w*v) is the same as basket-vol over weighted-component-vol as mentioned in my post. For a 500 stock index or for your 100 stock random index, it is going to be pretty close.
code is working, thanks.

I am still a little confused on the output. The output is .31. When raised to the power of .5 I get the same result as basket vol/weighted component vol and the same result as CBOE implied cor index. So do we take the square root of the output to get implied corr or leave as is?
 
I am still a little confused on the output. The output is .31.

That is probably close to correct.... for your inputs. Do you have the ICJ white paper. It is based on Jan 22 component vols (top 50 stocks in sp500 only), and some calc of Dec 2021 vix30. I haven't looked up the 50 Jan 2022 component vols but let's assume flat vol and that they are the same as current iv30d. And don't forget to normalized w so it sums to one. (w <- w / sum(w)). My current calc for vix30 on Dec 17 is .25, but that is on a sparse chain so it may be higher. Plugging in current top 50 component vols, and top 50 weights normalized and spIV of .25 gives an implied correlation of around 0.6.

Edit: Reading the white paper, it looks like the CBOE is using an atmIV for Dec 2021 SPX. not a VIX calc like I thought.
 
Last edited:
Agree though I don't have the time to verify with current data; 0.36 sounds way too low at current levels. 0.5-0.7 sounds more like it. Just my feel from having traded dispersion baskets before. I don't know (or missed it in the OP post) what data he used to arrive at his result.

This result is way off. You can see this intuitively as weighted component vol is .229.
For large baskets, as n -> inf, implied corr will converge on basket-vol / weighted-component-vol. This overstates corr for small baskets. Rule of thumb iv**3 / crossprod(w**3,v**3) yields a guess of .77/

Explicitly calculating it corr comes in around .75:

rho = (iv**2 - crossprod(w**2,v**2) / sum(outer(v,v) * outer(w,w) - eye(3) * diag(outer(v,v) * outer(w,w)))
 
Last edited:
that's what I thought :D

You didn't respond, so I'll follow up...

In case you're thinking I'm some sort of noob, au contraire...

Apparently you (and many others) see trading the markets as a complicated endeavor rather than a simple one... like chess vs. checkers.

Price TA, KISS is more like checkers. And because it's simple a trader is more likely to understand and better able to execute.

As to your jab about "implied correlation", KISS doesn't address that at all.... so neither do I. In fact, there are no calculations of any kind required or even used in KISS.

Good luck with your "complicatin' things up" with your formulae.

:)
 
Back
Top