| Overall Statistics |
|
Total Trades 35 Average Win 3.04% Average Loss -0.66% Compounding Annual Return 37.327% Drawdown 6.600% Expectancy 1.629 Net Profit 21.877% Sharpe Ratio 1.652 Probabilistic Sharpe Ratio 68.965% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 4.59 Alpha 0.253 Beta 0.058 Annual Standard Deviation 0.158 Annual Variance 0.025 Information Ratio 0.371 Tracking Error 0.358 Treynor Ratio 4.496 Total Fees $2510.41 |
'''
**
* Author: Joseph A Bastulli
* Created: 2.02.2020
*
* (c) Copyright Joseph A Bastulli
**
'''
import numpy as np
import pandas as pd
from collections import deque
class QuantumOptimizedPrism(QCAlgorithm):
def Initialize(self):
# Max window size
self.Lookback = 168 # 1 week in hours
# list of symbols we want to trade
self.symbolList = ["BTCUSD","ETHUSD","LTCUSD","BCHUSD"]
#self.symbolList = ["BTCUSD","ETHUSD","LTCUSD","BCHUSD","XRPUSD","XLMUSD","EOSUSD","REPUSD","XTZUSD","ETCUSD","ZRXUSD"]
# dictionary to store info per symbol
self.rollingWindow = {}
# init insights for plotting alpha
self.insightPeriod = Time.Multiply(Extensions.ToTimeSpan(Resolution.Hour), self.Lookback)
self.insightTemp = None
# create plot and consolidator for each symbol we want to trade
for name in self.symbolList:
cryptoSymbol = self.AddCrypto(name, Resolution.Minute, Market.GDAX).Symbol
self.Debug('{}'.format(cryptoSymbol))
fiveConsolidator = TradeBarConsolidator(timedelta(hours=1))
fiveConsolidator.DataConsolidated += self.FiveConsolidator
self.SubscriptionManager.AddConsolidator(cryptoSymbol, fiveConsolidator)
self.rollingWindow["close_{0}".format(cryptoSymbol)] = deque(maxlen=self.Lookback)
stockPlot = Chart(str(cryptoSymbol))
stockPlot.AddSeries(Series('Price', SeriesType.Line, 0))
stockPlot.AddSeries(Series('Top', SeriesType.Line, 0))
stockPlot.AddSeries(Series('Mid', SeriesType.Line, 0))
stockPlot.AddSeries(Series('Bot', SeriesType.Line, 0))
self.AddChart(stockPlot)
# max buy sell amount
self.weight = 1 / len(self.symbolList)
self.SetCash(100000)
self.SetStartDate(2020, 1, 1)
self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
self.SetWarmUp(self.Lookback)
def GetInsight(self, bar, price, top, mid, bot):
'''Updates this alpha model with the latest data from the consolidator'''
insights = []
if price > top:
direction = InsightDirection.Up
elif price < top and price > mid:
direction = InsightDirection.Flat
else:
direction = InsightDirection.Down
if self.insightTemp is not None and direction == self.insightTemp:
return insights
self.insightTemp = direction
insight = Insight.Price(bar.Symbol, self.insightPeriod, direction)
insights.append(insight)
return insights
def Indicator(self, symbol):
'''Rolling quantile for upper and lower bounds'''
data = np.array(self.rollingWindow["close_"+str(symbol)])
top = np.quantile(data,0.99, interpolation='higher')
bot = np.quantile(data,0.01, interpolation='higher')
mid = (top+bot)/2
return top, bot, mid
def FiveConsolidator(self, sender, bar):
stringSym = str(bar.Symbol)
sym_price = bar.Close
# Append price data
self.rollingWindow["close_{0}".format(bar.Symbol)].append(sym_price)
if not self.IsWarmingUp:
if len(self.rollingWindow["close_{0}".format(bar.Symbol)]) < self.Lookback:
return
# Get indicators
top, bot, mid = self.Indicator(bar.Symbol)
# buy
if sym_price > top and not self.Portfolio.Invested:
self.SetHoldings(bar.Symbol, self.weight)
# sell
elif sym_price < mid and self.Portfolio.Invested:
self.SetHoldings(bar.Symbol, 0)
else:
pass
# plot insights (not needed for trading). Disable for faster backtesting
self.EmitInsights(self.GetInsight(bar, sym_price, top, mid, bot))
# plot every interval defined plot!
if self.Time.hour % 24 == 0 and self.Time.minute == 0:
self.Plot(str(bar.Symbol), 'Price', sym_price)
self.Plot(str(bar.Symbol), 'Top', top)
self.Plot(str(bar.Symbol), 'Mid', mid)
self.Plot(str(bar.Symbol), 'Bot', bot)
def OnData(self, data):
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))