Overall Statistics |
Total Trades 92 Average Win 1.11% Average Loss -0.89% Compounding Annual Return 8.772% Drawdown 16.000% Expectancy 0.194 Net Profit 6.858% Sharpe Ratio 0.464 Probabilistic Sharpe Ratio 27.750% Loss Rate 47% Win Rate 53% Profit-Loss Ratio 1.24 Alpha 0.006 Beta 0.367 Annual Standard Deviation 0.158 Annual Variance 0.025 Information Ratio -0.663 Tracking Error 0.167 Treynor Ratio 0.199 Total Fees $563.19 Estimated Strategy Capacity $88000000.00 Lowest Capacity Asset NFLX SEWJWLJNHZDX |
# MACD Alpha Model class FrameworkAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 1, 1) self.SetEndDate(2021, 10, 15) self.SetCash(1000000) tickers = ["AAPL", "MSFT", "TSLA", "NVDA", "DIS", "AMD", "NFLX"] symbols = [Symbol.Create(t, SecurityType.Equity, Market.USA) for t in tickers] self.SetUniverseSelection(ManualUniverseSelectionModel(symbols)) self.UniverseSettings.Resolution = Resolution.Daily self.AddAlpha(MacdAlphaModel()) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(self.DateRules.Every(DayOfWeek.Monday))) self.SetExecution(ImmediateExecutionModel()) class MacdAlphaModel(AlphaModel): def __init__(self, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9, movingAverageType = MovingAverageType.Exponential, resolution = Resolution.Daily): self.fastPeriod = fastPeriod self.slowPeriod = slowPeriod self.signalPeriod = signalPeriod self.movingAverageType = movingAverageType self.resolution = resolution self.insightPeriod = Time.Multiply(Extensions.ToTimeSpan(resolution), fastPeriod) self.bounceThresholdPercent = 0.01 self.symbolData = {} resolutionString = Extensions.GetEnumString(resolution, Resolution) movingAverageTypeString = Extensions.GetEnumString(movingAverageType, MovingAverageType) self.Name = '{}({},{},{},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, signalPeriod, movingAverageTypeString, resolutionString) def Update(self, algorithm, data): insights = [] for key, sd in self.symbolData.items(): if sd.Security.Price == 0: continue direction = InsightDirection.Flat normalized_signal = sd.MACD.Signal.Current.Value / sd.Security.Price if normalized_signal > self.bounceThresholdPercent: direction = InsightDirection.Up elif normalized_signal < -self.bounceThresholdPercent: direction = InsightDirection.Flat if direction == sd.PreviousDirection: continue insight = Insight.Price(sd.Security.Symbol, self.insightPeriod, direction) sd.PreviousDirection = insight.Direction insights.append(insight) return insights def OnSecuritiesChanged(self, algorithm, changes): for added in changes.AddedSecurities: self.symbolData[added.Symbol] = SymbolData(algorithm, added, self.fastPeriod, self.slowPeriod, self.signalPeriod, self.movingAverageType, self.resolution) for removed in changes.RemovedSecurities: data = self.symbolData.pop(removed.Symbol, None) if data is not None: algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator) class SymbolData: def __init__(self, algorithm, security, fastPeriod, slowPeriod, signalPeriod, movingAverageType, resolution): self.Security = security self.MACD = MovingAverageConvergenceDivergence(fastPeriod, slowPeriod, signalPeriod, movingAverageType) self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution) algorithm.RegisterIndicator(security.Symbol, self.MACD, self.Consolidator) self.PreviousDirection = None