Finding low fee trading pairs#

An example to list low fee (5 BPS) Uniswap v3 pairs across different blockchains.

You can also explore this data using the website search. Here we write Python filters to further narrow down search results.

Preface#

Most DEX pairs are low liquidity pairs with 30 BPS fee. These pairs are not well-suitable for traditional technical indicator based trading algorithms. They can be still traded, but strategies need to be non-single pair, portfolio construction model ones.

In this example we construct a list of pairs that have low LP fees and meet volume threshold for automated trading.

Create a data client#

First, let’s create Trading Strategy dataset client.

[1]:
from tradingstrategy.client import Client

client = Client.create_jupyter_client()
Started Trading Strategy in Jupyter notebook environment, configuration is stored in /Users/moo/.tradingstrategy

Download exchange and pair data#

[2]:
from tradingstrategy.exchange import ExchangeUniverse
from pyarrow import Table

# Exchange map data is so small it does not need any decompression
exchange_universe: ExchangeUniverse = client.fetch_exchange_universe()

# Decompress the pair dataset to Python map
columnar_pair_table: Table = client.fetch_pair_universe()

print(f"Total pairs {len(columnar_pair_table)}, total exchanges {len(exchange_universe.exchanges)}")
Total pairs 168541, total exchanges 4352

Filtering pairs with 5 BPS fee on Uniswap 3#

Get a list of pairs

[3]:
from tradingstrategy.stablecoin import ALL_STABLECOIN_LIKE
import pandas as pd
from tradingstrategy.pair import filter_for_stablecoins
from tradingstrategy.pair import StablecoinFilteringMode

fee_tier = 5  # BPS

pairs_df = columnar_pair_table.to_pandas()

low_fee_pairs: pd.DataFrame = pairs_df.loc[
    (pairs_df["exchange_slug"] == "uniswap-v3") &
    (pairs_df["fee"] == fee_tier)  # BPS
]

print(f"Found {len(low_fee_pairs)} total pairs at {fee_tier} BPS fee tier")

# Filter out stablecoin pairs,
# because trading dollars to dollars do not make trading sense
low_fee_pairs = filter_for_stablecoins(low_fee_pairs, StablecoinFilteringMode.only_volatile_pairs)

print(f"Found {len(low_fee_pairs)} volatile pairs quoted in any token")

stablecoin_quoted_pairs = low_fee_pairs.loc[low_fee_pairs["quote_token_symbol"].isin(ALL_STABLECOIN_LIKE)]

print(f"Found {len(stablecoin_quoted_pairs)} volatile pairs quoted in a stablecoin")

# Assume no volume data is zero volume
stablecoin_quoted_pairs = stablecoin_quoted_pairs.fillna(0)

volume_threshold_30d = 1_000_000
volume_pairs = stablecoin_quoted_pairs.loc[stablecoin_quoted_pairs["buy_volume_30d"] >= volume_threshold_30d]

print(f"Found {len(volume_pairs)} pairs with enough volume")

Found 373 total pairs at 5 BPS fee tier
Found 308 volatile pairs quoted in any token
Found 156 volatile pairs quoted in a stablecoin
Found 13 pairs with enough volume