def test_basics():
    print("\ntokens_json():", token_utils.tokens_json())
    print("\ntokens():", token_utils.tokens())
    print("\ntokens_decimals():", token_utils.token_decimals())
    print("\nselect_tokens():", token_utils.select_tokens())
    print("\ntradable_tokens():", token_utils.tradable_tokens())
    print("\nTradable Tokens:", sorted(token_utils.tradable_tokens().keys()))
    print("\bUSD Tokens:", [
        t for t in token_utils.tradable_tokens().keys() if t.find('USD') >= 0
    ])
def print_top_tokens_by_vol_and_mkt_cap():
    tradable_tokens = token_utils.tradable_tokens()
    top_by_volume = top_tokens.top_tokens_by_volume(100, day_volume=90)
    top_by_mkt_cap = top_tokens.top_tokens_by_market_cap(100)
    top_both = set(top_by_volume) & set(top_by_mkt_cap)
    print(f"TOKEN\tVOL RANK\tMKT CAP RANK\tTRADABLE")
    for token in top_both:
        if token not in tradable_tokens:
            print(
                f"{token:<6} number {top_by_volume.index(token) + 1} by 90-day volume, number {top_by_mkt_cap.index(token) + 1} by market cap"
            )
def print_totle_cex_overlap():
    totle_tokens = token_utils.tradable_tokens()
    kraken_overlap_pairs = kraken_client.get_overlap_pairs(totle_tokens)
    binance_overlap_pairs = binance_client.get_overlap_pairs(totle_tokens)
    huobi_overlap_pairs = huobi_client.get_overlap_pairs(totle_tokens)

    totle_kraken_binance_tokens = sorted([
        b for b, q in kraken_overlap_pairs if (b, q) in binance_overlap_pairs
    ])
    print(f"totle_kraken_binance_tokens={totle_kraken_binance_tokens}")
    totle_kraken_huobi_tokens = sorted(
        [b for b, q in kraken_overlap_pairs if (b, q) in huobi_overlap_pairs])
    print(f"totle_kraken_huobi_tokens={totle_kraken_huobi_tokens}")
    totle_binance_huobi_tokens = sorted(
        [b for b, q in binance_overlap_pairs if (b, q) in huobi_overlap_pairs])
    print(f"totle_binance_huobi_tokens={totle_binance_huobi_tokens}")
def tradable_tokens_by_market_cap(top_n=100):
    """List tradable tokens ordered by market cap (does not include those not in the top_n"""
    top_by_market_cap = list(
        enumerate(top_tokens.top_tokens_by_market_cap(top_n)))

    tokens_by_market_cap = []
    for t in token_utils.tradable_tokens():
        vr = [r + 1 for r, s in top_by_market_cap if s == t]
        if vr: tokens_by_market_cap.append((vr[0], t))

    #
    # PAX #9 by  market_cap	    ADD THIS TO ORDER SPLITTING
    # MCO #24 by  market_cap	ADD THIS TO ORDER SPLITTING
    # NEXO #25 by  market_cap	ADD THIS TO ORDER SPLITTING
    # SNT #33 by  market_cap	ADD THIS TO ORDER SPLITTING
    for r, t in sorted(tokens_by_market_cap):
        add = 'ADD THIS TO ORDER SPLITTING' if r < 100 and t not in OS_TOKENS else ''
        print(f"{t:<8} #{r} by market_cap\t{add}")
