Overall Statistics Total Trades 10 Average Win 2.78% Average Loss -0.55% Compounding Annual Return 0.307% Drawdown 5.200% Expectancy 0.208 Net Profit 0.309% Sharpe Ratio 0.073 Probabilistic Sharpe Ratio 15.369% Loss Rate 80% Win Rate 20% Profit-Loss Ratio 5.04 Alpha 0.004 Beta -0.03 Annual Standard Deviation 0.056 Annual Variance 0.003 Information Ratio 0.006 Tracking Error 0.16 Treynor Ratio -0.136 Total Fees \$45.29
from math import ceil,floor
import pandas as pd
import numpy as np

class ResistanceOptimizedAutosequencers(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015,2,1)  #Set Start Date
self.SetEndDate(2016,2,1)    #Set End Date
self.SetCash(100000)            #Set Strategy Cash
self.rebalance_flag = True

self.TF_filter = False
self.TF_lookback = 126
self.num_positions = 50
self.relative_momentum_lookback = 126 #Momentum lookback
self.momentum_skip_days = 10

self.symbols = None
self.SetWarmUp(200)

self.UniverseSettings.Resolution = Resolution.Daily
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 60), Action(self.rebalance))

def CoarseSelectionFunction(self, coarse):
if self.rebalance_flag and not self.IsWarmingUp:
CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData and x.Price > 5]
sortedByDollarVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True)[:1000]
return [i.Symbol for i in sortedByDollarVolume]
else:
return []

def FineSelectionFunction(self, fine):
if self.rebalance_flag and not self.IsWarmingUp:
filtered_fine = [x for x in fine if x.OperationRatios.ROIC.Value
and x.OperationRatios.LongTermDebtEquityRatio.Value
and x.ValuationRatios.CashReturn
and x.ValuationRatios.FCFYield
and x.MarketCap]
filtered_marketcap = sorted(filtered_fine, key=lambda x: x.MarketCap, reverse=True)[:700]
sortedByfactor1 = sorted(filtered_marketcap, key=lambda x: x.OperationRatios.ROIC.Value, reverse=True)
sortedByfactor2 = sorted(filtered_marketcap, key=lambda x: x.OperationRatios.LongTermDebtEquityRatio.Value, reverse=True)
sortedByfactor3 = sorted(filtered_marketcap, key=lambda x: x.ValuationRatios.CashReturn, reverse=True)
sortedByfactor4 = sorted(filtered_marketcap, key=lambda x: x.ValuationRatios.FCFYield, reverse=True)

num_stocks = floor(len(filtered_marketcap)/self.num_positions)

stock_dict = {}

for i,ele in enumerate(sortedByfactor1):
rank1 = i
rank2 = sortedByfactor2.index(ele)
rank3 = sortedByfactor3.index(ele)
rank4 = sortedByfactor4.index(ele)

score = [ceil(rank1/num_stocks),
ceil(rank2/num_stocks),
ceil(rank3/num_stocks),
ceil(rank4/num_stocks)]
score = sum(score)
stock_dict[ele] = score

top_stocks = sorted(stock_dict.items(), key=lambda d:d[1],reverse=True)
top_symbols = [top_stocks[i][0] for i in range(len(top_stocks))][:100]
self.rebalance_flag = False
self.symbols = [i.Symbol for i in top_symbols]
return self.symbols
else:
return []

def rebalance(self):
if not self.IsWarmingUp:
############Trend Following Regime Filter############
spy_history = self.History(["SPY"], 200, Resolution.Daily).loc["SPY"]
spy_ma50 = spy_history["close"].iloc[:-50].mean()
spy_ma200 = spy_history["close"].mean()
if spy_ma50 > spy_ma200:
self.TF_filter = True
else:
self.TF_filter = False

if self.symbols:
prices = self.History(self.symbols, 200, Resolution.Daily).unstack(level=0)["close"]
quality_momentum = prices.iloc[:-self.momentum_skip_days].pct_change(self.relative_momentum_lookback).iloc[-1]
top_momentum_stocks = quality_momentum.sort_values(ascending=False)[:self.num_positions]
top_momentum_symbols = [self.Symbol(i) for i in top_momentum_stocks.index.values]
portfolio_holdings = [x.Key for x in self.Portfolio if x.Value.Invested]

for symbol in portfolio_holdings:
if not symbol == self.Symbol("IEF") and symbol not in top_momentum_symbols:
self.Debug(f"Liquidating {symbol}")
self.Liquidate(symbol)

if self.TF_filter:
self.Debug("Tf Filter True")
self.Liquidate(self.bond.Symbol)
for symbol in top_momentum_symbols:
self.rebalance_flag = True