Hi everyone,
I am aiming for a 60/30/10 portfolio allocation to momentum stocks, bond etfs, and market neutral etf respectively with annual rebalancement (using rebalancement flags for triggers). I also conduct universe selection monthly and update my momentum stocks on a monthly basis.
When i first run my algo, i expect to be holding 60/30/10 60/30/10 portfolio allocation to momentum stocks, bond etfs (IEI, TLT) and market neutral ETF (BTAL). However, when i look through the orders for the backtest, my algo did not execute long positions in the bond etfs nor the market neutral etf at the start but it did execute the positions in the momentum stocks.
Can someone please help me out on this issue? Much appreciated!!
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from QuantConnect.Data.UniverseSelection import *
from scipy.stats import linregress
class Momentum(QCAlgorithm):
def __init__(self):
self.reb1 = 1 # set the flag for rebalance
self.reb2 = 12 # set the flag for rebalance
self.num_coarse = 500 # Number of stocks to pass CoarseSelection process
self.num_fine = 20 # Number of stocks to long
self.symbols = None
def Initialize(self):
self.SetStartDate(2012, 1, 1) # Set Start Date
self.SetEndDate(2013,6, 1) # Set End Date
self.SetCash(150000) # Set Strategy Cash
self.btal = self.AddEquity("BTAL", Resolution.Minute).Symbol # BTAL hedge
self.iei = self.AddEquity("IEI", Resolution.Minute).Symbol # bond hedge
self.tlt = self.AddEquity("TLT", Resolution.Minute).Symbol # bond hedge
self.list = [self.btal, self.iei, self.tlt]
self.reb1 = 1 # set the flag for momentum stock rebalancement
self.reb2 = 1 # set the flag for rebalance
self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)
self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
self.Schedule.On(self.DateRules.MonthStart(self.spy),
self.TimeRules.AfterMarketOpen(self.spy,5), Action(self.rebalance))
self.SetSecurityInitializer(self.CustomSecurityInitializer)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash)
def CustomSecurityInitializer(self, security):
security.SetDataNormalizationMode(DataNormalizationMode.SplitAdjusted)
def CoarseSelectionFunction(self, coarse):
# if the rebalance flag is not 1, return null list to save time.
if self.reb1 != 1:
return self.long
# make universe selection once a month
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
filtered = [x.Symbol for x in sortedByDollarVolume if x.HasFundamentalData]
# filtered down to the 500 most liquid stocks
return filtered[:self.num_coarse]
def FineSelectionFunction(self, fine):
# return null list if it's not time to rebalance
if self.reb1 != 1:
return self.long
# drop counter (will update back to 1 after rebalancement has occurred)
self.reb1 = 0
#will not include this portion of code - essentially filters for top momentum stocks
self.long = sorted_symbolLong[:self.num_fine]
return self.long
def OnData(self, data):
pass
def rebalance(self):
long_list = self.long
# to update the momentum stocks only monthly
for i in self.Portfolio.Values:
if i.Invested and i.Symbol not in long_list and i.Symbol not in self.list:
self.Liquidate(i.Symbol)
# annual portfolio rebalancement
if self.reb2 % 12 == 0:
self.SetHoldings(self.iei, 0.15)
self.SetHoldings(self.tlt, 0.15)
self.SetHoldings(self.btal, 0.10)
for i in long_list:
self.SetHoldings(i, 0.6/self.num_fine)
else:
# monthly rebalancement of momentum stocks only, leaving bonds and market neutral etfs untouched
for i in long_list:
if not self.Securities[i].Invested:
self.SetHoldings(i, 0.6/self.num_fine)
self.reb1 = 1
self.reb2 += 1
Shile Wen
Hi John,
I was not able to reproduce the error. Furthermore, I made a few changes, including returning Universe.Unchanged in the Course/Fine filters when we don't want to change our universe securities. Please see the attached backtest for reference (also note I reduced the coarse size to 20 to reduce backtest time).
Best,
Shile Wen
John Fogel
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!