Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization 投资组合优化中的基数约束_Optimization_Convex Optimization_Cvxpy_Mixed Integer Programming - Fatal编程技术网

Optimization 投资组合优化中的基数约束

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.

我正在使用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)

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))
  • 您的代码尝试这样做毫无意义
    • 您引入了一些二进制变量,但它们与任何其他变量都没有连接(因此对其和的约束是无用的)
    • 您引入了一些整数变量,但它们没有任何用处
这是一种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))
将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从此发生了变化!