| Overall Statistics |
|
Total Trades 3015 Average Win 0.03% Average Loss -0.02% Compounding Annual Return 0.260% Drawdown 9.100% Expectancy -0.078 Net Profit 1.462% Sharpe Ratio 0.083 Loss Rate 65% Win Rate 35% Profit-Loss Ratio 1.63 Alpha -0.027 Beta 1.674 Annual Standard Deviation 0.036 Annual Variance 0.001 Information Ratio -0.416 Tracking Error 0.036 Treynor Ratio 0.002 Total Fees $3018.20 |
class TwelveMonthCycle(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 1, 1)
self.SetEndDate(2018, 8, 1)
self.SetCash(100000)
self.AddEquity("SPY", Resolution.Daily)
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), self.Rebalance)
self.monthly_rebalance = False
self.filtered_fine = None
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
def CoarseSelectionFunction(self, coarse):
if self.monthly_rebalance:
coarse = [x for x in coarse if (x.HasFundamentalData)
and (x.Market == "usa")]
return [i.Symbol for i in coarse]
else:
return []
def FineSelectionFunction(self, fine):
if self.monthly_rebalance:
fine =[i for i in fine if ((i.SecurityReference.ExchangeId == "NYS") or (i.SecurityReference.ExchangeId == "ASE"))]
self.filtered_fine = []
for i in fine:
i.MarketCap = float(i.EarningReports.BasicAverageShares.TwelveMonths * (i.EarningReports.BasicEPS.TwelveMonths*i.ValuationRatios.PERatio))
history_start = self.History([i.Symbol], TimeSpan.FromDays(365))
history_end = self.History([i.Symbol],TimeSpan.FromDays(335))
if not history_start.empty and not history_end.empty:
i.Returns = float(history_end.iloc[0]["close"] - history_start.iloc[0]["close"])
self.filtered_fine.append(i)
size = int(len(fine)*.3)
self.filtered_fine = sorted(self.filtered_fine, key = lambda x: x.MarketCap, reverse=True)
self.filtered_fine = self.filtered_fine[:size]
self.filtered_fine = sorted(self.filtered_fine, key = lambda x: x.Returns, reverse=True)
symbols = [i.Symbol for i in self.filtered_fine]
self.filtered_fine = symbols
return symbols
else:
return []
def Rebalance(self):
self.monthly_rebalance = True
def OnData(self, data):
if not (self.monthly_rebalance): return
if not (self.filtered_fine): return
self.monthly_rebalance = False
portfolio_size = int(len(self.filtered_fine)/10)
short_stocks = self.filtered_fine[-portfolio_size:]
long_stocks = self.filtered_fine[:portfolio_size]
stocks_invested = [x.Key for x in self.Portfolio]
for i in stocks_invested:
#liquidate the stocks not in the filtered balance sheet accrual list
if i not in self.filtered_fine:
self.Liquidate(i)
#long the stocks in the list
elif i in long_stocks:
self.SetHoldings(i, 1/(portfolio_size*2))
#short the stocks in the list
elif i in short_stocks:
self.SetHoldings(i,-1/(portfolio_size*2))