1
$\begingroup$

I have a problem with the MVP-optimization and scipy. My code is the following. The Maximum-Sharpe-Ratio-Portfolio works. But if I want to optimise the MVP, scipy optimiser doesn't seem to work, because the asset weights are still equal weighted like the input weights for the optimisation.

The data ist available at Dropbox: Returns

# Read in returns
ret = pd.read_excel('/Users/XXX/Desktop/Data/003 Data/Returns.xlsx') # Import
ret.drop('DataDate', axis=1, inplace=True)
# No. of assets
no_assets=len(ret.columns.tolist())

#Standard simulation
MC_returns =[]
MC_vols =[]
N=1000
#In a loop, generate portfolio weights and make sure they add up to 1 (one).
for p in range(N):
    weights=np.random.rand(no_assets)
    weights/= np.sum(weights)
    MC_returns.append(np.sum(ret.mean()*weights)*252)
    MC_vols.append (np.sqrt(np.dot(weights.T, np.dot(ret.cov()*252, weights))))

# Plot
plt.scatter(MC_vols,MC_returns, s=1.5)
plt.xlabel('Vol ') # Bezeichnung der x-Achse
plt.ylabel('Return') # Bezeichnung der y-Achse
plt.title('Efficient Frontier') # Titel des Diagramms
plt.show()

# Function fpr portfolio standard deviation, return and sharpe ratio
def portfolio(weights):
    weights=np.array(weights)
    P_ret=np.sum(ret.mean()*weights)*252
    P_vol=np.sqrt(np.dot(weights.T,np.dot(ret.cov()*252, weights)))
    return np.array([P_ret,P_vol, P_ret/P_vol])

# negative sharpe should be optimized
def Sharpe(weights):
    return -portfolio(weights)[2]
# Set up the constraint that portfolio weights add up to one.
cons=({'type':'eq','fun':lambda x: np.sum(x)-1})
# Set up boundaries for the portfolio weights (between 0 and 1).
bnds=tuple((0,1) for x in range(no_assets))

#Optimization
opt_S=sco.minimize(Sharpe, no_assets*[1.0/no_assets], method='SLSQP', bounds=bnds, constraints=cons)

opt_S['x'].round(3)

MSRP = portfolio(opt_S['x']).round(3) # ok works

# Plot
plt.scatter(MC_vols,MC_returns, s=1.5)
plt.scatter(x=MSRP[1], y=MSRP[0], c='gold', marker='D', s=10)
plt.xlabel('Vol ')
plt.ylabel('Return')
plt.title('Efficient Frontier')
plt.show()

# Same for portfolio variance
def Variance(weights):
    return portfolio(weights)[1]**2
#Set up the constraint that portfolio weights add up to one.
cons=({'type':'eq','fun':lambda x: np.sum(x)-1})
# Set up boundaries for the portfolio weights (between 0 and 1).
bnds=tuple((0,1) for x in range(no_assets))

#Optimisation function.
opt_V=sco.minimize (Variance, no_assets*[1.0/no_assets], method='SLSQP', bounds=bnds, constraints=cons)
#Print portfolio weights.
opt_V['x'].round(3)

MVP = portfolio(opt_V['x']).round(3)

plt.scatter(MC_vols,MC_returns, s=1.5)
plt.scatter(x=MSRP[1], y=MSRP[0], c='gold', marker='D', s=10)
plt.scatter(x=MVP[1], y=MVP[0], c='gold', marker='D', s=10)
plt.xlabel('Vol ')
plt.ylabel('Return')
plt.title('Efficient Frontier')
plt.show()
$\endgroup$
  • $\begingroup$ I don't understand the statement "def Variance(weights): return portfolio(weights)[1]**2". I thought you wanted to minimize the variance of portfolio returns, which is a quadratic form such as: weights.T,np.dot(ret.cov()*252, weights) $\endgroup$ – Alex C Oct 2 '19 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.