Hi, in order to allocate to every symbol in a liquid universe, what I used to do was:
for security in self.changes.AddedSecurities:
if not security.Invested:
self.SetHoldings(security.Symbol, 0.10)
But if my algorithm was making use of and switching between 2 or more universes(e.g. a liquid one and a manual one), I can no longer use AddedSecurities because that only contains the symbols most recently added, and will not include other symbols that have been added a long time ago but are still contained in the liquid universe. I need to be able to do this because if the algorithm liquidates positions that are still within the liquid universe due to switching to the manual universe, it would not be able to re-allocate back into symbols still inside the liquid universe because AddedSecurities will no longer contain them.
I tried:
for security in self.ActiveSecurities:
if not security.Invested:
self.SetHoldings(security.Symbol, 0.10)
But that didn't seem to work
Shile Wen
Hi Vncne,
self.ActiveSecurities is a list of Symbol : Security Key-Value pairs, so to iterate through the securities, we need to iterate through the Values of ActiveSecurities.So instead of iterating using
for security in self.ActiveSecurities
we should iterate using
for security in self.ActiveSecurities.Values
I’ve shown an example in the attached backtest.
Best,
Shile Wen
Vncne
Hi Shile Wen , I did what you suggested and implemented it like so:
for security in self.ActiveSecurities.Values: if security.Symbol not in self.symbols: self.SetHoldings(security.Symbol, 0.20)
It worked and was exactly what I needed, but there seems to be a new issue; in my algorithm, I set it so that only 5 securities can be contained in the liquid universe at any given time, but when I used the code above, it seems to still be allocating to securities that had been removed from the universe resulting in the security being bought and liquidated everyday due to:
for security in self.changes.RemovedSecurities: if security.Invested: self.Liquidate(security.Symbol) for security in self.ActiveSecurities.Values: if security.Symbol not in self.symbols: self.SetHoldings(security.Symbol, 0.20)
You can see in the backtest I attached that ROKU was a security that had been removed from the Universe and so was liquidated, but the algorithm kept allocating to it again the same or next day, and liquidates it again the following day, it keeps doing this in a loop for the entirety of the backtest. What's causing this?
I tried doing this to make the algo do nothing when everything in the universe is already allocated to:
if self.Portfolio.TotalHoldingsValue < 5: for security in self.ActiveSecurities.Values: if security.Symbol not in self.symbols: self.SetHoldings(security.Symbol, 0.20)
But I don't think that solves the issue at its core, which is why is the algo still allocating to securities that have been removed from the universe? Are removed securities contained within ActiveSecurities for some reason?
Gahl Goziker
Hi Vncne,
When Liquidate removes a security from the universe, behind the scenes that security is added to a “pending removal list”. After that security gets liquidated, it remains an active security until it leaves the pending removal list, which doesn’t happen until the next data iteration.
If SetHoldings is called on every security in self.ActiveSecurities within the same data iteration as Liquidate was called, the Liquidate call will never successfully remove securities from the universe.
To amend this, instead of calling SetHoldings on every security in self.ActiveSecurities, we can keep our own list of securities in the universe. For example, we could implement two lists symbol and static to track universe symbols and user-selected symbols respectively.
In Initialize:
self.symbols = None self.static = [Symbol.Create(x, SecurityType.Equity, Market.USA) for x in ["SPY", "QQQ"]]
In OnSecuritiesChanged:
def OnSecuritiesChanged(self, changes): for security in changes.RemovedSecurities: self.Liquidate(security.Symbol, 'Removed from Universe') self.symbols.pop(security.Symbol) for security in changes.AddedSecurities: if symbol not in self.static: self.symbols.append(security.Symbol)
Then, in OnData, we can selectively call SetHoldings on securities from one list or the other.
I hope that it helps understand the problem, and provides a way of thinking about it.
Best,
Gahl Goziker
Vncne
Makes sense! Thanks Gahl Goziker!
Vncne
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!