I conducted a research about using mean-variance portfolio optimization model to get the optimal weights for stocks in the portfolio. Then I developed a long/short strategy based on my fundamental factor analysis research. The strategy is rebalanced each month and I use the mean-variance portfolio optimization result to allocate the assets. In contrast to equally weighted asset allocation, the new model improves the performance of the strategy.
Liquidgenius
Impressive work! It is going to take some time for work through this, but offhand, I like the implementation of Monte Carlo, lots for me to learn from here.
I ran through a few variations on portfolios from Motifinvesting, to see the differences in how this would weight them. Is it missing the weighting routine at the end? I see return and volatility, but not Sharpe or weights in the final output. Maybe I missed something.
# print out the return, volatility, Sharpe ratio and weights of the optimal portfolio
Again, pretty awesome work,
Liquidgenius
Jing Wu
Hi Liquidgenius, thanks for your suggestions. I add the sharpe ratio and the weight. Check this updated notebook
Liquidgenius
Much thanks for the update and sharing your hard work Jing Wu
Liquidgenius
weight GOOG 1.055932e-01 IBM 1.471221e-01 AAPL 4.302119e-01 AAP 1.576335e-15 CCE 0.000000e+00 AMZN 3.170728e-01
Does the result weight CCE at 0 due to the Monte Carlo simulation finding and optimal result where CCE plays no part? I experimented with alternative assets and received similar results, sometimes with multiple assets weighted at 0.
Liquidgenius
Updated lines 52 and 69 to include a minimum bound of .01 which forces a non-zero weight for each asset. Note this may not be the absolute best optimization but should be closest possible while retaining all assets in the portfolio.
bnds = tuple((.01, 1) for x in range(self.n))
Alex Muci
Hi Jing Wu. Thanks for sharing.
Just a quick note. Shoudn't the Coarse- or FineSelectionFunction report the same list in case of no rebalancing (rather than an empty list)? I.e. same issue discussed at the end of this post
Thx
Alex Muci
by 'same' I mean the previous list (so to avoid un-registering tickers and frozing their prices)
Jing Wu
Hi Alex Muci, you're right. return [] in the algorithm should be changed to
return [i.Symbol for i in (self.long+self.short)]
The universe selection takes much time to run. I'll update the backtest when I get the new result.
Jing Wu
Hi Liquidgenius, Mean-variance optimization portfolios often involve taking extreme long and short positions. Sometimes the zero lower bound would lead to zero weight for some stocks in optimal portfolio. Impose portfolio weight constraints when constructing efficient portfolios is a good way. Some papers talked about this topic. Here's one of them for your reference
https://papers.ssrn.com/sol3/papers.cfm?abstract_id=310469
Ryan M
Could you please explain why the short positions are not optimized and why "0.2/" is used for the short positions?
self.SetHoldings(i.Symbol,-0.2/self.num_short)
What impact do this values have?
self.num_portfolios = 6 self.num_long = 8 self.num_short = 6
The backtest only includes about a dozen positions and I'd like to investigate what impact having many more positions has.
Cheng Zhou
Hi Jing,
Thank you for sharing this. I have a question about the long-short strategy, if you are doing long-short portfolio, is that the sum weight should equall to 0 every time you reblance your portfolio?
def opt_portfolio(self):
''' maximize the sharpe ratio to find the optimal weights '''
cons = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bnds = tuple((.01, 1) for x in range(self.n))
opt = minimize(self.min_func,
np.array(self.n * [1. / self.n]),
method='SLSQP',
bounds=bnds,
constraints=cons)
opt_sharpe = - opt['fun']
opt_weights = opt['x']
opt_return = self.annual_port_return(opt_weights)
opt_volatility = self.annual_port_vol(opt_weights)
return opt_weights, opt_return, opt_volatility, opt_sharpe
So in the optimization function, the constraint lambda x: np.sum(x)-1 should that just be np.sum(x) with the bnds tuple(-1,1)?
And one last question, can you explain to me how do you realized the monthly rebalance in this code? Which part exactly realized this? Thank you in advance!
Jing Wu
Hi Cheng Zhou,
In this algorithm, I calculated the weight for long stocks and short stocks separately. Long stocks weight is based on this portfolio optimization model. Short stocks are equally weighted. In addition, the number of long and short stocks are fixed in this algorithm because the filter criteria are different from them. If you put all stocks into this optimization model and let the model decide which one should long or short, then the criteria for choosing the universe should be changed. But I suppose it's a good idea you could try in your model.
The monthly rebalance is implemented by using the flag variable and the scheduled event function. Then the coarse and fine universe selection function will be activated at the first trading day of a month, they other days they will just return an empty list.
DEVON
Python3's range is Python2's xrange?
28 | 20:32:22:
Runtime Error: NameError : name 'xrange' is not defined
at FateSelectionFunction in main.py:line 83
NameError : name 'xrange' is not defined (Open Stacktrace)
Cheng Zhou
Hi Jing, thank you so much for your comment.
self.SetStartDate(2000,1,04) Â #Set Start Date
I got an syntax error in this line, saying invalid token, How can I fix this?
Also for the montly reblancing, if I want to reblance on a daily basis how could I do that?
Jing Wu
Hi Devon, yes you should use "range" in python3.
Jing Wu
Cheng zhou, remove unnecessary zeros self.SetStartDate(2000, 1, 4).
Universe Selection function is set default to be refreshed daily in LEAN.
Jing Wu
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!