| Overall Statistics |
|
Total Orders 45 Average Win 8.29% Average Loss -4.16% Compounding Annual Return 34.619% Drawdown 34.000% Expectancy 1.244 Start Equity 100000 End Equity 441627.62 Net Profit 341.628% Sharpe Ratio 0.931 Sortino Ratio 1.029 Probabilistic Sharpe Ratio 48.354% Loss Rate 25% Win Rate 75% Profit-Loss Ratio 1.99 Alpha 0.171 Beta 0.867 Annual Standard Deviation 0.236 Annual Variance 0.056 Information Ratio 0.81 Tracking Error 0.202 Treynor Ratio 0.253 Total Fees $196.13 Estimated Strategy Capacity $240000000.00 Lowest Capacity Asset SMH V2LT3QH97TYD Portfolio Turnover 1.44% Drawdown Recovery 714 |
# region imports
from AlgorithmImports import *
# endregion
class FinalProjectMomentumStrategy(QCAlgorithm):
def initialize(self):
self.set_cash(100_000)
self.set_start_date(self.end_date - timedelta(5 * 365))
self._lookback = 252
self._securities = []
for ticker in ["QQQ", "XLK", "SMH", "XLP", "XLU", "GLD", "TLT", "IEF"]:
self._securities.append(self.add_equity(ticker, Resolution.DAILY))
self.set_warm_up(self._lookback + 5, Resolution.DAILY)
self.schedule.on(self.date_rules.month_start("SPY"), self.time_rules.at(8, 0), self._rebalance)
def on_warmup_finished(self):
self._rebalance()
def _rebalance(self):
if self.is_warming_up:
return
momentum_by_security = {}
for security in self._securities:
history = self.history(security, self._lookback + 1, Resolution.DAILY)
if history.empty or len(history) < self._lookback:
continue
closes = history["close"]
momentum_by_security[security] = closes.iloc[-1] / closes.iloc[0] - 1
# Hold the single strongest name, but only while its momentum is positive.
selected = [security for security in sorted(momentum_by_security, key=lambda s: momentum_by_security[s])[-1:] if momentum_by_security[security] > 0]
if not selected:
selected = [self._securities[0]]
weight = 0.97 / len(selected)
targets = [PortfolioTarget(security, weight if security in selected else 0) for security in self._securities]
self.set_holdings(targets)