Overall Statistics |
Total Trades 1 Average Win 0% Average Loss 0% Compounding Annual Return 0.002% Drawdown 0.000% Expectancy 0 Net Profit 0.000% Sharpe Ratio 0.688 Probabilistic Sharpe Ratio 45.870% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha -0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -8.116 Tracking Error 0.077 Treynor Ratio 0.544 Total Fees $0.00 Estimated Strategy Capacity $410000000.00 Lowest Capacity Asset XAGUSD 8I |
# the main idea is to determine the slope of an indicator and in this alpha it is the Donchian indicator class IndicatorSlopeAlphaModel(AlphaModel): def __init__(self, period): self.period = period self.resolution = Resolution.Daily self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(self.resolution), self.period) self.symbolData = {} def Update(self, context, data): insights = [] for symbol, symbolData in self.symbolData.items(): if not context.Portfolio[symbol].Invested: if symbolData.CanEmit: if data.ContainsKey(symbol): close = symbolData.QuoteBar.Close if symbolData.IndicatorSlope >= 0: direction = InsightDirection.Up insights.append(Insight.Price(symbol, self.predictionInterval, direction, None, None)) elif symbolData.IndicatorSlope < 0: direction = InsightDirection.Down insights.append(Insight.Price(symbol, self.predictionInterval, direction, None, None)) return insights def OnSecuritiesChanged(self, context, changes): for removed in changes.RemovedSecurities: symbol = removed.Symbol if removed in self.symbolData: symbolData = self.symbolData.pop(symbol, None) if symbolData is not None: symbolData.RemoveConsolidators(context) # initialize data for added securities symbols = [x.Symbol for x in changes.AddedSecurities] history = context.History(symbols, self.period, self.resolution) if history.empty: return tickers = history.index.levels[0] context.Debug("{} -- {} Added to Alpha Model".format(context.Time, [str(added.Symbol) for added in changes.AddedSecurities])) for added in changes.AddedSecurities: symbol = added.Symbol if symbol not in self.symbolData: context.Debug("{} -- {} Added to Alpha Model Symbol Data".format(context.Time, str(symbol))) data = SymbolData(context, added, self.period) self.symbolData[symbol] = data data.RegisterIndicators(context, self.resolution) if symbol not in tickers: continue else: data.WarmUpIndicators(history.loc[symbol]) class SymbolData: def __init__(self, context, security, lookback): self.context = context self.Security = security self.Symbol = security.Symbol self.TestIndicator = DonchianChannel(self.Symbol, 20, Resolution.Daily) self.IndicatorSlope = 0 # Try rolling windows to access previous indicator values to subtract it to determine the slope self.dchWindow = RollingWindow[IndicatorDataPoint](5) ''' #####~~ indicator extensions begin ~~ uncomment the 3's #Tried to get the slope of the Chanel indicater by using the ROC of the indictor # the indicator extensions seems NOT working on these two indicators below self.ROC = RateOfChange(18) self.meanDCH = float(self.TestIndicator.Current.Value) self.IndicatorSlope = IndicatorExtensions.Of(self.ROC, self.meanDCH ) #####~~ indicator extensions end ~~ uncomment the 3's below and one line further on line 95 ''' self.Consolidator = None self.QuoteBar = None self.Previous = None self.print = True def RegisterIndicators(self, context, resolution): self.Consolidator = context.ResolveConsolidator(self.Symbol, Resolution.Daily) self.Consolidator.DataConsolidated += self.OnDataConsolidated context.RegisterIndicator(self.Symbol, self.TestIndicator, self.Consolidator) #####~~ indicator extensions begin ~~ uncomment the # below #context.RegisterIndicator(self.Symbol, self.IndicatorSlope, self.Consolidator) #Uncomment to get the IndicatorExtensions working #####~~ indicator extensions end ~~ context.Debug("Indicator registered for {} @ {}".format(self.Symbol, context.Time)) def OnDataConsolidated(self, sender, bar): ''' #####~~ Rolling Window begin ~~ uncomment the 3's above and below codesnipet # Try Rolling Window to determine the slope of the testindicztor self.dchWindow.Add(self.TestIndicator.Current.Value) currentDch = self.dchWindow[0] previousDch = self.dchWindow[1] self.IndicatorSlope = currentDch - previousDch #####~~ Rolling Window end ~~ uncomment the 3's below ''' if self.print: self.context.Debug("{} -- Data Consol. for {}: {}, Ending: {}".format(self.context.Time, self.Symbol, bar.Close, bar.EndTime)) self.context.Debug("{} -- for symbol {} and ROC ON Channel value: ROC value {} and Ending: {}".format(self.context.Time, self.Symbol, self.IndicatorSlope, bar.EndTime)) self.print = False self.QuoteBar = bar @property def CanEmit(self): # this will be getting checked at a higher freq. than the consolidator, check if a new Daily bar is available if self.Previous == self.QuoteBar: return False self.Previous = self.QuoteBar return self.TestIndicator.IsReady def RemoveConsolidators(self, context): if self.Consolidator is not None: conext.SubscriptionManager.RemoveConsolidator(self.Symbol, self.Consolidator) def WarmUpIndicators(self, history): for index, tuple in history.iterrows(): tradeBar = TradeBar() tradeBar.Close = tuple['close'] self.TestIndicator.Update(tradeBar)
class IndicatorSlopePortfolioConstructionModel(PortfolioConstructionModel): def CreateTargets(self, context, insights): targets = [] for insight in insights: targets.append(PortfolioTarget(insight.Symbol, insight.Direction)) return targets
from Alpha import IndicatorSlopeAlphaModel from Portfolio import IndicatorSlopePortfolioConstructionModel from Universe import IndicatorSlopeUniverseModel class IndicatorSlope(QCAlgorithm): def Initialize(self): # Set Start Date for backtest self.SetStartDate(2018, 1, 1) self.SetEndDate(2018, 2, 1) # Set $100k Strategy Cash self.SetCash(100000) self.SetExecution( ImmediateExecutionModel() ) self.SetPortfolioConstruction( IndicatorSlopePortfolioConstructionModel() ) self.AddAlpha( IndicatorSlopeAlphaModel(period=20) ) self.UniverseSettings.Resolution = Resolution.Minute self.AddUniverseSelection( IndicatorSlopeUniverseModel() ) def OnData(self, data): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. Arguments: data: Slice object keyed by symbol containing the stock data '''
from QuantConnect import * from Selection.ManualUniverseSelectionModel import ManualUniverseSelectionModel class IndicatorSlopeUniverseModel(ManualUniverseSelectionModel): def __init__(self): metals = ["XAGUSD"] universe = metals super().__init__([Symbol.Create(x, SecurityType.Cfd, Market.Oanda) for x in universe])