Loading exchange, pair, and candlestick data for Uniswap V3#
In this notebook, we create a basic example of how to load:
Exchanges
Pairs
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 185803, total exchanges 4668
[3]:
pairs_df = columnar_pair_table.to_pandas()
display(pairs_df.head())
pair_id | chain_id | exchange_id | address | token0_address | token1_address | token0_symbol | token1_symbol | dex_type | base_token_symbol | ... | sell_count_all_time | buy_volume_all_time | sell_volume_all_time | buy_count_30d | sell_count_30d | buy_volume_30d | sell_volume_30d | buy_tax | transfer_tax | sell_tax | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc | 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 | 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 | USDC | WETH | uniswap_v2 | WETH | ... | 2366545.0 | 2.169846e+10 | 2.151672e+10 | 27214.0 | 21778.0 | 4.145122e+07 | 4.134013e+07 | 0.0 | 0.0 | 0.0 |
1 | 3 | 1 | 1 | 0x12ede161c702d1494612d19f05992f43aa6a26fb | 0x06af07097c9eeb7fd685c692751d5c66db49c215 | 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 | CHAI | WETH | uniswap_v2 | CHAI | ... | 352.0 | 6.713448e+04 | 6.953514e+04 | 1.0 | 2.0 | 6.592286e+01 | 6.581656e+01 | 999.0 | 999.0 | 999.0 |
2 | 4 | 1 | 1 | 0xa478c2975ab1ea89e8196811f51a7b7ade33eb11 | 0x6b175474e89094c44da98b954eedeac495271d0f | 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 | DAI | WETH | uniswap_v2 | WETH | ... | 753814.0 | 7.832598e+09 | 7.730437e+09 | 2626.0 | 3131.0 | 3.699619e+06 | 3.692982e+06 | 0.0 | 0.0 | 0.0 |
3 | 5 | 1 | 1 | 0x07f068ca326a469fc1d87d85d448990c8cba7df9 | 0x408e41876cccdc0f92210600ef50372656052a38 | 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 | REN | USDC | uniswap_v2 | REN | ... | 565.0 | 4.783008e+04 | 4.966043e+04 | NaN | NaN | NaN | NaN | 999.0 | 999.0 | 999.0 |
4 | 6 | 1 | 1 | 0xae461ca67b15dc8dc81ce7615e0320da1a9ab8d5 | 0x6b175474e89094c44da98b954eedeac495271d0f | 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 | DAI | USDC | uniswap_v2 | DAI | ... | 86735.0 | 2.862940e+08 | 2.853550e+08 | 172.0 | 228.0 | 2.170395e+05 | 2.190588e+05 | 0.0 | 0.0 | 0.0 |
5 rows × 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 420 total pairs at 5 BPS fee tier
Found 352 volatile pairs quoted in any token
Found 176 volatile pairs quoted in a stablecoin
Found 17 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()
(key, value) = json.popitem()
candles = pd.DataFrame.from_dict(value)
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('timestamp')
return candles
pair_data = dict([ (k,get_candles(r)) for k,r in pairs.items()])
pair_data['usdt_usdc'].head()
[5]:
date | open | high | low | close | volume | xr | b | s | tc | bv | sv | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
timestamp | ||||||||||||
2023-07-23 08:00:00 | 2023-07-23T08:00:00 | 1.0000 | 1.0001 | 1.0000 | 1.0001 | 1.153055e+06 | 1.0 | None | None | None | None | None |
2023-07-23 12:00:00 | 2023-07-23T12:00:00 | 1.0001 | 1.0001 | 1.0001 | 1.0001 | 5.719236e+05 | 1.0 | None | None | None | None | None |
2023-07-23 16:00:00 | 2023-07-23T16:00:00 | 1.0001 | 1.0001 | 1.0001 | 1.0001 | 3.719233e+06 | 1.0 | None | None | None | None | None |
2023-07-23 20:00:00 | 2023-07-23T20:00:00 | 1.0001 | 1.0001 | 1.0001 | 1.0001 | 1.241179e+06 | 1.0 | None | None | None | None | None |
2023-07-24 00:00:00 | 2023-07-24T00:00:00 | 1.0001 | 1.0001 | 1.0001 | 1.0001 | 5.094711e+06 | 1.0 | None | None | None | None | None |
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()])
fig1 = figures['eth_usdc']
fig2 = figures['eth_usdt']
fig3 = figures['usdt_usdc']
# update titles
fig1.update_layout(title="ETH/USDC")
fig2.update_layout(title="ETH/USDT")
fig3.update_layout(title="USDT/USDC")
fig1.show()
fig2.show()
fig3.show()