| Overall Statistics |
|
Total Orders 1198 Average Win 0.18% Average Loss -0.22% Compounding Annual Return 4.518% Drawdown 31.300% Expectancy 0.088 Start Equity 1000000 End Equity 1247343.24 Net Profit 24.734% Sharpe Ratio 0.047 Sortino Ratio 0.058 Probabilistic Sharpe Ratio 2.542% Loss Rate 41% Win Rate 59% Profit-Loss Ratio 0.83 Alpha -0.048 Beta 0.766 Annual Standard Deviation 0.156 Annual Variance 0.024 Information Ratio -0.553 Tracking Error 0.117 Treynor Ratio 0.01 Total Fees $8216.68 Estimated Strategy Capacity $75000.00 Lowest Capacity Asset RRF R735QTJ8XC9X Portfolio Turnover 0.89% Drawdown Recovery 124 |
#region imports
from AlgorithmImports import *
#endregion
class MomentumInREIT(QCAlgorithm):
def initialize(self):
self.set_start_date(self.end_date - timedelta(5*365))
self.settings.seed_initial_prices = True
self.set_cash(1_000_000)
date_rule = self.date_rules.month_start("SPY")
self.universe_settings.resolution = Resolution.DAILY
self._universe = self.add_universe(date_rule, self._select_assets)
# Add a monthly Scheduled Event.
self.schedule.on(date_rule, self.time_rules.midnight, self._rebalance)
self.set_warm_up(timedelta(100))
def _new_quarter(self):
return self.time.month % 3 == 1
def _select_assets(self, fundamentals):
if not self._new_quarter():
return Universe.UNCHANGED
# Drop penny stocks, stocks with no fundamental data,
# and companies that aren't REITs.
fundamentals = [
f for f in fundamentals
if (f.price > 1
and f.has_fundamental_data
and f.volume > 10_000
and f.company_reference.is_reit)
]
# Calculate the 11 month (1-month lagged) returns of all
# the remaining assets.
history = self.history(
[f.symbol for f in fundamentals],
self.time - timedelta(365),
self.time - timedelta(30),
Resolution.DAILY
).close.unstack(0).dropna(axis=1)
sorted_by_momentum = list((history.iloc[-1] / history.iloc[0]).sort_values().index)
# Select the 1/3 of assets with the greatest momentum.
return sorted_by_momentum[-int(len(sorted_by_momentum)/3):]
def _rebalance(self, wait_for_new_quarter=True):
if wait_for_new_quarter and not self._new_quarter():
return
targets = [
PortfolioTarget(symbol, 1/len(self._universe.selected))
for symbol in self._universe.selected
]
self.set_holdings(targets, True)
def on_warmup_finished(self):
self._rebalance(False)