Overall Statistics |
Total Trades 3219 Average Win 0.07% Average Loss -0.11% Compounding Annual Return -25.639% Drawdown 56.700% Expectancy -0.215 Net Profit -25.759% Sharpe Ratio -0.385 Probabilistic Sharpe Ratio 6.629% Loss Rate 51% Win Rate 49% Profit-Loss Ratio 0.60 Alpha 0.08 Beta -1.111 Annual Standard Deviation 0.398 Annual Variance 0.158 Information Ratio -0.538 Tracking Error 0.675 Treynor Ratio 0.138 Total Fees $3408.03 |
# https://quantpedia.com/Screener/Details/25 from System.Drawing import Color from Alphas.EmaCrossAlphaModel import EmaCrossAlphaModel class SmallCapInvestmentAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 8) self.SetEndDate(2021, 1, 10) self.SetCash(100000) self.lastMonth = -1 self.emaLongestWindow = 200 self.UniverseSettings.MinimumTimeInUniverse = self.emaLongestWindow self.SetWarmUp(self.emaLongestWindow) self.coarseCount = 100 self.fineCount = 10 self.indicators = {} self.UniverseSettings.Resolution = Resolution.Hour self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) stockPlot = Chart("Trade Plot") stockPlot.AddSeries(Series('Price', SeriesType.Line, '$', Color.Blue)) stockPlot.AddSeries(Series(" 200EMAIndicator", SeriesType.Line, '$', Color.Yellow)) stockPlot = Chart("Diamonds") stockPlot.AddSeries(Series('coarseSelect', SeriesType.Scatter, '$', Color.Gold, ScatterMarkerSymbol.Diamond)) stockPlot.AddSeries(Series('fineSelect', SeriesType.Scatter, '$', Color.Purple, ScatterMarkerSymbol.Diamond)) stockPlot.AddSeries(Series('Above220EMA', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Diamond)) self.AddChart(stockPlot) coarseSelectAction = 0 self.Plot("Diamonds", "coarseSelect", coarseSelectAction) fineSelectAction = 0 self.Plot("Diamonds", "fineSelect", fineSelectAction) def CoarseSelectionFunction(self, coarse): ''' Drop stocks which have no fundamental data or have low price ''' if self.lastMonth == self.Time.month: return Universe.Unchanged self.lastMonth = self.Time.month sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) self.symbols = [ x.Symbol for x in sortedByDollarVolume[:self.coarseCount] ] coarseSelectAction = 45 self.Plot("Diamonds", "coarseSelect", coarseSelectAction) return self.symbols def FineSelectionFunction(self, fine): ''' Selects the stocks by lowest market cap ''' sortedByPeRatio = sorted(fine, key=lambda x: x.ValuationRatios.PERatio, reverse=True) self.symbols = [ x.Symbol for x in sortedByPeRatio[:self.fineCount] ] fineSelectAction = 50 self.Plot("Diamonds", "fineSelect", fineSelectAction) #return [x.Symbol for x in sorted_market_cap[:self.count]] return self.symbols def OnData(self, data): for symbol in self.symbols: if not data.ContainsKey(symbol): continue if data[symbol] is None: continue if symbol not in self.indicators: self.indicators[symbol] = SymbolData(symbol, self, self.emaLongestWindow) # update by bar #self.indicators[symbol].update_bar(data[symbol]) #update by value self.indicators[symbol].update_value(self.Time, data[symbol].Price) if self.IsWarmingUp: continue self.Log(str(symbol) + " : " + str(self.indicators[symbol].get_longestEMA())) sym_price = data[symbol].Price #self.EMAreq = self.EMA(symbol, 220, Resolution.Hour); #self.PlotIndicator('Trade Plot', self.EMAreq); self.Plot('Trade Plot',symbol.Value + " " + 'Price', data.Bars[symbol].Close) longestEMA = self.indicators[symbol].get_longestEMA() self.Plot("Trade Plot", (symbol.Value + " " + "200EMAIndicator"), self.indicators[symbol].get_longestEMA()); if longestEMA != 0.0: if longestEMA > sym_price: self.SetHoldings(symbol, -0.1) emaclear = 0 self.Plot("Diamonds", "Above220EMA", emaclear) else: self.Liquidate(symbol) def OnSecuritiesChanged(self, changes): for security in changes.RemovedSecurities: symbol = security.Symbol if self.Portfolio[symbol].Invested: self.Liquidate(symbol, 'Removed from Universe') # clean up del self.indicators[security.Symbol] class SymbolData(object): def __init__(self, symbol, context, window): self.symbol = symbol self.window = window self.indicator = context.EMA(symbol, self.window) self.longestEMA = 0.0 def update_bar(self, bar): self.indicator.Update(bar) def update_value(self, time, value): self.indicator.Update(time, value) def get_longestEMA(self): return self.indicator.Current.Value