Overall Statistics |
Total Trades 145 Average Win 0.26% Average Loss -0.13% Compounding Annual Return -1.935% Drawdown 3.300% Expectancy -0.079 Net Profit -0.484% Sharpe Ratio -0.254 Loss Rate 69% Win Rate 31% Profit-Loss Ratio 2.01 Alpha -0.183 Beta 8.557 Annual Standard Deviation 0.067 Annual Variance 0.004 Information Ratio -0.545 Tracking Error 0.067 Treynor Ratio -0.002 Total Fees $181.58 |
# 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 System import * from QuantConnect import * from QuantConnect.Data.Consolidators import * from QuantConnect.Data.Market import * from QuantConnect.Orders import OrderStatus from QuantConnect.Algorithm import QCAlgorithm from QuantConnect.Indicators import * import numpy as np from datetime import timedelta, datetime ### <summary> ### Example structure for structuring an algorithm with indicator and consolidator data for many tickers. ### </summary> ### <meta name="tag" content="consolidating data" /> ### <meta name="tag" content="indicators" /> ### <meta name="tag" content="using data" /> ### <meta name="tag" content="strategy example" /> class MultipleSymbolConsolidationAlgorithm(QCAlgorithm): # Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. def Initialize(self): # This is the period of bars we'll be creating BarPeriod = TimeSpan.FromMinutes(5) BarPeriod15 = TimeSpan.FromMinutes(15) # This is the period of our sma indicators SimpleMovingAveragePeriod = 5 SimpleMovingAveragePeriod15 = 15 # This is the number of consolidated bars we'll hold in symbol data for reference RollingWindowSize = 10 # Holds all of our data keyed by each symbol self.Data = {} self.Data15 = {} # Contains all of our equity symbols EquitySymbols = ["AAPL","SPY","IBM"] self.PositionSize = (1/ len(EquitySymbols)) self.SetStartDate(2018, 9, 1) self.SetEndDate(2018, 12, 1) # initialize our equity data for symbol in EquitySymbols: equity = self.AddEquity(symbol) self.Data[symbol] = SymbolData(equity.Symbol, BarPeriod, RollingWindowSize) self.Data15[symbol] = SymbolData(equity.Symbol, BarPeriod15, RollingWindowSize) # loop through all our symbols and request data subscriptions and initialize indicator for symbol, symbolData in self.Data.items(): # define the indicator symbolData.SMA = SimpleMovingAverage(self.CreateIndicatorName(symbol, "SMA" + str(SimpleMovingAveragePeriod), Resolution.Minute), SimpleMovingAveragePeriod) symbolData.MACD = MovingAverageConvergenceDivergence(self.CreateIndicatorName(symbol, "MACD" + str(SimpleMovingAveragePeriod) , Resolution.Minute), 12, 26, 9, MovingAverageType.Exponential) # define a consolidator to consolidate data for this symbol on the requested period consolidator = TradeBarConsolidator(BarPeriod) consolidator.DataConsolidated += self.OnDataConsolidated # write up our consolidator to update the indicator # we need to add this consolidator so it gets auto updates self.SubscriptionManager.AddConsolidator(symbolData.Symbol, consolidator) for symbol, symbolData15 in self.Data15.items(): symbolData15.SMA15 = SimpleMovingAverage(self.CreateIndicatorName(symbol, "SMA15" + str(SimpleMovingAveragePeriod15) , Resolution.Minute), SimpleMovingAveragePeriod) symbolData15.MACD15 = MovingAverageConvergenceDivergence(self.CreateIndicatorName(symbol, "MACD15" + str(SimpleMovingAveragePeriod15) , Resolution.Minute), 12, 26, 9, MovingAverageType.Exponential) # define a consolidator to consolidate data for this symbol on the requested period consolidator15 = TradeBarConsolidator(BarPeriod15) #consolidator15.DataConsolidated += self.OnDataConsolidated # write up our consolidator to update the indicator # we need to add this consolidator so it gets auto updates self.SubscriptionManager.AddConsolidator(symbolData15.Symbol, consolidator15) def OnDataConsolidated(self, sender, bar): self.Data[bar.Symbol.Value].SMA.Update(bar.Time, bar.Close) self.Data[bar.Symbol.Value].MACD.Update(bar.Time, bar.Close) self.Data[bar.Symbol.Value].Bars.Add(bar) self.Data15[bar.Symbol.Value].SMA15.Update(bar.Time, bar.Close) self.Data15[bar.Symbol.Value].MACD15.Update(bar.Time, bar.Close) #self.Data15[bar.Symbol.Value].Bars15.Add(bar) # OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. # Argument "data": Slice object, dictionary object with your stock data def OnData(self,data): # loop through each symbol in our structure for symbol in self.Data.keys(): symbolData = self.Data[symbol] for symbol in self.Data15.keys(): symbolData15 = self.Data15[symbol] # this check proves that this symbol was JUST updated prior to this OnData function being called if not self.Portfolio[symbol].Invested and symbolData15.MACD15.Current.Value > symbolData15.MACD15.Signal.Current.Value and symbolData.MACD.Current.Value > 0 : self.SetHoldings(symbol, self.PositionSize) if self.Portfolio[symbol].Invested and symbolData.MACD.Current.Value < 0 : self.Liquidate(symbol) """ if symbolData.IsReady() and symbolData.WasJustUpdated(self.Time): if not self.Portfolio[symbol].Invested: self.MarketOrder(symbol, 1)""" # End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets). # Method is called 10 minutes before closing to allow user to close out position. def OnEndOfDay(self): i = 0 for symbol in sorted(self.Data.keys()): symbolData = self.Data[symbol] # we have too many symbols to plot them all, so plot every other i += 1 if symbolData.IsReady() and i%2 == 0: self.Plot(symbol, symbol, symbolData.SMA.Current.Value) class SymbolData(object): def __init__(self, symbol, barPeriod, windowSize): self.Symbol = symbol # The period used when population the Bars rolling window self.BarPeriod = barPeriod # A rolling window of data, data needs to be pumped into Bars by using Bars.Update( tradeBar ) and can be accessed like: # mySymbolData.Bars[0] - most first recent piece of data # mySymbolData.Bars[5] - the sixth most recent piece of data (zero based indexing) self.Bars = RollingWindow[IBaseDataBar](windowSize) # The simple moving average indicator for our symbol self.SMA = None self.MACD = None # Returns true if all the data in this instance is ready (indicators, rolling windows, ect...) def IsReady(self): return self.Bars.IsReady and self.SMA.IsReady and self.MACD.IsReady # Returns true if the most recent trade bar time matches the current time minus the bar's period, this # indicates that update was just called on this instance def WasJustUpdated(self, current): return self.Bars.Count > 0 and self.Bars[0].Time == current - self.BarPeriod class SymbolData15(object): def __init__(self, symbol, barPeriod15, windowSize): self.Symbol = symbol # The period used when population the Bars rolling window self.BarPeriod15 = barPeriod15 # A rolling window of data, data needs to be pumped into Bars by using Bars.Update( tradeBar ) and can be accessed like: # mySymbolData.Bars[0] - most first recent piece of data # mySymbolData.Bars[5] - the sixth most recent piece of data (zero based indexing) self.Bars15 = RollingWindow[IBaseDataBar](windowSize) # The simple moving average indicator for our symbol self.SMA15 = None self.MACD15 = None # Returns true if all the data in this instance is ready (indicators, rolling windows, ect...) def IsReady(self): return self.Bars15.IsReady and self.SMA15.IsReady and self.MACD15.IsReady # Returns true if the most recent trade bar time matches the current time minus the bar's period, this # indicates that update was just called on this instance def WasJustUpdated(self, current): return self.Bars15.Count > 0 and self.Bars15[0].Time == current - self.BarPeriod15