Simple portfolio optimization. Solution by Chris Dembia.
from cvxpy import *
from simple_portfolio_data import *
one = np.matrix(np.ones((n, 1)))
r_min = pbar.T * x_unif
risk_unif = quad_form(x_unif, S).value
print('Minimum return: {}'.format(r_min))
Minimum return: [[ 0.08399391]]
x = Variable(n)
objective_a = Minimize( quad_form(x, S) )
constraints_i = [pbar.T * x == r_min, sum(x) == 1]
problem_ai = Problem(objective_a, constraints_i)
risk_ai = problem_ai.solve()
constraints_ii = [pbar.T * x == r_min, sum(x) == 1, x >= 0]
problem_aii = Problem(objective_a, constraints_ii)
risk_aii = problem_aii.solve()
constraints_iii = [pbar.T * x == r_min, sum(x) == 1,
one.T * max(-x, 0) <= 0.5]
problem_aiii = Problem(objective_a, constraints_iii)
risk_aiii = problem_aiii.solve()
print('Uniform portfolio risk: {}'.format(risk_unif))
print('No additional constraints risk: {}'.format(risk_ai))
print('Long-only risk: {}'.format(risk_aii))
print('Total short: {}'.format(risk_aiii))
Uniform portfolio risk: 0.00500978688334 No additional constraints risk: 6.56715701762e-05 Long-only risk: 0.00101937807592 Total short: 6.56717792366e-05
N = 20
mus = np.logspace(0, 5, N)
mean_longonly = np.zeros(N)
std_longonly = np.zeros(N)
mean_totalshort = np.zeros(N)
std_totalshort = np.zeros(N)
constraints_longonly = [sum(x) == 1, x >= 0]
constraints_totalshort = [sum(x) == 1, one.T * max(-x, 0) <= 0.5]
for i, mu in enumerate(mus):
print('mu = {}'.format(mu))
ret = pbar.T * x
risk = quad_form(x, S)
objective = Minimize( -ret + mu * risk )
# Long-only.
Problem(objective, constraints_longonly).solve()
mean_longonly[i] = ret.value
std_longonly[i] = np.sqrt(risk.value)
# Total short.
Problem(objective, constraints_totalshort).solve()
mean_totalshort[i] = ret.value
std_totalshort[i] = np.sqrt(risk.value)
mu = 1.0 mu = 1.83298071083 mu = 3.35981828628 mu = 6.15848211066 mu = 11.2883789168 mu = 20.6913808111 mu = 37.9269019073 mu = 69.5192796178 mu = 127.42749857 mu = 233.572146909 mu = 428.133239872 mu = 784.759970351 mu = 1438.44988829 mu = 2636.65089873 mu = 4832.93023857 mu = 8858.6679041 mu = 16237.7673919 mu = 29763.5144163 mu = 54555.9478117 mu = 100000.0
pl.plot(std_longonly, mean_longonly, label='long-only')
pl.plot(std_totalshort, mean_totalshort, label='total short')
pl.xlabel('standard deviation of return')
pl.ylabel('mean return')
pl.legend(loc='lower right', frameon=False);