| Overall Statistics |
|
Total Orders 359 Average Win 5.15% Average Loss -0.80% Compounding Annual Return 53.984% Drawdown 34.800% Expectancy 2.183 Start Equity 100000.00 End Equity 868570.26 Net Profit 768.570% Sharpe Ratio 1.328 Sortino Ratio 1.454 Probabilistic Sharpe Ratio 66.661% Loss Rate 57% Win Rate 43% Profit-Loss Ratio 6.41 Alpha 0.233 Beta 0.178 Annual Standard Deviation 0.293 Annual Variance 0.086 Information Ratio -0.824 Tracking Error 0.598 Treynor Ratio 2.192 Total Fees $0.00 Estimated Strategy Capacity $870000.00 Lowest Capacity Asset BSVUSD E3 Portfolio Turnover 0.41% Drawdown Recovery 330 |
# region imports
from AlgorithmImports import *
# endregion
class CasualOrangeEagle(QCAlgorithm):
def initialize(self): #all crypto use UTC time zone
self.set_start_date(2015, 1, 1)
self.set_end_date(2020, 1, 1)
self.set_cash(100000)
self.AddRiskManagement(TrailingStopRiskManagementModel(0.40))
self.Settings.FreePortfolioValuePercentage = 0.025
self.positionSizeUSD = 10000
self.rsiEntryThreshold = 60
self.rsiExitThreshold = 40
self.minimumVolume = 1000000
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 = []
for ticker in universe:
try:
self.pairs.append(self.Pair(self, ticker, self.minimumVolume))
except Exception as e:
self.Debug(f"Skipping {ticker}: {e}")
self.SetBenchmark("BTCUSD")
self.SetWarmup(30)
def on_data(self, data: Slice):
for pair in self.pairs:
if not pair.rsi.IsReady:
return
symbol = pair.symbol
rsi = pair.rsi.Current.Value
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
if rsi > self.rsiEntryThreshold and self.Portfolio.MarginRemaining > self.positionSizeUSD:
self.Buy(symbol, self.positionSizeUSD / self.Securities[symbol].Price)
if rsi < self.rsiExitThreshold:
self.liquidate(symbol, "RSI Below Threshold")
elif rsi < self.rsiExitThreshold and self.Portfolio.MarginRemaining > self.positionSizeUSD:
self.Sell(symbol, self.positionSizeUSD / self.Securities[symbol].Price)
if rsi > self.rsiEntryThreshold:
self.liquidate(symbol, "RSI Below Threshold")
class Pair:
def __init__(self, algorithm, ticker, minimumVolume):
self.symbol = algorithm.AddCrypto(ticker, Resolution.DAILY, Market.BITFINEX).Symbol
self.rsi = algorithm.RSI(self.symbol, 7, MovingAverageType.SIMPLE, Resolution.DAILY)
self.volume = IndicatorExtensions.times(algorithm.SMA(self.symbol, 50, Resolution.DAILY, Field.VOLUME), algorithm.SMA(self.symbol, 50, Resolution.DAILY, Field.CLOSE))
self.minimumVolume = minimumVolume
def Investable(self):
return (self.volume.Current.Value > self.minimumVolume)