I try to understand how the algorithm framework works. For this purpose, I experiment with boot camp code called Liquid Value Stocks. Several questions arose during this process.
- How to set the portfolio construction model to rebalance only once a month? Unfortunately, I did not find any example that would show me how to do this in a algorithm framework environment. In a given lesson, the portfolio rebalances on a daily basis.
- How to properly monitor the number of open positions? I just want to make sure I added the correct code. In this case, the number of open positions seems to be equal to the number of insights.
def OnData(self, data): self.Plot("Positions", "Number of open positions", len(self.Portfolio))
- Why does the algorithm constantly increase the number of insights? I would expect 10 insights for long positions and 10 insights for short positions to be issued at the beginning of each month. So a total of 20 insights (positions). That's not happening. Instead, the number of insights grows each month.
Thank you
.
.
Etienne RAINAUT
Hi Daniel,
I can help with an algo using the framework I tried recently that updates every week (and every 2 weeks something different happens). Hope it answers all 3 questions.
In the main.py file (algo initializing) you can set your portfolio to not rebalance on security and insight changes. With those settings, it will only rebalance when the Update() function of the alpha will be called.
class A0001(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 1, 1) # Set Start Date # self.SetEndDate(2021, 1, 10) # Set End Date self.SetCash(100000) # Set Strategy Cash # Data resolution self.UniverseSettings.Resolution = Resolution.Daily self.Settings.RebalancePortfolioOnInsightChanges = False self.Settings.RebalancePortfolioOnSecurityChanges = False
That being set, the trick is to Update the Alpha at the desired rebalancing frequency by following track of a self.currentMonth variable in the alpha init (see code below).
I set timedelta(days=1) for the insights, so there are only valid for 1 day (after that they expire and your active positions would normally be sold). But in this case, the portfolio will not be rebalanced thanks to self.Settings.RebalancePortfolioOnInsightChanges = False.
Number of open positions will be the number of insights you send each month. Be careful if you send an insight for TSLA in January, you will also have to resend an insight for TSLA in February to keep the position open.
class ClenowMomentumAlphaModel(AlphaModel): def __init__(self, resolution, linRegPeriod, SMAperiod, ATRperiod, referenceSMAperiod, referenceTicker, referenceSMA, riskFactor): self.resolution = resolution self.currentMonth = None def Update(self, algorithm, data): insights = [] if algorithm.Time.month() != self.currentMonth: #when a new month shows up, set the current month to the new month self.currentMonth = algorithm.Time.month() #do stuff once a month here #append insight with timedelta(days=1) insights.append(Insight.Price(stockToBuy[0].Symbol, timedelta(days=1), InsightDirection.Up, None, 1.00, None, stockToBuy[2])) return insights
Etienne RAINAUT
This doc will be useful if you need another frequency.
https://docs.python.org/3/library/datetime.html
Daniel Jurnik
Hi Etienne,
Thank you for your suggestions. I really appreciate your help. Unfortunately, your solution doesn't work for me. It also doesn't answer all my questions.
I tried to modify the code according to your recommendations. You can see the result below.
The algorithm now appears to issue insights for 20 stocks. However, when timedelta(1) is set, the stocks are liquidated the next day and not until the beginning of the next month.
Also, sometimes only 19 insights are released instead of 20. I don't understand why. It's a mystery to me.
Etienne RAINAUT
Hi Daniel, I am sorry I missed 1 important detail for it to work. You need this line in the main file to rebalance every month giving what I said before. Check the backtest attached, I tried a monthly momentum algo recently.
Hope it helps (sorry I am not an expert on the framework and it also took me time to make it work).
self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel(self.DateRules.MonthStart()))
Etienne RAINAUT
I attached the backtest of your code when adding the line, seems to work without liquidation after 1 day now. self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel(self.DateRules.MonthStart()))
Concerning the number of insights. I guess that ActiveSecurities keeps the stocks from the past month and keeps adding every new month. You should dig more exemple to keep track of added and removed securities with SymbolData (see backtest in comments before).
for security in algorithm.ActiveSecurities.Values: direction = 1 if security.Fundamentals.ValuationRatios.EarningYield > 0 else -1 insights.append(Insight.Price(security.Symbol, timedelta(1), direction))
Derek Melchin
Hi Daniel,
To rebalance the portfolio monthly, we should:
(1) Override the rebalancing function of the PCM
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(lambda time: None))
(2) Comment out these lines
#self.Settings.RebalancePortfolioOnInsightChanges = False #self.Settings.RebalancePortfolioOnSecurityChanges = False
(3) Adjust our insight duration to the following
insights.append(Insight.Price(symbol, Expiry.EndOfMonth(data.Time) - timedelta(seconds=1), direction))
To ensure the algorithm emits 20 insights each month, we can keep track of the symbols inside the alpha model.
def OnSecuritiesChanged(self, algorithm, changes): for security in changes.AddedSecurities: self.symbols.append(security.Symbol) for security in changes.RemovedSecurities: self.symbols.remove(security.Symbol)
See the attached backtest for reference.
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.
Daniel Jurnik
Thank you Derek,
This is a very nice and elegant solution. I wouldn't figure it out myself. Unfortunately, I was not able to find anything similar in the documentation. We really need more examples like this!
I tried to implement your solution and it seems to work well. The only problem occurs when I use a longer period.
For example, when I selected the period 2011/1/1 to 2015/12/1, this error occurred:
Runtime Error: ValueError : list.remove(x): x not in list
at OnSecuritiesChanged
self.symbols.remove(security.Symbol)
===
at Python.Runtime.PyObject.Invoke (Python.Runtime.PyTuple args in main.py:line 111
ValueError : list.remove(x): x not in list
Honestly, I don't understand this type of error.
Thank you for any suggestions.
Derek Melchin
Hi Daniel,
We are in the process of updating our documentation, so we appreciate your feedback and patience.
To resolve the error above, we should check if a symbol is in `self.symbols` before removing it.
for security in changes.RemovedSecurities: if security.Symbol in self.symbols: self.symbols.remove(security.Symbol)
See the attached backtest for reference.
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.
KevinW
Hi Derek,
When I run the code the code above, I got the following error message. So what needs to be changed in the code? Thanks.
=====
During the algorithm initialization, the following exception has occurred: __init__() takes from 2 to 3 positional arguments but 4 were given at __init__ super().__init__(True in main.py: line 30 at Initialize self.AddUniverseSelection(LiquidValueUniverseSelectionModel()) at Python.Runtime.PythonException.ThrowLastAsClrException() at Python.Runtime.PyObject.Invoke(PyTuple args in main.py: line 14 __init__() takes from 2 to 3 positional arguments but 4 were given
Nico Xenox
Hey KevinW,
the security initializer was removed from there. here's the post that explains it. To solve this issue just delete the last None on that line.
Best,
Nico
Daniel Jurnik
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!