import pandas as pd
import numpy as np
import requests
pd.set_option('display.precision',10)
Bid-ask spread is a normalized value: (bid+ask)/(2*bid) - 1
tick = requests.get('https://poloniex.com/public?command=returnTicker').json()
tick_df = pd.DataFrame.from_records([(k,v['highestBid'],v['lowestAsk']) for k,v in tick.items()])
tick_df.columns = ('symbol','bid','ask')
tick_df['bid'] = tick_df['bid'].astype(float)
tick_df['ask'] = tick_df['ask'].astype(float)
tick_df.head()
symbol | bid | ask | |
---|---|---|---|
0 | BTC_BCN | 0.00000046 | 0.00000047 |
1 | BTC_BELA | 0.00001745 | 0.00001751 |
2 | BTC_BLK | 0.00003257 | 0.00003315 |
3 | BTC_BTCD | 0.01015829 | 0.01020906 |
4 | BTC_BTM | 0.00007724 | 0.00007725 |
tick_df['bid_ask_spread_norm'] = (tick_df['bid']+tick_df['ask'])/(2*tick_df['bid'])-1
tick_df.sort_values('bid_ask_spread_norm').head(10)
symbol | bid | ask | bid_ask_spread_norm | |
---|---|---|---|---|
63 | BTC_LSK | 0.00189000 | 0.00189001 | 0.0000026455 |
60 | BTC_RADS | 0.00055500 | 0.00055501 | 0.0000090090 |
7 | BTC_CLAM | 0.00053662 | 0.00053663 | 0.0000093176 |
46 | USDT_XRP | 0.93812950 | 0.93815047 | 0.0000111765 |
66 | BTC_STEEM | 0.00031632 | 0.00031633 | 0.0000158068 |
4 | BTC_BTM | 0.00007724 | 0.00007725 | 0.0000647333 |
8 | BTC_DASH | 0.05748979 | 0.05749990 | 0.0000879287 |
36 | BTC_XEM | 0.00003659 | 0.00003660 | 0.0001366494 |
92 | BTC_CVC | 0.00003410 | 0.00003411 | 0.0001466276 |
27 | BTC_RIC | 0.00002948 | 0.00002949 | 0.0001696065 |
tick_df.sort_values('bid_ask_spread_norm').tail(10)
symbol | bid | ask | bid_ask_spread_norm | |
---|---|---|---|---|
11 | BTC_EMC2 | 0.00002891 | 0.00002935 | 0.0076098236 |
57 | BTC_BCY | 0.00004402 | 0.00004474 | 0.0081781009 |
10 | BTC_DOGE | 0.00000060 | 0.00000061 | 0.0083333333 |
22 | BTC_NMC | 0.00024959 | 0.00025403 | 0.0088945871 |
2 | BTC_BLK | 0.00003257 | 0.00003315 | 0.0089038993 |
16 | BTC_HUC | 0.00002485 | 0.00002531 | 0.0092555332 |
47 | XMR_BCN | 0.00001619 | 0.00001650 | 0.0095738110 |
31 | BTC_XVC | 0.00004103 | 0.00004188 | 0.0103582744 |
0 | BTC_BCN | 0.00000046 | 0.00000047 | 0.0108695652 |
52 | XMR_MAID | 0.00117875 | 0.00121206 | 0.0141293743 |
The main issue with this metrics is that spread changes rapidly and top/tail results are different in any given time.
Handy liquidity
HL = Bid-ask spread / Bid-ask spread by X units of an asset, where X is 1 BTC or equivalent for day traders; 10 BTC or equivalent for investors.
def calc_liquidity(symbol):
r = requests.get('https://poloniex.com/public?command=returnOrderBook¤cyPair={symbol}&depth=1000'.format(symbol=symbol)).json()
asks = pd.DataFrame.from_records(r['asks']).rename(columns={0:'price',1:'amount'})
bids = pd.DataFrame.from_records(r['bids']).rename(columns={0:'price',1:'amount'})
asks['price'] = asks['price'].astype(float)
bids['price'] = bids['price'].astype(float)
asks['vol'] = asks['price']*asks['amount']
bids['vol'] = bids['price']*bids['amount']
asks['cumvol'] = asks['vol'].cumsum()
bids['cumvol'] = bids['vol'].cumsum()
best_bid = bids['price'].values[0]
best_ask = asks['price'].values[0]
best_1b_bid = bids[bids['cumvol']>=1]['price'].values[0] if (bids['cumvol']>=1).sum()>0 else np.NaN
best_1b_ask = asks[asks['cumvol']>=1]['price'].values[0] if (asks['cumvol']>=1).sum()>0 else np.NaN
best_10b_bid = bids[bids['cumvol']>=10]['price'].values[0] if (bids['cumvol']>=10).sum()>0 else np.NaN
best_10b_ask = asks[asks['cumvol']>=10]['price'].values[0] if (asks['cumvol']>=10).sum()>0 else np.NaN
return (symbol, best_bid, best_ask, best_1b_bid, best_1b_ask, best_10b_bid, best_10b_ask)
col_names = ('symbol','best_bid', 'best_ask', 'best_1b_bid', 'best_1b_ask', 'best_10b_bid', 'best_10b_ask')
res = pd.DataFrame.from_records([calc_liquidity(symbol) for symbol in list(tick.keys())])
res.columns = col_names
res.head()
symbol | best_bid | best_ask | best_1b_bid | best_1b_ask | best_10b_bid | best_10b_ask | |
---|---|---|---|---|---|---|---|
0 | BTC_BCN | 0.00000046 | 0.00000047 | 0.00000046 | 0.00000048 | 0.00000044 | 0.00000050 |
1 | BTC_BELA | 0.00001744 | 0.00001745 | 0.00001695 | 0.00001861 | 0.00001127 | 0.00002670 |
2 | BTC_BLK | 0.00003259 | 0.00003282 | 0.00003111 | 0.00003286 | 0.00001886 | 0.00004600 |
3 | BTC_BTCD | 0.00992062 | 0.01000535 | 0.00975034 | 0.01195000 | NaN | 0.01647000 |
4 | BTC_BTM | 0.00007531 | 0.00007604 | 0.00007009 | 0.00009620 | NaN | 0.00013326 |
# filter out non BTC_XXX pairs
res = res[res['symbol'].str.startswith('BTC_')]
res['bid_ask_spread_norm'] = (res['best_bid']+res['best_ask'])/(2*res['best_bid'])-1
res['bid_ask_1b_spread_norm'] = (res['best_1b_bid']+res['best_1b_ask'])/(2*res['best_1b_bid'])-1
res['bid_ask_10b_spread_norm'] = (res['best_10b_bid']+res['best_10b_ask'])/(2*res['best_10b_bid'])-1
res.head()
symbol | best_bid | best_ask | best_1b_bid | best_1b_ask | best_10b_bid | best_10b_ask | bid_ask_spread_norm | bid_ask_1b_spread_norm | bid_ask_10b_spread_norm | |
---|---|---|---|---|---|---|---|---|---|---|
0 | BTC_BCN | 0.00000046 | 0.00000047 | 0.00000046 | 0.00000048 | 0.00000044 | 0.00000050 | 0.0108695652 | 0.0217391304 | 0.0681818182 |
1 | BTC_BELA | 0.00001744 | 0.00001745 | 0.00001695 | 0.00001861 | 0.00001127 | 0.00002670 | 0.0002866972 | 0.0489675516 | 0.6845607808 |
2 | BTC_BLK | 0.00003259 | 0.00003282 | 0.00003111 | 0.00003286 | 0.00001886 | 0.00004600 | 0.0035286898 | 0.0281260045 | 0.7195121951 |
3 | BTC_BTCD | 0.00992062 | 0.01000535 | 0.00975034 | 0.01195000 | NaN | 0.01647000 | 0.0042703984 | 0.1127991434 | NaN |
4 | BTC_BTM | 0.00007531 | 0.00007604 | 0.00007009 | 0.00009620 | NaN | 0.00013326 | 0.0048466339 | 0.1862605222 | NaN |
res.isnull().sum()
symbol 0 best_bid 0 best_ask 0 best_1b_bid 0 best_1b_ask 0 best_10b_bid 10 best_10b_ask 0 bid_ask_spread_norm 0 bid_ask_1b_spread_norm 0 bid_ask_10b_spread_norm 10 dtype: int64
# less then 10 btc
res[res['bid_ask_10b_spread_norm'].isnull()]
symbol | best_bid | best_ask | best_1b_bid | best_1b_ask | best_10b_bid | best_10b_ask | bid_ask_spread_norm | bid_ask_1b_spread_norm | bid_ask_10b_spread_norm | |
---|---|---|---|---|---|---|---|---|---|---|
3 | BTC_BTCD | 0.00992062 | 0.01000535 | 0.00975034 | 0.01195000 | NaN | 0.01647000 | 0.0042703984 | 0.1127991434 | NaN |
4 | BTC_BTM | 0.00007531 | 0.00007604 | 0.00007009 | 0.00009620 | NaN | 0.00013326 | 0.0048466339 | 0.1862605222 | NaN |
13 | BTC_FLO | 0.00000946 | 0.00000971 | 0.00000907 | 0.00001100 | NaN | 0.00001510 | 0.0132135307 | 0.1063947078 | NaN |
22 | BTC_NMC | 0.00025111 | 0.00025264 | 0.00023162 | 0.00026999 | NaN | 0.00041000 | 0.0030464737 | 0.0828296347 | NaN |
24 | BTC_PINK | 0.00000283 | 0.00000287 | 0.00000275 | 0.00000315 | NaN | 0.00000450 | 0.0070671378 | 0.0727272727 | NaN |
31 | BTC_XVC | 0.00004155 | 0.00004188 | 0.00003967 | 0.00004600 | NaN | 0.00006350 | 0.0039711191 | 0.0797832115 | NaN |
34 | BTC_XBC | 0.00706864 | 0.00708653 | 0.00661268 | 0.00750800 | NaN | 0.01220000 | 0.0012654485 | 0.0676972120 | NaN |
68 | BTC_SBD | 0.00033333 | 0.00033772 | 0.00030000 | 0.00035501 | NaN | 0.00060000 | 0.0065850659 | 0.0916833333 | NaN |
81 | BTC_NXC | 0.00001981 | 0.00002001 | 0.00001941 | 0.00002312 | NaN | 0.00003450 | 0.0050479556 | 0.0955692942 | NaN |
85 | BTC_GNO | 0.01237755 | 0.01265687 | 0.01218740 | 0.01350799 | NaN | 0.01755464 | 0.0112833315 | 0.0541784958 | NaN |
res.sort_values('bid_ask_10b_spread_norm').head(10)
symbol | best_bid | best_ask | best_1b_bid | best_1b_ask | best_10b_bid | best_10b_ask | bid_ask_spread_norm | bid_ask_1b_spread_norm | bid_ask_10b_spread_norm | |
---|---|---|---|---|---|---|---|---|---|---|
54 | BTC_ETH | 0.08258519 | 0.08265476 | 0.08238901 | 0.08265478 | 0.08218016 | 0.08281458 | 0.0004212014 | 0.0016128972 | 0.0038599341 |
37 | BTC_XMR | 0.02805566 | 0.02811975 | 0.02805563 | 0.02813053 | 0.02795000 | 0.02820082 | 0.0011421938 | 0.0013348479 | 0.0044869410 |
39 | BTC_XRP | 0.00008747 | 0.00008748 | 0.00008737 | 0.00008750 | 0.00008701 | 0.00008783 | 0.0000571625 | 0.0007439625 | 0.0047121021 |
17 | BTC_LTC | 0.02048206 | 0.02053499 | 0.02046751 | 0.02053499 | 0.02046750 | 0.02066601 | 0.0012921064 | 0.0016484663 | 0.0048493954 |
69 | BTC_ETC | 0.00335550 | 0.00336460 | 0.00335503 | 0.00336517 | 0.00334000 | 0.00337871 | 0.0013559827 | 0.0015111638 | 0.0057949102 |
87 | BTC_BCH | 0.11892012 | 0.11905362 | 0.11881506 | 0.11936296 | 0.11819207 | 0.11998970 | 0.0005613011 | 0.0023056841 | 0.0076046980 |
8 | BTC_DASH | 0.05727659 | 0.05754597 | 0.05727659 | 0.05754600 | 0.05700000 | 0.05789607 | 0.0023515716 | 0.0023518334 | 0.0078602632 |
76 | BTC_ZEC | 0.03860000 | 0.03865000 | 0.03858000 | 0.03873949 | 0.03833747 | 0.03928010 | 0.0006476684 | 0.0020670036 | 0.0122938472 |
94 | BTC_OMG | 0.00175756 | 0.00176447 | 0.00175541 | 0.00177440 | 0.00173737 | 0.00178452 | 0.0019657935 | 0.0054089928 | 0.0135693606 |
63 | BTC_LSK | 0.00187388 | 0.00187471 | 0.00185779 | 0.00188218 | 0.00182957 | 0.00188221 | 0.0002214656 | 0.0065642511 | 0.0143858940 |
res.dropna().sort_values('bid_ask_10b_spread_norm').tail(10)
symbol | best_bid | best_ask | best_1b_bid | best_1b_ask | best_10b_bid | best_10b_ask | bid_ask_spread_norm | bid_ask_1b_spread_norm | bid_ask_10b_spread_norm | |
---|---|---|---|---|---|---|---|---|---|---|
38 | BTC_XPM | 0.00009250 | 0.00009329 | 0.00008424 | 0.00009936 | 0.00005000 | 0.00011036 | 0.0042702703 | 0.0897435897 | 0.6036000000 |
1 | BTC_BELA | 0.00001744 | 0.00001745 | 0.00001695 | 0.00001861 | 0.00001127 | 0.00002670 | 0.0002866972 | 0.0489675516 | 0.6845607808 |
57 | BTC_BCY | 0.00004402 | 0.00004466 | 0.00004279 | 0.00005190 | 0.00003350 | 0.00007999 | 0.0072694230 | 0.1064501052 | 0.6938805970 |
2 | BTC_BLK | 0.00003259 | 0.00003282 | 0.00003111 | 0.00003286 | 0.00001886 | 0.00004600 | 0.0035286898 | 0.0281260045 | 0.7195121951 |
7 | BTC_CLAM | 0.00053662 | 0.00053663 | 0.00052990 | 0.00055826 | 0.00030000 | 0.00077154 | 0.0000093176 | 0.0267597660 | 0.7859000000 |
60 | BTC_RADS | 0.00055500 | 0.00055501 | 0.00055000 | 0.00058843 | 0.00028177 | 0.00095000 | 0.0000090090 | 0.0349363636 | 1.1857720836 |
12 | BTC_FLDC | 0.00000244 | 0.00000247 | 0.00000240 | 0.00000275 | 0.00000106 | 0.00000360 | 0.0061475410 | 0.0729166667 | 1.1981132075 |
21 | BTC_NEOS | 0.00040904 | 0.00041304 | 0.00039016 | 0.00045473 | 0.00017998 | 0.00065300 | 0.0048894974 | 0.0827481033 | 1.3140904545 |
11 | BTC_EMC2 | 0.00002848 | 0.00002856 | 0.00002751 | 0.00003112 | 0.00000980 | 0.00003642 | 0.0014044944 | 0.0656125045 | 1.3581632653 |
26 | BTC_PPC | 0.00030674 | 0.00031012 | 0.00030231 | 0.00032399 | 0.00010000 | 0.00049000 | 0.0055095521 | 0.0358572326 | 1.9500000000 |
** Handy liquidity 2 **
The cumulative volume that is present in an order book at levels that are away from the naive mid market price by 0.5% or less.
def calc_liquidity2(symbol):
r = requests.get('https://poloniex.com/public?command=returnOrderBook¤cyPair={symbol}&depth=1000'.format(symbol=symbol)).json()
asks = pd.DataFrame.from_records(r['asks']).rename(columns={0:'price',1:'amount'})
bids = pd.DataFrame.from_records(r['bids']).rename(columns={0:'price',1:'amount'})
asks['price'] = asks['price'].astype(float)
bids['price'] = bids['price'].astype(float)
asks['vol'] = asks['price']*asks['amount']
bids['vol'] = bids['price']*bids['amount']
asks = asks[asks['price'] < asks['price'].min()*1.005]
bids = bids[bids['price'] > bids['price'].max()*0.995]
asks['vol'].sum() + bids['vol'].sum()
return (symbol, asks['vol'].sum() + bids['vol'].sum())
col_names = ('symbol','cum_vol')
res = pd.DataFrame.from_records([calc_liquidity2(symbol) for symbol in list(tick.keys())])
res.columns = col_names
# filter out non BTC_XXX pairs
res = res[res['symbol'].str.startswith('BTC_')]
res.head()
symbol | cum_vol | |
---|---|---|
0 | BTC_BCN | 4.4682113194 |
1 | BTC_BELA | 0.5605750506 |
2 | BTC_BLK | 1.1104506010 |
3 | BTC_BTCD | 0.1226621214 |
4 | BTC_BTM | 0.0030424615 |
res.sort_values('cum_vol',ascending=False).head(20)
symbol | cum_vol | |
---|---|---|
54 | BTC_ETH | 58.5730282961 |
17 | BTC_LTC | 32.5292035913 |
69 | BTC_ETC | 28.7028977690 |
37 | BTC_XMR | 26.1032723523 |
10 | BTC_DOGE | 22.7971542676 |
87 | BTC_BCH | 15.3069679272 |
76 | BTC_ZEC | 10.4303819202 |
23 | BTC_NXT | 10.2905658708 |
8 | BTC_DASH | 9.9785985597 |
39 | BTC_XRP | 9.3337031694 |
36 | BTC_XEM | 7.5982164581 |
28 | BTC_STR | 6.5657469885 |
94 | BTC_OMG | 5.5874987200 |
0 | BTC_BCN | 4.4682113194 |
18 | BTC_MAID | 3.9953841949 |
63 | BTC_LSK | 3.1878769171 |
30 | BTC_VIA | 3.0570022787 |
90 | BTC_ZRX | 2.8576900372 |
62 | BTC_DCR | 2.3294610386 |
66 | BTC_STEEM | 2.1739351543 |
res.sort_values('cum_vol',ascending=True).head(10)
symbol | cum_vol | |
---|---|---|
4 | BTC_BTM | 0.0030424615 |
15 | BTC_GRC | 0.0083063213 |
12 | BTC_FLDC | 0.0084011532 |
21 | BTC_NEOS | 0.0229709587 |
24 | BTC_PINK | 0.0230291717 |
92 | BTC_CVC | 0.0266437533 |
13 | BTC_FLO | 0.0300599054 |
11 | BTC_EMC2 | 0.0648765530 |
27 | BTC_RIC | 0.0769361480 |
35 | BTC_XCP | 0.0780650952 |