| Overall Statistics |
|
Total Orders 209 Average Win 2.06% Average Loss -2.31% Compounding Annual Return 35.059% Drawdown 27.200% Expectancy 0.534 Start Equity 100000 End Equity 449623.45 Net Profit 349.623% Sharpe Ratio 1.046 Sortino Ratio 1.343 Probabilistic Sharpe Ratio 61.586% Loss Rate 19% Win Rate 81% Profit-Loss Ratio 0.89 Alpha 0.162 Beta 0.9 Annual Standard Deviation 0.206 Annual Variance 0.043 Information Ratio 0.957 Tracking Error 0.163 Treynor Ratio 0.24 Total Fees $282.93 Estimated Strategy Capacity $430000000.00 Lowest Capacity Asset XLK RGRPZX100F39 Portfolio Turnover 1.69% Drawdown Recovery 541 |
from AlgorithmImports import *
from datetime import timedelta
class TradingCompetitionAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_cash(100000)
self.set_start_date(self.end_date - timedelta(5 * 365))
self._symbols = []
self._mom_3m = {}
self._mom_6m = {}
self._mom_12m = {}
self._sma_200 = {}
tickers = [
"SPY",
"QQQ",
"XLK",
"SMH",
"NVDA",
"MSFT",
"AAPL",
"LLY",
"COST",
"UNH",
"GLD",
"SHY"
]
for ticker in tickers:
security = self.add_equity(ticker, Resolution.DAILY)
security.set_data_normalization_mode(DataNormalizationMode.ADJUSTED)
symbol = security.symbol
self._symbols.append(symbol)
self._mom_3m[symbol] = self.roc(symbol, 63, Resolution.DAILY)
self._mom_6m[symbol] = self.roc(symbol, 126, Resolution.DAILY)
self._mom_12m[symbol] = self.roc(symbol, 252, Resolution.DAILY)
self._sma_200[symbol] = self.sma(symbol, 200, Resolution.DAILY)
self.set_warm_up(260, Resolution.DAILY)
self.schedule.on(
self.date_rules.month_start("SPY"),
self.time_rules.at(8, 0),
self.rebalance
)
def on_warmup_finished(self) -> None:
self.rebalance()
def rebalance(self) -> None:
if self.is_warming_up:
return
ranked_symbols = []
for symbol in self._symbols:
security = self.securities[symbol]
mom_3m = self._mom_3m[symbol]
mom_6m = self._mom_6m[symbol]
mom_12m = self._mom_12m[symbol]
sma_200 = self._sma_200[symbol]
if not security.has_data:
continue
if security.price <= 0:
continue
if not mom_3m.is_ready or not mom_6m.is_ready or not mom_12m.is_ready or not sma_200.is_ready:
continue
if security.price < sma_200.current.value and symbol.value != "SHY":
continue
score = 0.45 * mom_3m.current.value
score += 0.35 * mom_6m.current.value
score += 0.20 * mom_12m.current.value
ranked_symbols.append((symbol, score))
ranked_symbols.sort(key=lambda item: item[1], reverse=True)
selected_symbols = []
for symbol, score in ranked_symbols:
if score > 0 and symbol.value != "SHY":
selected_symbols.append(symbol)
if len(selected_symbols) == 3:
break
if len(selected_symbols) == 0:
selected_symbols = [
self.symbol("SHY"),
self.symbol("GLD")
]
targets = []
total_weight = 0.97
target_weight = total_weight / len(selected_symbols)
for symbol in self._symbols:
weight = 0
if symbol in selected_symbols:
weight = target_weight
targets.append(PortfolioTarget(symbol, weight))
self.set_holdings(targets)