Price impact estimation#

In this notebook, we show how you can estimate the price impact of the simulated historical decentralised exchange trades.

The price impact is especially important when trading illiquid assets. If your trade profit is 2% but the price impact is also 2% you have essentially not made any profit.

About price impact on AMMs#

The price impact is a function of

  • Available liquidity

  • Liquidity provider fees

  • Protocol fees

Price impact indicates how much your market taker order loses in value due to insufficient liquidity. For example, if you are trying to buy 5000 USD worth of BNB token in a low liquidity pair and you end up with 4980 USD worth of token at the end of the trade, the loss in value due to low liquidity is called price impact. This can be expressed as USD value or as percent of the trade amount. Illiquid pairs higher price impact than liquid pairs.

Be careful not to confuse price impact and slippage. Slippage refers to a loss in value due to external trades in the same pair being executed by other users before yours and changing the relative prices of the assets in the pair.

In Uniswap v2 style decentralised exchanges any fees are included in the price impact calculation.

To understand the liquidity better, you can interactively view the available liquidity to any trading pair on Trading Strategy website.

For more information read more about XY=K liquidity model and automated market makers.

Getting started#

First let’s import libraries and initialise our 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

Fetching datasets#

Here we fetch the liquidity data for

To make this notebook run fast, we are operating on weekly candles (7 days) to keep the download size of datasets smaller.

[2]:

from tradingstrategy.chain import ChainId
from tradingstrategy.liquidity import GroupedLiquidityUniverse
from tradingstrategy.pair import PandasPairUniverse
from tradingstrategy.timebucket import TimeBucket

exchange_universe = client.fetch_exchange_universe()
raw_pairs = client.fetch_pair_universe().to_pandas()
raw_liquidity_samples = client.fetch_all_liquidity_samples(TimeBucket.d7).to_pandas()

pair_universe = PandasPairUniverse(raw_pairs)
liquidity_universe = GroupedLiquidityUniverse(raw_liquidity_samples)

# Do some test calculations for a single pair
sushi_swap = exchange_universe.get_by_chain_and_name(ChainId.ethereum, "sushi")
sushi_eth = pair_universe.get_one_pair_from_pandas_universe(sushi_swap.exchange_id, "SUSHI", "WETH")

Querying historical price impact#

Here we get the historical price impact what would have been for buying SUSHI for 6000 USD worth of ETH on 1st of June 2021.

Unlike many other examples, or the underlying DEX protocol, here we operate on US Dollar amounts. Any token price is converted to US Dollar through Trading Strategy reference pricing mechanism.

Currently Trading Strategy does not automatically fill you with the underlying liquidity provider and protocol fees paid with the transaction. In this example, we use Sushiswap fee model. You need to give these manually for the price estimator for now.

[3]:
import pandas as pd
from IPython.display import display
from tradingstrategy.priceimpact import HistoricalXYPriceImpactCalculator

# SUSHI-WETH started trading around 2020-09-01
trading_date = pd.Timestamp("2021-06-01")
trade_size = 6000.0  # USD

# See https://help.sushidocs.com/products/sushiswap-exchange
sushi_lp_fee = 0.0025
sushi_protocol_fee = 0.0005

price_impact_calculator = HistoricalXYPriceImpactCalculator(liquidity_universe, lp_fee=sushi_lp_fee, protocol_fee=sushi_protocol_fee)
impact = price_impact_calculator.calculate_price_impact(trading_date, sushi_eth.pair_id, trade_size, max_distance=pd.Timedelta(days=7))

# TODO: Show here more details about LP and protocol fees paid
# after we have confirmed them with an actual DEX smart contract

print(f"Trade date: {trading_date}")

print(f"Liquidity at the time of the trade: {impact.available_liquidity:,.2f} USD")

# we get 4 bps slippage
print(f"Price impact: {impact.price_impact*100:.2} %")

# We get 5984 USD worth of SUSHI
print(f"Delivered token amount: {impact.delivered:,.2f} USD")

Trade date: 2021-06-01 00:00:00
Liquidity at the time of the trade: 259,395,984.00 USD
Price impact: 0.017 %
Delivered token amount: 5,983.02 USD

Further info and sources of potential errors#

Because the lack of liquidity data, the price impact calculation may fail.

  • Trading pair lacks liquidity data

  • There is no liquidity data for a specific timestamp (see max_distance) parameter

See price impact API documentation for more information.