In volatility modelling, a typical challenge is to keep the covariance matrix estimate valid, meaning (1) symmetric and (2) positive semi definite^{*}. A new paper published in *Econometrica* (citing from the paper) “introduces a novel parametrization of the correlation matrix. The reparametrization facilitates modeling of correlation and covariance matrices by an unrestricted vector, where **positive definiteness is an innate property**” (emphasis mine). *Econometrica* is known to publish ground-breaking research, and you may wonder: what is the big deal in being able to reparametrise the correlation matrix?

There are many statistical methods that are problematic to use for volatility modelling, exactly because the results are not guaranteed to be valid. The new reparametrization opens the door for all those methods.

Say you have a 3 by 3 matrix, the 3 off-diagonal elements could be, courtesy of the new proposal, stacked and modeled\estimated\predicted **individually**. Once you are done, it is assured that you get a valid correlation matrix. This is in contrast to working with the matrix “as a whole” (a la exponentially moving average), or coming up with underlying process’ suggestions (a la GARCH) so as to guarantee a valid result (reminder: symmetric and positive semi definite).

The most straightforward method I can think of, which was never before relevant for volatility modelling is linear (or non-linear) regression and variants thereof. There was never a point in applying a regression (or ridge regression, or LASSO regression) to the individual entries of the covariance matrix if, at the end of it, the result would not be invertible. But now it is possible using the new proposed parameterization.

The paper “A New parameterization of Correlation Matrices” is short and clear. Code is included and the numerical algorithm is fast enough for practical purposes. Code from the paper is below.

### Code

You need to have the packages `fBasics`

and `expm`

installed to be able to execute this code.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
library(expm) library(fBasics) GFT_inverse_mapping <- function (gamma_in, tol_value) { C <- matrix (,nrow = 0, ncol = 0) iter_number <- -1 # Check if input is of proper format : gamma is of suitable length # and tolerance value belongs to a proper interval n <- 0.5 * (1+ sqrt(1+ 8*length(gamma_in)) ) if (!(is.vector(gamma_in) && n %% 1 == 0)) { stop("Dimension of 'gamma' is incorrect") } else if (!(tol_value >= (10)^(-10) && tol_value <= (10)^(-4)) ) { stop("Incorrect tolerance value") } else { # Place elements from gamma into off-diagonal parts # and put zeros on the main diagonal of nxn symmetric matrix A A <- matrix (0, nrow=n, ncol=n) A[upper.tri(A, diag = FALSE)] <- gamma_in A <- A + t(A) # Read properties of the input matrix diag_vec <- diag(A) # Iterative algorithm to get the proper diagonal vector dist <- sqrt(n) while (dist > sqrt(n) * tol_value) { diag_delta <- log(diag(expm(A))) diag_vec <- diag_vec - diag_delta diag(A) <- diag_vec dist <- norm(diag_delta, type = "2") # spectral norm, largest eigenvalue iter_number <- iter_number + 1 } # Get a unique reciprocal correlation matrix C <- expm(A) diag (C) <- rep(1, n) } return(list(C = C, iter_number = iter_number)) } |

**Example**

Assume you have a 5X5 correlation matrix, so 10 off-diagonal elements. Simulate from a random normal the diagonal, and verify that the mapping proposed in the aforementioned paper indeed result in a valid correlation matrix.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
TT <- 10 off_diag <- rnorm(TT, mean=0, sd= 3) C <- GFT_inverse_mapping(off_diag, tol_value= 10^(-10)) C isPositiveDefinite(C$C) $C [,1] [,2] [,3] [,4] [,5] [1,] 1.0000 0.817 -0.820 0.856 0.0351 [2,] 0.8170 1.000 -0.427 0.959 0.6037 [3,] -0.8203 -0.427 1.000 -0.415 0.4164 [4,] 0.8557 0.959 -0.415 1.000 0.4941 [5,] 0.0351 0.604 0.416 0.494 1.0000 $iter_number [1] 77 > isPositiveDefinite(C$C) [1] TRUE |

If you don’t get a positive definite result try reducing the tolerance level `tol_value`

.

### Footnotes and References

* See here for the rationale.

Can you explain how this works? I took a look at the arXiv version of the paper and couldn’t really grok how the while loop works.