我正在尝试修改从gurobi网站获得的投资组合示例。在示例中,存在一个线性问题,该线性问题可以用[0,1]中的所有var解决。我想将其更改为[-1,1]范围,而不是vars.sum() == 1
,我需要var的绝对值之和。
我尝试了很多事情... vars.abs_().sum()
,abs_(vars).sum()
等,无法完成。
#!/usr/bin/python
from gurobipy import *
from math import sqrt
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
def moneta():
# Import (normalized) historical return data using pandas
caminho = os.getcwd() + "\evo_val1h.csv"
#caminho = os.getcwd() + "\evo_val5min.csv"
data = pd.DataFrame.from_csv(caminho)
stocks = data.columns
retorno = []
# Calculate basic summary statistics for individual stocks
stock_volatility = data.std()
stock_return = data.mean()
# Create an empty model
m = Model('portfolio')
# Add a variable for each stock
vars = pd.Series(m.addVars(stocks, ub=1.0, lb=-1.0), index=stocks)
# Objective is to minimize risk (squared). This is modeled using the
# covariance matrix, which measures the historical correlation between stocks.
sigma = data.cov()
portfolio_risk = sigma.dot(vars).dot(vars)
m.setObjective(portfolio_risk, GRB.MINIMIZE)
# Fix budget with a constraint
m.addConstr(vars.sum() == 1, 'budget')
print(vars)
# Optimize model to find the minimum risk portfolio
m.setParam('OutputFlag', 0)
m.optimize()
# Create an expression representing the expected return for the portfolio
portfolio_return = stock_return.dot(vars)
m.setObjective(portfolio_return - 80*portfolio_risk, GRB.MAXIMIZE)
m.optimize()
# Display minimum risk portfolio
print('Minimum Risk Portfolio:\n')
soma = 0.0
for v in vars:
if v.x > 0.03 or v.x < -0.03:
print('\t%s\t: %g' % (v.varname, 100*v.x))
soma += 100*v.x
retorno.append(v.varname.replace("C", ""))
retorno.append(str(v.x))
print(soma)
minrisk_volatility = sqrt(portfolio_risk.getValue())
print('\nVolatility = %g' % minrisk_volatility)
minrisk_return = portfolio_return.getValue()
print('Expected Return = %g' % minrisk_return)
# Add (redundant) target return constraint
target = m.addConstr(portfolio_return == minrisk_return, 'target')
# Solve for efficient frontier by varying target return
frontier = pd.Series()
for r in np.linspace(stock_return.min(), stock_return.max(), 100):
target.rhs = r
m.optimize()
frontier.loc[sqrt(portfolio_risk.getValue())] = r
# Plot volatility versus expected return for individual stocks
ax = plt.gca()
ax.scatter(x=stock_volatility, y=stock_return,
color='Blue', label='Individual Stocks')
for i, stock in enumerate(stocks):
if stock_return[i] > 0.05:
ax.annotate(stock, (stock_volatility[i], stock_return[i]))
# Plot volatility versus expected return for minimum risk portfolio
ax.scatter(x=minrisk_volatility, y=minrisk_return, color='DarkGreen')
ax.annotate('Minimum\nRisk\nPortfolio', (minrisk_volatility, minrisk_return),
horizontalalignment='right')
# Plot efficient frontier
frontier.plot(color='DarkGreen', label='Efficient Frontier', ax=ax)
# Format and display the final plot
ax.axis([-0.05, 0.06, -0.01, 0.01])
ax.set_xlabel('Volatility (standard deviation)')
ax.set_ylabel('Expected Return')
ax.legend()
ax.grid()
plt.show()
return retorno
moneta()
由第33行插入:m.addConstr(vars.sum() == 1, 'budget')
我需要pd.Series vars的绝对值之和