使用Scipy fmin_slsqp求解器进行优化时遇到问题求助
问题修正与代码优化
原代码核心问题
- 约束函数参数顺序错误:
cons1的第一个参数应为优化变量w,fmin_slsqp会优先传递优化变量,再传递额外参数,原代码参数顺序完全颠倒。 args传递不匹配:目标函数和约束函数的额外参数需统一传递,原代码传递的w0属于冗余参数,且未正确给cons1传递fixed_value。mdd函数边界缺失:当序列无回撤(min=0)时,serie[:min]为空数组,np.nanargmax会返回nan,引发索引错误。- 冗余变量定义:
w = np.ndarray(shape=(5))未实际使用,可通过mat.shape[1]实现代码对任意列数的适配。
修正后的完整代码
import numpy as np from scipy.optimize import fmin_slsqp def mdd(serie): # 处理短序列或无回撤的边界情况 if len(serie) < 2: return 0.0 drawdowns = np.fmax.accumulate(serie) - serie min_idx = np.nanargmax(drawdowns) if drawdowns[min_idx] == 0: return 0.0 max_idx = np.nanargmax(serie[:min_idx]) return serie[max_idx] - serie[min_idx] # 输入数据 mat = np.array([ [1, 0, 0, 1, 1], [2, 0, 5, 3, 4], [3, 2, 4, 3, 7], [4, 1, 3, 3.1, -6], [5, 0, 2, 5, -7], [6, -1, 4, 1, -8] ]).astype('float32') w0 = np.array([1/5]*mat.shape[1], dtype='float32') # 自动适配列数的初始权重 fixed_value = 4.32 # 目标函数:最小化加权序列的最大回撤 def objective(w, mat): series = np.sum(mat * w, axis=1) return mdd(series) # 约束1:各列最后一行与权重乘积之和等于fixed_value def constraint1(w, mat, fixed_value): return np.sum(mat[-1, :] * w) - fixed_value # 约束2:所有权重之和等于1 def constraint2(w): return np.sum(w) - 1 # 执行优化 result = fmin_slsqp( func=objective, x0=w0, f_eqcons=[constraint1, constraint2], bounds=[(0.0, 1.0)]*mat.shape[1], args=(mat, fixed_value), full_output=True ) weights, fW, its, imode, smode = result print("最优权重:", weights) print("最小最大回撤:", fW)
关键修正说明
- 约束函数参数调整:将
constraint1的第一个参数改为w,匹配fmin_slsqp的参数传递逻辑,通过args统一传递mat和fixed_value。 mdd函数鲁棒性提升:增加序列长度判断、无回撤场景处理,避免空数组索引错误。- 代码通用性优化:用
mat.shape[1]替代固定列数,支持任意列数的输入数组。 - 冗余代码清理:删除未使用的变量,简化初始权重定义逻辑。
内容的提问来源于stack exchange,提问作者tibibou
相关产品推荐
相关产品推荐

