Problem Description
Solution
To automatically rebalance your portfolio on the first trading day of every month in QuantConnect, you should use the self.schedule.on() method within your initialize function.
You will specifically combine self.date_rules.month_start() with a time rule (usually after_market_open).
Key Implementation Details
self.date_rules.month_start(symbol): This rule triggers on the first trading day of the month for the specified symbol. It automatically skips weekends and holidays.self.set_holdings(symbol, percentage): This method automatically calculates the number of shares to buy or sell to reach the desired portfolio weight, making it ideal for rebalancing.
Complete Strategy Example
Here is a complete, runnable algorithm that rebalances a portfolio to 60% SPY (Stocks) and 40% TLT (Bonds) on the first trading day of every month.
# region imports
from AlgorithmImports import *
# endregion
class MonthlyRebalanceAlgorithm(QCAlgorithm):
def initialize(self):
# 1. Set Setup parameters
self.set_start_date(2020, 1, 1)
self.set_end_date(2023, 1, 1)
self.set_cash(100000)
# 2. Add assets
self.spy = self.add_equity("SPY", Resolution.MINUTE).symbol
self.tlt = self.add_equity("TLT", Resolution.MINUTE).symbol
# 3. Schedule the Rebalance
# We use the 'spy' symbol to determine market open days.
# We trigger 30 minutes after open to avoid initial volatility.
self.schedule.on(
self.date_rules.month_start(self.spy),
self.time_rules.after_market_open(self.spy, 30),
self.rebalance_portfolio
)
def on_data(self, data: Slice):
# We do not need to place trades here for this specific strategy
pass
def rebalance_portfolio(self):
"""
This function runs once a month on the first trading day.
"""
self.log(f"Rebalancing portfolio at {self.time}")
# 4. Set Holdings
# set_holdings automatically calculates the quantity needed to
# reach the target % and places market orders.
# If we already hold the asset, it buys/sells the difference.
# Target: 60% SPY, 40% TLT
self.set_holdings(self.spy, 0.60)
self.set_holdings(self.tlt, 0.40)
Common Questions & Answers
Q: Why use month_start(symbol) instead of just checking if day == 1?
A: month_start(symbol) is safer because the 1st of the month might fall on a Saturday, Sunday, or a market holiday. The QuantConnect DateRule automatically finds the first valid trading day for that specific asset's exchange.
Q: Does set_holdings liquidate other positions?
A: No. set_holdings only adjusts the specific symbol you pass to it. If you want to ensure all other positions are closed (e.g., if you dynamically pick stocks), you should call self.liquidate() before your set_holdings calls, or use self.set_holdings(symbol, 0) for assets you want to remove.
Q: Can I rebalance at the market close instead?
A: Yes. You can change the time rule in the schedule to:
self.time_rules.before_market_close(self.spy, 10) # 10 minutes before close