| 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)
'''