@orderly.network/perp 5.0.4-alpha.4 → 5.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -10,9 +10,9 @@ var __export = (target, all) => {
10
10
  // src/version.ts
11
11
  if (typeof window !== "undefined") {
12
12
  window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
13
- window.__ORDERLY_VERSION__["@orderly.network/perp"] = "5.0.4-alpha.4";
13
+ window.__ORDERLY_VERSION__["@orderly.network/perp"] = "5.1.0-alpha.0";
14
14
  }
15
- var version_default = "5.0.4-alpha.4";
15
+ var version_default = "5.1.0-alpha.0";
16
16
 
17
17
  // src/positions/index.ts
18
18
  var positions_exports = {};
@@ -65,6 +65,8 @@ function totalUnrealizedPnL(positions) {
65
65
 
66
66
  // src/constants.ts
67
67
  var IMRFactorPower = 4 / 5;
68
+ var IsoTakerFeeBuffer = 6e-4;
69
+ var MaxQtySafetyFactor = 0.995;
68
70
  var DMax = (...values) => {
69
71
  if (values.length === 0) {
70
72
  throw new Error("DMax requires at least one argument");
@@ -300,7 +302,8 @@ function liquidationPriceIsolated(inputs) {
300
302
  referencePrice,
301
303
  orderSide,
302
304
  orderQty = 0,
303
- leverage
305
+ leverage,
306
+ isoTakerFeeBuffer = IsoTakerFeeBuffer
304
307
  } = inputs;
305
308
  const refPrice = referencePrice != null ? referencePrice : 0;
306
309
  if (refPrice <= 0 && orderQty !== 0) {
@@ -313,12 +316,13 @@ function liquidationPriceIsolated(inputs) {
313
316
  }
314
317
  let newIsolatedPositionMargin;
315
318
  let newCostPosition;
319
+ const getMarginRate = () => new Decimal(1).div(leverage).add(isoTakerFeeBuffer);
316
320
  if (orderQty === 0) {
317
321
  newIsolatedPositionMargin = new Decimal(isolatedPositionMargin);
318
322
  newCostPosition = new Decimal(costPosition);
319
323
  } else if (positionQty === 0 || orderSideMultiplier > 0 && positionQty > 0 || orderSideMultiplier < 0 && positionQty < 0) {
320
324
  newIsolatedPositionMargin = new Decimal(isolatedPositionMargin).add(
321
- new Decimal(orderQty).mul(refPrice).div(leverage)
325
+ new Decimal(orderQty).mul(refPrice).mul(getMarginRate())
322
326
  );
323
327
  newCostPosition = new Decimal(costPosition).add(
324
328
  new Decimal(orderSideMultiplier).mul(orderQty).mul(refPrice)
@@ -332,7 +336,7 @@ function liquidationPriceIsolated(inputs) {
332
336
  new Decimal(orderSideMultiplier).mul(orderQty).mul(refPrice)
333
337
  );
334
338
  } else {
335
- newIsolatedPositionMargin = new Decimal(Math.abs(newPositionQty)).mul(refPrice).div(leverage);
339
+ newIsolatedPositionMargin = new Decimal(Math.abs(newPositionQty)).mul(refPrice).mul(getMarginRate());
336
340
  newCostPosition = new Decimal(newPositionQty).mul(refPrice);
337
341
  }
338
342
  }
@@ -376,6 +380,7 @@ __export(account_exports, {
376
380
  getQtyFromOrdersBySide: () => getQtyFromOrdersBySide,
377
381
  getQtyFromPositions: () => getQtyFromPositions,
378
382
  groupOrdersBySymbol: () => groupOrdersBySymbol,
383
+ isolatedMarginRate: () => isolatedMarginRate,
379
384
  maxAdd: () => maxAdd,
380
385
  maxQty: () => maxQty,
381
386
  maxQtyByLong: () => maxQtyByLong,
@@ -764,6 +769,10 @@ function maxQtyByShort(inputs, options) {
764
769
  return 0;
765
770
  }
766
771
  }
772
+ function isolatedMarginRate(inputs) {
773
+ var _a;
774
+ return new Decimal(1).div(inputs.leverage).add((_a = inputs.isoTakerFeeBuffer) != null ? _a : IsoTakerFeeBuffer);
775
+ }
767
776
  function maxQtyForIsolatedMargin(inputs) {
768
777
  const {
769
778
  orderSide,
@@ -776,8 +785,10 @@ function maxQtyForIsolatedMargin(inputs) {
776
785
  pendingLongOrders,
777
786
  pendingSellOrders,
778
787
  symbolMaxNotional,
779
- epsilon = 1
788
+ epsilon = 1,
789
+ isoTakerFeeBuffer = IsoTakerFeeBuffer
780
790
  } = inputs;
791
+ const marginRate = isolatedMarginRate({ leverage, isoTakerFeeBuffer });
781
792
  const maxNotional = Math.min(
782
793
  new Decimal(1).div(new Decimal(leverage).mul(IMR_Factor)).pow(5 / 4).toNumber(),
783
794
  symbolMaxNotional
@@ -788,7 +799,7 @@ function maxQtyForIsolatedMargin(inputs) {
788
799
  (acc, order) => acc + new Decimal(order.referencePrice).mul(order.quantity).toNumber(),
789
800
  0
790
801
  );
791
- const maxQtyByBalance = new Decimal(availableBalance2).div(currentOrderReferencePrice).mul(leverage).toNumber();
802
+ const maxQtyByBalance = new Decimal(availableBalance2).div(marginRate).div(currentOrderReferencePrice).mul(MaxQtySafetyFactor).toNumber();
792
803
  const maxQtyByNotional = new Decimal(maxNotional).sub(new Decimal(markPrice).mul(positionQty)).sub(pendingLongNotional).div(currentOrderReferencePrice).toNumber();
793
804
  return Math.max(0, Math.min(maxQtyByBalance, maxQtyByNotional));
794
805
  } else {
@@ -803,7 +814,8 @@ function maxQtyForIsolatedMargin(inputs) {
803
814
  pendingLongOrders,
804
815
  pendingSellOrders,
805
816
  isoOrderFrozenLong: inputs.isoOrderFrozenLong,
806
- isoOrderFrozenShort: inputs.isoOrderFrozenShort
817
+ isoOrderFrozenShort: inputs.isoOrderFrozenShort,
818
+ isoTakerFeeBuffer
807
819
  },
808
820
  maxNotional,
809
821
  epsilon,
@@ -816,7 +828,7 @@ function maxQtyForIsolatedMargin(inputs) {
816
828
  (acc, order) => acc + new Decimal(order.referencePrice).mul(order.quantity).toNumber(),
817
829
  0
818
830
  );
819
- const maxQtyByBalance = new Decimal(availableBalance2).div(currentOrderReferencePrice).mul(leverage).toNumber();
831
+ const maxQtyByBalance = new Decimal(availableBalance2).div(marginRate).div(currentOrderReferencePrice).mul(MaxQtySafetyFactor).toNumber();
820
832
  const maxQtyByNotional = new Decimal(maxNotional).sub(new Decimal(markPrice).mul(Math.abs(positionQty))).sub(pendingSellNotional).div(currentOrderReferencePrice).toNumber();
821
833
  return Math.max(0, Math.min(maxQtyByBalance, maxQtyByNotional));
822
834
  } else {
@@ -831,7 +843,8 @@ function maxQtyForIsolatedMargin(inputs) {
831
843
  pendingLongOrders,
832
844
  pendingSellOrders,
833
845
  isoOrderFrozenLong: inputs.isoOrderFrozenLong,
834
- isoOrderFrozenShort: inputs.isoOrderFrozenShort
846
+ isoOrderFrozenShort: inputs.isoOrderFrozenShort,
847
+ isoTakerFeeBuffer
835
848
  },
836
849
  maxNotional,
837
850
  epsilon,
@@ -849,7 +862,8 @@ function maxQtyIsolatedBinarySearch(inputs, maxNotional, epsilon, orderSide) {
849
862
  pendingLongOrders,
850
863
  pendingSellOrders,
851
864
  isoOrderFrozenLong,
852
- isoOrderFrozenShort
865
+ isoOrderFrozenShort,
866
+ isoTakerFeeBuffer
853
867
  } = inputs;
854
868
  inputs.baseIMR;
855
869
  inputs.IMR_Factor;
@@ -858,18 +872,22 @@ function maxQtyIsolatedBinarySearch(inputs, maxNotional, epsilon, orderSide) {
858
872
  let right = new Decimal(maxNotional).div(currentOrderReferencePrice).add(Math.abs(positionQty)).toNumber();
859
873
  for (let i = 0; i < 30; i++) {
860
874
  const mid = (left + right) / 2;
861
- const orderNotional = new Decimal(mid).mul(currentOrderReferencePrice);
862
- const orderMargin = orderNotional.div(leverage);
863
- const totalFrozenMargin = orderSide === OrderSide.BUY ? isoOrderFrozenLong + orderMargin.toNumber() : isoOrderFrozenShort + orderMargin.toNumber();
875
+ const pendingOrders = orderSide === OrderSide.BUY ? pendingLongOrders : pendingSellOrders;
876
+ const existingFrozen = orderSide === OrderSide.BUY ? isoOrderFrozenLong : isoOrderFrozenShort;
877
+ const totalOrderNotional = pendingOrders.reduce(
878
+ (acc, order) => acc.add(new Decimal(order.referencePrice).mul(order.quantity)),
879
+ new Decimal(mid).mul(currentOrderReferencePrice)
880
+ );
881
+ const orderFrozen = totalOrderNotional.mul(isolatedMarginRate({ leverage, isoTakerFeeBuffer })).sub(existingFrozen);
864
882
  const newPositionQty = orderSide === OrderSide.BUY ? positionQty + mid : positionQty - mid;
865
883
  const openNotional = new Decimal(Math.abs(newPositionQty)).mul(
866
884
  currentOrderReferencePrice
867
885
  );
868
- const frozenOk = totalFrozenMargin <= availableBalance2;
886
+ const frozenOk = orderFrozen.lte(availableBalance2);
869
887
  const notionalOk = openNotional.lte(maxNotional);
870
888
  if (frozenOk && notionalOk) {
871
889
  left = mid;
872
- if (new Decimal(availableBalance2).sub(totalFrozenMargin).lte(epsilon)) {
890
+ if (new Decimal(availableBalance2).sub(orderFrozen).lte(epsilon)) {
873
891
  break;
874
892
  }
875
893
  } else {
@@ -1106,6 +1124,7 @@ function estLiqPriceIsolated(inputs) {
1106
1124
  baseIMR,
1107
1125
  IMR_Factor: IMRFactor,
1108
1126
  leverage,
1127
+ isoTakerFeeBuffer = IsoTakerFeeBuffer,
1109
1128
  newOrder
1110
1129
  } = inputs;
1111
1130
  const signedOrderQty = (_a = newOrder == null ? void 0 : newOrder.qty) != null ? _a : 0;
@@ -1130,6 +1149,7 @@ function estLiqPriceIsolated(inputs) {
1130
1149
  const decCostPosition = new Decimal(costPosition);
1131
1150
  const decIsolatedMargin = new Decimal(isolatedPositionMargin);
1132
1151
  const decOrderCost = new Decimal(signedOrderQty).mul(orderRefPrice);
1152
+ const getMarginRate = () => new Decimal(1).div(leverage).add(isoTakerFeeBuffer);
1133
1153
  let newIsolatedPositionMargin;
1134
1154
  let newCostPosition;
1135
1155
  switch (getScenario()) {
@@ -1139,7 +1159,7 @@ function estLiqPriceIsolated(inputs) {
1139
1159
  break;
1140
1160
  case "OPEN_ADD":
1141
1161
  newIsolatedPositionMargin = decIsolatedMargin.add(
1142
- new Decimal(Math.abs(signedOrderQty)).mul(orderRefPrice).div(leverage)
1162
+ new Decimal(Math.abs(signedOrderQty)).mul(orderRefPrice).mul(getMarginRate())
1143
1163
  );
1144
1164
  newCostPosition = decCostPosition.add(decOrderCost);
1145
1165
  break;
@@ -1148,7 +1168,7 @@ function estLiqPriceIsolated(inputs) {
1148
1168
  newCostPosition = decCostPosition.add(decOrderCost);
1149
1169
  break;
1150
1170
  case "FLIP":
1151
- newIsolatedPositionMargin = decAbsNewPositionQty.mul(orderRefPrice).div(leverage);
1171
+ newIsolatedPositionMargin = decAbsNewPositionQty.mul(orderRefPrice).mul(getMarginRate());
1152
1172
  newCostPosition = decNewPositionQty.mul(orderRefPrice);
1153
1173
  break;
1154
1174
  }