Hi Guys,
I wanted to share with the community my implementation of a Custom Optimization Portfolio Construction Model.
The Portfolio Construction Model calculates the desired targets for each asset in our portfolio. This is a custom implementation of the model that will allow you to use different optimization techniques for your portfolio (maximize portfolio return, minimize portfolio volatility, maximize portfolio sharpe ratio, and even a standard equal weighting for comparison).
Once the predictions are sent to the Portfolio Construction Model, it will get the daily log-returns of the last 252 trading days and calculate the weights for each individual security that optimize the provided objective function. The model will also plot the optimal allocation for each asset so we can inspect what it's doing.
The below algorithm is a simple example to show how it works with a buy and hold strategy, but this module can be plugged into any other strategy requiring portfolio target calculations.
Ideas to try (user-defined inputs in the main.py script):
- Change the objectiveFunction parameter to test other objective functions to optimize. Options are: 'return' (maximize portfolio return), 'std' (minimize portfolio standard deviation), 'sharpe' (maximize portfolio sharpe ratio), and also 'equal' (for a standard equal weighting).
- The rebalancingParam is currently set to 365 days, but it can be set to a discretionary number of days to rebalance the portfolio and go back to optimal weights. For instance, if you want to rebalance every 30 days simply do rebalancingParam = 30
Emilio
Petter Hansson
This is really cool, thanks for sharing!
It also highlights the power of the algorithm framework, since it effectively separates concerns and makes code like this highly reusable.
Emilio Freire
Thanks Petter, I'm glad you liked it!
I totally agree with you and that was exactly the purpose of the post. t's challenging to make 100% reusable modules, but I think with time we will get there and sharing with the community will become super powerful.
Emilio
InnoQuantivity.com
LukeI
Thanks for this excellent peice of code, I'm very interested in adopting it.
Just a few qustions though I'm having trouble trying to incorporate this into my framework algorithm:
1. Since the framework is modular there is the possibility that there is more than 1 alpha (as there is in my case), possibly working on the same security symbols simultaniously. How do you recommend that we combine multiple signals into one optimization?
2. There are a lot of allocation based alphas that asign a % allocation to a security and not a simple "up, down, flat" signal. Do you have any ideas on how to incorporate these into the optimization?
As it's programed currently, it seems to be acting as an alpha in disguise and it will replace any other alpha your algorithm is already generating outside of the "up, down, flat" limitations rather than improving the alphas you already have.
Emilio Freire
Hi Lukel,
I'm glad you found the algo useful!
Regarding your questions:
The whole idea is to treat each Alpha model as an "asset" that generates a series of returns with a certain distribution that can be modelled accordingly. Bear in mind I do this in the context of intraday strategies so for me what matters is which Alpha to "trust" for today, rather than actually constructing an optimal portfolio. But just sharing my thoughts here.
- Regarding your point 2, could you please give an example so I can understand and give a better answer?
Thanks! Emilio InnoQuantivity.comSeersquant
This is really cool! Thanks for sharing!
Liam Morrow
Hi Emilio,
After cloning the algorithm, I'm getting a runtime error when backtesting with your settings. Is this caused by some update? Any help is appreciated. The logic looks great.
Runtime Error: UnboundLocalError : local variable 'errorSymbols' referenced before assignment<br> at CreateTargets in CustomOptimizationPortfolioConstruction.py:line 153 <br> UnboundLocalError : local variable 'errorSymbols' referenced before assignment
Thanks,
Liam
Arthur Asenheimer
Hi Liam,
just move the line
errorSymbols = {}
to the beginning of CreateTargets() and the algorithm will finish successfully (see attached backtest).
Chibuike Azubuike
i am having zero division errror on line 315
Derek Melchin
Hi Chibuike,
I was unable to reproduce this. Please attach a backtest which causes this error.
Best,
Derek Melchin
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.
Miguel Palanca
Hi Emilio and Derek,
I seem to get the same issue as Chibuike here when backtesting from 2004. Specifically with the variable x0 in the CustomOptimizationPortfolioConstruction.py file.
I think it may be caused by if the universe has no stocks or recommended weights being zero? With a dynamic universe where stocks are added and removed, do you think that a daily rebalancing would help to avoid this error? Or should I add a: if len(invested) > 2
where invested = [x.Key for x in self.Portfolio if x.Value.Invested]
Tried to attach a backtest but I dont think the site allows me to attach a backtest with a runtime error.
Thanks,
Miguel
Miguel Palanca
Hi Chibuke,
Not sure if you may have already found a fix for this, but I have found what is potentially a band-aid solution. Working off the hypothesis above, where it would seem the optimizer doesnt like it when there are no securities in the universe.
I went in to find the error which seems to stem from line 315 in the CustomOptimizationPortfolioConstruction file. I included line 314 for reference. Note these are located in the class CustomPortfolioOptimizer
size = historicalLogReturns.columns.size # K x 1 #if len(size.columns) > 0: if size > 0: x0 = np.array(size * [1. / size]) else: return
Please let me know if this fixes it for you!
Thanks,
Miguel
Derek Melchin
Hi Miguel,
We were unable to reproduce the error with either of the backtests attached in this thread. Since we can't attach backtests that throw a runtime error, please just paste the full code in this thread for further assistance with debugging the issue.
Best,
Derek Melchin
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.
Emilio Freire
Hi Derek, Miguel,
I faced the same issue a while back when running this algo and others using scipy.optimize and I believe it's a bug related to an older version of the library which QuantConnect has not upgraded yet.
I found at the time the LEAN open issue regarding this but can't seem to find it now on GH. I found the general thread about the bug though:
https://github.com/scipy/scipy/issues/11403Derek Melchin
Hi Emilio,
Thank you. Here's our related GitHub Issue.
Best,
Derek Melchin
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.
.ekz.
Emilio Freire , Derek Melchin: I'm attempting to implement this on a crypto universe, with trend following signals. Any caveats / nuances I should be aware of? (it's my first time using the alpha framework).
Also, Emilio Freire: I've been learning a bit about Post Modern Portfolio Theory (PMPT), and the premise does seem to have merit. I'd like to try adapting this to include an objective function for Sortino ratio.
Looking at the code, it seems it would involve just adding a condition for the sortino calculation, calculating it similarly to the sharpe, but with standard dev of the downside risk only (as opposed to Std of the entire portfolio)
So i would create a ‘donwside risk only’ version of this below code.
That said, my python skills are a bit lacking… what would the code look like for this?
Thanks in advance!
Emilio Freire
Hi .ekz. !
Great to hear you’re exploring this for Crypto.
Please refer to this post to find the implementation of Sortino Ratio!
.ekz.
Heres a good video that runs through the math (in excel) to illustrate Post Modern Portfolio theory. I got the gist of it, but he lose me at some parts (I'm more of a coder than a mathematician or data scientist).
Emilio Freire: it looks like Volatility Skewness might be another objective function to consider as well. IE: upside variance / downside variance.
Volatility skewness, which measures the ratio of a distribution’s percentage of total variance from returns above the mean to the returns below the mean, was the second portfolio-analysis statistic to be added to the PMPT rubric."
.ekz.
Brilliant Emilio Freire, thanks for the quick reply, and for the link to the Sortino implementation.
Some time ago I had actually bookmarked that thread / post, but forgot about it.
Thanks again!
Emilio Freire
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!