Overall Statistics |
Total Trades 279 Average Win 2.38% Average Loss -0.94% Compounding Annual Return 113.862% Drawdown 29.900% Expectancy 0.823 Net Profit 128.601% Sharpe Ratio 1.536 Probabilistic Sharpe Ratio 51.108% Loss Rate 48% Win Rate 52% Profit-Loss Ratio 2.52 Alpha 1.196 Beta -0.166 Annual Standard Deviation 0.763 Annual Variance 0.582 Information Ratio 1.325 Tracking Error 0.774 Treynor Ratio -7.055 Total Fees $437.02 Estimated Strategy Capacity $670000000.00 Lowest Capacity Asset NVDA RHM8UTD8DT2D |
from datetime import timedelta class EMAMomentumUniverse(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 1, 1) self.SetEndDate(2022, 2, 1) self.SetCash(100000) self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction) self.averages = { } def CoarseSelectionFunction(self, _input): selected = [] universe = sorted(_input, key=lambda c: c.DollarVolume, reverse=True) universe = [c for c in universe if c.Price > 10][:100] for coarse in universe: symbol = coarse.Symbol if symbol not in self.averages: self.averages[symbol] = SelectionData(self) history = self.History(symbol, 1, Resolution.Daily) self.averages[symbol].update(history) if self.averages[symbol].is_ready(): selected.append(symbol) self.Debug(f"Selected: [{','.join(map(str, selected[:5]))}]") return selected[:5] def OnSecuritiesChanged(self, changes): for security in changes.RemovedSecurities: self.Liquidate(security.Symbol) for security in changes.AddedSecurities: self.SetHoldings(security.Symbol, 0.20) class SelectionData(): def __init__(self, algo): self.obv = OnBalanceVolume() self.algo = algo def is_ready(self): return self.obv.IsReady def update(self, history): for bar in history.itertuples(): self.algo.Debug(f"Bar: {bar}") try: tradeBar = TradeBar(bar.Index[1] - timedelta(days=1), bar.Index[0], bar.open, bar.high, bar.low, bar.close, bar.volume, timedelta(days=1)) self.obv.Update(tradeBar) except AttributeError: self.algo.Debug("No volume!")