Skip to content

Commit 5b981cb

Browse files
moosecat20xbigz
authored andcommitted
ref price offset amm math fix (#1828)
* ref price offset amm math fix * add latest slot optional var to callers of update amm spread
1 parent 0a45d88 commit 5b981cb

File tree

5 files changed

+70
-38
lines changed

5 files changed

+70
-38
lines changed

sdk/src/dlob/orderBookLevels.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,14 @@ export function getVammL2Generator({
182182
numOrders,
183183
now = new BN(Math.floor(Date.now() / 1000)),
184184
topOfBookQuoteAmounts = [],
185+
latestSlot,
185186
}: {
186187
marketAccount: PerpMarketAccount;
187188
mmOraclePriceData: MMOraclePriceData;
188189
numOrders: number;
189190
now?: BN;
190191
topOfBookQuoteAmounts?: BN[];
192+
latestSlot?: BN;
191193
}): L2OrderBookGenerator {
192194
const updatedAmm = calculateUpdatedAMM(marketAccount.amm, mmOraclePriceData);
193195
const paused = isOperationPaused(
@@ -211,7 +213,8 @@ export function getVammL2Generator({
211213
updatedAmm,
212214
mmOraclePriceData,
213215
now,
214-
isVariant(marketAccount.contractType, 'prediction')
216+
isVariant(marketAccount.contractType, 'prediction'),
217+
latestSlot
215218
);
216219

217220
const numBaseOrders = Math.max(1, numOrders - topOfBookQuoteAmounts.length);

sdk/src/math/amm.ts

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,16 @@ export function calculateUpdatedAMMSpreadReserves(
197197
amm: AMM,
198198
direction: PositionDirection,
199199
mmOraclePriceData: MMOraclePriceData,
200-
isPrediction = false
200+
isPrediction = false,
201+
latestSlot?: BN
201202
): { baseAssetReserve: BN; quoteAssetReserve: BN; sqrtK: BN; newPeg: BN } {
202203
const newAmm = calculateUpdatedAMM(amm, mmOraclePriceData);
203204
const [shortReserves, longReserves] = calculateSpreadReserves(
204205
newAmm,
205206
mmOraclePriceData,
206207
undefined,
207-
isPrediction
208+
isPrediction,
209+
latestSlot
208210
);
209211

210212
const dirReserves = isVariant(direction, 'long')
@@ -225,7 +227,8 @@ export function calculateBidAskPrice(
225227
amm: AMM,
226228
mmOraclePriceData: MMOraclePriceData,
227229
withUpdate = true,
228-
isPrediction = false
230+
isPrediction = false,
231+
latestSlot?: BN
229232
): [BN, BN] {
230233
let newAmm: AMM;
231234
if (withUpdate) {
@@ -238,7 +241,8 @@ export function calculateBidAskPrice(
238241
newAmm,
239242
mmOraclePriceData,
240243
undefined,
241-
isPrediction
244+
isPrediction,
245+
latestSlot
242246
);
243247

244248
const askPrice = calculatePrice(
@@ -939,7 +943,8 @@ export function calculateSpreadReserves(
939943
amm: AMM,
940944
mmOraclePriceData: MMOraclePriceData,
941945
now?: BN,
942-
isPrediction = false
946+
isPrediction = false,
947+
latestSlot?: BN
943948
) {
944949
function calculateSpreadReserve(
945950
spread: number,
@@ -1041,28 +1046,28 @@ export function calculateSpreadReserves(
10411046
amm.curveUpdateIntensity > 100;
10421047

10431048
if (doReferencePricOffsetSmooth) {
1044-
if (mmOraclePriceData.slot !== amm.lastUpdateSlot) {
1045-
const slotsPassed =
1046-
mmOraclePriceData.slot.toNumber() - amm.lastUpdateSlot.toNumber();
1047-
const fullOffsetDelta = referencePriceOffset - amm.referencePriceOffset;
1048-
const raw = Math.trunc(
1049-
Math.min(Math.abs(fullOffsetDelta), slotsPassed * 1000) / 10
1050-
);
1051-
const maxAllowed =
1052-
Math.abs(amm.referencePriceOffset) || Math.abs(referencePriceOffset);
1049+
const slotsPassed =
1050+
latestSlot != null
1051+
? BN.max(latestSlot.sub(amm.lastUpdateSlot), ZERO).toNumber()
1052+
: 0;
1053+
const fullOffsetDelta = referencePriceOffset - amm.referencePriceOffset;
1054+
const raw = Math.trunc(
1055+
Math.min(Math.abs(fullOffsetDelta), slotsPassed * 1000) / 10
1056+
);
1057+
const maxAllowed =
1058+
Math.abs(amm.referencePriceOffset) || Math.abs(referencePriceOffset);
10531059

1054-
const magnitude = Math.min(Math.max(raw, 10), maxAllowed);
1055-
const referencePriceDelta = Math.sign(fullOffsetDelta) * magnitude;
1060+
const magnitude = Math.min(Math.max(raw, 10), maxAllowed);
1061+
const referencePriceDelta = Math.sign(fullOffsetDelta) * magnitude;
10561062

1057-
referencePriceOffset = amm.referencePriceOffset + referencePriceDelta;
1063+
referencePriceOffset = amm.referencePriceOffset + referencePriceDelta;
10581064

1059-
if (referencePriceDelta < 0) {
1060-
longSpread += Math.abs(referencePriceDelta);
1061-
shortSpread += Math.abs(referencePriceOffset);
1062-
} else {
1063-
shortSpread += Math.abs(referencePriceDelta);
1064-
longSpread += Math.abs(referencePriceOffset);
1065-
}
1065+
if (referencePriceDelta < 0) {
1066+
longSpread += Math.abs(referencePriceDelta);
1067+
shortSpread += Math.abs(referencePriceOffset);
1068+
} else {
1069+
shortSpread += Math.abs(referencePriceDelta);
1070+
longSpread += Math.abs(referencePriceOffset);
10661071
}
10671072
}
10681073

sdk/src/math/market.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,16 @@ export function calculateReservePrice(
6161
*/
6262
export function calculateBidPrice(
6363
market: PerpMarketAccount,
64-
mmOraclePriceData: MMOraclePriceData
64+
mmOraclePriceData: MMOraclePriceData,
65+
latestSlot?: BN
6566
): BN {
6667
const { baseAssetReserve, quoteAssetReserve, newPeg } =
6768
calculateUpdatedAMMSpreadReserves(
6869
market.amm,
6970
PositionDirection.SHORT,
70-
mmOraclePriceData
71+
mmOraclePriceData,
72+
undefined,
73+
latestSlot
7174
);
7275

7376
return calculatePrice(baseAssetReserve, quoteAssetReserve, newPeg);
@@ -81,13 +84,16 @@ export function calculateBidPrice(
8184
*/
8285
export function calculateAskPrice(
8386
market: PerpMarketAccount,
84-
mmOraclePriceData: MMOraclePriceData
87+
mmOraclePriceData: MMOraclePriceData,
88+
latestSlot?: BN
8589
): BN {
8690
const { baseAssetReserve, quoteAssetReserve, newPeg } =
8791
calculateUpdatedAMMSpreadReserves(
8892
market.amm,
8993
PositionDirection.LONG,
90-
mmOraclePriceData
94+
mmOraclePriceData,
95+
undefined,
96+
latestSlot
9197
);
9298

9399
return calculatePrice(baseAssetReserve, quoteAssetReserve, newPeg);

sdk/src/math/position.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export function calculateBaseAssetValue(
3737
userPosition: PerpPosition,
3838
mmOraclePriceData: MMOraclePriceData,
3939
useSpread = true,
40-
skipUpdate = false
40+
skipUpdate = false,
41+
latestSlot?: BN
4142
): BN {
4243
if (userPosition.baseAssetAmount.eq(ZERO)) {
4344
return ZERO;
@@ -52,7 +53,9 @@ export function calculateBaseAssetValue(
5253
calculateUpdatedAMMSpreadReserves(
5354
market.amm,
5455
directionToClose,
55-
mmOraclePriceData
56+
mmOraclePriceData,
57+
undefined,
58+
latestSlot
5659
);
5760
prepegAmm = {
5861
baseAssetReserve,

sdk/src/math/trade.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ export function calculateTradeSlippage(
7878
market: PerpMarketAccount,
7979
inputAssetType: AssetType = 'quote',
8080
mmOraclePriceData: MMOraclePriceData,
81-
useSpread = true
81+
useSpread = true,
82+
latestSlot?: BN
8283
): [BN, BN, BN, BN] {
8384
let oldPrice: BN;
8485

@@ -115,7 +116,9 @@ export function calculateTradeSlippage(
115116
calculateUpdatedAMMSpreadReserves(
116117
market.amm,
117118
direction,
118-
mmOraclePriceData
119+
mmOraclePriceData,
120+
undefined,
121+
latestSlot
119122
);
120123
amm = {
121124
baseAssetReserve,
@@ -170,7 +173,8 @@ export function calculateTradeAcquiredAmounts(
170173
market: PerpMarketAccount,
171174
inputAssetType: AssetType = 'quote',
172175
mmOraclePriceData: MMOraclePriceData,
173-
useSpread = true
176+
useSpread = true,
177+
latestSlot?: BN
174178
): [BN, BN, BN] {
175179
if (amount.eq(ZERO)) {
176180
return [ZERO, ZERO, ZERO];
@@ -184,7 +188,9 @@ export function calculateTradeAcquiredAmounts(
184188
calculateUpdatedAMMSpreadReserves(
185189
market.amm,
186190
direction,
187-
mmOraclePriceData
191+
mmOraclePriceData,
192+
undefined,
193+
latestSlot
188194
);
189195
amm = {
190196
baseAssetReserve,
@@ -236,7 +242,8 @@ export function calculateTargetPriceTrade(
236242
pct: BN = MAXPCT,
237243
outputAssetType: AssetType = 'quote',
238244
mmOraclePriceData?: MMOraclePriceData,
239-
useSpread = true
245+
useSpread = true,
246+
latestSlot?: BN
240247
): [PositionDirection, BN, BN, BN] {
241248
assert(market.amm.baseAssetReserve.gt(ZERO));
242249
assert(targetPrice.gt(ZERO));
@@ -272,7 +279,9 @@ export function calculateTargetPriceTrade(
272279
calculateUpdatedAMMSpreadReserves(
273280
market.amm,
274281
direction,
275-
mmOraclePriceData
282+
mmOraclePriceData,
283+
undefined,
284+
latestSlot
276285
);
277286
baseAssetReserveBefore = baseAssetReserve;
278287
quoteAssetReserveBefore = quoteAssetReserve;
@@ -430,7 +439,13 @@ export function calculateEstimatedPerpEntryPrice(
430439
const swapDirection = getSwapDirection(assetType, direction);
431440

432441
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
433-
calculateUpdatedAMMSpreadReserves(market.amm, direction, mmOraclePriceData);
442+
calculateUpdatedAMMSpreadReserves(
443+
market.amm,
444+
direction,
445+
mmOraclePriceData,
446+
undefined,
447+
new BN(slot)
448+
);
434449
const amm = {
435450
baseAssetReserve,
436451
quoteAssetReserve,

0 commit comments

Comments
 (0)