One of the most common problem encountered by all novice researches of the crypto-markets and (algo-)traders is knowing a list of all cryptocurrency pairs being actively traded at specific crypto exchange. This knowledge is a gateway to a vast research over correlations of crypto-assets, looking for arbitrage trading opportunities, targeting exchanges with most liquid assets or lowest spreads, etc.
In this post we will see how one can scan a selected crypto-exchange (Bitfinex) for available data, in particular the daily close prices. The broader context of this solution with some examples of its applications can be found in my upcoming book Cryptocurrencies with Python.
To begin, we will make use of the resources provided by CryptoCompare. Thanks to their API, it is easy to figure out how to employ Python in search for relevant data. Let’s import few libraries followed by reaching for an information pack covering the most relevant crypto-exchanges:
# Scanning Crypto Exchanges for Available Cryptocurrency Price Data # # (c) 2020 QuantAtRisk.com, by Pawel Lachowicz, PhD import ccrypto as cc import numpy as np import pandas as pd import matplotlib.pyplot as plt import requests import json from bs4 import BeautifulSoup url = "https://min-api.cryptocompare.com/data/v4/all/exchanges?topTier=1" # fetch the raw data response = requests.get(url) soup = BeautifulSoup(response.content, "html.parser") dic = json.loads(soup.prettify()) # convert from json to dictionary print(dic)
In return, at the first glance, we will receive the feedback of a rich structure:
{'Response': 'Success', 'Message': '', 'HasWarning': False, 'Type': 100, 'RateLimit': {}, 'Data': {'exchanges': {'ACX': {'isActive': False, 'isTopTier': True, 'pairs': {'PLA': {'tsyms': {'AUD': {'histo_minute_start_ts': 1575244800, 'histo_minute_start': '2019-12-02', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}, 'USDT': {'histo_minute_start_ts': 1575244800, 'histo_minute_start': '2019-12-02', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, 'ETC': {'tsyms': {'AUD': {'histo_minute_start_ts': 1571356800, 'histo_minute_start': '2019-10-18', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, 'BTC': {'tsyms': {'USDT': {'histo_minute_start_ts': 1533859200, 'histo_minute_start': '2018-08-10', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}, 'AUD': {'histo_minute_start_ts': 1571356800, 'histo_minute_start': '2019-10-18', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, 'XRP': {'tsyms': {'AUD': {'histo_minute_start_ts': 1571356800, 'histo_minute_start': '2019-10-18', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, ...
Since we are interested in data available for all exchanges, we can limit ourselves just to:
d = dic['Data']['exchanges'] print(d)
i.e.
{'ACX': {'isActive': False, 'isTopTier': True, 'pairs': {'PLA': {'tsyms': {'AUD': {'histo_minute_start_ts': 1575244800, 'histo_minute_start': '2019-12-02', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}, 'USDT': {'histo_minute_start_ts': 1575244800, 'histo_minute_start': '2019-12-02', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, 'ETC': {'tsyms': {'AUD': {'histo_minute_start_ts': 1571356800, 'histo_minute_start': '2019-10-18', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, 'BTC': {'tsyms': {'USDT': {'histo_minute_start_ts': 1533859200, 'histo_minute_start': '2018-08-10', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}, 'AUD': {'histo_minute_start_ts': 1571356800, 'histo_minute_start': '2019-10-18', 'histo_minute_end_ts': 1604102400, 'histo_minute_end': '2020-10-31'}}}, 'XRP': {'tsyms': {'AUD': {'histo_minute_start_ts': 1571356800, 'histo_minute_start': '2019-10-18', 'histo_minute_end_ts': 1604102400, ...
where
print(len(d.keys()))
68
will tell us how many Top Tier crypto-exchanges are currently out there (i.e. at the time of running the code). We can list them all:
i = 0 for e in d.keys(): if d[e]['isActive']: i += 1 print('%5gt%s' % (i, e))
1 BTCAlpha 2 BTCMarkets 3 BTCTurk 4 Bibox 5 Binance 6 Binanceje 7 Bit2C 8 BitBank 9 BitBay 10 BitMart 11 BitTrex 12 Bitfinex 13 Bithumb 14 Bitso 15 Bitstamp 16 Bleutrade 17 Cexio 18 CoinCorner 19 CoinDeal 20 CoinFalcon 21 CoinJar 22 Coinbase 23 Coincheck ... 65 huobijapan 66 huobikorea 67 itBit 68 lmax
In next step, we need to select the exchange of our interest. Let’s assume we want to focus on Bitfinex exchnage and find out what cryptocurrencies are/were quoted vs USD, traded there, and CryptoCompare has the records of them:
coins = list() for e in d.keys(): if d[e]['isActive']: if e == 'Bitfinex': for p in d[e]['pairs']: x = list() for f in d[e]['pairs'].values(): x.extend(list(f['tsyms'].keys())) if 'BTC' in set(x): coins.append(p) coins = sorted(coins) print(coins)
['ABYSS', 'ADA', 'AGI', 'AID', 'AION', 'ALGO', 'AMPL', 'ANT', 'AST', 'ATMI', 'ATOM', 'AUC', 'AUTON', 'AVAX', 'AVT', 'BAL', 'BAND', 'BAT', 'BCH', 'BCI', 'BFT', 'BFX', 'BNN', 'BNT', 'BOX', 'BSV', 'BT1', 'BT2', 'BTC', 'BTG', 'BTSE', 'BTT', 'CBT', 'CFI', 'CHZ', 'CLO', 'CND', 'CNH', 'CNN', 'COMP', 'CRDTS', 'CSEN', 'CTXC', 'DADI', 'DAI', 'DAPP', 'DASH', 'DATA', 'DGB', 'DGX', 'DOT', 'DOT_NO_SPLIT', 'DRGN', 'DTA', 'DTH', 'DTX', 'DUSK', 'EDO', 'EGLD', 'ELF', 'ENJ', 'EOS', 'EOSDT', 'ESS', 'ETC', 'ETH', 'ETP', 'EURS', 'EURT', 'FET', 'FIL', 'FOAM', 'FSN', 'FTT', 'FTXT', 'FUN', 'GENS', 'GNO', 'GNT', 'GOT', 'GT', 'GUSD', 'HOT', 'HYPERS', 'IMPT', 'INT', 'IOST', 'IQ', 'JST', 'KAN', 'KNC', 'KSM', 'LEO', 'LINK', 'LOOM', 'LRC', 'LTC', 'LYM', 'MANA', 'MDCL', 'MGO', 'MIOTA', 'MITH', 'MKR', 'MLN', 'MXAI', 'NCASH', 'NEC', 'NEO', 'NIO', 'NUT', 'ODE', 'OKB', 'OMG', 'OMNI', 'ONL', 'ORS', 'PASS', 'PAX', 'PNK', 'PNT', 'POA', 'POLY', 'PPAI', 'QASH', 'QTUM', 'RBTC', 'RCN', 'RDNN', 'REP', 'REQ', 'RIF', 'RINGX', 'RLC', 'RRB', 'RRT', 'RTE', 'SAI', 'SAN', 'SEER', 'SNGLS', 'SNT', 'SNX', 'SPANK', 'STORJ', 'SWM', 'TKN', 'TNB', 'TRIO', 'TRX', 'TUSD', 'UFR', 'ULTRA', 'UNI', 'USDC', 'USDK', 'USDT', 'UTK', 'UTNP', 'VEE', 'VET', 'VLD', 'VSYS', 'WAX', 'WBTC', 'WLO', 'WPR', 'WTC', 'XAUT', 'XCHF', 'XLM', 'XMR', 'XRA', 'XRP', 'XTZ', 'XVG', 'YEED', 'YFI', 'YOYOW', 'ZB', 'ZCN', 'ZEC', 'ZIL', 'ZRX']
This is a lot!
The last step it to fetch the historical time-series of daily close prices for all abovementioned cryptocurrencies vs USD, and by doing so, check the actual data span:
data = pd.DataFrame(columns=['Cryptocurrency', 'From', 'To']) k = 0 for coin in coins: try: df = cc.getCryptoSeries(coin, 'USD', freq='d', exch='Bitfinex') if df.size > 0: print("%7s%12s%12s" % (coin, df.index[0].strftime("%Y-%m-%d"), df.index[-1].strftime("%Y-%m-%d"))) data.loc[k] = (coin, df.index[0].strftime("%Y-%m-%d"), df.index[-1].strftime("%Y-%m-%d")) k += 1 except: pass data.From = pd.to_datetime(data.From) data.To = pd.to_datetime(data.To)
Here, we construct an empty DataFrame where we want to store the results. In a loop, we go over all coins (alternatively speaking: cryptocurrencies) identified in the previous step. For each one, we use getCryptoSeries function from ccrypto library (available with the release of my book Cryptocurrencies with Python) to fetch the daily close price time-series for selected cryptocoin vs USD. Based on them, we check at what day the records begin and at what day they end.
The above loop, as of time of writing, returns:
ABYSS 2018-09-01 2020-10-31 ADA 2020-08-06 2020-10-30 AGI 2018-05-09 2020-10-29 AID 2018-01-30 2020-10-29 AION 2018-05-09 2020-10-31 ALGO 2019-07-01 2020-10-31 AMPL 2019-06-28 2020-10-30 ANT 2018-05-09 2020-10-31 AST 2019-05-29 2020-10-27 ... YOYOW 2017-12-01 2020-10-31 ZB 2019-11-02 2020-10-30 ZCN 2018-08-29 2020-10-31 ZEC 2016-10-29 2020-10-29 ZIL 2018-09-05 2020-10-23 ZRX 2018-02-05 2020-10-31
For the grand finale, let us visualise data availability between 2015 and 2020:
# reverse the order of rows in DataFrame for plotting only dataV = data.iloc[::-1] dataV.index = np.arange(dataV.shape[0]) # plot plt.figure(figsize=(12,40)) for i in np.arange(dataV.shape[0]): dr = pd.date_range(dataV.From[i], dataV.To[i]) yr = np.zeros(len(dr)) + i plt.plot(dr, yr, 'r-', label=dataV.Cryptocurrency[i]) plt.yticks(np.arange(dataV.shape[0]), dataV.Cryptocurrency) plt.grid() plt.xticks(rotation=45) plt.ylim([-1, dataV.shape[0]])
In this way, we obtain a quick overview of time span of all available cryptocurrencies quoted vs USD traded at Bitfinex crypto-exchange. In many instances, it’s extremely needed solution.
Although it does not check whether all daily price quotes are available for every cryptocurrency pair but, at least, it allows to understand the lifetime of specific cryptocurrency on the Bitfinex market.