Using Bisection to Solve for Risk Aversion in Mean–Variance Optimization
Summary
The document describes solving for the risk-aversion parameter in a mean–variance portfolio setup. Portfolio weights are expressed as a function of the parameter, expected returns, the covariance matrix, and a budget constraint. Those weights are substituted into a target equation involving expected portfolio return and a volatility adjustment based on a normal quantile. The resulting scalar function is then evaluated at candidate parameter values.
The suggested approach is to find a bracket and use bisection, rather than relying on derivative-based optimization, which the author reports can fail when the function becomes nearly flat at large parameter values. A randomly generated four-asset example illustrates the procedure and reports a solution for a chosen target and probability level. This is an implementation example, not evidence that the function is well behaved for every input: bisection requires a valid sign-changing bracket, and the example does not establish uniqueness or address invalid covariance matrices or other constraints.
Key ideas
- Portfolio weights are written as a function of the risk-aversion parameter and model inputs.
- Substituting those weights produces a scalar equation for the target portfolio measure.
- Bisection can solve the scalar equation when a sign-changing bracket is available.
- The example reports that derivative-based methods may struggle in a flat region.
- The random example does not establish uniqueness or guarantee a suitable bracket for other portfolios.
Tags
Full text
# Solving a system of two equations with non-convex matrix multiplication for MV optimization
# Solving a system of two equations with non-convex matrix multiplication for MV optimization
Scenario: I am trying to do a variation of the MV optimization for a portfolio. In this instance, I already have a vector of mean returns ($\mu$), a vector of ones, a covariance matrix ($\Sigma$), and $\phi^{-1}$ which is the inverse of the standard normal cumulative distribution function (function of probability alpha).
Problem: From the two equations stated below, I am going to input: $\mu$, $\Sigma$, 1 (vector of ones), $H$, and $\alpha$, and try to get a value for $\gamma$ (also, the ' represents the transpose of the vector).
Equations:
$$ H = w(\gamma)'\mu + \Phi^{−1}(α)[w(\gamma)' \Sigma w(γ)]^{1/2}$$ $$ w(\gamma) = \frac{1}{\gamma}\Sigma^{-1}\Big[\mu − \Big(\frac{\mathbf{1}' \Sigma^{-1} \mu-\gamma}{\mathbf{1}' \Sigma^{-1} \mathbf{1}}\Big) \mathbf{1}\Big]$$
What I already tried: I am trying to solve this system using a python solver. But I am not able to do it since the matrix multiplication apparently becomes non-convex.
Question: How to solve this problem?
Obs: This question comes from the article Portfolio Optimization with mental accounts from Sanjiv Das, Harry Markowitz, Jonathan Scheid, and Meir Statman, Equations (7) and (8). The article is found at: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.410.8747&rep=rep1&type=pdf
## Answer by caverac (score 2, accepted)
https://quant.stackexchange.com/a/36202
I will use a case in which I randomly generate both $\Sigma$ and $\mu$ randomly in 4 dimensions
```
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from scipy.optimize import bisect
n = 4
np.random.seed(0)
S = np.random.uniform(0, 1, [n, n])
S = 0.5 * (S + S.transpose())
mu = np.random.uniform(-1, 1, n)
```
The trick with the transpose is just there to ensure that `S` is symmetric. I will choose $\alpha = 0.90$, and define the function $H$ as
```
Sinv = np.linalg.inv(S)
ones = np.ones_like(mu)
def H(gamma):
# w
w = (ones.dot(Sinv).dot(mu) - gamma) / (ones.dot(Sinv).dot(ones))
w = Sinv.dot(mu - w) / gamma
# H
H = w.dot(mu) + norm.ppf(alpha) * np.sqrt(w.dot(S).dot(w))
return H
```
This is a plot of $H = H(\gamma)$.
```
g = np.linspace(4, 50, num = 500)
h = np.array(map(H, g))
i = h > 0
plt.plot(g[i], h[i])
plt.show()
```
The function is indeed sort of problematic for large values of $\gamma$ in the sense that any optimization algorithm (pretty much all of them) that uses derivatives will fail. But still you can use bisection to find the root
As an example I will use $H = 1.04$ (up in the flat region)
```
f = lambda x: H(np.exp(x)) - 1.04
r = bisect(f, 1.5, 6, xtol = 1e-12)
g0 = np.exp(r)
print g0, H(g0)
```
which generates the output
```
231.206991393 1.04
```
So the root is $\gamma = 231.20699$Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.