Overall Statistics |
Total Trades 6605 Average Win 0.32% Average Loss -0.50% Compounding Annual Return 124.196% Drawdown 34.600% Expectancy 0.245 Net Profit 1461.773% Sharpe Ratio 2.066 Probabilistic Sharpe Ratio 84.915% Loss Rate 24% Win Rate 76% Profit-Loss Ratio 0.63 Alpha 0.741 Beta 0.401 Annual Standard Deviation 0.458 Annual Variance 0.209 Information Ratio 0.811 Tracking Error 0.537 Treynor Ratio 2.358 Total Fees $38883.53 Estimated Strategy Capacity $33000.00 Lowest Capacity Asset DASHBTC XJ |
import numpy as np import pandas as pd from collections import deque class QuantumOptimizedPrism(QCAlgorithm): def Initialize(self): '''Look back for breakout''' self.Lookback = 168 self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash) self.SetCash(15000) self.symbolList = ["BTCUSD", "ETHUSD", "BCHUSD", "LINKETH", "ETHBTC", "BCHBTC", "ATOMBTC", "DASHBTC", "UNIUSD", "XLMBTC", "MKRBTC", "LINKUSD", "ATOMUSD"] self.rollingWindow = {} self.weights = {} self.flashcheck = {} for name in self.symbolList: self.AddCrypto(name, Resolution.Hour, Market.GDAX) self.rollingWindow["close_top_{0}".format(name)] = deque(maxlen=self.Lookback) self.weights[name] = 0.25 self.flashcheck[name] = 0 self.SetStartDate(2018, 1, 1) self.SetBenchmark("BTCUSD") self.SetWarmUp(self.Lookback) def flashcrashcheck(self, symbol, price): '''Check for significant price change''' pchange = (price - self.flashcheck[symbol]) / ((price + self.flashcheck[symbol])/2) * 100 self.flashcheck[symbol] = price if pchange >= 10: flash = True #self.Log("{} - FlashCrash: {}".format(self.Time, pchange)) else: flash = False return flash def indicator(self, sym): '''Rolling quantile for upper and lower bounds''' top = pd.Series(self.rollingWindow["close_top_"+str(sym)]).quantile(0.99) bot = pd.Series(self.rollingWindow["close_top_"+str(sym)]).quantile(0.01) return top, bot def OnData(self, data): if self.IsWarmingUp: return #if not self.rollingWindow.empty '''The data is bugged on this day for BTC''' if self.Time.day == 10 and self.Time.month == 8 and self.Time.year == 2018: return for symbol in self.symbolList: if not data.ContainsKey(symbol): return sym_price = data[symbol].Price stop = self.flashcrashcheck(symbol, sym_price) self.rollingWindow["close_top_{0}".format(symbol)].appendleft(sym_price) if not self.IsWarmingUp and not stop: top, bot = self.indicator(symbol) if sym_price >= top: self.SetHoldings(symbol, self.weights[symbol]) elif sym_price <= bot: self.SetHoldings(symbol, 0) else: pass def OnOrderEvent(self, orderEvent): '''order = self.Transactions.GetOrderById(orderEvent.OrderId) for symbol in self.symbolList: if orderEvent.Status == OrderStatus.Invalid: self.SetHoldings(symbol, 0.01*0.1) '''