Mean-Variance_Portfolio_Optimization
Mean-variance portfolio selection¶
Copyright By PowCoder代写 加微信 powcoder
Import libraries¶
import cvxpy as cp
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
np.random.seed(978351)
Generate random data for 10 stocks¶
# Random data for 10 stocks
Q = np.random.random((n,n))
Q = np.dot(Q,Q.T)/1000
mu = np.random.rand(n) / 100
Step 1 – compute minimum variance portfolio¶
\begin{equation}
\begin{array}{rl}
\displaystyle \min_{w} & w^TQw \\
{\rm s.t.} & \sum_i w_i = 1\\
& w \geq 0
\end{array}
\end{equation}
w1 = cp.Variable(n)
prob1 = cp.Problem(cp.Minimize(cp.quad_form(w1, Q)),
[sum(w1) == 1,
prob1.solve(verbose=True)
# Print results
print(“\nSolution status: “, prob1.status)
print(“Solution optimal value: “, prob1.value)
print(“Solution w: “)
print(w1.value)
===============================================================================
===============================================================================
(CVXPY) Mar 07 03:02:30 AM: Your problem has 10 variables, 2 constraints, and 0 parameters.
(CVXPY) Mar 07 03:02:30 AM: It is compliant with the following grammars: DCP, DQCP
(CVXPY) Mar 07 03:02:30 AM: (If you need to solve this problem multiple times, but with different data, consider using parameters.)
(CVXPY) Mar 07 03:02:30 AM: CVXPY will first compile your problem; then, it will invoke a numerical solver to obtain a solution.
——————————————————————————-
Compilation
——————————————————————————-
(CVXPY) Mar 07 03:02:30 AM: Compiling problem (target solver=OSQP).
(CVXPY) Mar 07 03:02:30 AM: Reduction chain: CvxAttr2Constr -> Qp2SymbolicQp -> QpMatrixStuffing -> OSQP
(CVXPY) Mar 07 03:02:30 AM: Applying reduction CvxAttr2Constr
(CVXPY) Mar 07 03:02:30 AM: Applying reduction Qp2SymbolicQp
(CVXPY) Mar 07 03:02:30 AM: Applying reduction QpMatrixStuffing
(CVXPY) Mar 07 03:02:30 AM: Applying reduction OSQP
(CVXPY) Mar 07 03:02:30 AM: Finished problem compilation (took 2.735e-02 seconds).
——————————————————————————-
Numerical solver
——————————————————————————-
(CVXPY) Mar 07 03:02:30 AM: Invoking solver OSQP to obtain a solution.
—————————————————————–
OSQP v0.6.2 – Operator Splitting QP Solver
University of Oxford – Stanford University 2021
—————————————————————–
problem: variables n = 10, constraints m = 11
nnz(P) + nnz(A) = 75
settings: linear system solver = qdldl,
eps_abs = 1.0e-05, eps_rel = 1.0e-05,
eps_prim_inf = 1.0e-04, eps_dual_inf = 1.0e-04,
rho = 1.00e-01 (adaptive),
sigma = 1.00e-06, alpha = 1.60, max_iter = 10000
check_termination: on (interval 25),
scaling: on, scaled_termination: off
warm start: on, polish: on, time_limit: off
iter objective pri res dua res rho time
1 0.0000e+00 1.00e+00 1.00e+02 1.00e-01 7.40e-04s
75 1.8991e-03 2.33e-06 2.98e-07 1.92e-02 1.63e-03s
plsh 1.8991e-03 1.16e-20 5.51e-17 ——– 3.12e-03s
status: solved
solution polish: successful
number of iterations: 75
optimal objective: 0.0019
run time: 3.12e-03s
optimal rho estimate: 4.04e-03
——————————————————————————-
——————————————————————————-
(CVXPY) Mar 07 03:02:30 AM: Problem status: optimal
(CVXPY) Mar 07 03:02:30 AM: Optimal value: 1.899e-03
(CVXPY) Mar 07 03:02:30 AM: Compilation took 2.735e-02 seconds
(CVXPY) Mar 07 03:02:30 AM: Solver (including time spent in interface) took 1.107e-02 seconds
Solution status: optimal
Solution optimal value: 0.0018990924026013078
Solution w:
[ 5.76806436e-21 4.02040700e-01 2.12890590e-01 -1.15963427e-20
1.16246384e-20 -4.68602221e-21 7.72053642e-21 3.85068710e-01
4.66783461e-22 3.16722448e-21]
# Check constraint
np.allclose(np.sum(w1.value),1)
w_minVar = w1.value
var_minVar = np.dot(w_minVar, np.dot(Q, w_minVar))
ret_minVar = np.dot(mu, w_minVar)
print(“Minimum variance portfolio:\n”)
print(” Solution status =”, prob1.status)
print(” Solution value =”, prob1.value)
print(” Variance =”, var_minVar)
print(” Expected return =”, ret_minVar)
print(“Standard deviation =”, np.sqrt(var_minVar))
Minimum variance portfolio:
Solution status = optimal
Solution value = 0.0018990924026013078
Variance = 0.0018990924026013078
Expected return = 0.003267477841642329
Standard deviation = 0.043578577335673864
Step 2 – compute maximum return portfolio¶
\begin{equation}
\begin{array}{rl}
\displaystyle \max_{w} & \mu^Tw \\
{\rm s.t.} & \sum_i w_i = 1\\
& w \geq 0
\end{array}
\end{equation}
w2 = cp.Variable(n)
[sum(w2) == 1,
prob2.solve(verbose=True)
# Print results
print(“\nSolution status: “, prob2.status)
print(“Solution optimal value: “, prob2.value)
print(“Solution w: “)
print(w2.value)
===============================================================================
===============================================================================
(CVXPY) Mar 07 03:02:45 AM: Your problem has 10 variables, 2 constraints, and 0 parameters.
(CVXPY) Mar 07 03:02:45 AM: It is compliant with the following grammars: DCP, DQCP
(CVXPY) Mar 07 03:02:45 AM: (If you need to solve this problem multiple times, but with different data, consider using parameters.)
(CVXPY) Mar 07 03:02:45 AM: CVXPY will first compile your problem; then, it will invoke a numerical solver to obtain a solution.
——————————————————————————-
Compilation
——————————————————————————-
(CVXPY) Mar 07 03:02:45 AM: Compiling problem (target solver=ECOS).
(CVXPY) Mar 07 03:02:45 AM: Reduction chain: FlipObjective -> Dcp2Cone -> CvxAttr2Constr -> ConeMatrixStuffing -> ECOS
(CVXPY) Mar 07 03:02:45 AM: Applying reduction FlipObjective
(CVXPY) Mar 07 03:02:45 AM: Applying reduction Dcp2Cone
(CVXPY) Mar 07 03:02:45 AM: Applying reduction CvxAttr2Constr
(CVXPY) Mar 07 03:02:45 AM: Applying reduction ConeMatrixStuffing
(CVXPY) Mar 07 03:02:45 AM: Applying reduction ECOS
(CVXPY) Mar 07 03:02:45 AM: Finished problem compilation (took 2.164e-02 seconds).
——————————————————————————-
Numerical solver
——————————————————————————-
(CVXPY) Mar 07 03:02:45 AM: Invoking solver ECOS to obtain a solution.
ECOS 2.0.7 – (C) embotech GmbH, , 2012-15. Web: www.embotech.com/ECOS
It pcost dcost gap pres dres k/t mu step sigma IR | BT
0 -3.824e-03 -3.824e-03 +1e+00 2e-02 8e-01 1e+00 2e-01 — — 1 1 – | – –
1 -3.838e-03 -3.997e-03 +2e-02 3e-04 4e-02 1e-02 3e-03 0.9850 1e-04 0 0 0 | 0 0
2 -4.739e-03 -5.072e-03 +5e-03 7e-05 1e-02 4e-03 8e-04 0.7513 3e-02 0 0 0 | 0 0
3 -7.217e-03 -8.365e-03 +4e-03 3e-05 8e-03 2e-03 5e-04 0.6337 5e-01 0 0 0 | 0 0
4 -8.753e-03 -8.820e-03 +2e-04 1e-06 4e-04 7e-05 3e-05 0.9579 9e-03 0 0 0 | 0 0
5 -8.933e-03 -8.934e-03 +2e-06 2e-08 5e-06 8e-07 3e-07 0.9890 1e-04 1 0 0 | 0 0
6 -8.935e-03 -8.935e-03 +3e-08 2e-10 5e-08 8e-09 3e-09 0.9890 1e-04 1 0 0 | 0 0
7 -8.935e-03 -8.935e-03 +3e-10 2e-12 6e-10 9e-11 4e-11 0.9890 1e-04 1 0 0 | 0 0
OPTIMAL (within feastol=5.7e-10, reltol=3.4e-08, abstol=3.1e-10).
Runtime: 0.000342 seconds.
——————————————————————————-
——————————————————————————-
(CVXPY) Mar 07 03:02:45 AM: Problem status: optimal
(CVXPY) Mar 07 03:02:45 AM: Optimal value: 8.935e-03
(CVXPY) Mar 07 03:02:45 AM: Compilation took 2.164e-02 seconds
(CVXPY) Mar 07 03:02:45 AM: Solver (including time spent in interface) took 4.969e-04 seconds
Solution status: optimal
Solution optimal value: 0.008934923691822914
Solution w:
[5.92195886e-09 5.74678502e-09 3.42952593e-09 3.11870923e-09
5.91967975e-09 9.99999954e-01 9.06976763e-09 7.27168066e-09
2.63140981e-09 3.31438393e-09]
w_maxRet = w2.value
var_maxRet = np.dot(w_maxRet, np.dot(Q, w_maxRet))
ret_maxRet = np.dot(mu, w_maxRet)
print(“Maximum return portfolio:\n”)
print(” Solution status =”, prob2.status)
print(” Solution value =”, prob2.value)
print(” Expected return =”, ret_maxRet)
print(” Variance =”, var_maxRet)
print(“Standard deviation =”, np.sqrt(var_maxRet))
Maximum return portfolio:
Solution status = optimal
Solution value = 0.008934923691822914
Expected return = 0.008934923691822914
Variance = 0.00445041516526107
Standard deviation = 0.06671143204324931
Step 3 – compute mean-variance efficient frontier¶
\begin{equation}
\begin{array}{rl}
\displaystyle \min_{w} & w^TQw \\
{\rm s.t.} & \mu^Tw \geq \varepsilon \\
&\sum_i w_i = 1\\
& w \geq 0
\end{array}
\end{equation}\begin{equation}
\varepsilon \in [\varepsilon_{R_{\rm minVar}},\varepsilon_{R_{\rm maxRet}}]
\end{equation}
# Target returns
targetRet = np.linspace(ret_minVar,ret_maxRet,50)
array([0.00326748, 0.00338314, 0.0034988 , 0.00361446, 0.00373013,
0.00384579, 0.00396145, 0.00407711, 0.00419278, 0.00430844,
0.0044241 , 0.00453976, 0.00465542, 0.00477109, 0.00488675,
0.00500241, 0.00511807, 0.00523373, 0.0053494 , 0.00546506,
0.00558072, 0.00569638, 0.00581205, 0.00592771, 0.00604337,
0.00615903, 0.00627469, 0.00639036, 0.00650602, 0.00662168,
0.00673734, 0.006853 , 0.00696867, 0.00708433, 0.00719999,
0.00731565, 0.00743132, 0.00754698, 0.00766264, 0.0077783 ,
0.00789396, 0.00800963, 0.00812529, 0.00824095, 0.00835661,
0.00847228, 0.00858794, 0.0087036 , 0.00881926, 0.00893492])
# Define optimization problem and compute one portfolio on efficient frontier
w = cp.Variable(n)
eps = cp.Parameter()
eps.value = targetRet[0]
prob3 = cp.Problem(cp.Minimize(cp.quad_form(w, Q)),
sum(w) == 1,
prob3.solve(verbose=False)
# Print results
print(“\nSolution status: “, prob3.status)
print(“Solution optimal value: “, prob3.value)
print(“Solution w: “)
print(w.value)
Solution status: optimal
Solution optimal value: 0.0018990924026013076
Solution w:
[ 9.28605604e-21 4.02040700e-01 2.12890590e-01 -6.61871670e-21
5.27546398e-21 3.63970324e-22 1.82291320e-20 3.85068710e-01
1.15272364e-20 -2.99767995e-22]
# Compute efficient frontier
w_front = []
var_front = []
ret_front = []
for epsilon in targetRet:
eps.value = epsilon
prob3.solve(verbose=False)
w_front.append(w.value)
var_front.append(np.dot(w.value, np.dot(Q, w.value)))
ret_front.append(np.dot(mu, w.value))
Plot efficient frontier
fig=plt.figure(figsize=(10,5), dpi= 100, facecolor=’w’, edgecolor=’k’)
ax = plt.gca()
# Plot volatility versus expected return for minimum variance portfolio
ax.scatter(x=np.sqrt(var_minVar), y=ret_minVar, marker=’D’, s=50, color=’DarkGreen’, label=’minimum variance portfolio’)
# Plot volatility versus expected return for maximum return portfolio
ax.scatter(x=np.sqrt(var_maxRet), y=ret_maxRet, marker=’s’, s=50, color=’DarkMagenta’, label=’maximum return portfolio’)
# Plot efficient frontier
ax.plot(np.sqrt(var_front), ret_front, ‘k-‘, label=’efficient frontier’)
# Plot volatility versus expected return for individual stocks
ax.scatter(x=np.sqrt(np.diag(Q)), y=mu, color=’Blue’, label=’individual stocks’)
# Format and display the final plot
ax.axis([0.9*np.sqrt(var_minVar), 1.2*np.max(np.sqrt(np.diag(Q))), np.min(mu)-0.1*(np.max(mu)-np.min(mu)), 1.1*ret_maxRet])
ax.set_xlabel(‘Volatility (Standard Deviation)’)
ax.set_ylabel(‘Expected Return’)
plt.title(‘Efficient Frontier’)
ax.legend(loc=”lower right”)
plt.show()
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com