| Overall Statistics |
|
Total Trades 2171 Average Win 0.09% Average Loss -0.11% Compounding Annual Return 0.564% Drawdown 17.900% Expectancy -0.020 Net Profit 3.189% Sharpe Ratio 0.101 Probabilistic Sharpe Ratio 0.529% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 0.78 Alpha 0.027 Beta -0.202 Annual Standard Deviation 0.052 Annual Variance 0.003 Information Ratio -0.779 Tracking Error 0.132 Treynor Ratio -0.026 Total Fees $2171.00 Estimated Strategy Capacity $820000.00 Lowest Capacity Asset CEA R735QTJ8XC9X |
#region imports
from AlgorithmImports import *
#endregion
class TwelveMonthCycle(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 1, 1)
self.SetEndDate(2018, 8, 1)
self.SetCash(100000)
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
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
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:
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)[:size]
self.filtered_fine = sorted(self.filtered_fine, key = lambda x: x.Returns, reverse=True)
self.filtered_fine = [i.Symbol for i in self.filtered_fine]
return self.filtered_fine
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))