Price Impact
Calculate how your swap affects price as it consumes liquidity across multiple bins. Essential for understanding large trade costs and market impact.
What is Price Impact?
Price impact measures the difference between:
Spot Price: Current price at active bin
Execution Price: Average price after swap
Small swap: Uses 1 bin → Low impact
Large swap: Uses 5 bins → High impact
Basic Impact Calculation
async function calculatePriceImpact(
pair: LBPair,
amountIn: bigint,
xtoy: boolean
): Promise<number> {
// Get spot price
const spotPrice = getPriceFromBinId(
pair.parameters.active_id,
Number(pair.binStep)
);
// Calculate output
const amountOut = await calculateSwapOutput(pair, amountIn, xtoy);
// Calculate execution price
const executionPrice = xtoy
? Number(amountOut) / Number(amountIn)
: Number(amountIn) / Number(amountOut);
// Price impact percentage
return ((executionPrice - spotPrice) / spotPrice) * 100;
}
Bin-by-Bin Analysis
async function analyzeBinImpact(
pair: LBPair,
amountIn: bigint,
xtoy: boolean
) {
const activeId = pair.parameters.active_id;
const binStep = Number(pair.binStep);
// Get affected bins
const binRange = xtoy
? [activeId, activeId + 50]
: [activeId - 50, activeId];
const bins = await sdk.Pair.getPairBins(pair, binRange);
let remaining = amountIn;
let totalOut = 0n;
const binImpacts = [];
for (let i = 0; i < bins.length; i++) {
const binId = binRange[0] + i;
const bin = bins[i];
const binPrice = getPriceFromBinId(binId, binStep);
// How much liquidity consumed from this bin
const available = xtoy ? bin.reserve_y : bin.reserve_x;
const consumed = remaining > available ? available : remaining;
if (consumed > 0n) {
binImpacts.push({
binId,
price: binPrice,
consumed: consumed.toString(),
percentOfTotal: (Number(consumed) / Number(amountIn) * 100).toFixed(2)
});
remaining -= consumed;
totalOut += consumed; // Simplified
}
if (remaining === 0n) break;
}
return {
binsUsed: binImpacts.length,
startPrice: binImpacts[0]?.price,
endPrice: binImpacts[binImpacts.length - 1]?.price,
details: binImpacts
};
}
Impact Thresholds
function categorizeImpact(impactPercent: number): string {
if (impactPercent < 0.1) return "Negligible";
if (impactPercent < 0.5) return "Low";
if (impactPercent < 1.0) return "Moderate";
if (impactPercent < 3.0) return "High";
return "Severe";
}
// Warning system
async function checkSwapViability(
pair: LBPair,
amountIn: bigint,
xtoy: boolean
) {
const impact = await calculatePriceImpact(pair, amountIn, xtoy);
return {
impact: impact.toFixed(2) + "%",
category: categorizeImpact(Math.abs(impact)),
warning: Math.abs(impact) > 1.0 ? "Consider smaller trade size" : null
};
}
Depth Chart Analysis
// Calculate cumulative depth and impact
async function getMarketDepth(
pair: LBPair,
xtoy: boolean,
maxBins: number = 50
) {
const activeId = pair.parameters.active_id;
const binRange = xtoy
? [activeId, activeId + maxBins]
: [activeId - maxBins, activeId];
const bins = await sdk.Pair.getPairBins(pair, binRange);
let cumulativeLiquidity = 0n;
const depthLevels = [];
for (let i = 0; i < bins.length; i++) {
const bin = bins[i];
const liquidity = xtoy ? bin.reserve_y : bin.reserve_x;
cumulativeLiquidity += liquidity;
const impact = await calculatePriceImpact(
pair,
cumulativeLiquidity,
xtoy
);
depthLevels.push({
cumulative: cumulativeLiquidity,
impactPercent: impact,
binId: binRange[0] + i
});
}
return depthLevels;
}
Optimal Trade Size
// Find max trade size for target impact
async function findOptimalTradeSize(
pair: LBPair,
maxImpactPercent: number,
xtoy: boolean
): Promise<bigint> {
const testAmounts = [
parseEther("0.1"),
parseEther("1"),
parseEther("10"),
parseEther("100"),
parseEther("1000")
];
let optimalAmount = 0n;
for (const amount of testAmounts) {
const impact = await calculatePriceImpact(pair, amount, xtoy);
if (Math.abs(impact) <= maxImpactPercent) {
optimalAmount = amount;
} else {
break;
}
}
return optimalAmount;
}
Real-Time Display
// User-friendly impact display
async function displayPriceImpact(
pair: LBPair,
inputAmount: string,
decimals: number,
xtoy: boolean
) {
const amount = parseUnits(inputAmount, decimals);
const analysis = await analyzeBinImpact(pair, amount, xtoy);
const impact = await calculatePriceImpact(pair, amount, xtoy);
return {
priceImpact: impact.toFixed(2) + "%",
binsAffected: analysis.binsUsed,
priceRange: {
start: analysis.startPrice?.toFixed(4),
end: analysis.endPrice?.toFixed(4)
},
recommendation: Math.abs(impact) > 2
? "Consider splitting into smaller trades"
: "Acceptable impact"
};
}
Key Insights
Linear in bins: Each bin adds similar impact
Exponential in size: Doubling size > doubles impact
Direction matters: Buy/sell impacts differ
Time sensitive: Impact changes with liquidity
Related Topics
Calculate Swap Output - Get exact amounts
Get Pair Bins - Check liquidity
Slippage Protection - Set safety limits
Last updated