Additional note: The example covariance-matrix hides some fairly-strong dependencies between the asset returns, which may not be obvious from looking at the data:
library("NMOF")
R <- randomReturns(na = 4, ns = 100,
sd = sqrt(diag(S)),
rho = cov2cor(S), exact = TRUE)
pairs(R)
Computations based on such a matrix (such as a marginal-risk calculation) will typically be sensitive and react strongly to small changes ("perturbations") of inputs. In the example, you can get around this by increasing the iterations:
w <- riskParityPortfolio(S)$w
FRAPO::mrc(w, S)
## [1] -194.71 -8.58 151.97 151.32
w <- riskParityPortfolio(S, maxiter = 1e4)$w
FRAPO::mrc(w, S)
## [1] -67.3 11.2 78.2 77.9
w <- riskParityPortfolio(S, maxiter = 1e5)$w
FRAPO::mrc(w, S)
## [1] 23.1 24.7 26.1 26.1
w <- riskParityPortfolio(S, maxiter = 1e6)$w
FRAPO::mrc(w, S)
## [1] 25 25 25 25
(I use the marginal-risk function mrc from Bernhard Pfaff's FRAPO package.)
But of course, this is all the result of an empirical problem (not a computational one): the assets are highly-correlated, and so an algorithm will always have trouble differentiating between linear combinations of those assets.
