Loading exchange, pair, and candlestick data for Uniswap V3#

In this notebook, we create a basic example of how to load:

  1. Exchanges

  2. Pairs

  3. Candle data

  • We use the TradingStrategy API to get data for 3 pairs on Uniswap V3

  • This is done for 3 pairs: eth_usdc, eth_usdt, and usdt_usdc

The following code block shows an example of some the data from the api

Load exchanges and pairs#

First, let’s create a TradingStrategy dataset client#

[1]:
from tradingstrategy.client import Client

client = Client.create_jupyter_client()
Started Trading Strategy in Jupyter notebook environment, configuration is stored in /home/alex/.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 172857, total exchanges 4431
[3]:
pairs_df = columnar_pair_table.to_pandas()
print(pairs_df.head())
   pair_id  chain_id  exchange_id                                     address  \
0        1         1            1  0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc
1        3         1            1  0x12ede161c702d1494612d19f05992f43aa6a26fb
2        4         1            1  0xa478c2975ab1ea89e8196811f51a7b7ade33eb11
3        5         1            1  0x07f068ca326a469fc1d87d85d448990c8cba7df9
4        6         1            1  0xae461ca67b15dc8dc81ce7615e0320da1a9ab8d5

                               token0_address  \
0  0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
1  0x06af07097c9eeb7fd685c692751d5c66db49c215
2  0x6b175474e89094c44da98b954eedeac495271d0f
3  0x408e41876cccdc0f92210600ef50372656052a38
4  0x6b175474e89094c44da98b954eedeac495271d0f

                               token1_address token0_symbol token1_symbol  \
0  0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2          USDC          WETH
1  0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2          CHAI          WETH
2  0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2           DAI          WETH
3  0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48           REN          USDC
4  0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48           DAI          USDC

     dex_type base_token_symbol  ... sell_count_all_time  buy_volume_all_time  \
0  uniswap_v2              WETH  ...           2327412.0         2.162229e+10
1  uniswap_v2              CHAI  ...               349.0         6.703155e+04
2  uniswap_v2              WETH  ...            748406.0         7.822935e+09
3  uniswap_v2               REN  ...               564.0         4.783008e+04
4  uniswap_v2               DAI  ...             86257.0         2.858813e+08

   sell_volume_all_time buy_count_30d sell_count_30d buy_volume_30d  \
0          2.144116e+10       24031.0        18386.0   4.362241e+07
1          6.941784e+04           NaN            NaN            NaN
2          7.720916e+09        3185.0         2928.0   5.676228e+06
3          4.963640e+04           NaN            NaN            NaN
4          2.849519e+08         348.0          354.0   4.752193e+05

   sell_volume_30d  buy_tax  transfer_tax  sell_tax
0     4.428402e+07      0.0           0.0       0.0
1              NaN    999.0         999.0     999.0
2     5.855924e+06      0.0           0.0       0.0
3              NaN    999.0         999.0     999.0
4     4.767471e+05      0.0           0.0       0.0

[5 rows x 36 columns]

Filtering pairs to have 5 BPS fee on Uniswap V3#

[4]:
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

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 does not make trading sense (unless in arbitrage, which is not covered here)
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 382 total pairs at 5 BPS fee tier
Found 317 volatile pairs quoted in any token
Found 161 volatile pairs quoted in a stablecoin
Found 15 pairs with enough volume

Get candle data using API#

This is an example of gettting data directly from the TradingStrategy API. Visit the API explorer for the full API documentation.

Note: This is a slow method and shouldn’t be used for actual backtesting purposes. For backtesting, candle data comes from the TradingStrategyUniverse (created by the create_trading_universe function). Visit the strategy examples section for backtesting examples.

[5]:
import requests
import pandas as pd

pairs = {
    'eth_usdc': 'https://tradingstrategy.ai/api/candles?pair_id=2697765&exchange_type=uniswap_v3&time_bucket=4h',
    'usdt_usdc': 'https://tradingstrategy.ai/api/candles?pair_id=2711887&exchange_type=uniswap_v3&time_bucket=4h',
    'eth_usdt': 'https://tradingstrategy.ai/api/candles?pair_id=2697770&exchange_type=uniswap_v3&time_bucket=4h'

}

def get_candles(url: str) -> pd.DataFrame:
    x = requests.get(url)
    json = x.json()

    candles = pd.DataFrame.from_dict(json)
    candles.rename(columns = {'ts':'date','o':'open', 'h':'high','l':'low','c':'close','v':'volume'}, inplace = True)
    candles['timestamp'] = pd.to_datetime(candles['date'])
    candles = candles.set_index('date')
    return candles

pair_data = dict([ (k,get_candles(r)) for k,r in pairs.items()])

pair_data['usdt_usdc'].head()
[5]:
open high low close volume xr b s tc bv sv timestamp
date
2023-05-22T20:00:00 1.0003 1.0003 1.0003 1.0003 4.419615e+06 1.0 None None None None None 2023-05-22 20:00:00
2023-05-23T00:00:00 1.0003 1.0003 1.0003 1.0003 5.208769e+06 1.0 None None None None None 2023-05-23 00:00:00
2023-05-23T04:00:00 1.0003 1.0003 1.0003 1.0003 2.442417e+07 1.0 None None None None None 2023-05-23 04:00:00
2023-05-23T08:00:00 1.0003 1.0003 1.0003 1.0003 2.184966e+07 1.0 None None None None None 2023-05-23 08:00:00
2023-05-23T12:00:00 1.0003 1.0003 1.0003 1.0003 2.106995e+07 1.0 None None None None None 2023-05-23 12:00:00

Visualize candlestick data#

Here we visualize the prices and volumes of each of the 3 pairs.

[6]:
from tradingstrategy.charting.candle_chart import visualise_ohlcv

def get_figure(candles: pd.DataFrame, chart_name: str):
    return visualise_ohlcv(
            candles,
            height=600,
            theme="plotly_white",
            chart_name=chart_name,
            y_axis_name="Price",
            volume_axis_name="volume",
        )
figures = dict([ (k,get_figure(r, k)) for k,r in pair_data.items()])

figures['eth_usdc'].show()
figures['eth_usdt'].show()
figures['usdt_usdc'].show()