Overall Statistics |
Total Trades 499 Average Win 1.32% Average Loss -0.57% Compounding Annual Return 34.229% Drawdown 19.500% Expectancy 0.364 Net Profit 58.484% Sharpe Ratio 1.358 Probabilistic Sharpe Ratio 60.313% Loss Rate 59% Win Rate 41% Profit-Loss Ratio 2.33 Alpha 0.304 Beta 0.006 Annual Standard Deviation 0.225 Annual Variance 0.05 Information Ratio 0.331 Tracking Error 0.335 Treynor Ratio 47.744 Total Fees $501.99 |
class EMVIndicatorAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 1, 1) self.SetEndDate(2020, 7, 24) self.SetCash(100000) self.tickers = ["SPY", "TSLA"] self.emv_by_symbol = {} for ticker in self.tickers: symbol = self.AddEquity(ticker, Resolution.Daily).Symbol self.emv_by_symbol[symbol] = EMV(symbol, self) self.portfolioPercentage = 1/len(self.tickers) self.lastday = None EMVPlot = Chart("EMV Plot") EMVPlot.AddSeries(Series("Buy", SeriesType.Scatter, 0)) EMVPlot.AddSeries(Series("Short", SeriesType.Scatter, 0)) EMVPlot.AddSeries(Series("Sell", SeriesType.Scatter, 0)) EMVPlot.AddSeries(Series("Price", SeriesType.Line, 0)) self.AddChart(EMVPlot) EMVValuePlot = Chart("EMV Value Plot") EMVValuePlot.AddSeries(Series("EMV", SeriesType.Line, 0)) self.AddChart(EMVValuePlot) def OnData(self, data): for symbol, emv in self.emv_by_symbol.items(): if not data.ContainsKey(symbol) or data[symbol] is None: continue close = data[symbol].Close invested = self.Portfolio[symbol].Invested if not emv.IsReady: return '''Enters a long or short position''' if emv.value > 0 and not invested: self.SetHoldings(symbol, self.portfolioPercentage) self.Plot("EMV Plot", "Buy", close) if emv.value < 0 and not invested: self.SetHoldings(symbol, -(self.portfolioPercentage)/20) #Allows 5% of portfolioPercentage to short self.Plot("EMV Plot", "Short", close) '''Liquidates a long or short position''' if emv.value < 0 and self.Portfolio[symbol].IsLong: self.Liquidate(symbol) self.Plot("EMV Plot", "Sell", close) if emv.value > 0 and self.Portfolio[symbol].IsShort: self.Liquidate(symbol) self.Plot("EMV Plot", "Sell", close) self.Plot("EMV Plot", "Price", close) self.Plot("EMV Value Plot", "EMV", emv.value) class EMV: def __init__(self, symbol, algorithm): self.symbol = symbol self.algorithm = algorithm self.value = None self.highs = RollingWindow[float](2) self.lows = RollingWindow[float](2) self.volume = None # Warm up indicator history = algorithm.History(symbol, 2, Resolution.Daily) for idx, row in history.iterrows(): self.highs.Add(row.high) self.lows.Add(row.low) self.volume = row.volume self.update_value() # Setup daily consolidator self.consolidator = TradeBarConsolidator(timedelta(hours=24)) self.consolidator.DataConsolidated += self.DailyHandler algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator) @property def IsReady(self): return self.highs.IsReady and \ self.lows.IsReady and \ self.volume is not None and \ self.value is not None def update_value(self): mov_mid_today = (self.highs[0] + self.lows[0]) / 2 mov_mid_yesterday = (self.highs[1] + self.lows[1]) / 2 MID = mov_mid_today - mov_mid_yesterday if self.volume/10000 == 0 or self.highs[0] - self.lows[0] == 0: self.value = None return ratio = (self.volume/10000) / (self.highs[0] - self.lows[0]) self.value = MID/ratio def DailyHandler(self, sender, consolidated): self.highs.Add(consolidated.High) self.lows.Add(consolidated.Low) self.volume = consolidated.Volume self.update_value()