Hi Guys, 

I am new to QC. I am trying to recreate the following trading strategy: 

1. On the last business day of every month, invest in the top 5 assets with the highest momentum score. 

2. Sell any asset that was previously in the top 5 but has since dropped out. 

3. Weight each asset by the inverse of its 63-day historical volatility.

When I do the back test is see no positions being entered. I experimented with the weights and excluded the Inverse volatility weights to enter a hard coded 1/5 as a position size, but still no trades are happening. What am I missing here? 

Many thanks and regards,


# https://quantpedia.com/Screener/Details/15
import pandas as pd
import numpy as np
from statistics import mean
from datetime import datetime
from collections import defaultdict

class CountryEquityIndexesMomentumAlgorithm(QCAlgorithm):

def Initialize(self):

self.SetStartDate(2006, 1, 1)
# create a dictionary to store momentum indicators for all symbols
self.CombinedMomentum = {}
self.inv_vola = {}
self.weights = {}

self.symbols = ["SPY","IWM", "QQQ", "EFA", "EEM","VNQ", "LQD", "GLD", "SHY", "IEF", "TLT", "AGG"]

# warm up the MOM indicator

for symbol in self.symbols:
self.AddEquity(symbol, Resolution.Daily)
self.CombinedMomentum[symbol] = CombinedMomentum(self, symbol)

#schedule the function to fire at the month start

def getMonthLastTradingDay(self):
month_last_day = DateTime(self.Time.year, self.Time.month, DateTime.DaysInMonth(self.Time.year, self.Time.month))
tradingDays = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, DateTime(self.Time.year, self.Time.month, 1), month_last_day)
tradingDays = [day.Date.date() for day in tradingDays]
return tradingDays[-1]

#self.Schedule.On(self.DateRules.MonthEnd("SPY"), self.TimeRules.AfterMarketOpen("SPY", 60), self.Rebalance)

def OnData(self, data):
if self.IsWarmingUp: return

def Rebalance(self):
#Determine the sec. to invest in at the last trading day of the month
if (self.Time.date() == self.getMonthLastTradingDay()) and (self.Time.hour == 15):
top = pd.Series(self.CombinedMomentum).sort_values(ascending = False)[:5]
#Determine the weights of the portfolio
# for symbol in top.index:
# self.DailyReturn[symbol] = self.LOGR(symbol, 1, Resolution.Daily)
# self.inv_vola[symbol] = 1/(self.STD(self.DailyReturn[symbol], 63, Resolution.Daily))
# self.Weights[symbol] = self.inv_vola[symbol].Current.Value/ self.SUM(self.inv_vola.Current.Values)

for kvp in self.Portfolio:
security_hold = kvp.Value
# liquidate the security which is no longer in the top momentum list
if security_hold.Invested and (security_hold.Symbol.Value not in top.index):
#Buy the new sucurities
added_symbols = []
for symbol in top.index:
if not self.Portfolio[symbol].Invested:
for added in added_symbols:
self.SetHoldings(added, 1/5)

class CombinedMomentum():
def __init__(self, algo, symbol):

self.MOMP_1M = algo.MOMP(symbol, 21, Resolution.Daily)
self.MOMP_3M = algo.MOMP(symbol, 63, Resolution.Daily)
self.MOMP_6M = algo.MOMP(symbol, 126, Resolution.Daily)
self.MOMP_12M = algo.MOMP(symbol, 252, Resolution.Daily)

def getValue(self):
value = (self.MOMP_1M.Current.Value + self.MOMP_3M.Current.Value + self.MOMP_6M.Current.Value + self.MOMP_12M.Current.Value)/4

return value

# class InverseVolatility():

# def __init__(self,algo,symbol):
# self.DailyReturn = algo.LOGR(symbol, 1, Resolution.Daily)

# def getValue(self):
# value = 1/(self.STD(self.DailyReturn, 63, Resolution.Daily).Current.Value)
# return value