前面我们讨论了等式约束下的情况,那么如果有不等式约束呢?比如,我们不能做空股票,那么就要求每一个股票的权重都要大于1,或者对于特定的股票我们给予特殊的权重的设定等等。 这里,我们就假设我们设置两个不等式约束: 不能做空 股票s2的权重要要大于等于0.1. 这个时候,我们的约束条件就是:
subjectto.A′x≤b
subject to. A^{'}x \leq b 其中,
A=⎛⎝⎜⎜⎜⎜⎜⎜1u1−1001u20−101u300−1⎞⎠⎟⎟⎟⎟⎟⎟
A = \left( \begin{array}{ccc} 1 & 1 & 1 \\ u_1 & u_2 & u_3\\ -1 &0&0\\ 0&-1&0\\ 0&0&-1\end{array} \right)
b=⎛⎝⎜⎜⎜⎜⎜⎜10.150−0.10⎞⎠⎟⎟⎟⎟⎟⎟
b = \left( \begin{array}{ccc} 1\\ 0.15\\ 0\\ -0.1\\ 0\end{array} \right) 当然,这个时候就没有解析解了,我们需要用到python的一个凸优化的包来解决这个问题。
大家可以查看一下cvxopt这个包的官网,http://cvxopt.org/install/index.html 按照官网的方法按照cvxopt似乎是不可以的,我们可以在下面的网站下载wheel,然后安装。 http://www.lfd.uci.edu/~gohlke/pythonlibs/#cvxopt 对于cvxopt这个包而言,他的优化通式是这样的:
min12xTPx+qTx
min \quad \frac{1}{2}x^TPx+q^Tx
s.t.Gx≤h
s.t. \quad Gx\leq h
Ax=b
\qquad Ax=b 言下之意,就是我们要构建这几个矩阵:P,q,G,h,A,b
from cvxopt import matrix
from cvxopt import solvers
cvxopt 中自带matrix数据结构,要注意,这个和我们前面对矩阵的表达不一样,这里一个list代表的是一个列,而不是行。
P = matrix([[0.100162,0.045864,0.005712],[0.045864,0.210773,0.028283],[0.005712,0.028283,0.066884]])
q = matrix([0.0,0.0,0.0])
A = matrix([[1.0,1.0,1.0], [0.100162,0.164244,0.182082]]).T
b = matrix([1.0, 0.15])
sol = solvers.qp(P,q,A=A,b=b)
print sol['x']
结果如下: [ 3.83e-01] [ 3.97e-02] [ 5.77e-01] 我们发现,优化器优化出来的结构和我们前面的用拉格朗日乘子法算出来的是一样的。然后,我们来算不等式约束吧。
我们根据一开始的情景来进行不等式优化。
P = matrix([[0.100162,0.045864,0.005712],[0.045864,0.210773,0.028283],[0.005712,0.028283,0.066884]])
q = matrix([0.0,0.0,0.0])
G = matrix([[0.0,-1.0,0.0], [-1.0,0.0,0.0],[0.0,0.0,-1.0]])
h = matrix([-0.1,0.0,0.0])
A = matrix([[1.0,1.0,1.0], [0.100162,0.164244,0.182082]]).T
b = matrix([1.0, 0.15])
sol = solvers.qp(P,q,G=G, h=h, A=A,b=b)
print sol['x']
[ 3.70e-01] [ 1.00e-01] [ 5.30e-01] 结果如上,这就是我们不等式条件下的优化结果。 既然如此,还是老样子,画有效前沿吧。
return_list = list()
risk_list = list()
P = matrix([[0.100162,0.045864,0.005712],[0.045864,0.210773,0.028283],[0.005712,0.028283,0.066884]])
q = matrix([0.0,0.0,0.0])
G = matrix([[0.0,-1.0,0.0], [-1.0,0.0,0.0],[0.0,0.0,-1.0]])
h = matrix([-0.1,0.0,0.0])
A = matrix([[1.0,1.0,1.0], [0.100162,0.164244,0.182082]]).T
for i in range(1, 100):
up = i/1000.0
b = matrix([1.0, up])
sol = solvers.qp(P,q,G=G, h=h, A=A,b=b)
w = np.matrix([sol['x'][0], sol['x'][1], sol['x'][2]]).T
return_list.append((A_matrix * w)[1,0])
risk_list.append((w.T * cov_matrix * w)[0,0])
plot_df = pd.DataFrame()
plot_df['return'] = return_list
plot_df['risk'] = risk_list
plot_df.plot.scatter(x='risk', y='return')
结果如下:
我们之所以要先讲述组合构建和优化器,是因为,接下来我们将进行最最具有艺术的两个部分,就是我们前面提到的收益率预测模型和股票直接协方差矩阵,也就是风险模型。