title: cvxopt for Markowitz Portfolio Optimization - finding point of optimal Sharpe Ratio
body: <p>I've been trying for 3 days to understand how to use cvxopt module in python to calculate the efficient frontier. A code snippet that I found at: <a href="https://github.com/markharley/Markowitz/blob/master/markowitz.py" rel="noreferrer">https://github.com/markharley/Markowitz/blob/master/markowitz.py</a></p>
  
  <p>is probably the best way to illustrate my problem, and I have included in entirety at the bottom of this post.</p>
  
  <p>Using the equations found on the wikipedia page for Modern Portoflio Theory:</p>
  
  <p><a href="https://en.wikipedia.org/wiki/Modern_portfolio_theory#Efficient_frontier_with_no_risk-free_asset" rel="noreferrer">https://en.wikipedia.org/wiki/Modern_portfolio_theory#Efficient_frontier_with_no_risk-free_asset</a> </p>
  
  <p><a href="https://i.stack.imgur.com/hVjau.png" rel="noreferrer"><img src="https://i.stack.imgur.com/hVjau.png" alt="enter image description here"></a></p>
  
  <p>I understand why the first use of solvers.qp uses:</p>
  
  <pre><code>solvers.qp(S, -q*pbar, G, h, A, b)['x']
  </code></pre>
  
  <p>where q is a risk tolerance factor.
  The code then goes on to calculate the point of optimal Sharpe Ratio using polyfit, which I also understand, but where I am lost is why the code now is:</p>
  
  <pre><code># Calculate the optimal portfolio
  wt = solvers.qp(opt.matrix(x1 * S), -pbar, G, h, A, b)['x']
  </code></pre>
  
  <p>where x1 is the return at the point of optimal Sharpe Ratio. I am lost as to why all of a sudden we can multiply S (covariance matrix) by x1 and also get rid of q in the -pbar term.</p>
  
  <p>Could anyone shed some light on this please? Apologies if I am not explaining this properly, any request for clarification would probably help me make my question clearer as well.</p>
  
  <p>Thanks! </p>
  
  <pre><code>def optimal_portfolio(returns):
  n = len(returns)
  returns = np.asmatrix(returns)
  
  N = 100
  qs = [10**(-5.0 * t/N + 1.0) for t in range(N)]
  
  # Convert to cvxopt matrices
  S = opt.matrix(np.cov(returns))
  
  # np.mean computes vector of means along
  # as mean of each row
  pbar = opt.matrix(np.mean(returns, axis=1))
  
  # Create constraint matrices
  # -- documentation at http://cvxopt.org/userguide/coneprog.html#quadratic-programming
  G = -opt.matrix(np.eye(n)) # negative nxn id
  h = opt.matrix(0.0, (n, 1)) # n x 1 zero vector
  A = opt.matrix(1.0, (1, n)) # 1 x n 1-vector
  b = opt.matrix(1.0) # [1.0]
  
  ## Calculate efficient frontier weights using quadratic programming
  ## https://en.wikipedia.org/wiki/Quadratic_programming
  # Minimizes (1/2) w^T * S * w - q pbar^T * w for weights w
  # subject to the constrains:
  # G * w &lt;= h (component-wise) -- positive weights
  # and A*w = b -- Sum of weights == 1
  # where S is the covariance matrix,
  # pbar are the mean returns,
  # q is a measure of risk tolerance
  portfolios = [solvers.qp(S, -q*pbar, G, h, A, b)['x'] for q in qs]
  
  ## Could replace above with Lagrange multiplier (or convex hull)
  
  # Calculate risks and mean returns for frontier
  returns = [blas.dot(pbar, x) for x in portfolios]
  risks = [np.sqrt(blas.dot(x, S * x)) for x in portfolios]
  
  # Calculate quadratic for the frontier curve
  m1 = np.polyfit(returns, risks, 2)
  x1 = np.sqrt(m1[2] / m1[0])
  
  # Calculate the optimal portfolio
  wt = solvers.qp(opt.matrix(x1 * S), -pbar, G, h, A, b)['x']
  
  return np.asarray(wt), returns, risks
  </code></pre>