Hello, as Pro Quant Anthony FJ Garner suggested me, I came up with the code for my strategy looking on some other codes in the forum. I have paste it down.
This strategy is really simple:
1. Filter top 100 stocks with lowest PE ratio
2. Buy top 10 stocks with lowest Price to Sales ratio over the stocks of Step 1.
3. Repeat process each month.
When backtesting some errors have appeared on console and as much as I try to find a solution I'm stuck:
Error 1:
Backtest Handled Error: Order Error: id: 3998, Insufficient buying power to complete order (Value:17125.8339), Reason: Id: 3998, Initial Margin: 8591.791968375, Free Margin: 7076.9178954346771965.
Error 2:
Backtest Handled Error: Unable to compute order quantity of AE R735QTJ8XC9X. Reason: The portfolio does not have enough margin available. Returning null.
I don't know why those margin calls, if I hold for a month each and every month the would be updated to some new stocks, are they not being sold or something?
Here is the code:
class MultidimensionalModulatedInterceptor(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 11, 1) # Set Start Date
self.SetEndDate(2020, 1, 1) #Set End Date
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily # Set Resolution to Daily
self.AddUniverse(self.CoarseSelection, self.FineSelection)
self.month = -1
self.symbols= []
def CoarseSelection(self, coarse):
if self.Time.month == self.month:
return self.symbols
else:
self.month = self.Time.month
# Filter for DollarVolume, Price and Fundamental Data availability
filtered = [x for x in coarse if x.Price > 2 and x.HasFundamentalData]
self.symbols=[x.Symbol for x in filtered]
return [x.Symbol for x in filtered]
def FineSelection(self, fine):
if self.Time.month == self.month:
return self.symbols
else:
self.month = self.Time.month
# Filter for market cap and profitable company
filtered = [f for f in fine if f.CompanyProfile.MarketCap > 300000000 and f.ValuationRatios.PERatio > 0]
sortedByPE = sorted(filtered, key = lambda x : x.ValuationRatios.PERatio, reverse = False)
sortedByPS = sorted(sortedByPE[:100], key = lambda x : x.ValuationRatios.PSRatio, reverse = False)
# retrieve 10 lowest positive PS
self.symbols= [f.Symbol for f in sortedByPS][:10]
return [f.Symbol for f in sortedByPS][:10]
def OnSecuritiesChanged(self, changes):
for security in changes.RemovedSecurities:
self.Liquidate(security.Symbol)
for security in changes.AddedSecurities:
self.SetHoldings(security.Symbol, 0.10)
I hope someone could help me here.
Rahul Chowdhury
Hey Gonzalo,
Welcome to QuantConnect!
This is a pretty great algorithm. Your unsufficient margin issue is being created by your universe selection. When we want to keep our universe the same, that is wait until the new month to rebalance, we should return Universe.Unchanged. You can learn more about universe selection in our bootcamps. You learn specifically about Universe.Unchanged in the Liquid Value Stocks bootcamp.
I made some changes to your code to fix the issues with the universe selection.
Gonzalo Fernández
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!