Overall Statistics |
Total Trades 3 Average Win 0% Average Loss -0.37% Compounding Annual Return 18.556% Drawdown 69.800% Expectancy -1 Net Profit 134.327% Sharpe Ratio 0.524 Probabilistic Sharpe Ratio 5.107% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.315 Beta -0.166 Annual Standard Deviation 0.558 Annual Variance 0.311 Information Ratio 0.264 Tracking Error 0.587 Treynor Ratio -1.761 Total Fees $11.81 Estimated Strategy Capacity $2600000.00 Lowest Capacity Asset GME SC72NCBXXAHX |
# 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 * from System.Collections.Generic import List ### <summary> ### In this algorithm we demonstrate how to perform some technical analysis as ### part of your coarse fundamental universe selection ### </summary> ### <meta name="tag" content="using data" /> ### <meta name="tag" content="indicators" /> ### <meta name="tag" content="universes" /> ### <meta name="tag" content="coarse universes" /> class EmaCrossUniverseSelectionAlgorithm(QCAlgorithm): 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.SetStartDate(2017,1,1) #Set Start Date self.SetEndDate(2022,1,1) #Set End Date self.SetCash(100000) #Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Daily self.UniverseSettings.Leverage = 2 self.coarse_count = 1 self.averages = { } #reshuffle monthly self.month = -1 # this add universe method accepts two parameters: # - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol> self.AddUniverse(self.CoarseSelectionFunction) def OnData(self,slice): self.Debug('On data called') # sort the data by daily dollar volume and take the top 'NumberOfSymbols' def CoarseSelectionFunction(self, coarse): self.Debug('universe selection called') sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) filtered = [ x for x in sortedByDollarVolume if x.Symbol.Value=='GME' ] #x.DollarVolume > 10000000 # We are going to use a dictionary to refer the object that will keep the moving averages for cf in filtered: if cf.Symbol not in self.averages: self.averages[cf.Symbol] = SymbolData(cf.Symbol) # Updates the SymbolData object with current EOD price avg = self.averages[cf.Symbol] avg.update(cf.EndTime, cf.AdjustedPrice) #we want to update all EMA, but dont want to trade till month changes if self.month == self.Time.month: return Universe.Unchanged else: self.month = self.Time.month # liquidate and rerank everything to see # if each month actual orders are being placed # self.Liquidate() # Filter the values of the dict: we only want up-trending securities from ones which has indicator values values = list(filter(lambda x: x.is_uptrend, self.averages.values())) # Sorts the values of the dict: we want those with greater difference between the moving averages values.sort(key=lambda x: x.scale, reverse=True) for x in values[:self.coarse_count]: self.Debug(str(self.Time) + 'price: ' + str(filtered[0].AdjustedPrice)+ ' 52w High: ' + str(x.fiftyTwoHigh.Current.Value) + ' Down from 52w High: ' + str(x.downFromHigh) +' period since 52w Low: ' + str(x.fiftyTwoLow.PeriodsSinceMinimum)+' 52w Low: ' + str(x.fiftyTwoLow.Current.Value)+' Up from 52w Low: ' + str(x.upFromLow)) # ensure the universe selection only run once in every month # we need to return only the symbol objects return [ x.symbol for x in values[:self.coarse_count] ] # this event fires whenever we have changes to our universe def OnSecuritiesChanged(self, changes): self.Debug('On security changed called') # liquidate removed securities for security in changes.RemovedSecurities: if security.Invested: self.Liquidate(security.Symbol) # we want 20% allocation in each security in our universe for security in changes.AddedSecurities: self.SetHoldings(security.Symbol, 0.1) class SymbolData(object): def __init__(self, symbol): self.symbol = symbol self.tolerance = 1.01 self.fast = ExponentialMovingAverage(50) self.slow = ExponentialMovingAverage(200) self.fiftyTwoHigh = Maximum(253) self.fiftyTwoLow = Minimum(253) self.downFromHigh=1 self.upFromLow=0 self.is_uptrend = False self.scale = 0 def update(self, time, value): #Updates the state of this indicator with the given value and returns true #if this indicator is ready, false otherwise self.fiftyTwoHigh.Update(time, value) self.fiftyTwoLow.Update(time, value) if self.fiftyTwoHigh.Update(time, value) and self.fiftyTwoLow.Update(time, value) and self.fast.Update(time, value) and self.slow.Update(time, value): fast = self.fast.Current.Value slow = self.slow.Current.Value self.downFromHigh=1-(value/self.fiftyTwoHigh.Current.Value) self.upFromLow=(value/self.fiftyTwoLow.Current.Value)-1 self.is_uptrend = fast > slow * self.tolerance if self.is_uptrend: self.scale = (fast - slow) / ((fast + slow) / 2.0)
# 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 * from System.Collections.Generic import List ### <summary> ### In this algorithm we demonstrate how to perform some technical analysis as ### part of your coarse fundamental universe selection ### </summary> ### <meta name="tag" content="using data" /> ### <meta name="tag" content="indicators" /> ### <meta name="tag" content="universes" /> ### <meta name="tag" content="coarse universes" /> class EmaCrossUniverseSelectionAlgorithm(QCAlgorithm): 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.SetStartDate(2015,1,1) #Set Start Date self.SetEndDate(2019,1,1) #Set End Date self.SetCash(100000) #Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Daily self.UniverseSettings.Leverage = 2 self.coarse_count = 10 self.averages = { } # this add universe method accepts two parameters: # - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol> self.AddUniverse(self.CoarseSelectionFunction) # sort the data by daily dollar volume and take the top 'NumberOfSymbols' def CoarseSelectionFunction(self, coarse): # We are going to use a dictionary to refer the object that will keep the moving averages for cf in coarse: if cf.Symbol not in self.averages: self.averages[cf.Symbol] = SymbolData(cf.Symbol) # Updates the SymbolData object with current EOD price avg = self.averages[cf.Symbol] avg.update(cf.EndTime, cf.AdjustedPrice) # Filter the values of the dict: we only want up-trending securities values = list(filter(lambda x: x.is_uptrend, self.averages.values())) # Sorts the values of the dict: we want those with greater difference between the moving averages values.sort(key=lambda x: x.scale, reverse=True) for x in values[:self.coarse_count]: self.Log('symbol: ' + str(x.symbol.Value) + ' scale: ' + str(x.scale)) # we need to return only the symbol objects return [ x.symbol for x in values[:self.coarse_count] ] # this event fires whenever we have changes to our universe def OnSecuritiesChanged(self, changes): # liquidate removed securities for security in changes.RemovedSecurities: if security.Invested: self.Liquidate(security.Symbol) # we want 20% allocation in each security in our universe for security in changes.AddedSecurities: self.SetHoldings(security.Symbol, 0.1) class SymbolData(object): def __init__(self, symbol): self.symbol = symbol self.tolerance = 1.01 self.fast = ExponentialMovingAverage(50) self.slow = ExponentialMovingAverage(200) self.is_uptrend = False self.scale = 0 def update(self, time, value): if self.fast.Update(time, value) and self.slow.Update(time, value): fast = self.fast.Current.Value slow = self.slow.Current.Value self.is_uptrend = fast > slow * self.tolerance if self.is_uptrend: self.scale = (fast - slow) / ((fast + slow) / 2.0)