Optimization 投资组合优化中的基数约束
我正在使用cvxpy处理一些简单的投资组合优化问题。我唯一无法理解的约束是非零投资组合持有量的基数约束。我尝试了两种方法,MIP方法和传统的凸面方法 下面是一个正常工作的传统示例的一些伪代码Optimization 投资组合优化中的基数约束,optimization,convex-optimization,cvxpy,mixed-integer-programming,Optimization,Convex Optimization,Cvxpy,Mixed Integer Programming,我正在使用cvxpy处理一些简单的投资组合优化问题。我唯一无法理解的约束是非零投资组合持有量的基数约束。我尝试了两种方法,MIP方法和传统的凸面方法 下面是一个正常工作的传统示例的一些伪代码 import numpy as np import cvxpy as cvx np.random.seed(12345) n = 10 k = 6 mu = np.abs(np.random.randn(n, 1)) Sigma = np.random.randn(n, n) Sigma = Sigma.
import numpy as np
import cvxpy as cvx
np.random.seed(12345)
n = 10
k = 6
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
ret = mu.T*w
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
constraints = [cvx.sum_entries(w) == 1, w>= 0, cvx.sum_smallest(w, n-k) >= 0, cvx.sum_largest(w, k) <=1 ]
prob = cvx.Problem(objective, constraints)
prob.solve()
print prob.status
output = []
for i in range(len(w.value)):
output.append(round(w[i].value,2))
print 'Number of non-zero elements : ',sum(1 for i in output if i > 0)
查看我的二进制向量,它似乎做了正确的事情,但是sum_entries约束不起作用,查看二进制向量值,我注意到0不是0,它非常小,例如xxe^-20,我认为这会把事情搞砸。如果这是正确的方法,任何人都可以给我任何指导吗?我可以使用标准解算器,如果有帮助的话,也可以使用Mosek。我更喜欢非MIP实现,因为我知道这是一个组合问题,对于更大的问题,它会变得非常缓慢。最终,我想限制目标持股的确切数量或范围,例如20-30
此外,cvxpy中关于MIP的文档非常简短。谢谢,这个问题有点混乱 首先,这种基数约束是NP难的。这意味着,如果不使用整数规划,就不能使用cvxpy来表示它(否则它将隐含P=NP) 比因说,如果有一个纯版本的代码,而不试图制定这个约束,那就更好了。我只是假设它是第一个没有
sum\u最小
和sum\u最大
约束的代码
因此,让我们来解决MIP方法:
import numpy as np
import cvxpy as cvx
np.random.seed(12345)
n = 10
k = 6
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
ret = mu.T*w
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
binary = cvx.Bool(n) # !!!
constraints = [cvx.sum_entries(w) == 1, w>= 0, w - binary <= 0., cvx.sum_entries(binary) == k] # !!!
prob = cvx.Problem(objective, constraints)
prob.solve(verbose=True)
print(prob.status)
output = []
for i in range(len(w.value)):
output.append(round(w[i].value,2))
print('Number of non-zero elements : ',sum(1 for i in output if i > 0))
- 您的代码尝试这样做毫无意义
- 您引入了一些二进制变量,但它们与任何其他变量都没有连接(因此对其和的约束是无用的)李>
- 您引入了一些整数变量,但它们没有任何用处李>
import numpy as np
import cvxpy as cvx
np.random.seed(12345)
n = 10
k = 6
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
ret = mu.T*w
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
binary = cvx.Bool(n) # !!!
constraints = [cvx.sum_entries(w) == 1, w>= 0, w - binary <= 0., cvx.sum_entries(binary) == k] # !!!
prob = cvx.Problem(objective, constraints)
prob.solve(verbose=True)
print(prob.status)
output = []
for i in range(len(w.value)):
output.append(round(w[i].value,2))
print('Number of non-zero elements : ',sum(1 for i in output if i > 0))
将numpy导入为np
将cvxpy作为cvx导入
np.random.seed(12345)
n=10
k=6
mu=np.abs(np.random.randn(n,1))
Sigma=np.random.randn(n,n)
西格玛=西格玛T点(西格玛)
w=cvx.变量(n)
ret=μT*w
风险=cvx.四元形式(w,西格玛)
目标=cvx最大化(ret-风险)
二进制=cvx.Bool(n)#!!!
约束=[cvx.sum_条目(w)==1,w>=0,w-二进制0))
所以我们只是添加了一些二进制变量,并将它们连接到w
,以指示w是否为非零
如果w为非零
:
- 由于约束
w>=0
binary
需要为1,否则约束w-binary我遇到了一个类似的问题,我的权重可能为负数,不需要求和为1(但仍然需要有界),因此我修改了sascha的示例,以适应使用CVXpy绝对值函数来放松这些约束。这应该允许使用MIP处理基数约束的更通用的方法
import numpy as np
import cvxpy as cvx
np.random.seed(12345)
n = 10
k = 6
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
ret = mu.T*w
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
binary = cvx.Variable(n,boolean=True) # !!!
maxabsw=2
constraints = [ w>= -maxabsw,w<=maxabsw, cvx.abs(w)/maxabsw - binary <= 0., cvx.sum(binary) == k] # !!!
prob = cvx.Problem(objective, constraints)
prob.solve(verbose=True)
print(prob.status)
output = []
for i in range(len(w.value)):
output.append(round(w[i].value,2))
print('Number of non-zero elements : ',sum(1 for i in output if i > 0))
将numpy导入为np
将cvxpy作为cvx导入
np.random.seed(12345)
n=10
k=6
mu=np.abs(np.random.randn(n,1))
Sigma=np.random.randn(n,n)
西格玛=西格玛T点(西格玛)
w=cvx.变量(n)
ret=μT*w
风险=cvx.四元形式(w,西格玛)
目标=cvx最大化(ret-风险)
binary=cvx.Variable(n,boolean=True)#!!!
maxabsw=2
约束=[w>=-maxabsw,w这看起来不错,谢谢,你介意把范围版本放在你的工作示例中吗?我正在努力研究你如何使用你的指示器。谢谢,我会接受这个答案。我不明白限制是什么-binary@qfd不清楚的是什么?有一些解释。w-binary就是1或1的数组0s?不是。这是一个0/1变量的向量。请记住:cvxpy api从此发生了变化!