Trading pairs¶
Trading pair information and pair datasets.
The core classes to understand the data are
To download the pairs dataset see
- exception tradingstrategy.pair.NoPairFound¶
No trading pair found matching the given criteria.
- exception tradingstrategy.pair.DuplicatePair¶
Found multiple trading pairs for the same naive lookup.
- class tradingstrategy.pair.PairType¶
What kind of an decentralised exchange, AMM or other the pair is trading on.
Note that each type can have multiple implementations. For example QuickSwap, Sushi and Pancake are all Uniswap v2 types.
- uniswap_v2 = 'uni_v2'¶
Uniswap v2 style exchange
- uniswap_v3 = 'uni_v3'¶
Uniswap v3 style exchange
- class tradingstrategy.pair.DEXPair¶
Trading pair information for a single pair.
Presents a single trading pair on decentralised exchanges.
DEX trading pairs can be uniquely identified by
Internal id.
(Chain id, address) tuple - the same address can exist on multiple chains.
(Chain slug, exchange slug, pair slug) tuple.
Token names and symbols are not unique - anyone can create any number of trading pair tickers and token symbols. Do not rely on token symbols for anything.
About data:
There is a different between token0 and token1 and base_token and quote_token conventions - the former are raw DEX (Uniswap) data while the latter are preprocessed by the server to make the data more understandable. Base token is the token you are trading and the quote token is the token you consider “money” for the trading. E.g. in WETH-USDC, USDC is the quote token. In SUSHI-WETH, WETH is the quote token.
Optional fields may be available if the candle server 1) detected the pair popular enough 2) managed to fetch the third party service information related to the token
When you download a trading pair dataset from the server, not all trading pairs are available. For more information about trading pair availability see trading pair tracking.
The class provides some JSON helpers to make it more usable with JSON based APIs.
This data class is serializable via dataclasses-json methods. Example:
info_as_string = pair.to_json()You can also do __json__() convention data export:
info_as_dict = pair.__json__()Note
Currently all flags are disabled and will be removed in the future. The historical dataset does not contain any filtering flags, because the data has to be filtered prior to download, to keep the download dump in a reasonasble size. The current data set of 800k trading pairs produce 100 MB dataset of which most of the pairs are useless. The server prefilters trading pairs and thus you cannot access historical data of pairs that have been prefiltered.
- pair_id: tradingstrategy.types.PrimaryKey¶
Internal primary key for any trading pair
- chain_id: tradingstrategy.chain.ChainId¶
The chain id on which chain this pair is trading. 1 for Ethereum.
- exchange_id: tradingstrategy.types.PrimaryKey¶
The exchange where this token trades
- address: tradingstrategy.types.NonChecksummedAddress¶
Smart contract address for the pair. In the case of Uniswap this is the pair (pool) address.
- dex_type: tradingstrategy.pair.PairType¶
What kind of exchange this pair is on
- token0_symbol: Optional[str]¶
Token0 as in raw Uniswap data. ERC-20 contracst are not guaranteed to have this data.
- token1_symbol: Optional[str]¶
Token1 as in raw Uniswap data ERC-20 contracst are not guaranteed to have this data.
- base_token_symbol: Optional[str] = None¶
Naturalised base and quote token. Uniswap may present the pair in USDC-WETH or WETH-USDC order based on the token address order. However we humans always want the quote token to be USD, or ETH or BTC. For the reverse token orders, the candle serve swaps the token order so that the quote token is the more natural token of the pair (in the above case USD)
- quote_token_symbol: Optional[str] = None¶
Naturalised base and quote token. Uniswap may present the pair in USDC-WETH or WETH-USDC order based on the token address order. However we humans always want the quote token to be USD, or ETH or BTC. For the reverse token orders, the candle serve swaps the token order so that the quote token is the more natural token of the pair (in the above case USD)
- token0_decimals: Optional[int] = None¶
Number of decimals to convert between human amount and Ethereum fixed int raw amount. Note - this information might be missing from ERC-20 smart contracts. If the information is missing the token is not tradeable in practice.
- token1_decimals: Optional[int] = None¶
Number of decimals to convert between human amount and Ethereum fixed int raw amount Note - this information might be missing from ERC-20 smart contracts. If the information is missing the token is not tradeable in practice.
- exchange_address: Optional[str] = None¶
Exchange factory address. Denormalised here, so we do not need an additional lookup.
- first_swap_at_block_number: Optional[tradingstrategy.types.BlockNumber] = None¶
Block number of the first Uniswap Swap event
- last_swap_at_block_number: Optional[tradingstrategy.types.BlockNumber] = None¶
Block number of the last Uniswap Swap event
- first_swap_at: Optional[tradingstrategy.types.UNIXTimestamp] = None¶
Timestamp of the first Uniswap Swap event
- last_swap_at: Optional[tradingstrategy.types.UNIXTimestamp] = None¶
Timestamp of the first Uniswap Swap event
- flag_inactive: Optional[bool] = None¶
Pair has been flagged inactive, because it has not traded at least once during the last 30 days. TODO - inactive, remove.
- flag_blacklisted_manually: Optional[bool] = None¶
Pair is blacklisted by operators. Current there is no blacklist process so this is always false. TODO - inactive, remove.
- flag_unsupported_quote_token: Optional[bool] = None¶
Quote token is one of USD, ETH, BTC, MATIC or similar popular token variants. Because all candle data is outputted in the USD, if we have a quote token for which we do not have an USD conversation rate reference price source, we cannot create candles for the pair. TODO - inactive, remove.
- flag_unknown_exchange: Optional[bool] = None¶
Pair is listed on an exchange we do not if it is good or not TODO - inactive, remove.
- fee: Optional[tradingstrategy.types.BasisPoint] = None¶
Swap fee in basis points if known
- buy_tax: Optional[float] = None¶
Buy token tax for this trading pair. See Token tax and deflationary tokens for details.
- transfer_tax: Optional[float] = None¶
Transfer token tax for this trading pair. See Token tax and deflationary tokens for details.
- sell_tax: Optional[float] = None¶
Sell tax for this trading pair. See Token tax and deflationary tokens for details.
- property base_token_address: str¶
Get smart contract address for the base token.
- Returns
Lowercase, non-checksummed.
- property quote_token_address: str¶
Get smart contract address for the quote token
- Returns
Token address in checksummed case
- get_friendly_name(exchange_universe: tradingstrategy.exchange.ExchangeUniverse) str ¶
Get a very human readable name for this trading pair.
We need to translate the exchange id to someething human readable, and for this we need to have the access to the exchange universe.
- get_trading_pair_page_url() Optional[str] ¶
Get information page for this trading pair.
- Returns
URL of the trading pair page or None if page/data not available.
- classmethod to_pyarrow_schema() pyarrow.lib.Schema ¶
Construct schema for reading writing Parquet filss for pair information.
- classmethod convert_to_pyarrow_table(pairs: List[tradingstrategy.pair.DEXPair], check_schema=False) pyarrow.lib.Table ¶
Convert a list of DEXPair instances to a Pyarrow table.
Used to prepare a data export on a server.
- Parameters
pairs – The list wil be consumed in the process
check_schema – Run additional checks on the data. Slow. Use only in tests. May be give happier error messages instead of “OverflowError” what pyarrow spits out.
- classmethod convert_to_dataframe(pairs: List[tradingstrategy.pair.DEXPair]) pandas.core.frame.DataFrame ¶
Convert Python DEXPair objects back to the Pandas dataframe presentation.
As this is super-inefficient, do not use for large amount of data.
- __init__(pair_id: tradingstrategy.types.PrimaryKey, chain_id: tradingstrategy.chain.ChainId, exchange_id: tradingstrategy.types.PrimaryKey, address: tradingstrategy.types.NonChecksummedAddress, dex_type: tradingstrategy.pair.PairType, token0_address: str, token1_address: str, token0_symbol: Optional[str], token1_symbol: Optional[str], base_token_symbol: Optional[str] = None, quote_token_symbol: Optional[str] = None, token0_decimals: Optional[int] = None, token1_decimals: Optional[int] = None, exchange_slug: Optional[str] = None, exchange_address: Optional[str] = None, pair_slug: Optional[str] = None, first_swap_at_block_number: Optional[tradingstrategy.types.BlockNumber] = None, last_swap_at_block_number: Optional[tradingstrategy.types.BlockNumber] = None, first_swap_at: Optional[tradingstrategy.types.UNIXTimestamp] = None, last_swap_at: Optional[tradingstrategy.types.UNIXTimestamp] = None, flag_inactive: Optional[bool] = None, flag_blacklisted_manually: Optional[bool] = None, flag_unsupported_quote_token: Optional[bool] = None, flag_unknown_exchange: Optional[bool] = None, fee: Optional[tradingstrategy.types.BasisPoint] = None, buy_count_all_time: Optional[int] = None, sell_count_all_time: Optional[int] = None, buy_volume_all_time: Optional[float] = None, sell_volume_all_time: Optional[float] = None, buy_count_30d: Optional[int] = None, sell_count_30d: Optional[int] = None, buy_volume_30d: Optional[float] = None, sell_volume_30d: Optional[float] = None, buy_tax: Optional[float] = None, transfer_tax: Optional[float] = None, sell_tax: Optional[float] = None) None ¶
- class tradingstrategy.pair.PandasPairUniverse¶
A pair universe implementation that is created from Pandas dataset.
This is a helper class, as
pandas.DataFrame
is somewhat more difficult to interact with. This class will read the raw data frame and convert it to DEXPair objects with a lookup index. Because the DEXPair conversion is expensive for 10,000s of Python objects, it is recommended that you filter the rawpandas.DataFrame
by using filtering functions intradingstrategy.pair
first, before initializingPandasPairUniverse
.About the usage:
Single trading pairs can be looked up using
PandasPairUniverse.get_pair_by_smart_contract()
andPandasPairUniverse.get_pair_by_id()
Multiple pairs can be looked up by directly reading PandasPairUniverse.df Pandas dataframe
Example how to use:
# Get dataset from the server as Apache Pyarrow table columnar_pair_table = client.fetch_pair_universe() # Convert Pyarrow -> Pandas -> in-memory DEXPair index pair_universe = PandasPairUniverse(columnar_pair_table.to_pandas()) # Lookup SUSHI-WETH trading pair from DEXPair index # https://tradingstrategy.ai/trading-view/ethereum/sushi/sushi-eth pair: DEXPair = pair_universe.get_pair_by_smart_contract("0x795065dcc9f64b5614c407a6efdc400da6221fb0")If the pair index is too slow to build, or you want to keep it lean, you can disable the indexing with build_index. In this case, some of the methods won’t work:
# Get dataset from the server as Apache Pyarrow table columnar_pair_table = client.fetch_pair_universe() # Convert Pyarrow -> Pandas -> in-memory DEXPair index pair_universe = PandasPairUniverse(columnar_pair_table.to_pandas(), build_index=False)
- __init__(df: pandas.core.frame.DataFrame, build_index=True)¶
- Parameters
df – The source DataFrame that contains all DEXPair entries
build_index – Build quick lookup index for pairs
- build_index()¶
Create pair_id -> data mapping.
Allows fast lookup of individual pairs.
- get_pair_by_id(pair_id: tradingstrategy.types.PrimaryKey) Optional[tradingstrategy.pair.DEXPair] ¶
Look up pair information and return its data.
- Returns
Nicely presented
DEXPair
.
- get_pair_by_smart_contract(address: str) Optional[tradingstrategy.pair.DEXPair] ¶
Resolve a trading pair by its pool smart contract address.
- Parameters
address – Ethereum smart contract address of the Uniswap pair contract
- get_token(address: str) Optional[tradingstrategy.token.Token] ¶
Get a token that is part of any trade pair.
Get a token details for a token that is base or quotetoken of any trading pair.
..note
TODO: Not a final implementation subject to chage.
- Returns
Tuple (name, symbol, address, decimals) or None if not found.
- get_all_tokens() Set[tradingstrategy.token.Token] ¶
Get all base and quote tokens in trading pairs.
Warning
This method is useful for only test/limited pair count universes. It is very slow and mainly purported for debugging and diagnostics.
- get_single() tradingstrategy.pair.DEXPair ¶
For strategies that trade only a single trading pair, get the only pair in the universe.
- Raises
AssertionError – If our pair universe does not have an exact single pair
- get_by_symbols(base_token_symbol: str, quote_token_symbol: str) Optional[tradingstrategy.pair.DEXPair] ¶
For strategies that trade only a few trading pairs, get the only pair in the universe.
Warning
Currently, this method is only safe for prefiltered universe. There are no safety checks if the returned trading pair is legit. In the case of multiple matching pairs, a random pair is returned.g
- get_one_pair_from_pandas_universe(exchange_id: tradingstrategy.types.PrimaryKey, base_token: str, quote_token: str, pick_by_highest_vol=False) Optional[tradingstrategy.pair.DEXPair] ¶
Get a trading pair by its ticker symbols.
Note that this method works only very simple universes, as any given pair is poised to have multiple tokens and multiple trading pairs on different exchanges.
Example:
# Get PancakeSwap exchange, # for the full exchange list see https://tradingstrategy.ai/trading-view/exchanges pancake = exchange_universe.get_by_chain_and_slug(ChainId.bsc, "pancakeswap-v2") # Because there can be multiple trading pairs with same tickers, # we pick the genuine among the scams based on its trading volume wbnb_busd_pair = pair_universe.get_one_pair_from_pandas_universe( pancake.exchange_id, "WBNB", "BUSD", pick_by_highest_vol=True, ) print("WBNB address is", wbnb_busd_pair.base_token_address) print("BUSD address is", wbnb_busd_pair.quote_token_address) print("WBNB-BUSD pair contract address is", wbnb_busd_pair.address)
- Parameters
pick_by_highest_vol – If multiple trading pairs with the same symbols are found, pick one with the highest volume. This is because often malicious trading pairs are create to attract novice users.
- Raises
DuplicatePair – If the universe contains more than single entry for the pair.
- Returns
None if there is no match
- static create_single_pair_universe(df: pandas.core.frame.DataFrame, exchange: tradingstrategy.exchange.Exchange, base_token_symbol: str, quote_token_symbol: str, pick_by_highest_vol=True) tradingstrategy.pair.PandasPairUniverse ¶
Create a trading pair universe that contains only a single trading pair.
This is useful for trading strategies that to technical analysis trading on a single trading pair like BTC-USD.
- Parameters
df – Unfiltered DataFrame for all pairs
exchange – Exchange instance on the pair is trading
base_token_symbol – Base token symbol of the trading pair
quote_token_symbol – Base token symbol of the trading pair
pick_by_highest_vol – In the case of multiple match per token symbol, or scam tokens, pick one with the highest trade volume
- Raises
DuplicatePair – Multiple pairs matching the criteria
NoPairFound – No pairs matching the criteria
- static create_limited_pair_universe(df: pandas.core.frame.DataFrame, exchange: tradingstrategy.exchange.Exchange, pairs: List[Tuple[str, str]], pick_by_highest_vol=True) tradingstrategy.pair.PandasPairUniverse ¶
Create a trading pair universe that contains only few trading pairs.
This is useful for trading strategies that to technical analysis trading on a few trading pairs, or single pair three-way trades like Cake-WBNB-BUSD.
- Parameters
df – Unfiltered DataFrame for all pairs
exchange – Exchange instance on the pair is trading
pairs – List of trading pairs as ticket tuples. E.g. [ (“WBNB, “BUSD”), (“Cake”, “WBNB”) ]
pick_by_highest_vol – In the case of multiple match per token symbol, or scam tokens, pick one with the highest trade volume
- Raises
DuplicatePair – Multiple pairs matching the criteria
NoPairFound – No pairs matching the criteria
- class tradingstrategy.pair.LegacyPairUniverse¶
The queries universe, as returned by the server.
Note
TODO: Legacy prototype implementation and will be deprecated.
Converts raw pair dataset to easier to use DEXPair in-memory index.
You likely want to use
PandasPairUniverse
, as its offers much more functionality than this implemetation.
- __init__(pairs: Dict[int, tradingstrategy.pair.DEXPair])¶
- pairs: Dict[int, tradingstrategy.pair.DEXPair]¶
Internal id -> DEXPair mapping
- classmethod create_from_pyarrow_table(table: pyarrow.lib.Table) tradingstrategy.pair.LegacyPairUniverse ¶
Convert columnar presentation to a Python in-memory objects.
Some data manipulation is easier with objects instead of columns.
Note
This seems to quite slow operation. It is recommend you avoid this if you do not need row-like data.
- classmethod create_from_pyarrow_table_with_filters(table: pyarrow.lib.Table, chain_id_filter: Optional[tradingstrategy.chain.ChainId] = None) tradingstrategy.pair.LegacyPairUniverse ¶
Convert columnar presentation to a Python in-memory objects.
Filter the pairs based on given filter arguments.
- get_pair_by_id(pair_id: int) Optional[tradingstrategy.pair.DEXPair] ¶
Resolve pair by its id.
Only useful for debugging. Does a slow look
- get_pair_by_ticker(base_token, quote_token) Optional[tradingstrategy.pair.DEXPair] ¶
Get a trading pair by its ticker symbols.
Note that this method works only very simple universes, as any given pair is poised to have multiple tokens and multiple trading pairs on different exchanges.
- Raises
DuplicatePair – If the universe contains more than single entry for the pair.
- Returns
None if there is no match
- get_pair_by_ticker_by_exchange(exchange_id: int, base_token: str, quote_token: str) Optional[tradingstrategy.pair.DEXPair] ¶
Get a trading pair by its ticker symbols.
Note that this method works only very simple universes, as any given pair is poised to have multiple tokens and multiple trading pairs on different exchanges.
- Parameters
exchange_id – E.g. 1 for uniswap_v2
- Raises
DuplicatePair – If the universe contains more than single entry for the pair. Because we are looking by a token symbol there might be fake tokens with the same symbol.
- Returns
None if there is no match
- get_all_pairs_on_exchange(exchange_id: int) Iterable[tradingstrategy.pair.DEXPair] ¶
Get all trading pair on a decentralsied exchange.
Use ExchangeUniverse.get_by_chain_and_slug to resolve the exchange_id first. :param chain_id: E.g. ChainId.ethereum
- Parameters
exchange_id – E.g. 1 for uniswap_v2
- Raises
DuplicatePair – If the universe contains more than single entry for the pair. Because we are looking by a token symbol there might be fake tokens with the same symbol.
- Returns
None if there is no match
- get_active_pairs() Iterable[tradingstrategy.pair.DEXPair] ¶
Filter for pairs that have see a trade for the last 30 days
- get_inactive_pairs() Iterable[tradingstrategy.pair.DEXPair] ¶
Filter for pairs that have not see a trade for the last 30 days
- tradingstrategy.pair.filter_for_exchanges(pairs: pandas.core.frame.DataFrame, exchanges: List[tradingstrategy.exchange.Exchange]) pandas.core.frame.DataFrame ¶
Filter dataset so that it only contains data for the trading pairs from a certain exchange.
Useful as a preprocess step for creating
tradingstrategy.candle.GroupedCandleUniverse
ortradingstrategy.liquidity.GroupedLiquidityUniverse
.
- tradingstrategy.pair.filter_for_quote_tokens(pairs: pandas.core.frame.DataFrame, quote_token_addresses: Union[List[str], Set[str]]) pandas.core.frame.DataFrame ¶
Filter dataset so that it only contains data for the trading pairs that have a certain quote tokens.
Useful as a preprocess step for creating
tradingstrategy.candle.GroupedCandleUniverse
ortradingstrategy.liquidity.GroupedLiquidityUniverse
.You might, for example, want to construct a trading universe where you have only BUSD pairs.
- Parameters
quote_token_addresses – List of Ethereum addresses of the tokens - most be lowercased, as Ethereum addresses in our raw data are.
- class tradingstrategy.pair.StablecoinFilteringMode¶
How to filter pairs in stablecoin filtering.
- tradingstrategy.pair.filter_for_stablecoins(pairs: pandas.core.frame.DataFrame, mode: tradingstrategy.pair.StablecoinFilteringMode) pandas.core.frame.DataFrame ¶
Filter dataset so that it only contains data for the trading pairs that are either stablecoin pairs or not.
Trading logic might not be able to deal with or does not want to deal with stable -> stable pairs. Trading stablecoin to another does not make sense, unless you are doing high volume arbitration strategies.
Uses internal stablecoin list from
tradingstrategy.stablecoin
.