繁体   English   中英

使用scipy进行优化

[英]Optimization using scipy

我正在尝试建立一个类似Markowitz问题的有效边界。 我已经写了下面的代码,但出现错误“ ValueError:目标函数必须返回标量”。 我已经用一些值测试了“有趣”,例如,我输入到控制台:

W = np.ones([n])/n     # start optimization with equal weights
cov_matrix = returns.cov() 
fun = 0.5*np.dot(np.dot(W, cov_matrix), W)    # variance of the portfolio
fun

输出为0.00015337622774133828,它是一个标量。 我不知道有什么问题。 任何帮助表示赞赏。

码:

from scipy.optimize import minimize
import pandas as pd
import numpy as np
from openpyxl import load_workbook

wb = load_workbook('path/Assets_3.xlsx') # in this workbook there is data for returns.
# The next lines clean unnecessary first column and first row.
ws = wb.active
df = pd.DataFrame(ws.values)
df1 = df.drop(0,axis=1)
df1 = df1.drop(0)
df1 = df1.astype(float)

rf = 0.05
r_bar = 0.05
returns = df1.copy()

def efficient_frontier(rf, r_bar, returns):   
    n = len(returns.transpose())
    W = np.ones([n])/n     # start optimization with equal weights
    exp_ret = returns.mean() 
    cov_matrix = returns.cov() 

    fun = 0.5*np.dot(np.dot(W, cov_matrix), W)    # variance of the portfolio

    cons = ({'type': 'eq', 'fun': lambda W: sum(W) - 1. },  
         {'type': 'ineq', 'fun': lambda W: np.dot(exp_ret,W) - r_bar })

    bnds = [(0.,1.) for i in range(n)]    # weights between 0..1. 

    res = minimize(fun, W, (returns, cov_matrix, rf), 
                method='SLSQP', bounds = bnds, constraints = cons)
    return res

x= efficient_frontier(rf,r_bar,returns)
x

一些数据

           1         2         3   
1   0.060206  0.005781  0.001117    
2   0.006463 -0.007390  0.001133    
3  -0.003211 -0.015730  0.001167    
4   0.044227 -0.006250  0.001225    
5  -0.040571 -0.006910  0.001292    
6  -0.007900 -0.006160  0.001208    
7   0.068702  0.013836  0.001300    
8   0.039286  0.009854  0.001350    
9   0.012457 -0.007950  0.001358    
10 -0.013758  0.001021  0.001283    
11 -0.002616 -0.013600  0.001300    
12  0.059004 -0.006090  0.001442    
13  0.015566  0.002818  0.001308    
14 -0.036454  0.001395  0.001283    
15  0.058899  0.011072  0.001325    
16 -0.043086  0.017070  0.001308    
17  0.023156 -0.003350  0.001392    
18  0.063705  0.000301  0.001417    
19  0.017628 -0.001960  0.001508    
20 -0.014567 -0.006990  0.001525    
21 -0.007191 -0.013000  0.001425    
22 -0.000815  0.014773  0.001450    
23  0.046493 -0.001540  0.001542    
24  0.051832 -0.008580  0.001742    
25 -0.007151  0.001177  0.001633    
26 -0.018196 -0.008680  0.001642    
27 -0.013513 -0.008810  0.001675    
28 -0.026493 -0.010510  0.001825    
29 -0.003249 -0.014750  0.001800    
30  0.001222  0.022258  0.001758

这段代码是一团糟,尽管我可以向您展示可以运行的内容,但这并不意味着任何事情。

无论您的任务意味着什么,您都将看到收敛到起点的方法! 这有力地表明有些事情还是非常错误的(可能是基础理论)!

一些补充说明:

  • scipy的优化器可以与numpy数组一起使用,而不是pandas Dataframes或Series对象!
    • 原始问题中唯一提示pandas使用的是var- dfreturns.cov() ,对于numpy-arrays不存在!
  • 射频从未在任何地方使用!
  • Optimizer的args中有很多东西没有使用!
  • 似乎不应该使用scipy的优化器来解决问题! (但有可能;例如,这里我们为数值微分支付)
    • 如果正确地解释问题(没有进行太多分析),那么cvxpy可能会是一种更好的方法(更干净,更快,更准确)。
    • 但是同样的规则也适用:需要一些python知识!

码:

from scipy.optimize import minimize
import numpy as np
import pandas as pd

rf = 0.05
r_bar = 0.05
returns = pd.DataFrame(np.random.randn(30, 3), columns=list('ABC'))  # PANDAS DF
cov_matrix = returns.cov().as_matrix()                               # use PANDAS one last time
                                                                     # but result = np.array!
returns = returns.as_matrix()                                        # From now on: np-only!

def fun(x, returns, cov_matrix, rf):
    return 0.5*np.dot(np.dot(x, cov_matrix), x)

def efficient_frontier(rf, r_bar, returns):
    n = len(returns.transpose())
    W = np.ones([n])/n     # start optimization with equal weights
    exp_ret = returns.mean()

    cons = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1. },         # let's use numpy here
         {'type': 'ineq', 'fun': lambda x: np.dot(exp_ret, x) - r_bar })

    bnds = [(0.,1.) for i in range(n)]    # weights between 0..1.

    res = minimize(fun, W, (returns, cov_matrix, rf),
                method='SLSQP', bounds = bnds, constraints = cons)
    return res

x= efficient_frontier(rf,r_bar,returns)
print(x)

输出:

A         B         C
A  0.813375 -0.001370  0.173901
B -0.001370  1.482756  0.380514
C  0.173901  0.380514  1.285936
fun: 0.2604530793556774
jac: array([ 0.32863522,  0.62063321,  0.61345008])
message: 'Optimization terminated successfully.'
nfev: 35
nit: 7
njev: 3
status: 0
success: True
x: array([ 0.33333333,  0.33333333,  0.33333333])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM