I am currently using Python and am getting strange results when using Scipy.optimize - specifically the minimize function. Everything up to def optimize_portfolio(initial,returns,rf)
seems to run fine. The first few iterations of minimizing run fine, but after that it appears that the arguments "weights" and "returns" get switched around in def portfolio_stats(returns,weights,rf)
and I am not sure why. If anyone can figure out what is going on, that would be much appreciated!
from math import exp
import numpy as np
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import scipy.optimize as optimization
#Get data from Yahoo
def stock_data(stocks,start_date,end_date):
start_date= start_date
end_date= end_date
data=web.DataReader(stocks,data_source='yahoo',start=start_date,end=end_date)['Adj Close']
return data
#Calulate daily log returns (as opposed to arithmetic returns)
def stock_returns(data):
daily_returns=(data/data.shift(1))
daily_returns=np.log(daily_returns)
return daily_returns
#Get statistics for stocks (yearly approximate based on log returns)
def stock_stats(returns):
expected=returns.mean()*252
variance=returns.var()*252
covariance=returns.cov()*252
return [expected,variance,covariance]
#Get statistics for porfolio (yearly approximate based on log returns)
def portfolio_stats(returns,weights,rf):
expected=np.sum(returns.mean()*weights)*252
variance =np.dot(weights.T,np.dot(returns.cov()*252,weights))
sd=np.sqrt(variance)
sharpe=(expected-rf)/sd
return [expected,sd,sharpe]
#Run simulation of portfolios
def monte_carlo_porfolios(stocks,returns,simulations,rf):
mc_expected=[]
mc_sd=[]
optimum=[]
sharpe=0
for i in range(simulations):
weights=np.random.random(len(stocks))
weights /= np.sum(weights)
stats =portfolio_stats(returns,weights,rf)
expected =stats[0]
sd =stats[1]
mc_expected.append(expected)
mc_sd.append(sd)
if (expected-rf)/sd>sharpe:
optimum=weights
sharpe=(expected-rf)/sd
mc_expected=np.array(mc_expected)
mc_sd=np.array(mc_sd)
return [mc_expected,mc_sd,np.array(optimum)]
#Define function to minmise
def min_func_sharpe(weights,*args):
return -portfolio_stats(weights,args[0],args[1])[2]
#Find best combination via optimization algorithm
def optimize_portfolio(initial,returns,rf):
constraints = ({'type':'eq','fun':lambda x:np.sum(x)-1})
bounds = tuple((0,1) for x in range(len(stocks)))
optimum = optimization.minimize(fun=min_func_sharpe,x0=initial,args=(returns,rf),method='SLSQP',bounds=bounds,constraints=constraints)
return optimum
stocks = ['AAPL','WMT','TSLA','GE','AMZN','DB']
start_date ='01/01/2010'
end_date ='01/01/2020'
rf=0.02
data = stock_data(stocks,start_date,end_date)
log_returns = stock_returns(data)
monte_carlo = monte_carlo_porfolios(stocks,log_returns,1000,rf)
print(optimize_portfolio(monte_carlo[2],log_returns,rf))
you have weights, and the other arguments mixed up in their positional order in the
function call within min_func_sharpe
-portfolio_stats(weights,args[0],args[1])[2]
this does not match the signature in portfolio stats
def portfolio_stats(returns,weights,rf):