In [1]:
import pandas as pd
import numpy as np
import requests
In [31]:
pd.set_option('display.precision',10)

Bid-ask spread is a normalized value: (bid+ask)/(2*bid) - 1

In [37]:
tick = requests.get('https://poloniex.com/public?command=returnTicker').json()
In [38]:
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()
Out[38]:
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
In [39]:
tick_df['bid_ask_spread_norm'] = (tick_df['bid']+tick_df['ask'])/(2*tick_df['bid'])-1
In [40]:
tick_df.sort_values('bid_ask_spread_norm').head(10)
Out[40]:
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
In [41]:
tick_df.sort_values('bid_ask_spread_norm').tail(10)
Out[41]:
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.

In [124]:
def calc_liquidity(symbol):
    r = requests.get('https://poloniex.com/public?command=returnOrderBook&currencyPair={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)
In [125]:
col_names = ('symbol','best_bid', 'best_ask', 'best_1b_bid', 'best_1b_ask', 'best_10b_bid', 'best_10b_ask')
In [147]:
res = pd.DataFrame.from_records([calc_liquidity(symbol) for symbol in list(tick.keys())])
res.columns = col_names
In [148]:
res.head()
Out[148]:
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
In [149]:
# filter out non BTC_XXX pairs
res = res[res['symbol'].str.startswith('BTC_')]
In [150]:
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
In [151]:
res.head()
Out[151]:
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
In [152]:
res.isnull().sum()
Out[152]:
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
In [153]:
# less then 10 btc
res[res['bid_ask_10b_spread_norm'].isnull()]
Out[153]:
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
In [154]:
res.sort_values('bid_ask_10b_spread_norm').head(10)
Out[154]:
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
In [155]:
res.dropna().sort_values('bid_ask_10b_spread_norm').tail(10)
Out[155]:
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.

In [156]:
def calc_liquidity2(symbol):
    r = requests.get('https://poloniex.com/public?command=returnOrderBook&currencyPair={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())
In [157]:
col_names = ('symbol','cum_vol')
In [158]:
res = pd.DataFrame.from_records([calc_liquidity2(symbol) for symbol in list(tick.keys())])
res.columns = col_names
In [161]:
# filter out non BTC_XXX pairs
res = res[res['symbol'].str.startswith('BTC_')]
In [162]:
res.head()
Out[162]:
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
In [168]:
res.sort_values('cum_vol',ascending=False).head(20)
Out[168]:
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
In [167]:
res.sort_values('cum_vol',ascending=True).head(10)
Out[167]:
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
In [ ]: