Overall Statistics |
Total Trades 288 Average Win 0.09% Average Loss -0.17% Compounding Annual Return 28.767% Drawdown 12.100% Expectancy 0.293 Net Profit 27.967% Sharpe Ratio 1.113 Sortino Ratio 1.549 Probabilistic Sharpe Ratio 66.904% Loss Rate 16% Win Rate 84% Profit-Loss Ratio 0.55 Alpha 0 Beta 0 Annual Standard Deviation 0.135 Annual Variance 0.018 Information Ratio 1.5 Tracking Error 0.135 Treynor Ratio 0 Total Fees $454.03 Estimated Strategy Capacity $13000000.00 Lowest Capacity Asset SGEN S2TCB9V1OIG5 Portfolio Turnover 0.53% |
# region imports from AlgorithmImports import * # endregion TICKER = "QQQ" class ETF_Debug(QCAlgorithm): def Initialize(self): self.SetStartDate(2023, 1, 8) # Set Start Date self.SetEndDate(2024, 1, 1) self.SetCash(1000000) # Set Strategy Cash self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetSecurityInitializer(self.CustomSecurityInitializer) self.UniverseSettings.Resolution = Resolution.Minute self.AddUniverse(self.Universe.ETF(TICKER, Market.USA, self.UniverseSettings, self.ETFConstituentsFilter)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(9, 30), self.CheckSecurities) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15,30), self.Rebalance) self.selected = [] def CustomSecurityInitializer(self, security: Security): seeder = FuncSecuritySeeder(self.GetLastKnownPrices) seeder.SeedSecurity(security) def ETFConstituentsFilter(self, constituents: List[ETFConstituentData]) -> List[Symbol]: for c in constituents: if c.Weight is None: self.Log(f"{c.Symbol} weight is None, skipping!") if len(list(constituents)) > 100: self.Log(f"{len(list(constituents))} constituents in filter!") self.selected = [c.Symbol for c in constituents] return self.selected def OnSecuritiesChanged(self, changes: SecurityChanges) -> None: if 0 < len(changes.AddedSecurities) < 90: line = ", ".join([f"{x.Symbol.Value}" for x in changes.AddedSecurities]) self.Log(f"{line} were added to universe") if len(changes.RemovedSecurities) > 0: line = ", ".join([f"{x.Symbol.Value}" for x in changes.RemovedSecurities]) self.Log(f"{line} were removed from universe") def CheckSecurities(self): if self.ActiveSecurities.Count > 0 and self.ActiveSecurities.Count > 100: self.Log(f"Active securities count = {self.ActiveSecurities.Count}!") for s in self.selected: if s not in self.ActiveSecurities: self.Log(f"{s.Value} is not in ActiveSecurities!") def Rebalance(self): if self.Securities.Count == 0 or len(self.selected) == 0: return if self.Securities.Values[0].Exchange.DateIsOpen(self.Time+timedelta(1)): return targets = [PortfolioTarget(x, 1/len(self.selected)) for x in self.selected] self.SetHoldings(targets, liquidateExistingHoldings=True)