我正在使用cvxpy进行简单的投资组合优化。
我实现了以下虚拟代码
from cvxpy import *
import numpy as np
np.random.seed(1)
n = 10
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
orig_weight = [0.15,0.25,0.15,0.05,0.20,0,0.1,0,0.1,0]
w = Variable(n)
mu = np.abs(np.random.randn(n, 1))
ret = mu.T*w
lambda_ = Parameter(sign='positive')
lambda_ = 5
risk = quad_form(w, Sigma)
constraints = [sum_entries(w) == 1, w >= 0, sum_entries(abs(w-orig_weight)) <= 0.750]
prob = Problem(Maximize(ret - lambda_ * risk), constraints)
prob.solve()
print 'Solver Status : ',prob.status
print('Weights opt :', w.value)
我正在限制完全投资,只是长期并且营业额<= 75%。但是我想将周转作为一个“软”约束,因为求解器将尽可能少地使用但是尽可能多地使用,目前求解器几乎完全可以最大化周转率。
我基本上想要这样的东西,它是凸的并且不违反DCP规则
sum_entries(abs(w-orig_weight)) >= 0.05
我认为这应该设置一个最小阈值(此处为5%),然后使用尽可能多的周转率,直到找到可行的解决方案。
我尝试将目标函数重写为
prob = Problem(Maximize(lambda_ * ret - risk - penalty * max(sum_entries(abs(w-orig_weight))+0.9,0)) , constraints)
罚款例如2,我的约束对象仍然看起来像
constraints = [sum_entries(w) == 1, w >= 0, sum_entries(abs(w-orig_weight)) <= 0.9]
我从未使用过软限制,任何解释都会受到高度赞赏。
编辑:中级解决方案
from cvxpy import *
import numpy as np
np.random.seed(1)
n = 10
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = Variable(n)
mu = np.abs(np.random.randn(n, 1))
ret = mu.T*w
risk = quad_form(w, Sigma)
orig_weight = [0.15,0.2,0.2,0.2,0.2,0.05,0.0,0.0,0.0,0.0]
min_weight = [0.35,0.0,0.0,0.0,0.0,0,0.0,0,0.0,0.0]
max_weight = [0.35,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]
lambda_ret = Parameter(sign='positive')
lambda_ret = 5
lambda_risk = Parameter(sign='positive')
lambda_risk = 1
penalty = Parameter(sign='positive')
penalty = 100
penalized = True
if penalized == True:
print '-------------- RELAXED ------------------'
constraints = [sum_entries(w) == 1, w >= 0, w >= min_weight, w <= max_weight]
prob = Problem(Maximize(lambda_ * ret - lambda_ * risk - penalty * max_entries(sum_entries(abs(w-orig_weight)))-0.01), constraints)
else:
print '-------------- HARD ------------------'
constraints = [sum_entries(w) == 1, w >= 0, w >= min_weight, w <= max_weight, sum_entries(abs(w-orig_weight)) <= 0.40]
prob = Problem(Maximize(lambda_ret * ret - lambda_risk * risk ),constraints)
prob.solve()
print 'Solver Status : ',prob.status
print('Weights opt :', w.value)
all_in = []
for i in range(n):
all_in.append(np.abs(w.value[i][0] - orig_weight[i]))
print 'Turnover : ', sum(all_in)
以上代码将强制项目[0]的权重特定增加,此处为+ 20%,以保持sum()= 1约束必须抵消-20%的减少,因此我知道它需要至少40%的营业额才能做到这一点,如果一个运行代码,惩罚= False,&lt; = 0.4必须硬编码,任何小于此的东西都将失败。惩罚=真实案例将找到40%的最低要求营业额并解决优化问题。我还没想到的是如何在宽松的情况下设置最低阈值,即至少达到45%(如果需要的话,或者更多)。
我在第4.6章第37页找到了解决这个问题的一些解释。