Overall Statistics |
Total Trades 395 Average Win 0.11% Average Loss -0.11% Compounding Annual Return 1.744% Drawdown 3.700% Expectancy -0.063 Net Profit 0.185% Sharpe Ratio 0.172 Probabilistic Sharpe Ratio 38.487% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 0.98 Alpha 0.515 Beta -1.017 Annual Standard Deviation 0.14 Annual Variance 0.02 Information Ratio -2.714 Tracking Error 0.169 Treynor Ratio -0.024 Total Fees $395.00 |
class VerticalOptimizedThrustAssembly(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 10, 12) # Set Start Date self.SetEndDate(2019, 11, 19) self.SetCash(100000) # Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction) self.symbolDataBySymbol = {} def CoarseSelectionFunction(self, coarse): sortedCoarse = sorted(coarse, key=lambda c:c.DollarVolume, reverse=True) liquidSymbols = [c.Symbol for c in sortedCoarse][:500] symbols = [s for s in liquidSymbols if s not in self.symbolDataBySymbol] history = self.History(symbols, 252, Resolution.Daily) if not history.empty: history = history.close.unstack(0) for symbol in symbols: if str(symbol) not in history: continue df = history[symbol].dropna() if not df.empty: self.symbolDataBySymbol[symbol] = SymbolData(self, symbol, df) for x in coarse: symbol = x.Symbol if symbol in self.symbolDataBySymbol: self.symbolDataBySymbol[symbol].Update(x.EndTime, x.AdjustedPrice) selectedSymbols = [symbol for symbol, symbolData in self.symbolDataBySymbol.items() if symbolData.HasNewMax] return selectedSymbols def OnSecuritiesChanged(self, changes): for security in changes.AddedSecurities: symbol = security.Symbol self.MarketOrder(symbol, 100) for security in changes.RemovedSecurities: symbol = security.Symbol self.Liquidate(symbol) class SymbolData: def __init__(self, algorithm, symbol, history): self.symbol = symbol self.max = Maximum(252) self.maxWindow = RollingWindow[IndicatorDataPoint](2) self.max.Updated += self.OnMax for time, close in history.iteritems(): self.Update(time, close) def OnMax(self, sender, updated): if self.max.IsReady: self.maxWindow.Add(updated) def Update(self, time, close): self.max.Update(time, close) @property def HasNewMax(self): if self.maxWindow.IsReady: return self.maxWindow[0] > self.maxWindow[1] else: return False