【问题标题】:Constrained Linear Optimization Setup约束线性优化设置
【发布时间】:2019-08-07 02:38:30
【问题描述】:

我正在为以下设置而苦苦挣扎。

我的数据如下:

Group   ID  Wt       Coeff      Coeff*Wt
------  --- ------   -------    -------
Group1  A   10.00%   1.00000     0.100 
Group1  B   10.00%   1.00000     0.100 
Group1  C   10.00%   3.00005     0.300 
Group2  D   10.00%   1.00000     0.100 
Group2  E   10.00%   1.00000     0.100 
Group2  F   10.00%   1.00000     0.100 
Group2  G   10.00%   7.80016     0.780 
Group3  H   10.00%   7.80485     0.780 
Group3  I   10.00%   1.00000     0.100 
Group3  J   10.00%   0.39529     0.040 



Objective function: Fmin = mimimize(sum of weights * coeff)

我需要实现以下约束:

Sum of Weights*Coeff of Group1 = 20% of total minimized fmin
Sum of Weights*Coeff of Group1 = 45% of total minimized fmin
Sum of Weights*Coeff of Group1 = 35% of total minimized fmin

以及以下边界条件:

Weights <=10% and Weights > 0.30%

Sum of weights = 100%

我正在尝试使用以下代码来完成此操作。

我不知道为什么这不起作用:

from scipy.optimize import linprog

c = [ 1.0000 ,1.0000 ,3.0001 ,1.0000 ,1.0000 ,1.0000 ,7.8002 ,7.8049 ,1.0000 ,0.3953 ]

groupPerID = ['Group1','Group1','Group1','Group2','Group2','Group2','Group2','Group3','Group3','Group3']

groupList = ['Group1','Group2','Group3']

groupUpperBound = [0.20,0.45,0.40]

A_eq_list = []
A_eq_list.append([1]*len(c))

b_eq_list = [1]

for idx,currentGroup in enumerate(groupList):

    matches = [i for i in range(len(groupPerID)) if groupPerID[i] == currentGroup]

    currentGroupUB = groupUpperBound[idx]

    x_list = [float(-1*currentGroupUB*coeff) for coeff in c]

    for idx in matches:
        x_list[idx] = float((1-currentGroupUB)*c[idx])

    A_eq_list.append(x_list)

b_eq_list.extend([0]*len(groupUpperBound))
res = linprog(c, A_eq=A_eq_list, b_eq=b_eq_list,bounds =(0.003,0.1),options={'tol':0.05})
print(res)

谁能指出我犯了什么错误?

【问题讨论】:

  • 如果我理解正确,您正在尝试优化要分配的权重,对吗?所以你每10%权重的数据只是一个例子?
  • 是的,这是正确的。该解决方案在 excel 求解器中进行了优化。我想将 excel 求解器约束转换为 python linprog。
  • [0.20,0.45,0,40] 中多了一个逗号,而不是一个点。但一般来说,我会做的是打印 A_eq 和 b_eq 并考虑它们与您期望的不等式的不同之处。
  • 谢谢 - 这是一个错字。我修好了它。你还看到什么吗?

标签: python optimization scipy portfolio


【解决方案1】:

所以我在 scipy 包装器 symfit 中实现了它,它负责所有样板代码。它现在可以工作了,除了我还没有在权重上实现你的界限。但是,我认为这些都是错误的,如您的问题所述,因为满足所有权重总和为 1 的约束的唯一方法是将它们全部设置为上限 0.1。除此之外,这是我的尝试:

from symfit import parameters, Minimize, Variable, Eq
import numpy as np

# Make 10 weight parameters w_i to optimize
weights = parameters(','.join('w_{}'.format(i) for i in range(1, 11)))
c = np.array([1.0000, 1.0000, 3.0001, 1.0000, 1.0000, 1.0000, 7.8002, 7.8049, 1.0000, 0.3953])
f = Variable()

for w_i in weights:
    w_i.min = 0.003
    w_i.max = 1.0
    w_i.value = 0.1

sum_of_group_1 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[0:3])
sum_of_group_2 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[3:7])
sum_of_group_3 = sum(c_i * w_i for c_i, w_i in zip(c, weights)[7:10])
# Function to minimize
model = {f: sum_of_group_1 + sum_of_group_2 + sum_of_group_3}

constraints = [
    Eq(0.20 * sum_of_group_1, 0.45 * sum_of_group_2),
    Eq(0.20 * sum_of_group_1, 0.35 * sum_of_group_3),
    Eq(sum(weights), 1)
]

fit = Minimize(model, constraints=constraints)
fit.eval_jacobian = None  # Workaround needed because f is just a scalar, not an array
fit_result = fit.execute()

print(fit_result)
print(sum(fit_result.value(w) for w in weights)) # >>> 1.0

您可以在文档here 中阅读更多内容。

【讨论】:

  • 谢谢 tBuli。我现在正在努力检查我试图解决的优化问题是否完全可行。我会回来更新我的发现并接受您的帮助作为最终答案。
  • 很高兴我能帮上忙!是的,如果不仔细研究,我会认为系统不确定,因此解决方案不是唯一的,如果有的话。祝你好运!
猜你喜欢
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多