Skip to content

Commit 3b6af90

Browse files
0xbigzcrispheaney
andauthored
sdk: add getTriggerAuctionStartPrice (#1654)
* sdk: add getTriggerAuctionStartPrice * updates * precisions * remove startBuffer param --------- Co-authored-by: Chris Heaney <[email protected]>
1 parent 9855f62 commit 3b6af90

File tree

1 file changed

+96
-1
lines changed

1 file changed

+96
-1
lines changed

sdk/src/math/auction.ts

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import { isOneOfVariant, isVariant, Order, PositionDirection } from '../types';
2-
import { BN, getVariant, ONE, OrderBitFlag, ZERO } from '../.';
2+
import {
3+
BN,
4+
getVariant,
5+
ONE,
6+
OrderBitFlag,
7+
ZERO,
8+
PerpMarketAccount,
9+
getPerpMarketTierNumber,
10+
QUOTE_PRECISION,
11+
PRICE_PRECISION,
12+
} from '../.';
313

414
export function isAuctionComplete(order: Order, slot: number): boolean {
515
if (order.auctionDuration === 0) {
@@ -177,3 +187,88 @@ export function deriveOracleAuctionParams({
177187
oraclePriceOffset: oraclePriceOffsetNum,
178188
};
179189
}
190+
191+
export function getTriggerAuctionStartPrice(params: {
192+
perpMarket: PerpMarketAccount;
193+
direction: PositionDirection;
194+
oraclePrice: BN;
195+
limitPrice?: BN;
196+
}): BN {
197+
const { perpMarket, direction, oraclePrice, limitPrice } = params;
198+
199+
const twapMismatch =
200+
perpMarket.amm.historicalOracleData.lastOraclePriceTwapTs
201+
.sub(perpMarket.amm.lastMarkPriceTwapTs)
202+
.abs()
203+
.gte(new BN(60)) ||
204+
perpMarket.amm.volume24H.lte(new BN(100_000).mul(QUOTE_PRECISION));
205+
206+
let baselineStartOffset: BN;
207+
208+
if (twapMismatch) {
209+
const contractTierNumber = getPerpMarketTierNumber(perpMarket);
210+
const priceDivisor = contractTierNumber <= 1 ? 500 : 100;
211+
baselineStartOffset = isVariant(direction, 'long')
212+
? perpMarket.amm.lastBidPriceTwap.divn(priceDivisor)
213+
: perpMarket.amm.lastAskPriceTwap.divn(priceDivisor).neg();
214+
} else {
215+
const markTwapSlow = isVariant(direction, 'long')
216+
? perpMarket.amm.lastBidPriceTwap
217+
: perpMarket.amm.lastAskPriceTwap;
218+
219+
const markTwapFast = perpMarket.amm.lastMarkPriceTwap5Min;
220+
const oracleTwapSlow =
221+
perpMarket.amm.historicalOracleData.lastOraclePriceTwap;
222+
const oracleTwapFast =
223+
perpMarket.amm.historicalOracleData.lastOraclePriceTwap5Min;
224+
225+
const offsetSlow = markTwapSlow.sub(oracleTwapSlow);
226+
const offsetFast = markTwapFast.sub(oracleTwapFast);
227+
228+
const fracOfLongSpreadInPrice = new BN(perpMarket.amm.longSpread)
229+
.mul(markTwapSlow)
230+
.div(PRICE_PRECISION.muln(10)); // divide by 10x for safety
231+
232+
const fracOfShortSpreadInPrice = new BN(perpMarket.amm.shortSpread)
233+
.mul(markTwapSlow)
234+
.div(PRICE_PRECISION.muln(10)); // divide by 10x for safety
235+
236+
baselineStartOffset = isVariant(direction, 'long')
237+
? BN.min(
238+
offsetSlow.add(fracOfLongSpreadInPrice),
239+
offsetFast.sub(fracOfShortSpreadInPrice)
240+
)
241+
: BN.max(
242+
offsetSlow.sub(fracOfShortSpreadInPrice),
243+
offsetFast.add(fracOfLongSpreadInPrice)
244+
);
245+
}
246+
247+
let startBuffer = -3500;
248+
249+
if (
250+
isVariant(perpMarket.contractTier, 'a') ||
251+
isVariant(perpMarket.contractTier, 'b')
252+
) {
253+
startBuffer = -500;
254+
}
255+
256+
// Apply start buffer (in BPS)
257+
const startBufferPrice = oraclePrice
258+
.mul(new BN(startBuffer))
259+
.div(new BN(PRICE_PRECISION));
260+
261+
let auctionStartPrice = isVariant(direction, 'long')
262+
? oraclePrice.add(baselineStartOffset).sub(startBufferPrice)
263+
: oraclePrice.add(baselineStartOffset).add(startBufferPrice);
264+
265+
if (limitPrice) {
266+
if (isVariant(direction, 'long')) {
267+
auctionStartPrice = BN.min(auctionStartPrice, limitPrice);
268+
} else {
269+
auctionStartPrice = BN.max(auctionStartPrice, limitPrice);
270+
}
271+
}
272+
273+
return auctionStartPrice;
274+
}

0 commit comments

Comments
 (0)