| Overall Statistics |
|
Total Trades 2632 Average Win 0.14% Average Loss -0.05% Compounding Annual Return 11.876% Drawdown 22.700% Expectancy 1.306 Net Profit 134.205% Sharpe Ratio 0.699 Loss Rate 35% Win Rate 65% Profit-Loss Ratio 2.56 Alpha 0.186 Beta -3.712 Annual Standard Deviation 0.168 Annual Variance 0.028 Information Ratio 0.589 Tracking Error 0.168 Treynor Ratio -0.032 Total Fees $16861.88 |
from datetime import datetime, timedelta
class MomentumInREIT(QCAlgorithm):
def Initialize(self):
#rebalancing should occur in July
self.SetStartDate(2010,12,15) #Set Start Date
self.SetEndDate(2018,7,15) #Set End Date
self.SetCash(1000000) #Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.filtered_fine = None
self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)
self.AddEquity("SPY", Resolution.Daily)
#monthly scheduled event
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.At(23, 0), self.rebalance)
self.months = -1
self.quarterly_rebalance = False
def CoarseSelectionFunction(self, coarse):
if self.quarterly_rebalance:
# drop stocks which have that are not in the United States
self.filtered_coarse = [x.Symbol for x in coarse if (x.Market == "usa")]
return self.filtered_coarse
else:
return []
def FineSelectionFunction(self, fine):
if self.quarterly_rebalance:
#filters out the companies that are not REITs
fine = [x for x in fine if (x.CompanyReference.IsREIT == 1)]
#calculating the 11 month (1-month lagged) returns
start = self.Time-timedelta(days = 365)
end = self.Time-timedelta(days = 30)
for x in fine:
hist = self.History([x.Symbol],start,end,Resolution.Daily)
if not hist.empty:
start_price = hist["close"].iloc[0]
end_price = hist["close"].iloc[-1]
x.momentum = (start_price-end_price)/start_price
fine = [x for x in fine if hasattr(x, 'momentum')]
#we sort REITs based on their returns
sorted_filter = sorted(fine, key=lambda x: x.momentum)
self.filtered_fine = [i.Symbol for i in sorted_filter]
return self.filtered_fine
else:
return []
def rebalance(self):
#quarterly rebalance
self.months+=1
if self.months%3 == 0:
self.quarterly_rebalance = True
def OnData(self, data):
if not self.quarterly_rebalance: return
if self.filtered_fine:
portfolio_size = int(len(self.filtered_fine)/3)
#pick the upper trecile to short and the lower decile to long
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 our filtered_fine list
if i not in long_stocks:
self.Liquidate(i)
#long the stocks in the list
elif i in long_stocks:
self.SetHoldings(i, 1/(portfolio_size))
self.quarterly_rebalance = False
self.filtered_fine = False