Overall Statistics |
Total Trades 407 Average Win 14.94% Average Loss -5.38% Compounding Annual Return 300.990% Drawdown 87.500% Expectancy 0.595 Net Profit 4583.053% Sharpe Ratio 4.163 Probabilistic Sharpe Ratio 81.636% Loss Rate 58% Win Rate 42% Profit-Loss Ratio 2.78 Alpha 5.3 Beta 0.659 Annual Standard Deviation 1.283 Annual Variance 1.647 Information Ratio 4.13 Tracking Error 1.278 Treynor Ratio 8.113 Total Fees $620855.83 Estimated Strategy Capacity $390000.00 Lowest Capacity Asset SNTI XZ6355XJQ4IT |
from Execution.ImmediateExecutionModel import ImmediateExecutionModel from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel from AlgorithmImports import * class TwoWeekMagnitudeEffectOnCurrentReturns(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.AddAlpha(MyHistoricalReturnsAlphaModel(14, Resolution.Daily)) self.SetExecution(ImmediateExecutionModel()) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) self.SetUniverseSelection(CoarseFundamentalUniverseSelectionModel(self.CoarseSelectionFunction)) def CoarseSelectionFunction(self, coarse): sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) filtered = [ x.Symbol for x in sortedByDollarVolume if x.HasFundamentalData and x.Price >= .1 and x.Price <= 10 and x.DollarVolume > 1000000 ] return [ x for x in filtered[:250] ] class MyHistoricalReturnsAlphaModel(AlphaModel): '''Uses Historical returns to create insights.''' def __init__(self, *args, **kwargs): '''Initializes a new default instance of the HistoricalReturnsAlphaModel class. Args: lookback(int): Historical return lookback period resolution: The resolution of historical data''' self.lookback = kwargs['lookback'] if 'lookback' in kwargs else 1 self.resolution = kwargs['resolution'] if 'resolution' in kwargs else Resolution.Daily self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(self.resolution), self.lookback) self.symbolDataBySymbol = {} def Update(self, algorithm, data): '''Updates this alpha model with the latest data from the algorithm. This is called each time the algorithm receives data for subscribed securities Args: algorithm: The algorithm instance data: The new data available Returns: The new insights generated''' insights = [] for symbol, symbolData in self.symbolDataBySymbol.items(): if symbolData.CanEmit: direction = InsightDirection.Flat magnitude = symbolData.Return if magnitude > .75: direction = InsightDirection.Down if magnitude < -.75: direction = InsightDirection.Up insights.append(Insight.Price(symbol, self.predictionInterval, direction, magnitude, None)) return insights def OnSecuritiesChanged(self, algorithm, changes): '''Event fired each time the we add/remove securities from the data feed Args: algorithm: The algorithm instance that experienced the change in securities changes: The security additions and removals from the algorithm''' # clean up data for removed securities for removed in changes.RemovedSecurities: symbolData = self.symbolDataBySymbol.pop(removed.Symbol, None) if symbolData is not None: symbolData.RemoveConsolidators(algorithm) # initialize data for added securities symbols = [ x.Symbol for x in changes.AddedSecurities ] history = algorithm.History(symbols, self.lookback, self.resolution) if history.empty: return tickers = history.index.levels[0] for ticker in tickers: symbol = SymbolCache.GetSymbol(ticker) if symbol not in self.symbolDataBySymbol: symbolData = SymbolData(symbol, self.lookback) self.symbolDataBySymbol[symbol] = symbolData symbolData.RegisterIndicators(algorithm, self.resolution) symbolData.WarmUpIndicators(history.loc[ticker]) class SymbolData: '''Contains data specific to a symbol required by this model''' def __init__(self, symbol, lookback): self.Symbol = symbol self.ROCP = RateOfChange('{}.ROCP({})'.format(symbol, lookback), lookback) self.Consolidator = None self.previous = 0 def RegisterIndicators(self, algorithm, resolution): self.Consolidator = algorithm.ResolveConsolidator(self.Symbol, resolution) algorithm.RegisterIndicator(self.Symbol, self.ROCP, self.Consolidator) def RemoveConsolidators(self, algorithm): if self.Consolidator is not None: algorithm.SubscriptionManager.RemoveConsolidator(self.Symbol, self.Consolidator) def WarmUpIndicators(self, history): for tuple in history.itertuples(): self.ROCP.Update(tuple.Index, tuple.close) @property def Return(self): return float(self.ROCP.Current.Value) @property def CanEmit(self): if self.previous == self.ROCP.Samples: return False self.previous = self.ROCP.Samples return self.ROCP.IsReady