Overall Statistics |
Total Orders 292 Average Win 1.47% Average Loss -0.50% Compounding Annual Return 7.666% Drawdown 27.200% Expectancy 0.523 Start Equity 100000.00 End Equity 146852.54 Net Profit 46.853% Sharpe Ratio 0.282 Sortino Ratio 0.256 Probabilistic Sharpe Ratio 6.050% Loss Rate 61% Win Rate 39% Profit-Loss Ratio 2.92 Alpha -0.034 Beta 0.109 Annual Standard Deviation 0.149 Annual Variance 0.022 Information Ratio -1.267 Tracking Error 0.516 Treynor Ratio 0.384 Total Fees $0.00 Estimated Strategy Capacity $2600000.00 Lowest Capacity Asset XRPUSD E3 Portfolio Turnover 0.42% |
#region imports from AlgorithmImports import * #endregion class CreativeRedHornet(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 1, 1) # self.SetEndDate(2021, 1, 1) self.SetCash(100000) self.Settings.FreePortfolioValuePercentage = 0.05 self.positionSizeUSD = 3500 self.rsiEntryThreshold = 75 # enter position if rsi rises above this threshold self.rsiExitThreshold = 30 # exit position if rsi drops below this threshold self.minimumVolume = 1000000 # filters out symbols with 30 day avg daily dollar volume less than this # add data for all tickers universe = ['BTCUSD', 'LTCUSD', 'ETHUSD', 'ETCUSD', 'RRTUSD', 'ZECUSD', 'XMRUSD', 'XRPUSD', 'EOSUSD', 'SANUSD', 'OMGUSD', 'NEOUSD', 'ETPUSD', 'BTGUSD', 'SNTUSD', 'BATUSD', 'FUNUSD', 'ZRXUSD', 'TRXUSD', 'REQUSD', 'LRCUSD', 'WAXUSD', 'DAIUSD', 'BFTUSD', 'ODEUSD', 'ANTUSD', 'XLMUSD', 'XVGUSD', 'MKRUSD', 'KNCUSD', 'LYMUSD', 'UTKUSD', 'VEEUSD', 'ESSUSD', 'IQXUSD', 'ZILUSD', 'BNTUSD', 'XRAUSD', 'VETUSD', 'GOTUSD', 'XTZUSD', 'MLNUSD', 'PNKUSD', 'DGBUSD', 'BSVUSD', 'ENJUSD', 'PAXUSD'] self.pairs = [ Pair(self, ticker, self.minimumVolume) for ticker in universe ] self.SetBenchmark("BTCUSD") self.SetWarmup(30) def OnData(self, data): for pair in self.pairs: if not pair.rsi.IsReady: return symbol = pair.symbol rsi = pair.rsi.Current.Value # Selling if self.Portfolio[symbol].Invested: if not pair.Investable(): self.Liquidate(symbol, "Not enough volume") elif rsi < self.rsiExitThreshold: self.Liquidate(symbol, "RSI below threshold") continue if not pair.Investable(): continue # Buying if rsi > self.rsiEntryThreshold and self.Portfolio.MarginRemaining > self.positionSizeUSD: self.Buy(symbol, self.positionSizeUSD / self.Securities[symbol].Price) class Pair: def __init__(self, algorithm, ticker, minimumVolume): self.symbol = algorithm.AddCrypto(ticker, Resolution.Daily, Market.Bitfinex).Symbol self.rsi = algorithm.RSI(self.symbol, 14, MovingAverageType.Simple, Resolution.Daily) self.volume = IndicatorExtensions.Times(algorithm.SMA(self.symbol, 30, Resolution.Daily, Field.Volume), algorithm.SMA(self.symbol, 30, Resolution.Daily, Field.Close)) self.minimumVolume = minimumVolume def Investable(self): return (self.volume.Current.Value > self.minimumVolume)