GEKKO优化求解夏普比率最大化时返回零解无有效解如何解决?
问题原因
- 决策变量边界配置错误
你定义手数变量时写了ub=0,即手数的上限为0,这直接限制了所有手数只能取小于等于0的值,自然只能得到全零解。正常买入做多的场景下应该设置下限lb=0,上限可以根据总资金和单股价格计算最大可买手数,或者暂时设一个足够大的合理值。 - 约束条件逻辑错误
你写的约束self.get_required_money(hands) >= -1 * self._total_money完全不符合实际业务逻辑。实际约束应该是买入股票占用的资金不超过总可用资金,也就是self.get_required_money(hands) <= self._total_money。你原来的约束在手数为0时左边等于0,天然满足大于等于-15000的条件,等于没有有效约束。 - 目标函数存在除零风险
当所有手数为0时,required_money等于0,计算权重时会触发除零错误,导致目标函数返回NaN,求解器无法正常迭代,直接返回初始的全零解。 - (业务逻辑错误,不影响解的输出,但会导致结果不符合预期)组合波动率计算错误,投资组合的标准差不是各资产标准差的加权求和,需要加入不同资产之间的协方差计算。
修复方案
修改calc_sharp_ratio方法的相关代码,参考修改后的片段:
def calc_sharp_ratio(self): m = GEKKO(remote = True) # 修正变量边界:手数下限为0,上限根据总资金计算最大可买手数 max_hands = [int(self._total_money/(100*float(s.get_price()))) for s in self._stocks] hands = [m.Var(integer = True, lb = 0, ub=max_hands[i]) for i in range(len(self._stocks))] # 修正约束:占用资金不超过总资金,且至少买1手避免除零 m.Equation(self.get_required_money(hands) <= self._total_money) min_price = min([float(s.get_price()) for s in self._stocks]) m.Equation(self.get_required_money(hands) >= 100 * min_price) m.Obj(self.get_sharpe_ratio(hands)) m.options.SOLVER = 1 m.solve() return hands
如果需要兼容做空场景,可以调整lb为负数,同时对应修改资金约束逻辑即可。
内容的提问来源于stack exchange,提问作者NNNNNNN
相关产品推荐
相关产品推荐

