Hello all, someone on my YouTube channel requested I make a video like this.
What the code does is every month it rebalances the stocks it owns based on the Federal Funds Rate. The way I do this is, that when we have 0% rates, we buy 50 equities, taking on more risk in the low-rate environment. Then when rates go up we only buy 10.
The code has some logical flaws like I simply use self.liquidate before buying the equities for the month. Well if AAPL was already in my portfolio, and it is still in the good equities I sell it and rebuy it. I also added SPY to the account to make sure we rebalance on the first of a new month. It does include SPY in the selected equities and will purchase it. I figured why not have some Beta? Something to know if you would rather it not.
Check out the back-test if you notice a large drawdown, in my YouTube video I went over ways to increase profitability. Enjoy!
My YouTube channel:
from AlgorithmImports import *
from datetime import datetime, timedelta
class FocusedYellowLemur(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.add_equity("SPY")
# Set the risk-free interest rate model
self.set_risk_free_interest_rate_model(InterestRateProvider())
# Now that the model is set, get the interest rate
self.interest_rate = self.risk_free_interest_rate_model.get_interest_rate(self.time)
self.universe_settings.asynchronous = True
self.add_universe_selection(FundamentalUniverseSelectionModel(self.fundamental_filter_function))
self.schedule.on(self.date_rules.month_start("SPY"),
self.time_rules.after_market_open("SPY"),
self.rebalancing_code)
#self.add_risk_management(MaximumDrawdownPercentPerSecurity(0.05))
#self.add_risk_management(MaximumUnrealizedProfitPercentPerSecurity(0.15))
def fundamental_filter_function(self, coarse: List[CoarseFundamental]) -> List[Symbol]:
if self.interest_rate < 0.0025:
amount = 50
else:
amount = 10
selected = [c for c in coarse if c.has_fundamental_data]
sorted_by_dollar_volume = sorted(selected, key=lambda c: c.dollar_volume, reverse=True)
filtered = [f for f in sorted_by_dollar_volume if f.has_fundamental_data and f.price > 10 and not np.isnan(f.valuation_ratios.pe_ratio)]
sorted_by_pe_ratio = sorted(filtered, key=lambda f: f.valuation_ratios.pe_ratio)
fundamental_symbols = [f.symbol for f in sorted_by_pe_ratio[:amount]]
return fundamental_symbols
def rebalancing_code(self):
self.interest_rate = self.risk_free_interest_rate_model.get_interest_rate(self.time)
self.liquidate()
for security in self.ActiveSecurities.Values:
self.SetHoldings(security.Symbol, 1 / len(self.ActiveSecurities))
self.Plot("interest rate", "value", self.interest_rate)
Mia Alissi
Hello Joseph,
Your algorithm is interesting as it adjusts the number of equities it holds based on the Federal Funds Rate. It's a good start, but as you mentioned, there are some areas that could be improved.
One of the issues you mentioned is that you're using
self.liquidate()
before buying the equities for the month. This means that if a stock like AAPL was already in your portfolio and it's still a good equity, you're selling it and rebuying it. This could lead to unnecessary transaction costs.Instead of liquidating all positions, you could adjust your holdings based on the new weights. You can do this by calculating the desired portfolio weights first, then adjusting the holdings for each security accordingly. If a security is already in the portfolio and its weight hasn't changed significantly, you won't need to trade it.
As for including SPY in your portfolio, it's a common practice to include a market index like SPY for beta exposure. However, if you don't want it to be included in the selected equities, you could add a condition in your universe selection function to exclude it.
Here's an example of how you could adjust your holdings:
This code will adjust the holdings for each symbol in the universe to the target weight. If a symbol is already in the portfolio and its current weight is close to the target weight,
SetHoldings
won't place any trades for that symbol.I hope this helps! Let me know if you have any other questions.
Sources:
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.
Joseph Matteo Scorsone
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!