add check that slippage crosses bba (#548)
* add check that slippage crosses bba * fix tests
This commit is contained in:
@@ -1172,6 +1172,7 @@ export const mapToMarketOrderParams = async (
|
||||
const startPrice = estimatedPrices[startPriceProperty];
|
||||
|
||||
processedSlippageTolerance = calculateDynamicSlippage(
|
||||
direction === PositionDirection.LONG ? 'long' : 'short',
|
||||
params.marketIndex,
|
||||
params.marketType,
|
||||
driftClient,
|
||||
@@ -1377,6 +1378,7 @@ export const fetchL2FromRedis = async (
|
||||
* @returns Dynamic slippage tolerance as a number
|
||||
*/
|
||||
export const calculateDynamicSlippage = (
|
||||
direction: 'long' | 'short',
|
||||
marketIndex: number,
|
||||
marketType: string,
|
||||
driftClient: DriftClient,
|
||||
@@ -1397,7 +1399,6 @@ export const calculateDynamicSlippage = (
|
||||
|
||||
// Calculate spread using L2 data
|
||||
let spreadBaseSlippage = 0.0005; // 0.05% fallback spread
|
||||
try {
|
||||
// Get oracle data
|
||||
const oracleData = isPerp
|
||||
? driftClient.getMMOracleDataForPerpMarket(marketIndex)
|
||||
@@ -1412,6 +1413,8 @@ export const calculateDynamicSlippage = (
|
||||
oraclePrice
|
||||
);
|
||||
|
||||
|
||||
try {
|
||||
const spreadPctNum = BigNum.from(
|
||||
spreadInfo.spreadPct,
|
||||
PERCENTAGE_PRECISION_EXP
|
||||
@@ -1464,7 +1467,39 @@ export const calculateDynamicSlippage = (
|
||||
const minSlippage = parseFloat(process.env.DYNAMIC_SLIPPAGE_MIN || '0.035'); // 0.035% minimum
|
||||
const maxSlippage = parseFloat(process.env.DYNAMIC_SLIPPAGE_MAX || '5'); // 5% maximum
|
||||
|
||||
return Math.min(Math.max(dynamicSlippage, minSlippage), maxSlippage);
|
||||
let finalSlippage = Math.min(Math.max(dynamicSlippage, minSlippage), maxSlippage);
|
||||
|
||||
// make sure the slippage goes at least 1bp past the bestBid/bestAsk
|
||||
const impliedEndPriceNum = direction === 'long' ? (startPrice.toNumber() * (1 + finalSlippage / 100)) : (startPrice.toNumber() * (1 - finalSlippage / 100));
|
||||
|
||||
const impliedEndPrice = new BN(impliedEndPriceNum);
|
||||
|
||||
// Adjust slippage to ensure it goes 1bp past best bid/ask if needed
|
||||
try {
|
||||
const ONE_BP = 0.0001; // 1 basis point = 0.01%
|
||||
|
||||
if (direction === 'long' && spreadInfo.bestAskPrice) {
|
||||
// For LONG: if impliedEndPrice < bestAskPrice, adjust so startPrice + finalSlippage is 1bp greater than bestAskPrice
|
||||
if (impliedEndPrice.lt(spreadInfo.bestAskPrice)) {
|
||||
// Calculate required slippage: ((bestAskPrice * (1 + 1bp)) / startPrice - 1) * 100
|
||||
const targetPrice = spreadInfo.bestAskPrice.toNumber() * (1 + ONE_BP);
|
||||
const requiredSlippagePct = ((targetPrice / startPrice.toNumber()) - 1) * 100;
|
||||
finalSlippage = Math.max(finalSlippage, requiredSlippagePct);
|
||||
}
|
||||
} else if (direction === 'short' && spreadInfo.bestBidPrice) {
|
||||
// For SHORT: if impliedEndPrice > bestBidPrice, adjust so startPrice - finalSlippage is 1bp less than bestBidPrice
|
||||
if (impliedEndPrice.gt(spreadInfo.bestBidPrice)) {
|
||||
// Calculate required slippage: (1 - (bestBidPrice * (1 - 1bp)) / startPrice) * 100
|
||||
const targetPrice = spreadInfo.bestBidPrice.toNumber() * (1 - ONE_BP);
|
||||
const requiredSlippagePct = (1 - (targetPrice / startPrice.toNumber())) * 100;
|
||||
finalSlippage = Math.max(finalSlippage, requiredSlippagePct);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Failed to adjust slippage for best bid/ask:', error);
|
||||
}
|
||||
|
||||
return finalSlippage;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user