Hi Alexandre,
Thank you for your detailed explanation which makes me better understand LEAN.
0.1. The empty return of universe is used in the original algorithm of your tutorial strategy (attached in my first comment) which does not use Algorithm Framework. I thought AF uses the same logic which seems not to be the case now. Thank you for this important advice. Maybe QuantConnect can indicate in the doc several points to pay attention to when converting algorithm to AF?
0.2. Yes, self._changes.RemovedSecurities contains the right securities when a security is removed for the first time. But then since the same security cannot appear in AddedSecurities again, it won't show in RemovedSecurites, either.
0.3. "only set holdings for added securities seems wrong"
-- This is the logic of the original algorithm which produces better performance and my purpose here is to use AF to replicate it. So this logic is also be replicated using AF. Actually the original algorithm does not rebalance the untouched securities. It liquidates removed ones and uses available funds to set holdings for added ones. If the percentage in SetHoldings refers to that of available fund instead of portfolio value, then this logic should be correct. If not, then there should be insufficient fund error but the original algorithm works fine.
0.4. "we should rebalance all holdings and not only use funds from removed securities"
-- Yes but that will be a new algorithm, here I simply want to replicate the original algorithm using AF. I suppose that any algorithm can be developped using AF. If this is not true, then AF will limit production possibilities.
1. Thank you for this important information.
2. Yes, this is one reason. After reviewing the order history of the new version backtest, I found another reason that the PCM keeps rebalancing portfolio despite that Shile already set the rebalance to None. For instance, the new version liquidates holding securites around 17 or 18 of each month which should happens only in the beginning of each month. I cannot find more documentation about AF PCM. Only by reading the source codes of EqualWeightingPortfolioConstructionModel and using dir() in debug mode to guess and test, I still cannot find out why. Maybe QC can add more doc for methods in AF classes. For example, the doc only introduces CreateTargets() for PCM, but the EqualWeightingPortfolioConstructionModel contains a DetermineTargetPercent() method which is not documented. For the ExecutionModel, doc only introduces the Execute() method, but I see that in ImmediateExecutionModel there is an internal member self.targetsCollection and an external one OrderSizing which are not mentioned in doc at all. This may reduce productivity when using AF if user want to develep their own AF models because user won't use those hidden functions correctly by only guessing and testing without doc.
I copied source codes of EqualWeightingPortfolioConstructionModel and ImmediateExecutionModel into the algorithm and set the ExecutionModel to only deal with securites in the Added- or RemovedSecurites. This sovles the 17/18 liquidating problem. But instead of completely liquidating removed securites in the begining of month, it only partially liquidates. So if the same security is to be bought in the next month in the original algorithm, it won't appear in AddedSecurities of the modified new version. Therefore I still cannot achieve the same performance.
3. Previously I used flags to control liquidating because universe could return [] as that in the original algorithm. After taking your advice, I set universe to return Universe.Unchanged and the flags are removed. I applied your logic to liquidate removed securites on top of OnData(), OnSecuritiesChanged() of QCAlogorithm and ExecutionModel, respectively. But none of the 3 attempts succeeded, the old problem remains that once a security is universe unselected and liquidated, it won't be removed from ActiveSecurites and therefore won't appear in AddedSecurites and be rebought again. Please see the attached backtest. I think my poorly constructed algorithm mostly replicates the logic of the original algorithm only with this problem to be solved.
Will you please provide more advice?
Best,
Zhe