When adding Bitfnex as my market I seemed to have trouble. I am manually adding from a dictionary created with the crypto listed on the documentation page.
for i in range(len(self.symbols)):
crypto = self.AddCrypto(self.symbols[i],Resolution.Minute, Market.Bitfinex).Symbol
self.symbols[i] = crypto
self.symbols[i].prices = []
self.symbols[i].dates = []
I am attempting to use the equity strategy for crypto currency:
https://www.quantconnect.com/tutorials/strategy-library/intraday-dynamic-pairs-trading-using-correlation-and-cointegration-approach
Derek Melchin
Hi OkiTrader,
We were unable to reproduce the issue. Please attach a sample backtest/code that reproduces the issue.
Best,
Derek Melchin
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
OkiTrader
Thanks for getting back. I am simply trying to create a crypto universe. I copied the copied the documentation.
import numpy as np import pandas as pd import datetime as datetime import statsmodels.formula.api as sm from pandas.core import datetools import statsmodels.tsa.stattools as ts from pair import * class PairsTrading(QCAlgorithm): def __init__(self): self.symbols = ['BTCUSD', 'LTCUSD', 'LTCBTC', 'ETHUSD', 'ETHBTC', 'ETCBTC', 'ETCUSD', 'RRTUSD', 'RRTBTC', 'ZECUSD', 'ZECBTC', 'XMRUSD', 'XMRBTC', 'DSHUSD', 'DSHBTC', 'BTCEUR', 'BTCJPY', 'XRPUSD', 'XRPBTC', 'IOTUSD', 'IOTBTC', 'IOTETH', 'EOSUSD', 'EOSBTC', 'EOSETH', 'SANUSD', 'SANBTC', 'SANETH', 'OMGUSD', 'OMGBTC', 'OMGETH', 'BCHUSD', 'BCHBTC', 'BCHETH', 'NEOUSD', 'NEOBTC', 'NEOETH', 'ETPUSD', 'ETPBTC', 'ETPETH', 'QTMUSD', 'QTMBTC', 'QTMETH', 'AVTUSD', 'AVTBTC', 'AVTETH', 'EDOUSD', 'EDOBTC', 'EDOETH', 'BTGUSD', 'BTGBTC', 'DATUSD', 'DATBTC', 'DATETH', 'QSHUSD', 'QSHBTC', 'QSHETH', 'YYWUSD', 'YYWBTC', 'YYWETH', 'GNTUSD', 'GNTBTC', 'GNTETH', 'SNTUSD', 'SNTBTC', 'SNTETH', 'IOTEUR', 'BATUSD', 'BATBTC', 'BATETH', 'MNAUSD', 'MNABTC', 'MNAETH', 'FUNUSD', 'FUNBTC', 'FUNETH', 'ZRXUSD', 'ZRXBTC', 'ZRXETH', 'TNBUSD', 'TNBBTC', 'TNBETH', 'SPKUSD', 'SPKBTC', 'SPKETH', 'TRXUSD', 'TRXBTC', 'TRXETH', 'RCNUSD', 'RCNBTC', 'RCNETH', 'RLCUSD', 'RLCBTC', 'RLCETH', 'AIDUSD', 'AIDBTC', 'AIDETH', 'SNGUSD', 'SNGBTC', 'SNGETH', 'REPUSD', 'REPBTC', 'REPETH', 'ELFUSD', 'ELFBTC', 'ELFETH', 'BTCGBP', 'ETHEUR', 'ETHJPY', 'ETHGBP', 'NEOEUR', 'NEOJPY', 'NEOGBP', 'EOSEUR', 'EOSJPY', 'EOSGBP', 'IOTJPY', 'IOTGBP', 'IOSUSD', 'IOSBTC', 'IOSETH', 'AIOUSD', 'AIOBTC', 'AIOETH', 'REQUSD', 'REQBTC', 'REQETH', 'RDNUSD', 'RDNBTC', 'RDNETH', 'LRCUSD', 'LRCBTC', 'LRCETH', 'WAXUSD', 'WAXBTC', 'WAXETH', 'DAIUSD', 'DAIBTC', 'DAIETH', 'CFIUSD', 'CFIBTC', 'CFIETH', 'AGIUSD', 'AGIBTC', 'AGIETH', 'BFTUSD', 'BFTBTC', 'BFTETH', 'MTNUSD', 'MTNBTC', 'MTNETH', 'ODEUSD', 'ODEBTC', 'ODEETH', 'ANTUSD', 'ANTBTC', 'ANTETH', 'DTHUSD', 'DTHBTC', 'DTHETH', 'MITUSD', 'MITBTC', 'MITETH', 'STJUSD', 'STJBTC', 'STJETH', 'XLMUSD', 'XLMEUR', 'XLMJPY', 'XLMGBP', 'XLMBTC', 'XLMETH', 'XVGUSD', 'XVGEUR', 'XVGJPY', 'XVGGBP', 'XVGBTC', 'XVGETH', 'BCIUSD', 'BCIBTC', 'MKRUSD', 'MKRBTC', 'MKRETH', 'VENUSD', 'VENBTC', 'VENETH', 'KNCUSD', 'KNCBTC', 'KNCETH', 'POAUSD', 'POABTC', 'POAETH', 'LYMUSD', 'LYMBTC', 'LYMETH', 'UTKUSD', 'UTKBTC', 'UTKETH', 'VEEUSD', 'VEEBTC', 'VEEETH', 'DADUSD', 'DADBTC', 'DADETH', 'ORSUSD', 'ORSBTC', 'ORSETH', 'AUCUSD', 'AUCBTC', 'AUCETH', 'POYUSD', 'POYBTC', 'POYETH', 'FSNUSD', 'FSNBTC', 'FSNETH', 'CBTUSD', 'CBTBTC', 'CBTETH', 'ZCNUSD', 'ZCNBTC', 'ZCNETH', 'SENUSD', 'SENBTC', 'SENETH', 'NCAUSD', 'NCABTC', 'NCAETH', 'CNDUSD', 'CNDBTC', 'CNDETH', 'CTXUSD', 'CTXBTC', 'CTXETH', 'PAIUSD', 'PAIBTC', 'SEEUSD', 'SEEBTC', 'SEEETH', 'ESSUSD', 'ESSBTC', 'ESSETH', 'ATMUSD', 'ATMBTC', 'ATMETH', 'HOTUSD', 'HOTBTC', 'HOTETH', 'DTAUSD', 'DTABTC', 'DTAETH', 'IQXUSD', 'IQXBTC', 'IQXEOS', 'WPRUSD', 'WPRBTC', 'WPRETH', 'ZILUSD', 'ZILBTC', 'ZILETH', 'BNTUSD', 'BNTBTC', 'BNTETH', 'ABSUSD', 'ABSETH', 'XRAUSD', 'XRAETH', 'MANUSD', 'MANETH', 'BBNUSD', 'BBNETH', 'NIOUSD', 'NIOETH', 'DGXUSD', 'DGXETH', 'VETUSD', 'VETBTC', 'VETETH', 'UTNUSD', 'UTNETH', 'TKNUSD', 'TKNETH', 'GOTUSD', 'GOTEUR', 'GOTETH', 'XTZUSD', 'XTZBTC', 'CNNUSD', 'CNNETH', 'BOXUSD', 'BOXETH', 'TRXEUR', 'TRXGBP', 'TRXJPY', 'MGOUSD', 'MGOETH', 'RTEUSD', 'RTEETH', 'YGGUSD', 'YGGETH', 'MLNUSD', 'MLNETH', 'WTCUSD', 'WTCETH', 'CSXUSD', 'CSXETH', 'OMNUSD', 'OMNBTC', 'INTUSD', 'INTETH', 'DRNUSD', 'DRNETH', 'PNKUSD', 'PNKETH', 'DGBUSD', 'DGBBTC', 'BSVUSD', 'BSVBTC', 'BABUSD', 'BABBTC', 'WLOUSD', 'WLOXLM', 'VLDUSD', 'VLDETH', 'ENJUSD', 'ENJETH', 'ONLUSD', 'ONLETH', 'RBTUSD', 'RBTBTC', 'USTUSD', 'EUTEUR', 'EUTUSD', 'GSDUSD', 'UDCUSD', 'TSDUSD', 'PAXUSD', 'RIFUSD', 'RIFBTC', 'PASUSD', 'PASETH', 'VSYUSD', 'VSYBTC', 'ZRXDAI', 'MKRDAI', 'OMGDAI'] self.data_resolution = 10 self.num_bar = 6.5*60*60/(self.data_resolution) self.one_month = 6.5*20*60/(self.data_resolution) self.selected_num = 10 self.pair_num = 120 self.pair_threshod = 0.88 self.BIC = -3.34 self.count = 0 self.pair_list = [] self.selected_pair = [] self.trading_pairs = [] self.generate_count = 0 self.open_size = 2.32 self.close_size = 0.5 self.stop_loss = 6 self.data_count = 0 def Initialize(self): self.SetStartDate(2016,1,1) self.SetEndDate(2018,5,1) self.SetCash(50000) for i in range(len(self.symbols)): crypto = self.AddCrypto(self.symbols[i],Resolution.Minute, Market.Bitfinex).Symbol self.symbols[i] = crypto self.symbols[i].prices = [] self.symbols[i].dates = [] def generate_pairs(self): for i in range(len(self.symbols)): for j in range(i+1,len(self.symbols)): self.pair_list.append(pairs(self.symbols[i],self.symbols[j])) self.pair_list = [x for x in self.pair_list if x.cor > self.pair_threshod] self.pair_list.sort(key = lambda x: x.cor, reverse = True) if len(self.pair_list) > self.pair_num: self.pair_list = self.pair_list[:self.pair_num] def pair_clean(self,list): l = [] l.append(list[0]) for i in list: symbols = [x.a for x in l] + [x.b for x in l] if i.a not in symbols and i.b not in symbols: l.append(i) else: pass return l def OnData(self,data): if not self.Securities[self.symbols[0]].Exchange.ExchangeOpen: return #data aggregation if self.data_count < self.data_resolution: self.data_count +=1 return # refill the initial df if len(self.symbols[0].prices) < self.num_bar: for i in self.symbols: if data.ContainsKey(i) is True: i.prices.append(float(data[i].Close)) i.dates.append(data[i].EndTime) else: self.Log('%s is missing'%str(i)) self.symbols.remove(i) self.data_count = 0 return # generate paris if self.count == 0 and len(self.symbols[0].prices) == self.num_bar: if self.generate_count == 0: for i in self.symbols: i.df = pd.DataFrame(i.prices, index = i.dates, columns = ['%s'%str(i)]) self.generate_pairs() self.generate_count +=1 self.Log('pair list length:'+str(len(self.pair_list))) # correlation selection for i in self.pair_list: i.cor_update() # updatet the dataframe and correlation selection if len(self.pair_list[0].a_price) != 0: for i in self.pair_list: i.df_update() i.cor_update() self.selected_pair = [x for x in self.pair_list if x.cor > 0.9] # cointegration selection for i in self.selected_pair: i.cointegration_test() self.selected_pair = [x for x in self.selected_pair if x.adf < self.BIC] self.selected_pair.sort(key = lambda x: x.adf) if len(self.selected_pair) == 0: self.Log('no selected pair') self.count += 1 return self.selected_pair = self.pair_clean(self.selected_pair) for i in self.selected_pair: i.touch = 0 self.Log(str(i.adf) + i.name) if len(self.selected_pair) > self.selected_num: self.selected_pair = self.selected_pair[:self.selected_num] self.count +=1 self.data_count = 0 return #update the pairs if self.count != 0 and self.count < self.one_month: num_select = len(self.selected_pair) for i in self.pair_list: if data.ContainsKey(i.a) is True and data.ContainsKey(i.b) is True: i.price_record(data[i.a],data[i.b]) else: self.Log('%s has no data'%str(i.name)) self.pair_list.remove(i) ## selected pairs for i in self.selected_pair: i.last_error = i.error for i in self.trading_pairs: i.last_error = i.error ## enter for i in self.selected_pair: price_a = float(data[i.a].Close) price_b = float(data[i.b].Close) i.error = price_a - (i.model.params[0] + i.model.params[1]*price_b) if (self.Portfolio[i.a].Quantity == 0 and self.Portfolio[i.b].Quantity == 0) and i not in self.trading_pairs: if i.touch == 0: if i.error < i.mean_error - self.open_size*i.sd and i.last_error > i.mean_error - self.open_size*i.sd: i.touch += -1 elif i.error > i.mean_error + self.open_size*i.sd and i.last_error < i.mean_error + self.open_size*i.sd: i.touch += 1 else: pass elif i.touch == -1: if i.error > i.mean_error - self.open_size*i.sd and i.last_error < i.mean_error - self.open_size*i.sd: self.Log('long %s and short %s'%(str(i.a),str(i.b))) i.record_model = i.model i.record_mean_error = i.mean_error i.record_sd = i.sd self.trading_pairs.append(i) self.SetHoldings(i.a, 5.0/(len(self.selected_pair))) self.SetHoldings(i.b, -5.0/(len(self.selected_pair))) i.touch = 0 elif i.touch == 1: if i.error < i.mean_error + self.open_size*i.sd and i.last_error > i.mean_error + self.open_size*i.sd: self.Log('long %s and short %s'%(str(i.b),str(i.a))) i.record_model = i.model i.record_mean_error = i.mean_error i.record_sd = i.sd self.trading_pairs.append(i) self.SetHoldings(i.b, 5.0/(len(self.selected_pair))) self.SetHoldings(i.a, -5.0/(len(self.selected_pair))) i.touch = 0 else: pass else: pass # close for i in self.trading_pairs: if data.ContainsKey(i.a) and data.ContainsKey(i.b): price_a = float(data[i.a].Close) price_b = float(data[i.b].Close) i.error = price_a - (i.record_model.params[0] + i.record_model.params[1]*price_b) if ((i.error < i.record_mean_error + self.close_size*i.record_sd and i.last_error >i.record_mean_error + self.close_size*i.record_sd) or (i.error > i.record_mean_error - self.close_size*i.record_sd and i.last_error <i.record_mean_error - self.close_size*i.record_sd)): self.Log('close %s'%str(i.name)) self.Liquidate(i.a) self.Liquidate(i.b) self.trading_pairs.remove(i) elif i.error < i.record_mean_error - self.stop_loss*i.record_sd or i.error > i.record_mean_error + self.stop_loss*i.record_sd: self.Log('close %s to stop loss'%str(i.name)) self.Liquidate(i.a) self.Liquidate(i.b) self.trading_pairs.remove(i) else: pass self.count +=1 self.data_count = 0 return if self.count == self.one_month: self.count = 0 self.data_count = 0 return # new module import numpy as np import pandas as pd import datetime as datetime import statsmodels.formula.api as sm import statsmodels.tsa.stattools as ts class pairs(object): def __init__(self,a,b): self.a = a self.b = b self.name = str(a) + ':' + str(b) self.df = pd.concat([a.df,b.df],axis = 1).dropna() self.num_bar = self.df.shape[0] self.cor = self.df.corr().ix[0][1] self.error = 0 self.last_error = 0 self.a_price = [] self.a_date = [] self.b_price = [] self.b_date = [] def cor_update(self): self.cor = self.df.corr().ix[0][1] def cointegration_test(self): self.model = sm.ols(formula = '%s ~ %s'%(str(self.a),str(self.b)), data = self.df).fit() self.adf = ts.adfuller(self.model.resid,autolag = 'BIC')[0] self.mean_error = np.mean(self.model.resid) self.sd = np.std(self.model.resid) def price_record(self,data_a,data_b): self.a_price.append(float(data_a.Close)) self.a_date.append(data_a.EndTime) self.b_price.append(float(data_b.Close)) self.b_date.append(data_b.EndTime) def df_update(self): new_df = pd.DataFrame({str(self.a):self.a_price,str(self.b):self.b_price},index = [self.a_date]).dropna() self.df = pd.concat([self.df,new_df]) self.df = self.df.tail(self.num_bar) for i in [self.a_price,self.a_date,self.b_price,self.b_date]: i = []
Alexandre Catarino
Hi OkiTrader ,
Please check out the Data Explorer or the Symbol Properties Database for available securities.
We can use try/exception to prevent the algorithm termination if the ticker is not found:
msg = 'Not found: ' for i in range(len(self.symbols)): try: crypto = self.AddCrypto(self.symbols[i],Resolution.Minute, Market.Bitfinex).Symbol except: msg += self.symbols[i] + ', ' continue self.Log(msg)
OkiTrader
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!