Overall Statistics Total Trades 391 Average Win 1.05% Average Loss -1.19% Compounding Annual Return 12.920% Drawdown 20.100% Expectancy 0.312 Net Profit 71.079% Sharpe Ratio 0.725 Loss Rate 30% Win Rate 70% Profit-Loss Ratio 0.88 Alpha 0.376 Beta -13.214 Annual Standard Deviation 0.178 Annual Variance 0.032 Information Ratio 0.621 Tracking Error 0.178 Treynor Ratio -0.01 Total Fees \$802.96
```# https://quantpedia.com/Screener/Details/14
from QuantConnect.Data.UniverseSelection import *
import math
import numpy as np
import pandas as pd
import scipy as sp

class MomentumEffectAlgorithm(QCAlgorithm):

def Initialize(self):

self.SetStartDate(2014, 1, 1)  # Set Start Date
self.SetEndDate(2018, 6, 1)    # Set Start Date
self.SetCash(100000)           # Set Strategy Cash
self.lookback = 21*12

self.UniverseSettings.Resolution = Resolution.Daily
self.num_coarse = 100
self.num_fine = 50
# rebalance the portfolio every month
self.Schedule.On(self.DateRules.MonthStart("SPY"),self.TimeRules.AfterMarketOpen("SPY"), self.rebalance)
self.monthly_rebalance = True
def CoarseSelectionFunction(self, coarse):
if self.monthly_rebalance:
# drop stocks which have no fundamental data or have too low prices
selected = [x for x in coarse if (x.HasFundamentalData) and (float(x.Price) > 5)]
# rank the stocks by dollar volume
filtered = sorted(selected, key=lambda x: x.DollarVolume, reverse=True)
self.filtered_coarse = [ x.Symbol for x in filtered[:self.num_coarse]]
return self.filtered_coarse
else:
return self.filtered_coarse

def FineSelectionFunction(self, fine):
if self.monthly_rebalance:
filtered_fine = [x for x in fine if x.EarningReports.BasicEPS.TwelveMonths > 0
and x.ValuationRatios.PERatio > 0
and x.EarningReports.BasicAverageShares.ThreeMonths > 0]
# filter stocks with the top market cap
top = sorted(filtered_fine, key = lambda x: x.EarningReports.BasicAverageShares.ThreeMonths * (x.EarningReports.BasicEPS.TwelveMonths*x.ValuationRatios.PERatio), reverse=True)[:self.num_fine]
self.filtered_fine = [x.Symbol for x in top]
self.monthly_rebalance = False
return self.filtered_fine
else:
return self.filtered_fine

def rebalance(self):
self.monthly_rebalance = True

def OnData(self, data):
# update the indicator value for securities already in the portfolio
symbolData.MOM.Update(IndicatorDataPoint(symbol, self.Time, self.Securities[symbol].Close))
# liquidate removed securities
if symbol in self.removedSymbols:
self.Liquidate(symbol)

self.removedSymbols = []

if self.monthly_rebalance:
long_stocks = sorted_symbolData[:5]
for long_stock in long_stocks:
self.SetHoldings(long_stock, 1/5)
stocks_invested = [x.Key for x in self.Portfolio if x.Value.Invested]
# liquidate stocks not in the list
for i in stocks_invested:
if i not in long_stocks:
self.Liquidate(i)

def OnSecuritiesChanged(self, changes):
# clean up data for removed securities
self.removedSymbols = [x.Symbol for x in changes.RemovedSecurities]
for removed in changes.RemovedSecurities:
# warm up the indicator with history price for newly added securities

symbolData = SymbolData(symbol, self.lookback)
if str(symbol) in history.index:
symbolData.WarmUpIndicator(history.loc[str(symbol)])

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

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

def WarmUpIndicator(self, history):
# warm up the Momentum indicator with the history request
for tuple in history.itertuples():
item = IndicatorDataPoint(self.symbol, tuple.Index, float(tuple.close))
self.MOM.Update(item)                        ```