Price impact is not tracked cumulatively
Description
The price impact of a trade is calculated in getTradePriceImpact
which calls getTradePriceImpactPure
:
function getTradePriceImpact(
uint openPrice,
uint pairIndex,
bool long,
uint tradeOpenInterest
) external view override
returns (uint priceImpactP, uint priceAfterImpact) {
(priceImpactP, priceAfterImpact) = getTradePriceImpactPure(
openPrice,
long,
tradeOpenInterest,
long ? pairParams[pairIndex].onePercentDepthAbove :
pairParams[pairIndex].onePercentDepthBelow
);
}
function getTradePriceImpactPure(
uint openPrice,
bool long,
uint tradeOpenInterest,
uint onePercentDepth
) public pure returns (uint priceImpactP, uint priceAfterImpact) {
if (onePercentDepth == 0) {
return (0, openPrice);
}
priceImpactP = (tradeOpenInterest * _PRECISION) / onePercentDepth;
uint priceImpact = (priceImpactP * openPrice) / _PRECISION / 100;
priceAfterImpact = long ? openPrice + priceImpact :
openPrice - priceImpact;
}
The price impact is calculated based only on the Pyth price openPrice
and the size of the position being opened tradeOpenInterest
. Using these parameters, the price impact is approximated linearly using a governance-set one percent depth above or below parameter.
Impact
Since the price impact is not cumulative across multiple successive trades, instead of placing one large trade with large price impact, a trader should instead split it up into multiple smaller trades. Allowing a sophisticated trader to experience a much lower price impact by splitting up their trade adds considerable risk because the price impact is then cumulatively not correctly modeled.
Recommendations
Cumulatively track the price impact, resetting it after a new price is obtained from the oracle so that there is little or no benefit to splitting up a trade into smaller trades.
Remediation
Avantis is changing the price impact formulation as per their ongoing economic modelling.