# Understand price impact and liquidity in pancakeswap

I am trying to understand how the price impact and liquidity was calculated in uniswap or pancakeswap through the router contract?

Is there is any direct method or what calculations need to do in my code? Pl. Guide me. Thanks in Advance

Disclaimer: I don't think this is the correct method to calculate the price impact but it's almost 100% accurate for price impacts of less than 1%. This calculation method assumes that multi-hop is disabled i.e. swapping is restricted to direct pairs. I've only tested this calculation method on PancakeSwap and it is less accurate for larger trade sizes compared to what is shown on their website. Attempting to calculate trade sizes for a 2% price impact, showed 1.99% on the PancakeSwap UI, 5% showed 4.99%, and 10% showed 9.97%. While these discrepancies could be attributed to the user interface lagging, I'm not confident that's the only reason. If anyone can better explain what's happening, I'd be very eager to know.

Given a liquidity pool with token A and token B, let:

• `reserve_a_initial` be the amount of token A in the liquidity pool before the trade
• `reserve_b_initial` be the amount of token B in the liquidity pool before the trade (not required to calculate the price impact)
• `fee` be the trading fee. For PancakeSwap, this is `0.0025`
• `amount_traded` be the amount of token A traded

To calculate the price impact:

``````amountInWithFee = amount_traded * (1 - fee);
price_impact = amountInWithFee / (reserve_a_initial + amountInWithFee);
``````

## Explanation

This article explains how to calculate the price impact. However, please note that what the article refers to as the "current market price" or "market rate", I refer to as the `mid_price`. Now, let's calculate the `price_impact`:

``````constant_product = reserve_a_initial * reserve_b_initial;
reserve_b_after_execution = constant_product / (reserve_a_initial + amountInWithFee);
amountOut = reserve_b_initial - reserve_b_after_execution;
market_price = amountInWithFee / amountOut;
mid_price = reserve_a_initial / reserve_b_initial;
price_impact = 1 - (mid_price / market_price);
``````

Before substituting and simplifying, let:

• `reserve_a_initial` be
• `reserve_b_initial` be
• `reserve_b_after_execution` be
• `amount_traded` be
• `fee` be
• `amountInWithFee` be
• `constant_product` be
• `amountOut` be
• `market_price` be
• `mid_price` be
• `price_impact` be

Now for the math:

I found this mind-blowing, but the amount of token B in the pool doesn't affect the `price_impact`. However, `reserve_b_initial` will affect `amount_out`.

## Calculating `amount_traded` given the `price_impact`

Rearranging the `price_impact` equation, it is possible to calculate `amount_traded` for a given `price_impact`:

## Slippage and minimum amount received

To account for slippage, `s`, and calculate the minimum received, `amount_out_min`:

``````amount_out_min = amount_out * (1 - s);
``````

Slippage does not affect `price_impact`.

## Sample code

I don't know if there's a function in a PancakeSwap contract that will directly return the `price_impact`, but you can get the reserves of a pool and then calculate it. Let's take CAKE-USDT as an example:

``````import { Contract, utils, providers } from 'ethers';
const poolAddress = '0xa39af17ce4a8eb807e076805da1e2b8ea7d0755b'; // CAKE-USDT
const poolContract = new Contract(
['function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast)'],
new providers.WebSocketProvider(PROVIDER_URL)
);

poolContract.getReserves()
.then((reserves) => {
let reserve_a_initial = parseFloat(utils.formatUnits(reserves._reserve0));
let reserve_b_initial = parseFloat(utils.formatUnits(reserves._reserve1));
console.log(`CAKE in pool: \${reserve_a_initial}`);
console.log(`USDT in pool: \${reserve_b_initial}`);

const fee = 0.0025;
let max_price_impact = 0.01;
let amount_traded_cake = reserve_a_initial * max_price_impact / ((1 - max_price_impact)*(1 - fee));
let amount_traded_usdt = reserve_b_initial * max_price_impact / ((1 - max_price_impact)*(1 - fee));
console.log(`Given a max price impact of \${max_price_impact*100}%, the max amount of CAKE tradeable is \${amount_traded_cake}`);
console.log(`Given a max price impact of \${max_price_impact*100}%, the max amount of USDT tradeable is \${amount_traded_usdt}`);

let amountInCAKE = amount_traded_cake * (1 - fee);
let amountInUSDT = amount_traded_usdt * (1 - fee);
let price_impact_trade_cake = amountInCAKE / (reserve_a_initial + amountInCAKE);
let price_impact_trade_usdt = amountInUSDT / (reserve_b_initial + amountInUSDT);
}).catch(console.error);
``````

Sample results:

``````CAKE in pool: 1030240.4016832297
USDT in pool: 19974605.474162016
Given a max price impact of 1%, the max amount of CAKE tradeable is 10432.550079068678
Given a max price impact of 1%, the max amount of USDT tradeable is 202269.36507087937
Price impact when trading 10432.550079068678 CAKE: 1%
Price impact when trading 202269.36507087937 USDT: 1%
``````

Please note that the price shown on the PancakeSwap UI is the `execution_price`:

``````execution_price = amount_traded / amountOut;
``````
• One of the best written answers on stackexchange! clap clap. Oct 16, 2021 at 13:40
• hi, somehow for me the 2 different ways of calculating price impact are not giving the same numbers. If we take first example of the article you linked we should get the same number if \$10000 / (2000000 + 10000) = 1 - (2000 / 2009.64)\$ which is not correct? Apr 22 at 4:46
• @Chris the article has some rounding errors. reserve_b_after_execution should be approx. 995.024876. amountOut (ETH received) should be approx. 4.975124. market_price (Price paid per ETH) should be exactly 2010. Thus, 10000 / (2000000 + 10000) = 1 - (2000 / 2010) Apr 22 at 14:25
• Thanks for this clear solution! really saved me a ton of time. May 12 at 23:36

.17% is added back to the pool, so we need to figure out how to split that up in order to get the exact rate of exchange. It's confusing me, because the rate is used in the calculation of rate.