Overall Statistics |
Total Trades 1593 Average Win 0.17% Average Loss -0.09% Compounding Annual Return 239.800% Drawdown 31.400% Expectancy 0.976 Net Profit 113.892% Sharpe Ratio 3.314 Probabilistic Sharpe Ratio 83.051% Loss Rate 34% Win Rate 66% Profit-Loss Ratio 1.98 Alpha 1.023 Beta 0.536 Annual Standard Deviation 0.486 Annual Variance 0.236 Information Ratio 1.123 Tracking Error 0.458 Treynor Ratio 3.004 Total Fees $729.34 |
import numpy as np import pandas as pd from collections import deque class QuantumOptimizedPrism(QCAlgorithm): def Initialize(self): '''Look back for breakout''' self.Lookback = 175 self.SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Cash) self.SetCash(10000) self.symbolList = ["BTCUSD","ETHUSD","LTCUSD"] 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] = 1 / len(self.symbolList) self.flashcheck[name] = 0 self.SetStartDate(2020, 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.Debug("{} - 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): '''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: 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): self.Debug("{} {}".format(self.Time, orderEvent.ToString())) def OnEndOfAlgorithm(self): self.Log("{} - TotalPortfolioValue: {}".format(self.Time, self.Portfolio.TotalPortfolioValue)) self.Log("{} - CashBook: {}".format(self.Time, self.Portfolio.CashBook))