def tradable_tokens_by_volume(top_n=100, day_volume=90):
    """List tradable tokens ordered by volume (does not include those not in the top_n"""
    top_by_volume = list(
        enumerate(top_tokens.top_tokens_by_volume(top_n, day_volume)))

    tokens_by_volume = []
    for t in token_utils.tradable_tokens():
        vr = [r + 1 for r, s in top_by_volume if s == t]
        if vr: tokens_by_volume.append((vr[0], t))

    # WBTC, VERI, XDCE, BMC, PAX, MCO, NEXO, SNT
    # WBTC  # 7 by 90-day volume	ADD THIS TO ORDER SPLITTING
    # VERI  # 17 by 90-day volume	ADD THIS TO ORDER SPLITTING
    # XDCE  # 33 by 90-day volume	ADD THIS TO ORDER SPLITTING
    # BMC  # 47 by 90-day volume	ADD THIS TO ORDER SPLITTING
    for r, t in sorted(tokens_by_volume):
        add = 'ADD THIS TO ORDER SPLITTING' if r < 100 and t not in OS_TOKENS else ''
        print(f"{t} #{r} by {day_volume}-day volume\t{add}")
def top_tokens_not_tradable_on_totle(top_n=100, day_volume=90):
    tradable_tokens = token_utils.tradable_tokens()
    print(f"tradable_tokens={sorted(tradable_tokens.keys())}")
    print(
        f"Below is a list of tokens in the top {top_n} by {day_volume}-day volume that are not tradable on Totle"
    )
    top_by_volume = list(
        enumerate(top_tokens.top_tokens_by_volume(top_n, day_volume)))
    # print(f"top_by_volume={top_by_volume}")
    for rank, token in top_by_volume:
        if not token in tradable_tokens:
            print(f"{rank:>3}. {token}")

    all_tokens = token_utils.tokens()
    print(
        f"Below is a list of tokens in the top {top_n} by {day_volume}-day volume that are not even in Totle's tokens API"
    )
    for rank, token in top_by_volume:
        if not token in all_tokens:
            print(f"{rank:>3}. {token}")
Exemple #7
0
def get_token_prices(tokens=None):
    all_tradable_tokens = tokens or token_utils.tradable_tokens()
    all_tradable_tokens.pop('ETH')
    # TODO: remove ETH it's not really an ERC-20
    cmc_data = json.load(open(f'data/cmc_tokens.json'))['data']
    usd_prices = {
        t['symbol']: float(t['quote']['USD']['price'])
        for t in cmc_data if t['symbol'] in all_tradable_tokens
    }

    skipped_tokens, missing_tokens = set(
    ), set(all_tradable_tokens) - set(usd_prices)
    print(
        f"CMC had prices for {len(usd_prices)}/{len(all_tradable_tokens)} tokens. Querying Totle for prices on the remaining {len(missing_tokens)} tokens"
    )
    for missing_token in missing_tokens:
        if missing_token == 'CETH':
            usd_prices[missing_token] = 2.83
        else:
            totle_quote = totle_client.try_swap(totle_client.name(),
                                                missing_token,
                                                'ETH',
                                                params={'toAmount': 0.1},
                                                verbose=False,
                                                debug=False)

            if totle_quote:  # set the from_amount so it's roughly the same across all swaps
                usd_prices[missing_token] = ETH_PRICE / totle_quote['price']
            else:
                # If we can't get a price from CMC or Totle, then just discard this token. Other aggs may have the pair, but if you can't
                # buy it for ETH on Totle, then it is essentially not a "tradable" token as curated by Totle, and thus not in this study.
                skipped_tokens.add(missing_token)

    print(
        f"Skipping {skipped_tokens} because we couldn't get a price from CMC or Totle"
    )
    return usd_prices
