Overall Statistics Total Trades 2542 Average Win 0.32% Average Loss -0.21% Compounding Annual Return 6.348% Drawdown 32.100% Expectancy 0.189 Net Profit 59.532% Sharpe Ratio 0.351 Loss Rate 53% Win Rate 47% Profit-Loss Ratio 1.52 Alpha -0.393 Beta 28.236 Annual Standard Deviation 0.205 Annual Variance 0.042 Information Ratio 0.271 Tracking Error 0.205 Treynor Ratio 0.003 Total Fees \$2630.20
```# https://quantpedia.com/Screener/Details/54
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data import SubscriptionDataSource
from QuantConnect.Python import PythonData
from datetime import date, timedelta, datetime
from decimal import Decimal
import numpy as np

class MomentumandStateofMarketFiltersAlgorithm(QCAlgorithm):

def Initialize(self):
self.SetStartDate(2011, 1, 1)
self.SetEndDate(2018, 8, 1)
self.SetCash(100000)
# add Wilshire 5000 Total Market Index data from Dropbox
self.W5000Return = self.ROC("W5000", 252)
# initialize the RateOfChange indicator of Wilshire 5000 total market index
history = self.History(["W5000"], 500, Resolution.Daily)
for tuple in history.loc["W5000"].itertuples():
self.W5000Return.Update(tuple.Index, tuple.value)

self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.At(0, 0), self.rebalance)
# mark it's the start of each month
self.month_start = False
# mark the coarse universe selection has finished
self.selection = False
self.mom = {}
self.lookback = 20*6
self.long = None
self.short = None

def CoarseSelectionFunction(self, coarse):
coarse = [x for x in coarse if (x.HasFundamentalData and x.AdjustedPrice > 1)]
for i in coarse:
if i.Symbol not in self.mom:
self.mom[i.Symbol] = SymbolData(i.Symbol, self.lookback)

if self.month_start:
self.selection = True
# sort stocks by 6-month momentum
self.long = sortByMOM[:20]
self.short = sortByMOM[-20:]
return self.long+self.short
else:
return []
else:
return []

def rebalance(self):
# rebalance every month
self.month_start = True

def OnData(self, data):
if self.month_start and self.selection:
self.month_start = False
self.selection = False
if self.long is None or self.short is None: return
# if the previous 12 months return on the broad equity market was positive
if self.W5000Return.Current.Value > 0:
stocks_invested = [x.Key for x in self.Portfolio if x.Value.Invested]
for i in stocks_invested:
if i not in self.long+self.short:
self.Liquidate(i)

short_weight = 0.5/len(self.short)
# goes short on the prior six-month losers (lowest decile)
for short_symbol in self.short:
self.SetHoldings(short_symbol, -short_weight)
# goes long on the prior six-month winners (highest decile)
long_weight = 0.5/len(self.long)
for long_symbol in self.long:
self.SetHoldings(long_symbol, long_weight)
else:
self.Liquidate()
self.SetHoldings(self.tlt, 1)

class Wilshire5000(PythonData):
"Class to import Wilshire 5000 Total Market Index data from Dropbox"

def GetSource(self, config, date, isLiveMode):
return SubscriptionDataSource("https://www.dropbox.com/s/z9rof4fr9cqzgpt/W5000.csv?dl=1", SubscriptionTransportMedium.RemoteFile)

def Reader(self, config, line, date, isLiveMode):
if not (line.strip() and line[1].isdigit()): return None
index = Wilshire5000()
index.Symbol = config.Symbol
try:
# Example File Format: (Data starts from 01/04/2010)
# Date      Open           High           Low            Close          Adj Close      Volume
# 1/4/10    11549.13965    11749.37012    11549.13965    11743.54004    11743.54004    0
data = line.split(',')
index.Time = datetime.strptime(data[0], "%Y-%m-%d")
index.Value = Decimal(data[5])
except:
return None

return index

class SymbolData:
'''Contains data specific to a symbol required by this model'''

def __init__(self, symbol, lookback):
self.symbol = symbol
self.MOM = Momentum(lookback)                        ```