title: Mean Variance Optimization + Python + tuning constraints
body: <p>I am trying to do Mean Variance Portfolio Optimization using the inbuilt SLSQP optimizer in scipi and am having difficulty in understanding how to define the constraint of solving for the weights of the portfolio using a constraint of constant portfolio variance of 10%. Was only able to incorporate the constraint that sum of all weights should be summing to 0</p>
  
  <p>I have been able to use this optimizer to find the portfolio for maximizing the portfolio Sharpe ratio and for finding the weights which minimize portfolio variance. Now need to add in the additional constrain so that the variance of the portfolio always stays at 10% and the optimizer solves for weights which maximize the portfolio return</p>
  
  <pre><code>
  def portfolio_annualised_performance(weights, mean_returns, carry_cov):
      returns = np.sum(mean_returns*weights) *12
      std = np.sqrt(np.dot(weights.T, np.dot(carry_cov, weights))) * np.sqrt(12)
      return std, returns
  
  def neg_sharpe_ratio(weights, mean_returns, carry_cov, risk_free_rate):
      p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, carry_cov)
      return -(p_ret - risk_free_rate) / p_var
  
  def max_sharpe_ratio(mean_returns, carry_cov, risk_free_rate):
      args = (mean_returns, carry_cov, risk_free_rate)
      no = int(len(mean_returns))
      constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 0})
      bound1 = (-1.0,0.0)
      bound2 = (0.0,1.0)
      bounds = tuple(bound2 for asset in range(int(no/2)))+tuple(bound1 for asset in range(int(no/2)))
      result = sco.minimize(neg_sharpe_ratio, no*[1./no,], args=args,method='SLSQP', bounds=bounds, constraints=constraints)
      return result
  
  ######## NEED HELP WITH THE FOLLOWING SNIPPET OF CODE
  
  def neg_return(weights, mean_returns, carry_cov, risk_free_rate):
      p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, carry_cov)
      return -(p_ret)
  
  def max_carry(mean_returns, carry_cov, risk_free_rate):
      args = (mean_returns, carry_cov, risk_free_rate)
      no = int(len(mean_returns))
      constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 0})
      bound1 = (-1.0,0.0)
      bound2 = (0.0,1.0)
      bounds = tuple(bound2 for asset in range(int(no/2)))+tuple(bound1 for asset in range(int(no/2)))
      result = sco.minimize(neg_return, no*[1./no,], args=args,method='SLSQP', bounds=bounds, constraints=constraints)
      return result
  
  </code></pre>
  
  <p>I am guessing I have to update this to ensure that p_var =10% for all the portfgolio space which the optimizer looks at but how do I modify the below constrasint dictionary ?</p>
  
  <pre><code>constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 0})
  
  </code></pre>
  
  <p>Also I have tried the following but doesn't seem to help at all (trying to return a large positive value of return if variance is above or below 10.5% or 9.5% which should add to the cost function for the optimizer):</p>
  
  <pre><code>def neg_return(weights, mean_returns, carry_cov, risk_free_rate):
      p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, carry_cov)
      if p_var &gt; 0.105 or p_var&lt; 0.095:
          p_ret = -p_ret*1000 
      return -(p_ret)
  
  </code></pre>