Exemple #8
0
def main():
    working_dir = os.path.dirname(__file__)
    if working_dir: os.chdir(working_dir)

    CEX_CLIENTS = [binance_client, huobi_client, kraken_client]
    # TOTLE_BINANCE_HUOBI_TOKENS = ['ADX', 'AST', 'BAT', 'CVC', 'ENG', 'KNC', 'LINK', 'MANA', 'MCO', 'NPXS', 'OMG', 'POWR', 'QSP', 'RCN', 'RDN', 'REQ', 'SALT', 'THETA', 'WTC', 'ZIL', 'ZRX']
    # TOKENS = ['BAT', 'LINK', 'OMG'] # Only 3 tokens overlap Totle and all three CEXs

    CEX_NAMES = [
        'binance', 'bitfinex', 'bittrex', 'coinbase-pro', 'hitbtc', 'huobi',
        'kraken', 'poloniex'
    ]

    QUOTE_TOKEN = 'ETH'

    TRADE_SIZES = [
        0.1, 0.5, 1.0, 5.0, 10.0, 50.0, 100.0, 200.0, 300.0, 400.0, 500.0
    ]

    CSV_FIELDS = "time action trade_size token exchange exchange_price totle_used totle_price pct_savings splits ex_prices".split(
    )

    all_savings = defaultdict(lambda: defaultdict(lambda: defaultdict(
        dict)))  # extra lambda prevents KeyError in print_savings
    tradable_tokens = token_utils.tradable_tokens()
    select_token_cexs = parse_markets('data/cryptowatch-markets-prices.json',
                                      tradable_tokens,
                                      CEX_NAMES,
                                      min_cexs=3)

    for order_type in ['buy', 'sell']:
        filename = get_filename_base(prefix='totle_vs_cexs', suffix=order_type)
        with SavingsCSV(filename, fieldnames=CSV_FIELDS) as csv_writer:
            for token, cex_list in select_token_cexs.items(
            ):  # Each token has it's own list of CEXs that support token/ETH pair
                # Get books for the 8 CEXs from cryptowatch
                bids, asks = {}, {}
                for cex_name in cex_list:  # these have all-lowercase keys, so we have to capitalize them later
                    bids[cex_name], asks[
                        cex_name] = cryptowatch_client.get_books(
                            cex_name, token, QUOTE_TOKEN)

                # Get books from 3 clients (BinanceC, HuobiC, KrakenC)
                cex_name_client = {}
                for cex_client in CEX_CLIENTS:
                    if cex_client.name().lower() in cex_list:
                        cex_name_c = cex_client.name().capitalize(
                        ) + 'C'  # capitalize, since we're choosing a unique key and a client map anyway
                        try:
                            bids[cex_name_c], asks[
                                cex_name_c] = cex_client.get_depth(
                                    token, QUOTE_TOKEN)
                            cex_name_client[cex_name_c] = cex_client
                        except (binance_client.BinanceAPIException,
                                huobi_client.HuobiAPIException,
                                kraken_client.KrakenAPIException) as e:
                            print(
                                f"{cex_name_c} get_depth({token}/{QUOTE_TOKEN}) raised {e}"
                            )

                # Now loop over trade sizes and compare against 8, then 3 CEXs
                books = asks if order_type == 'buy' else bids
                for trade_size in TRADE_SIZES:
                    # compare to the 8 CEXs in cex_list
                    cex_savings, totle_quote = compare_totle_and_cexs_same_fee(
                        cex_list, token, QUOTE_TOKEN, trade_size, books,
                        order_type)
                    for cex_name, savings in cex_savings.items():
                        # Save the capitalized version of the cex_name, not the lowercase cryptowatch name
                        cap_cex_name = cex_name.capitalize()
                        savings['exchange'] = cap_cex_name
                        all_savings[cap_cex_name][token][trade_size] = savings
                        csv_writer.append(savings)

                    # Re-do comparisons on 3 CEXs (BinanceC, HuobiC, and KrakenC) using the exchange API clients, but use Totle's fee (FIXED_FEE_PCT)
                    cex_c_savings = compare_totle_and_cexs(
                        cex_name_client,
                        token,
                        QUOTE_TOKEN,
                        trade_size,
                        books,
                        order_type,
                        totle_quote=totle_quote,
                        fee_override=FIXED_FEE_PCT)
                    for cex_name_c, savings in cex_c_savings.items():
                        all_savings[cex_name_c][token][trade_size] = savings
                        csv_writer.append(savings)

        # Prints a savings dict, token => trade_size => savings values
        for cex_name in all_savings:
            print_savings(order_type,
                          all_savings[cex_name],
                          TRADE_SIZES,
                          title=f"Savings vs. {cex_name}")