![](/img/trans.png)
[英]CPLEX Python API how to multiply a decision variable with a dummy in the objective function?
[英]How do I setup an objective function in CPLEX Python containing indicator functions?
以下是目标函数:
这个想法是,已经对所有证券进行了均值方差优化。 这为我们提供了目标投资组合的权重。 现在假设投资者已经持有一个投资组合,并且不想将其整个投资组合更改为目标投资组合。
令w_0 = [w_0(1),w_0(2),...,w_0(N)]为初始投资组合,其中w_0(i)是投资于股票i = 1,..., N. 令w_t = [w_t(1),w_t(2),...,w_t(N)]为目标投资组合,即重新平衡后希望拥有的投资组合。 可以使用二次方优化技术(例如方差最小化)来构造此目标投资组合。
目的是确定满足以下特征的最终投资组合w_f = [w_f(1),w_f(2),...,w_f(N)]:
通过将特征项1到4相加来创建要最小化的目标函数。
通过将最终投资组合和目标投资组合的权重绝对差相加得出第一项。
第二项是通过指标函数的总和乘以用户指定的惩罚来捕获的。 指标函数为y_ {transactions}(i),如果初始投资组合和最终投资组合中的安全权重i不同,则为1,否则为0。
第三项是总投资组合最终收益乘以用户指定的负罚金,因为目标是最小化。
最后一项是最终投资组合中资产的计数(即,一个指标函数对最终投资组合中正权数进行计数的总和)乘以用户指定的罚款。
假设我们已经将目标权重设为target_w,如何在docplex python库中设置此优化问题? 或者,如果任何人都熟悉NAG中的混合整数编程,那么了解如何在此处设置此类问题也将很有帮助。
`
final_w = [0.]*n
final_w = np.array(final_w)
obj1 = np.sum(np.absolute(final_w - target_w))
pen_trans = 1.2
def ind_trans(final,inital):
list_trans = []
for i in range(len(final)):
if abs(final[i]-inital[i]) == 0:
list_trans.append(0)
else:
list_trans.append(1)
return list_trans
obj2 = pen_trans*sum(ind_trans(final_w,initial_w))
pen_returns = 0.6
returns_np = np.array(df_secs['Return'])
obj3 = (-1)*np.dot(returns_np,final_w)
pen_count = 1.
def ind_count(final):
list_count = []
for i in range(len(final)):
if final[i] == 0:
list_count.append(0)
else:
list_count.append(1)
return list_count
obj4 = sum(ind_count(final_w))
objective = obj1 + obj2 + obj3 + obj4
代码中的主要问题是, final_w
不是变量数组,而是数据数组。 因此,没有什么可以优化的。 要在docplex中创建变量数组,您必须执行以下操作:
from docplex.mp.model import Model
with Model() as m:
final = m.continuous_var_list(n, 0.0, 1.0)
这将创建n
变量,这些变量的取值范围为0到1。 例如:
obj1 = m.sum(m.abs(initial[i] - final[i]) for i in range(n))
对于下一个目标,由于您需要指标约束,因此事情变得更加困难。 为了简化这些约束的定义,首先定义一个辅助变量delta
,该变量给出股票之间的绝对差:
delta = m.continuous_var_list(n, 0.0, 1.0)
m.add_constraints(delta[i] == m.abs(initial[i] - final[i]) for i in range(n))
接下来,如果需要交易以调整库存i
,则需要一个指标变量1:
needtrans = m.binary_var_list(n)
for i in range(n):
# If needtrans[i] is 0 then delta[i] must be 0.
# Since needtrans[i] is penalized in the objective, the solver will
# try hard to set it to 0. It will only set it to 1 if delta[i] != 0.
# That is exactly what we want
m.add_indicator(needtrans[i], delta[i] == 0, 0)
这样,您可以定义第二个目标:
obj2 = pen_trans * m.sum(needtrans)
一旦定义了所有目标,就可以将它们的总和添加到模型中:m.minimize(obj1 + obj2 + obj3 + obj4),然后求解模型并显示其解决方案:
m.solve()
print(m.solution.get_values(final))
如果您还不清楚以上任何内容,那么我建议您看看docplex附带的许多示例以及(参考)文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.