# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from AlgorithmImports import * ### ### Basic template algorithm simply initializes the date range and cash. This is a skeleton ### framework you can use for designing an algorithm. ### ### ### ### class IndicatorSuiteAlgorithm(QCAlgorithm): '''Demonstration algorithm of popular indicators and plotting them.''' def Initialize(self): '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' self.symbol = "SPY" self.customSymbol = "WIKI/FB" self.price = None self.SetStartDate(2013, 1, 1) #Set Start Date self.SetEndDate(2014, 12, 31) #Set End Date self.SetCash(25000) #Set Strategy Cash # Find more symbols here: http://quantconnect.com/data self.AddEquity(self.symbol, Resolution.Daily) self.AddData(Quandl, self.customSymbol, Resolution.Daily) # Set up default Indicators, these indicators are defined on the Value property of incoming data (except ATR and AROON which use the full TradeBar object) self.indicators = { 'BB' : self.BB(self.symbol, 20, 1, MovingAverageType.Simple, Resolution.Daily), 'RSI' : self.RSI(self.symbol, 14, MovingAverageType.Simple, Resolution.Daily), 'EMA' : self.EMA(self.symbol, 14, Resolution.Daily), 'SMA' : self.SMA(self.symbol, 14, Resolution.Daily), 'MACD' : self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Simple, Resolution.Daily), 'MOM' : self.MOM(self.symbol, 20, Resolution.Daily), 'MOMP' : self.MOMP(self.symbol, 20, Resolution.Daily), 'STD' : self.STD(self.symbol, 20, Resolution.Daily), # by default if the symbol is a tradebar type then it will be the min of the low property 'MIN' : self.MIN(self.symbol, 14, Resolution.Daily), # by default if the symbol is a tradebar type then it will be the max of the high property 'MAX' : self.MAX(self.symbol, 14, Resolution.Daily), 'ATR' : self.ATR(self.symbol, 14, MovingAverageType.Simple, Resolution.Daily), 'AROON' : self.AROON(self.symbol, 20, Resolution.Daily) } # Here we're going to define indicators using 'selector' functions. These 'selector' functions will define what data gets sent into the indicator # These functions have a signature like the following: decimal Selector(BaseData baseData), and can be defined like: baseData => baseData.Value # We'll define these 'selector' functions to select the Low value # # For more information on 'anonymous functions' see: http:#en.wikipedia.org/wiki/Anonymous_function # https:#msdn.microsoft.com/en-us/library/bb397687.aspx # self.selectorIndicators = { 'BB' : self.BB(self.symbol, 20, 1, MovingAverageType.Simple, Resolution.Daily, Field.Low), 'RSI' :self.RSI(self.symbol, 14, MovingAverageType.Simple, Resolution.Daily, Field.Low), 'EMA' :self.EMA(self.symbol, 14, Resolution.Daily, Field.Low), 'SMA' :self.SMA(self.symbol, 14, Resolution.Daily, Field.Low), 'MACD' : self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Simple, Resolution.Daily, Field.Low), 'MOM' : self.MOM(self.symbol, 20, Resolution.Daily, Field.Low), 'MOMP' : self.MOMP(self.symbol, 20, Resolution.Daily, Field.Low), 'STD' : self.STD(self.symbol, 20, Resolution.Daily, Field.Low), 'MIN' : self.MIN(self.symbol, 14, Resolution.Daily, Field.High), 'MAX' : self.MAX(self.symbol, 14, Resolution.Daily, Field.Low), # ATR and AROON are special in that they accept a TradeBar instance instead of a decimal, we could easily project and/or transform the input TradeBar # before it gets sent to the ATR/AROON indicator, here we use a function that will multiply the input trade bar by a factor of two 'ATR' : self.ATR(self.symbol, 14, MovingAverageType.Simple, Resolution.Daily, Func[IBaseData, IBaseDataBar](self.selector_double_TradeBar)), 'AROON' : self.AROON(self.symbol, 20, Resolution.Daily, Func[IBaseData, IBaseDataBar](self.selector_double_TradeBar)) } # Custom Data Indicator: self.rsiCustom = self.RSI(self.customSymbol, 14, MovingAverageType.Simple, Resolution.Daily) self.minCustom = self.MIN(self.customSymbol, 14, Resolution.Daily) self.maxCustom = self.MAX(self.customSymbol, 14, Resolution.Daily) # in addition to defining indicators on a single security, you can all define 'composite' indicators. # these are indicators that require multiple inputs. the most common of which is a ratio. # suppose we seek the ratio of BTC to SPY, we could write the following: spyClose = Identity(self.symbol) fbClose = Identity(self.customSymbol) # this will create a new indicator whose value is FB/SPY self.ratio = IndicatorExtensions.Over(fbClose, spyClose) # we can also easily plot our indicators each time they update using th PlotIndicator function self.PlotIndicator("Ratio", self.ratio) # The following methods will add multiple charts to the algorithm output. # Those chatrs names will be used later to plot different series in a particular chart. # For more information on Lean Charting see: https://www.quantconnect.com/docs#Charting Chart('BB') Chart('STD') Chart('ATR') Chart('AROON') Chart('MACD') Chart('Averages') # Here we make use of the Schelude method to update the plots once per day at market close. self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(self.symbol), self.update_plots) 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 ''' if (#not data.Bars.ContainsKey(self.symbol) or not self.indicators['BB'].IsReady or not self.indicators['RSI'].IsReady): return self.price = data[self.symbol].Close if not self.Portfolio.HoldStock: quantity = int(self.Portfolio.Cash / self.price) self.Order(self.symbol, quantity) self.Debug('Purchased SPY on ' + self.Time.strftime('%Y-%m-%d')) def update_plots(self): if not self.indicators['BB'].IsReady or not self.indicators['STD'].IsReady: return # Plots can also be created just with this one line command. self.Plot('RSI', self.indicators['RSI']) # Custom data indicator self.Plot('RSI-FB', self.rsiCustom) # Here we make use of the chats decalred in the Initialize method, plotting multiple series # in each chart. self.Plot('STD', 'STD', self.indicators['STD'].Current.Value) self.Plot('BB', 'Price', self.price) self.Plot('BB', 'BollingerUpperBand', self.indicators['BB'].UpperBand.Current.Value) self.Plot('BB', 'BollingerMiddleBand', self.indicators['BB'].MiddleBand.Current.Value) self.Plot('BB', 'BollingerLowerBand', self.indicators['BB'].LowerBand.Current.Value) self.Plot('AROON', 'Aroon', self.indicators['AROON'].Current.Value) self.Plot('AROON', 'AroonUp', self.indicators['AROON'].AroonUp.Current.Value) self.Plot('AROON', 'AroonDown', self.indicators['AROON'].AroonDown.Current.Value) # The following Plot method calls are commented out because of the 10 series limit for backtests #self.Plot('ATR', 'ATR', self.indicators['ATR'].Current.Value) #self.Plot('ATR', 'ATRDoubleBar', self.selectorIndicators['ATR'].Current.Value) #self.Plot('Averages', 'SMA', self.indicators['SMA'].Current.Value) #self.Plot('Averages', 'EMA', self.indicators['EMA'].Current.Value) #self.Plot('MOM', self.indicators['MOM'].Current.Value) #self.Plot('MOMP', self.indicators['MOMP'].Current.Value) #self.Plot('MACD', 'MACD', self.indicators['MACD'].Current.Value) #self.Plot('MACD', 'MACDSignal', self.indicators['MACD'].Signal.Current.Value) def selector_double_TradeBar(self, bar): trade_bar = TradeBar() trade_bar.Close = 2 * bar.Close trade_bar.DataType = bar.DataType trade_bar.High = 2 * bar.High trade_bar.Low = 2 * bar.Low trade_bar.Open = 2 * bar.Open trade_bar.Symbol = bar.Symbol trade_bar.Time = bar.Time trade_bar.Value = 2 * bar.Value trade_bar.Period = bar.Period return trade_bar