| Overall Statistics |
|
Total Orders 110 Average Win 3.85% Average Loss -1.68% Compounding Annual Return 33.520% Drawdown 29.600% Expectancy 1.277 Start Equity 100000 End Equity 423914.45 Net Profit 323.914% Sharpe Ratio 0.913 Sortino Ratio 1.021 Probabilistic Sharpe Ratio 47.452% Loss Rate 31% Win Rate 69% Profit-Loss Ratio 2.28 Alpha 0.164 Beta 0.84 Annual Standard Deviation 0.231 Annual Variance 0.053 Information Ratio 0.78 Tracking Error 0.199 Treynor Ratio 0.251 Total Fees $445.68 Estimated Strategy Capacity $300000000.00 Lowest Capacity Asset SMH V2LT3QH97TYD Portfolio Turnover 2.93% Drawdown Recovery 751 |
# 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.week_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)