1
$\begingroup$

Here is the premise: I have a three asset portfolio, I know the assets covariance, the client's risk aversion and the expected return of one of the assets. I also have a desired set of weights.

So, 1) how do I find the expected returns for the two assets I don't know that gives me my desired set of weights and 2) if I reverse the function can I get the desired weights back i.e. test the results?

Here's my Python code:

import numpy as np

# Define the function
def get_weight(expected_return, asset_covariance, risk_aversion):
   ER = expected_return
   S = asset_covariance
   L = risk_aversion
   return np.linalg.inv(L * S) @ ER

   # Given data
   risk_aversion = 1.0 # example value for L
   cov_matrix = np.array([[0.01, 0.002, 0.001], [0.002, 0.03, 0.004], [0.001, 0.004, 0.02]]) 
   # example covariance matrix

   # Desired weights
   desired_weights = np.array([0, 0.55, 0.45])

   # Solve for expected returns
   expected_returns = risk_aversion * cov_matrix @ desired_weights
   expected_returns[0] = 0.009 # given return 

   # Calculate weights using the original function
   calculated_weights = get_weight(expected_returns, cov_matrix, risk_aversion)

   # Output the results
   expected_returns, calculated_weights

Here's the output I get. You clearly see it's not circular. I expect the weights array to be 0.00,0.55,0.45. I can understand some rounding but the result is quite a bit off.

enter image description here

Where am I going wrong? Please reference Python in your comments if you can.

$\endgroup$
2
  • $\begingroup$ This may help you quant.stackexchange.com/questions/79059/… $\endgroup$
    – KaiSqDist
    Commented May 30 at 14:43
  • $\begingroup$ @KaiSqDist, essentially how I read this is that it can't be done in this way and the only option open to me is to use some sort of brute force loop that takes my existing known info into account? $\endgroup$
    – Farrep7
    Commented May 30 at 14:56

2 Answers 2

1
$\begingroup$

OP takes Black-Litterman reverse optimization expected returns, overrides one of the values with a different expected return, and finds that the resulting portfolio didn't match the original one. This is not surprising.

The answer referenced by @KaiSqDst is nearly sufficient to give an analytic solution (this is very close to a repeat of that question).

That answer (at least when I am viewing it) has the formula

$$ \gamma\Sigma(w^*-w_0)=\left(\mathbf{I}-\frac{1}{a}\mathbf{1}\mathbf{1^T}\Sigma^{-1}\right)\mu $$

and correctly notes that the problem is underdetermined and you cannot invert the right hand side matrix. However, it is possible, especially for a simple problem like this but perhaps not in the general case, to take a subset of the matrix and solve that. For your purpose, this would be to exclude the first asset that is assumed to have an expected return of 0.009. This would be like solving for the excess returns of the other assets. From the excess returns, you would add back 0.009 to each to get actual returns. The result is a 0.009 for asset 1, 0.09275 for asset 2, and 0.05725 for asset 3.

When double-checking the results, you need to make sure to assume the weights sum to 1. It isn't "circular" with unconstrained mean-variance.

$\endgroup$
3
  • $\begingroup$ Thank you @John, so essential we are treating the known return as if it were the risk free rate? I've run your numbers using the some other code that includes a fully invested constraint and a now short selling constraint as well as some asset limit constraints (which match the desired outcome weight levels) and the result is wildly off. 67.5% and 32.5% $\endgroup$
    – Farrep7
    Commented May 31 at 12:33
  • $\begingroup$ There's no guarantee of this "circular" behavior if you change up assumptions like that. $\endgroup$
    – John
    Commented May 31 at 19:27
  • $\begingroup$ Yes, this is becoming clearer to me. OK, what I've presented is a real world example. We do know what the current cash return is and we do have a choice between bonds and equity. But we also have a benchmark allocation of 55/45. So how would I approach this going forward, if I want to know what's required to generate that neutral 55/45 split on an ongoing basis? In my mind the circular argument seems so logical but in the mathematics it isn't. $\endgroup$
    – Farrep7
    Commented Jun 4 at 12:35
0
$\begingroup$

Referencing the original answer to the general problem and the definitions wherein, we remember the optimal investment decision which we can rewrite as:

$$ \begin{align} w^*&=w_0+\frac{b}{\gamma}\left(w_M-w_0\right)\\ \Rightarrow \gamma \Sigma \left(w^*-w_0\right)&=\mu-\frac{b}{a}\mathbf{1} \end{align} $$ We do know all elements of the vector on the lhs and we know one element of $\mu$, say $\mu_1$. Hence, we can trivially solve:

$$ \begin{align} \left(\gamma \Sigma \left(w^*-w_0\right)\right)_{(1)}&=\mu_1-\frac{b}{a}\\ \Rightarrow b&=a\mu_1 - a\left(\gamma \Sigma \left(w^*-w_0\right)\right)_{(1)} \end{align} $$

Given knowledge of $b$, we obtain:

$$ \mu=\gamma\Sigma\left(w^*-w_0\right)+\frac{b}{a}\mathbf{1} $$

$\endgroup$
6
  • $\begingroup$ if you were to code this in Python, how would you do it? $\endgroup$
    – Farrep7
    Commented May 31 at 12:29
  • $\begingroup$ As this is solely linear algebra, you can use numpy.org/doc/stable/reference/routines.linalg.html I think. $\endgroup$ Commented May 31 at 14:18
  • $\begingroup$ Thanks @Kermittfrog $\endgroup$
    – Farrep7
    Commented Jun 4 at 12:46
  • $\begingroup$ I've finally managed to program this and I have a couple of issues with the approach. First, if you change the weights of W0 and compare answers, you'll get different results and second if you set the weights of W0 to the benchmark weights you get nonsense result as well. So, think the problem needs to be approached from another angle. The search continues. $\endgroup$
    – Farrep7
    Commented Jun 20 at 20:44
  • $\begingroup$ I've prototyped this using Excel and it worked. Did you check all intermediate steps? $\endgroup$ Commented Jun 21 at 7:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.