Python 使用scipy.optimize的均值-方差优化

Python 使用scipy.optimize的均值-方差优化,python,scipy-optimize-minimize,Python,Scipy Optimize Minimize,我正在研究portefolio优化,因此我想最小化一个函数,该函数计算其净结果的方差,前提是其平均值等于或大于某个预期结果exp: minimize Var (Net Result) subject to E(Net result) >=exp 我将我的目标函数定义为: R=[] length_to_split=[26,56,46,38,48,38,45,55,59,47] from itertools import accumulate def objective(z): f

我正在研究portefolio优化,因此我想最小化一个函数,该函数计算其净结果的方差,前提是其平均值等于或大于某个预期结果exp:

minimize Var (Net Result) subject to E(Net result) >=exp
我将我的目标函数定义为:

R=[]
length_to_split=[26,56,46,38,48,38,45,55,59,47]
from itertools import accumulate 
def objective(z):
    for i in range(0, len(dataframe)):
        
        R.append((1- max(0, (dataframe.iloc[i,1]- z) /dataframe.iloc[i,1]) )*(dataframe.iloc[i,2]-dataframe.iloc[i,1]))
    R_ann=[R[x - y: x] for x, y in zip(accumulate(length_to_split), length_to_split)] #each sublist 
    #contains results of one year 
    R_avg=sum([sum(r) for r in R_ann ] )/len([sum(r) for r in R_ann ])  #[sum(r) for r in R_ann ] will 
    #return 10 results corresponding to net results for each year from 2010 to 2019.
    var = sum((Rj-R_avg)**2 for Rj in [sum(r) for r in R_ann ]) / len([sum(r) for r in R_ann ])
    return var
K=[]
from statistics import mean 
def constraint(z):
    exp=1000000
    for i in range(0, len(dataframe)):
        if dataframe.iloc[i,1]>z:
            K.append((1- ((dataframe.iloc[i,1]-z) /dataframe.iloc[i,1])) * (dataframe.iloc[i,2]-dataframe.iloc[1,1]))
        else: 
            K.append((dataframe.iloc[i,2]-dataframe.iloc[i,1])) 
    K_ann=[K[v - w: v] for v, w in zip(accumulate(length_to_split), length_to_split)] 
    return mean([sum(j)  for j in K_ann]) -exp
dataframe是一个包含4列的数据,其中第一列表示成本,第二列表示保费,然后我将约束函数定义为:

R=[]
length_to_split=[26,56,46,38,48,38,45,55,59,47]
from itertools import accumulate 
def objective(z):
    for i in range(0, len(dataframe)):
        
        R.append((1- max(0, (dataframe.iloc[i,1]- z) /dataframe.iloc[i,1]) )*(dataframe.iloc[i,2]-dataframe.iloc[i,1]))
    R_ann=[R[x - y: x] for x, y in zip(accumulate(length_to_split), length_to_split)] #each sublist 
    #contains results of one year 
    R_avg=sum([sum(r) for r in R_ann ] )/len([sum(r) for r in R_ann ])  #[sum(r) for r in R_ann ] will 
    #return 10 results corresponding to net results for each year from 2010 to 2019.
    var = sum((Rj-R_avg)**2 for Rj in [sum(r) for r in R_ann ]) / len([sum(r) for r in R_ann ])
    return var
K=[]
from statistics import mean 
def constraint(z):
    exp=1000000
    for i in range(0, len(dataframe)):
        if dataframe.iloc[i,1]>z:
            K.append((1- ((dataframe.iloc[i,1]-z) /dataframe.iloc[i,1])) * (dataframe.iloc[i,2]-dataframe.iloc[1,1]))
        else: 
            K.append((dataframe.iloc[i,2]-dataframe.iloc[i,1])) 
    K_ann=[K[v - w: v] for v, w in zip(accumulate(length_to_split), length_to_split)] 
    return mean([sum(j)  for j in K_ann]) -exp
当我试图最小化目标函数时

from scipy.optimize import minimize
con = {'type': 'ineq', 'fun': constraint}
guess=500000
minimize(objective,guess,constraints=con)

它给了我以下错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-404-ff80aabebc42> in <module>
      2 con = {'type': 'ineq', 'fun': constraint}
      3 guess=500000
----> 4 minimize(objective,guess,constraints=con)
      5 # initial guesses

~\Anaconda3\lib\site-packages\scipy\optimize\_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    607     elif meth == 'slsqp':
    608         return _minimize_slsqp(fun, x0, args, jac, bounds,
--> 609                                constraints, callback=callback, **options)
    610     elif meth == 'trust-constr':
    611         return _minimize_trustregion_constr(fun, x0, args, jac, hess, hessp,

~\Anaconda3\lib\site-packages\scipy\optimize\slsqp.py in _minimize_slsqp(func, x0, args, jac, bounds, constraints, maxiter, ftol, iprint, disp, eps, callback, **unknown_options)
    313               for c in cons['eq']]))
    314     mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
