Ambos el material del curso corto codificado por los desarrolladores de CVXPY y una respuesta en Quant SE sugieren que dado un presupuesto de riesgo deseado $b$ podemos encontrar la cartera de inversión completa con ponderaciones $w$ que tiene el presupuesto de riesgo (como se define en esos materiales) igual a $b$ realizando la siguiente optimización convexa:
$$\begin{align}\text{Minimize}\;&\frac{1}{2}w'\Sigma w - \sum_i b_i\,\text{log}w_i \\ \text{subject to} \;& 1'w=1\end{align}$$
Sin embargo, habiendo hecho esto yo mismo en Python con CVXPY, encontré los presupuestos de riesgo resultantes no eran los mismos que los deseados $b$ .
Luego traté de calcular esta minimización a mano, y encontré que la solución $w$ tiene
$$(\Sigma w)_i - \frac{b_i}{w_i} = \lambda\;\;\;\text{for all }i$$
donde $\lambda$ es el multiplicador lagrangiano.
En otras palabras, ya que podemos demostrar que el $i$ -el presupuesto de riesgo ${b_w}_i$ por definición es igual a $\frac{w_i(\Sigma w)_i}{w'\Sigma w}$ la solución a ese problema de optimización tiene:
$${b_w}_i = \dfrac{b_i+\lambda w_i}{w'\Sigma w} = \dfrac{b_i+\lambda w_i}{1 + \lambda}$$
y esto en general no es igual a $b_i$ (por lo demás, $w_i=b_i$ ). Esto ha sido verificado por la optimización que he ejecutado en Python.
Pero estoy seguro de que este método no está mal -hay un trabajo académico escrito para explicarlo por Spinu (2013), que está más allá de mis capacidades. Así que, ¡realmente agradecería a quien pueda explicar esta formulación!
Actualización:
Aquí está el código Python que escribí. Es un ejercicio que forma parte del curso corto CVXPY.
import numpy as np
import cvxpy as cp
#input data
Sigma = np.array([[6.1, 2.9, -0.8, 0.1],
[2.9, 4.3, -0.3, 0.9],
[-0.8, -0.3, 1.2, -0.7],
[0.1, 0.9, -0.7, 2.3]])
b = np.ones(4)/4 #risk parity
# optimization
w = cp.Variable(4) #portfolio weight
obj = 0.5 * cp.quad_form(w, Sigma) - cp.sum(cp.multiply(b, cp.log(w))) #objective
constr = [cp.sum(w) == 1, w >= 0] # constraint
prob = cp.Problem(cp.Minimize(obj), constr)
prob.solve()
# print the solution weight and solution risk budget
b_w = cp.multiply(w, Sigma @ w) / cp.quad_form(w, Sigma) #solution risk budget
print("The solution weight is", w.value)
print("The solution risk budget is", b_w.value)
Y los resultados impresos son:
The solution weight is [0.16073365 0.14918463 0.42056612 0.2695156 ]
The solution risk budget is [0.32355772 0.33307394 0.10944985 0.23391849]