--> 315                for c in cons['ineq']]))
    316     # m = The total number of constraints
    317     m = meq + mieq

~\Anaconda3\lib\site-packages\scipy\optimize\slsqp.py in <listcomp>(.0)
    313               for c in cons['eq']]))
    314     mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
--> 315                for c in cons['ineq']]))
    316     # m = The total number of constraints
    317     m = meq + mieq

<ipython-input-401-fe7f26be36f9> in constraint(z)
     10             K.append((dataframe.iloc[i,2]-dataframe.iloc[i,1]))
     11     K_ann=[K[v - w: v] for v, w in zip(accumulate(length_to_split), length_to_split)]
---> 12     return mean([sum(j)  for j in K_ann]) -exp
     13 #contrainte(900000)
     14 

~\Anaconda3\lib\statistics.py in mean(data)
    309     if n < 1:
    310         raise StatisticsError('mean requires at least one data point')
--> 311     T, total, count = _sum(data)
    312     assert count == n
    313     return _convert(total/n, T)

~\Anaconda3\lib\statistics.py in _sum(data, start)
    145     for typ, values in groupby(data, type):
    146         T = _coerce(T, typ)  # or raise TypeError
--> 147         for n,d in map(_exact_ratio, values):
    148             count += 1
    149             partials[d] = partials_get(d, 0) + n

~\Anaconda3\lib\statistics.py in _exact_ratio(x)
    227         return (x, None)
    228     msg = "can't convert type '{}' to numerator/denominator"
--> 229     raise TypeError(msg.format(type(x).__name__))
    230 
    231 

TypeError: can't convert type 'ndarray' to numerator/denominator
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在里面
2 con={'type':'ineq','fun':约束}
3猜=500000
---->4最小化(目标、猜测、约束=con)
5#初步猜测
最小化中的~\Anaconda3\lib\site packages\scipy\optimize\\u minimize.py(fun、x0、args、method、jac、hess、hessp、bounds、constraints、tol、callback、options)
607 elif meth==“slsqp”:
608返回_最小化_slsqp(fun、x0、args、jac、bounds、,
-->609约束,回调=回调,**选项)
610 elif meth==“信任契约”:
611返回最小信任区域(fun、x0、args、jac、hess、hessp、,
~\Anaconda3\lib\site packages\scipy\optimize\slsqp.py in_minimize_slsqp(func、x0、args、jac、bounds、constraints、maxiter、ftol、iprint、disp、eps、callback、**未知选项)
313对于cons['eq']]中的c)
314 mieq=sum(map(len,[u 1d(c['fun'](x,*c['args')))
-->315表示c在cons中['ineq']])
316#m=约束的总数
317 m=meq+mieq
~\Anaconda3\lib\site packages\scipy\optimize\slsqp.py in(.0)
313对于cons['eq']]中的c)
314 mieq=sum(map(len,[u 1d(c['fun'](x,*c['args')))
-->315表示c在cons中['ineq']])
316#m=约束的总数
317 m=meq+mieq
受约束(z)
10 K.append((dataframe.iloc[i,2]-dataframe.iloc[i,1]))
11 K_ann=[K[v-w:v]表示v,w在zip中(累计(长度从u到u分割),长度从u到u分割)]
--->12返回平均值([K_ann中j的和(j))-exp
13#合同(900000)
14
~\Anaconda3\lib\statistics.py平均值(数据)
309如果n<1:
310 raise StatisticsError('平均值至少需要一个数据点')
-->311吨,总计,计数=总和(数据)
312断言计数==n
313返回_转换(总计/n,T)
~\Anaconda3\lib\statistics.py in\u sum(数据,开始)
145对于类型,groupby中的值(数据,类型):
146 T=_强制(T,典型)#或引发类型错误
-->147表示映射图中的n,d(_精确比率,值):
148计数+=1
149个partials[d]=partials_get(d,0)+n
~\Anaconda3\lib\statistics.py的精确比率(x)
227返回(x,无)
228 msg=“无法将类型“{}”转换为分子/分母”
-->229 raise TypeError(消息格式(类型(x)。\uuuuu名称\uuuuu))
230
231
TypeError:无法将类型“ndarray”转换为分子/分母

有人能帮我解决这个问题吗?我无法得到正确的结果,我认为问题在于我的约束函数,即使我修正了这种类型的错误。

变量
exp
guess
那么高是什么?为什么变量
exp
guess
那么高?