@orderly.network/perp 4.10.2 → 4.11.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.d.mts +1496 -225
- package/dist/index.d.ts +1496 -225
- package/dist/index.js +638 -255
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +622 -220
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Decimal, zero, getTPSLDirection } from '@orderly.network/utils';
|
|
2
|
+
import { OrderSide, MarginMode, OrderType } from '@orderly.network/types';
|
|
3
|
+
|
|
1
4
|
var __defProp = Object.defineProperty;
|
|
2
5
|
var __export = (target, all) => {
|
|
3
6
|
for (var name in all)
|
|
@@ -7,11 +10,11 @@ var __export = (target, all) => {
|
|
|
7
10
|
// src/version.ts
|
|
8
11
|
if (typeof window !== "undefined") {
|
|
9
12
|
window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
|
|
10
|
-
window.__ORDERLY_VERSION__["@orderly.network/perp"] = "4.
|
|
13
|
+
window.__ORDERLY_VERSION__["@orderly.network/perp"] = "4.11.0";
|
|
11
14
|
}
|
|
12
|
-
var version_default = "4.
|
|
15
|
+
var version_default = "4.11.0";
|
|
13
16
|
|
|
14
|
-
// src/positions.ts
|
|
17
|
+
// src/positions/index.ts
|
|
15
18
|
var positions_exports = {};
|
|
16
19
|
__export(positions_exports, {
|
|
17
20
|
MMR: () => MMR,
|
|
@@ -21,6 +24,7 @@ __export(positions_exports, {
|
|
|
21
24
|
estPriceForTP: () => estPriceForTP,
|
|
22
25
|
estPriceFromOffsetForTP: () => estPriceFromOffsetForTP,
|
|
23
26
|
liqPrice: () => liqPrice,
|
|
27
|
+
liquidationPriceIsolated: () => liquidationPriceIsolated,
|
|
24
28
|
maintenanceMargin: () => maintenanceMargin,
|
|
25
29
|
maxPositionLeverage: () => maxPositionLeverage,
|
|
26
30
|
maxPositionNotional: () => maxPositionNotional,
|
|
@@ -32,34 +36,8 @@ __export(positions_exports, {
|
|
|
32
36
|
unrealizedPnLROI: () => unrealizedPnLROI,
|
|
33
37
|
unsettlementPnL: () => unsettlementPnL
|
|
34
38
|
});
|
|
35
|
-
import { Decimal as Decimal2, zero } from "@orderly.network/utils";
|
|
36
|
-
|
|
37
|
-
// src/constants.ts
|
|
38
|
-
var IMRFactorPower = 4 / 5;
|
|
39
|
-
|
|
40
|
-
// src/utils.ts
|
|
41
|
-
import { Decimal } from "@orderly.network/utils";
|
|
42
|
-
var DMax = (...values) => {
|
|
43
|
-
if (values.length === 0) {
|
|
44
|
-
throw new Error("DMax requires at least one argument");
|
|
45
|
-
}
|
|
46
|
-
const decimals = values.map(
|
|
47
|
-
(val) => val instanceof Decimal ? val : new Decimal(val)
|
|
48
|
-
);
|
|
49
|
-
let max = decimals[0];
|
|
50
|
-
for (let i = 1; i < decimals.length; i++) {
|
|
51
|
-
if (decimals[i].gte(max)) {
|
|
52
|
-
max = decimals[i];
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return max;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// src/positions.ts
|
|
59
|
-
var MaxIterates = 30;
|
|
60
|
-
var CONVERGENCE_THRESHOLD = 1e-4;
|
|
61
39
|
function notional(qty, mark_price) {
|
|
62
|
-
return new
|
|
40
|
+
return new Decimal(qty).mul(mark_price).abs().toNumber();
|
|
63
41
|
}
|
|
64
42
|
function totalNotional(positions) {
|
|
65
43
|
return positions.reduce((acc, cur) => {
|
|
@@ -67,13 +45,13 @@ function totalNotional(positions) {
|
|
|
67
45
|
}, 0);
|
|
68
46
|
}
|
|
69
47
|
function unrealizedPnL(inputs) {
|
|
70
|
-
return new
|
|
48
|
+
return new Decimal(inputs.qty).mul(inputs.markPrice - inputs.openPrice).toNumber();
|
|
71
49
|
}
|
|
72
50
|
function unrealizedPnLROI(inputs) {
|
|
73
|
-
const { openPrice, IMR:
|
|
74
|
-
if (inputs.unrealizedPnL === 0 || inputs.positionQty === 0 || openPrice === 0 ||
|
|
51
|
+
const { openPrice, IMR: IMR4 } = inputs;
|
|
52
|
+
if (inputs.unrealizedPnL === 0 || inputs.positionQty === 0 || openPrice === 0 || IMR4 === 0)
|
|
75
53
|
return 0;
|
|
76
|
-
return new
|
|
54
|
+
return new Decimal(inputs.unrealizedPnL).div(new Decimal(Math.abs(inputs.positionQty)).mul(openPrice).mul(IMR4)).toNumber();
|
|
77
55
|
}
|
|
78
56
|
function totalUnrealizedPnL(positions) {
|
|
79
57
|
return positions.reduce((acc, cur) => {
|
|
@@ -84,18 +62,40 @@ function totalUnrealizedPnL(positions) {
|
|
|
84
62
|
});
|
|
85
63
|
}, 0);
|
|
86
64
|
}
|
|
65
|
+
|
|
66
|
+
// src/constants.ts
|
|
67
|
+
var IMRFactorPower = 4 / 5;
|
|
68
|
+
var DMax = (...values) => {
|
|
69
|
+
if (values.length === 0) {
|
|
70
|
+
throw new Error("DMax requires at least one argument");
|
|
71
|
+
}
|
|
72
|
+
const decimals = values.map(
|
|
73
|
+
(val) => val instanceof Decimal ? val : new Decimal(val)
|
|
74
|
+
);
|
|
75
|
+
let max = decimals[0];
|
|
76
|
+
for (let i = 1; i < decimals.length; i++) {
|
|
77
|
+
if (decimals[i].gte(max)) {
|
|
78
|
+
max = decimals[i];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return max;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/positions/liqPrice.ts
|
|
85
|
+
var MaxIterates = 30;
|
|
86
|
+
var CONVERGENCE_THRESHOLD = 1e-4;
|
|
87
87
|
var mmForOtherSymbols = (positions) => {
|
|
88
88
|
return positions.reduce((acc, cur) => {
|
|
89
89
|
return acc.add(
|
|
90
|
-
new
|
|
90
|
+
new Decimal(cur.position_qty).abs().mul(cur.mark_price).mul(cur.mmr)
|
|
91
91
|
);
|
|
92
92
|
}, zero);
|
|
93
93
|
};
|
|
94
94
|
var calculateLiqPrice = (markPrice, positionQty, MMR3, totalCollateral2, positions) => {
|
|
95
|
-
const decimalMarkPrice = new
|
|
96
|
-
const absQty = new
|
|
95
|
+
const decimalMarkPrice = new Decimal(markPrice);
|
|
96
|
+
const absQty = new Decimal(positionQty).abs();
|
|
97
97
|
const denominator = absQty.mul(MMR3).sub(positionQty);
|
|
98
|
-
const liqPrice2 = new
|
|
98
|
+
const liqPrice2 = new Decimal(totalCollateral2).sub(absQty.mul(decimalMarkPrice).mul(MMR3)).sub(mmForOtherSymbols(positions)).div(denominator).add(decimalMarkPrice);
|
|
99
99
|
return DMax(liqPrice2, zero);
|
|
100
100
|
};
|
|
101
101
|
var compareCollateralWithMM = (inputs) => {
|
|
@@ -109,18 +109,18 @@ var compareCollateralWithMM = (inputs) => {
|
|
|
109
109
|
IMRFactor,
|
|
110
110
|
positions
|
|
111
111
|
} = inputs;
|
|
112
|
-
const decimalPositionQty = new
|
|
113
|
-
const collateral = new
|
|
112
|
+
const decimalPositionQty = new Decimal(positionQty);
|
|
113
|
+
const collateral = new Decimal(totalCollateral2).sub(decimalPositionQty.mul(markPrice)).add(decimalPositionQty.mul(price));
|
|
114
114
|
const mm = decimalPositionQty.abs().mul(price).mul(
|
|
115
115
|
Math.max(
|
|
116
116
|
baseMMR,
|
|
117
|
-
new
|
|
117
|
+
new Decimal(baseMMR).div(baseIMR).mul(IMRFactor).mul(decimalPositionQty.mul(price).abs().toPower(IMRFactorPower)).toNumber()
|
|
118
118
|
)
|
|
119
119
|
).add(mmForOtherSymbols(positions));
|
|
120
120
|
return collateral.gte(mm);
|
|
121
121
|
};
|
|
122
122
|
};
|
|
123
|
-
|
|
123
|
+
function liqPrice(inputs) {
|
|
124
124
|
const {
|
|
125
125
|
positionQty,
|
|
126
126
|
markPrice,
|
|
@@ -165,7 +165,7 @@ var liqPrice = (inputs) => {
|
|
|
165
165
|
if (liqPriceLeft.gte(liqPriceRight)) {
|
|
166
166
|
return liqPriceRight.toNumber();
|
|
167
167
|
}
|
|
168
|
-
const mid = new
|
|
168
|
+
const mid = new Decimal(liqPriceLeft).add(liqPriceRight).div(2);
|
|
169
169
|
if (compareCollateralWithMMFunc(mid)) {
|
|
170
170
|
liqPriceRight = mid;
|
|
171
171
|
} else {
|
|
@@ -189,8 +189,8 @@ var liqPrice = (inputs) => {
|
|
|
189
189
|
positionQty,
|
|
190
190
|
Math.max(
|
|
191
191
|
baseIMR,
|
|
192
|
-
new
|
|
193
|
-
new
|
|
192
|
+
new Decimal(baseMMR).div(baseIMR).mul(IMRFactor).mul(
|
|
193
|
+
new Decimal(positionQty).mul(liqPriceRight).abs().toPower(IMRFactorPower)
|
|
194
194
|
).toNumber()
|
|
195
195
|
),
|
|
196
196
|
totalCollateral2,
|
|
@@ -221,10 +221,10 @@ var liqPrice = (inputs) => {
|
|
|
221
221
|
}
|
|
222
222
|
return liqPriceLeft.toNumber();
|
|
223
223
|
}
|
|
224
|
-
}
|
|
224
|
+
}
|
|
225
225
|
function maintenanceMargin(inputs) {
|
|
226
226
|
const { positionQty, markPrice, MMR: MMR3 } = inputs;
|
|
227
|
-
return new
|
|
227
|
+
return new Decimal(positionQty).mul(markPrice).mul(MMR3).abs().toNumber();
|
|
228
228
|
}
|
|
229
229
|
function unsettlementPnL(inputs) {
|
|
230
230
|
const {
|
|
@@ -234,8 +234,8 @@ function unsettlementPnL(inputs) {
|
|
|
234
234
|
sumUnitaryFunding,
|
|
235
235
|
lastSumUnitaryFunding
|
|
236
236
|
} = inputs;
|
|
237
|
-
const qty = new
|
|
238
|
-
return qty.mul(markPrice).sub(costPosition).sub(qty.mul(new
|
|
237
|
+
const qty = new Decimal(positionQty);
|
|
238
|
+
return qty.mul(markPrice).sub(costPosition).sub(qty.mul(new Decimal(sumUnitaryFunding).sub(lastSumUnitaryFunding))).toNumber();
|
|
239
239
|
}
|
|
240
240
|
function totalUnsettlementPnL(positions) {
|
|
241
241
|
if (!Array.isArray(positions) || positions.length === 0) {
|
|
@@ -261,56 +261,127 @@ function MMR(inputs) {
|
|
|
261
261
|
} = inputs;
|
|
262
262
|
return Math.max(
|
|
263
263
|
baseMMR,
|
|
264
|
-
new
|
|
264
|
+
new Decimal(baseMMR).div(baseIMR).mul(IMRFactor).mul(Math.pow(Math.abs(positionNotional), IMR_factor_power)).toNumber()
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
267
|
function estPnLForTP(inputs) {
|
|
268
|
-
return new
|
|
268
|
+
return new Decimal(inputs.positionQty).mul(new Decimal(inputs.price).sub(inputs.entryPrice)).toNumber();
|
|
269
269
|
}
|
|
270
270
|
function estPriceForTP(inputs) {
|
|
271
|
-
return new
|
|
271
|
+
return new Decimal(inputs.pnl).div(inputs.positionQty).add(inputs.entryPrice).toNumber();
|
|
272
272
|
}
|
|
273
273
|
function estOffsetForTP(inputs) {
|
|
274
|
-
return new
|
|
274
|
+
return new Decimal(inputs.price).div(inputs.entryPrice).toNumber();
|
|
275
275
|
}
|
|
276
276
|
function estPriceFromOffsetForTP(inputs) {
|
|
277
|
-
return new
|
|
277
|
+
return new Decimal(inputs.offset).add(inputs.entryPrice).toNumber();
|
|
278
278
|
}
|
|
279
279
|
function estPnLForSL(inputs) {
|
|
280
280
|
return 0;
|
|
281
281
|
}
|
|
282
282
|
function maxPositionNotional(inputs) {
|
|
283
283
|
const { leverage, IMRFactor } = inputs;
|
|
284
|
-
return new
|
|
284
|
+
return new Decimal(1).div(new Decimal(leverage).mul(IMRFactor)).pow(1 / 0.8).toNumber();
|
|
285
285
|
}
|
|
286
286
|
function maxPositionLeverage(inputs) {
|
|
287
287
|
const { IMRFactor, notional: notional2 } = inputs;
|
|
288
|
-
return new
|
|
288
|
+
return new Decimal(1).div(new Decimal(IMRFactor).mul(new Decimal(notional2).pow(0.8))).toNumber();
|
|
289
|
+
}
|
|
290
|
+
function liquidationPriceIsolated(inputs) {
|
|
291
|
+
const {
|
|
292
|
+
isolatedPositionMargin,
|
|
293
|
+
costPosition,
|
|
294
|
+
positionQty,
|
|
295
|
+
sumUnitaryFunding,
|
|
296
|
+
lastSumUnitaryFunding,
|
|
297
|
+
baseMMR,
|
|
298
|
+
baseIMR,
|
|
299
|
+
IMRFactor,
|
|
300
|
+
referencePrice,
|
|
301
|
+
orderSide,
|
|
302
|
+
orderQty = 0,
|
|
303
|
+
leverage
|
|
304
|
+
} = inputs;
|
|
305
|
+
const refPrice = referencePrice != null ? referencePrice : 0;
|
|
306
|
+
if (refPrice <= 0 && orderQty !== 0) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const orderSideMultiplier = orderSide === "BUY" ? 1 : orderSide === "SELL" ? -1 : 0;
|
|
310
|
+
const newPositionQty = positionQty + orderSideMultiplier * orderQty;
|
|
311
|
+
if (newPositionQty === 0) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
let newIsolatedPositionMargin;
|
|
315
|
+
let newCostPosition;
|
|
316
|
+
if (orderQty === 0) {
|
|
317
|
+
newIsolatedPositionMargin = new Decimal(isolatedPositionMargin);
|
|
318
|
+
newCostPosition = new Decimal(costPosition);
|
|
319
|
+
} else if (positionQty === 0 || orderSideMultiplier > 0 && positionQty > 0 || orderSideMultiplier < 0 && positionQty < 0) {
|
|
320
|
+
newIsolatedPositionMargin = new Decimal(isolatedPositionMargin).add(
|
|
321
|
+
new Decimal(orderQty).mul(refPrice).div(leverage)
|
|
322
|
+
);
|
|
323
|
+
newCostPosition = new Decimal(costPosition).add(
|
|
324
|
+
new Decimal(orderSideMultiplier).mul(orderQty).mul(refPrice)
|
|
325
|
+
);
|
|
326
|
+
} else {
|
|
327
|
+
const signPositionQty = positionQty > 0 ? 1 : -1;
|
|
328
|
+
const signNewPositionQty = newPositionQty > 0 ? 1 : -1;
|
|
329
|
+
if (signNewPositionQty === signPositionQty) {
|
|
330
|
+
newIsolatedPositionMargin = new Decimal(isolatedPositionMargin).mul(newPositionQty).div(positionQty);
|
|
331
|
+
newCostPosition = new Decimal(costPosition).add(
|
|
332
|
+
new Decimal(orderSideMultiplier).mul(orderQty).mul(refPrice)
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
newIsolatedPositionMargin = new Decimal(Math.abs(newPositionQty)).mul(refPrice).div(leverage);
|
|
336
|
+
newCostPosition = new Decimal(newPositionQty).mul(refPrice);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const fundingAdjustment = new Decimal(newPositionQty).mul(
|
|
340
|
+
new Decimal(sumUnitaryFunding).sub(lastSumUnitaryFunding)
|
|
341
|
+
);
|
|
342
|
+
const newPositionNotional = new Decimal(Math.abs(newPositionQty)).mul(
|
|
343
|
+
refPrice
|
|
344
|
+
);
|
|
345
|
+
const dynamicMMR = new Decimal(baseMMR).div(baseIMR).mul(IMRFactor).mul(newPositionNotional.toPower(IMRFactorPower)).toNumber();
|
|
346
|
+
const newMMR = Math.max(baseMMR, dynamicMMR);
|
|
347
|
+
const denominator = new Decimal(Math.abs(newPositionQty)).mul(newMMR).sub(newPositionQty);
|
|
348
|
+
if (denominator.isZero()) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
const numerator = newIsolatedPositionMargin.sub(newCostPosition).sub(fundingAdjustment);
|
|
352
|
+
const liquidationPrice = numerator.div(denominator).toNumber();
|
|
353
|
+
if (liquidationPrice <= 0) {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
return liquidationPrice;
|
|
289
357
|
}
|
|
290
358
|
|
|
291
|
-
// src/account.ts
|
|
359
|
+
// src/account/index.ts
|
|
292
360
|
var account_exports = {};
|
|
293
361
|
__export(account_exports, {
|
|
294
362
|
IMR: () => IMR,
|
|
295
363
|
LTV: () => LTV,
|
|
296
364
|
MMR: () => MMR2,
|
|
297
365
|
availableBalance: () => availableBalance,
|
|
366
|
+
availableBalanceForIsolatedMargin: () => availableBalanceForIsolatedMargin,
|
|
298
367
|
buyOrdersFilter_by_symbol: () => buyOrdersFilter_by_symbol,
|
|
299
368
|
calcMinimumReceived: () => calcMinimumReceived,
|
|
300
369
|
collateralContribution: () => collateralContribution,
|
|
301
370
|
collateralRatio: () => collateralRatio,
|
|
302
371
|
currentLeverage: () => currentLeverage,
|
|
303
|
-
extractSymbols: () =>
|
|
372
|
+
extractSymbols: () => extractSymbols2,
|
|
304
373
|
freeCollateral: () => freeCollateral,
|
|
374
|
+
freeCollateralUSDCOnly: () => freeCollateralUSDCOnly,
|
|
305
375
|
getPositonsAndOrdersNotionalBySymbol: () => getPositonsAndOrdersNotionalBySymbol,
|
|
306
376
|
getQtyFromOrdersBySide: () => getQtyFromOrdersBySide,
|
|
307
377
|
getQtyFromPositions: () => getQtyFromPositions,
|
|
308
378
|
groupOrdersBySymbol: () => groupOrdersBySymbol,
|
|
309
|
-
|
|
310
|
-
maxLeverage: () => maxLeverage,
|
|
379
|
+
maxAdd: () => maxAdd,
|
|
311
380
|
maxQty: () => maxQty,
|
|
312
381
|
maxQtyByLong: () => maxQtyByLong,
|
|
313
382
|
maxQtyByShort: () => maxQtyByShort,
|
|
383
|
+
maxQtyForIsolatedMargin: () => maxQtyForIsolatedMargin,
|
|
384
|
+
maxReduce: () => maxReduce,
|
|
314
385
|
maxWithdrawalOtherCollateral: () => maxWithdrawalOtherCollateral,
|
|
315
386
|
maxWithdrawalUSDC: () => maxWithdrawalUSDC,
|
|
316
387
|
otherIMs: () => otherIMs,
|
|
@@ -318,42 +389,61 @@ __export(account_exports, {
|
|
|
318
389
|
positionQtyWithOrders_by_symbol: () => positionQtyWithOrders_by_symbol,
|
|
319
390
|
sellOrdersFilter_by_symbol: () => sellOrdersFilter_by_symbol,
|
|
320
391
|
totalCollateral: () => totalCollateral,
|
|
321
|
-
totalInitialMarginWithOrders: () => totalInitialMarginWithOrders,
|
|
322
392
|
totalInitialMarginWithQty: () => totalInitialMarginWithQty,
|
|
323
393
|
totalMarginRatio: () => totalMarginRatio,
|
|
324
394
|
totalUnrealizedROI: () => totalUnrealizedROI,
|
|
325
395
|
totalValue: () => totalValue
|
|
326
396
|
});
|
|
327
|
-
import { OrderSide } from "@orderly.network/types";
|
|
328
|
-
import { Decimal as Decimal3, zero as zero2 } from "@orderly.network/utils";
|
|
329
397
|
function totalValue(inputs) {
|
|
330
|
-
const {
|
|
398
|
+
const {
|
|
399
|
+
totalUnsettlementPnL: totalUnsettlementPnL2,
|
|
400
|
+
USDCHolding,
|
|
401
|
+
nonUSDCHolding,
|
|
402
|
+
totalIsolatedPositionMargin = 0
|
|
403
|
+
} = inputs;
|
|
331
404
|
const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {
|
|
332
|
-
return new
|
|
333
|
-
},
|
|
334
|
-
return nonUSDCHoldingValue.add(USDCHolding).add(totalUnsettlementPnL2);
|
|
405
|
+
return new Decimal(cur.holding).mul(cur.indexPrice).add(acc);
|
|
406
|
+
}, zero);
|
|
407
|
+
return nonUSDCHoldingValue.add(USDCHolding).add(totalIsolatedPositionMargin).add(totalUnsettlementPnL2);
|
|
335
408
|
}
|
|
336
409
|
function freeCollateral(inputs) {
|
|
337
410
|
const value = inputs.totalCollateral.sub(inputs.totalInitialMarginWithOrders);
|
|
338
|
-
return value.isNegative() ?
|
|
411
|
+
return value.isNegative() ? zero : value;
|
|
412
|
+
}
|
|
413
|
+
function freeCollateralUSDCOnly(inputs) {
|
|
414
|
+
const { freeCollateral: freeCollateral2, nonUSDCHolding } = inputs;
|
|
415
|
+
const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {
|
|
416
|
+
const finalHolding = Math.min(cur.holding, cur.collateralCap);
|
|
417
|
+
const value2 = new Decimal(finalHolding).mul(cur.collateralRatio).mul(cur.indexPrice);
|
|
418
|
+
return acc.add(value2);
|
|
419
|
+
}, zero);
|
|
420
|
+
const value = freeCollateral2.sub(nonUSDCHoldingValue);
|
|
421
|
+
return value.isNegative() ? zero : value;
|
|
339
422
|
}
|
|
340
423
|
function totalCollateral(inputs) {
|
|
341
|
-
const {
|
|
424
|
+
const {
|
|
425
|
+
USDCHolding,
|
|
426
|
+
nonUSDCHolding,
|
|
427
|
+
unsettlementPnL: unsettlementPnL2,
|
|
428
|
+
usdcBalancePendingShortQty = 0,
|
|
429
|
+
usdcBalanceIsolatedOrderFrozen = 0,
|
|
430
|
+
totalCrossUnsettledPnL
|
|
431
|
+
} = inputs;
|
|
432
|
+
const usdcPart = new Decimal(USDCHolding).add(usdcBalancePendingShortQty).sub(Math.abs(usdcBalanceIsolatedOrderFrozen));
|
|
342
433
|
const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {
|
|
343
434
|
const finalHolding = Math.min(cur.holding, cur.collateralCap);
|
|
344
|
-
const value = new
|
|
435
|
+
const value = new Decimal(finalHolding).mul(cur.collateralRatio).mul(cur.indexPrice);
|
|
345
436
|
return acc.add(value);
|
|
346
|
-
},
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
function initialMarginWithOrder() {
|
|
437
|
+
}, zero);
|
|
438
|
+
const pnl = totalCrossUnsettledPnL !== void 0 ? totalCrossUnsettledPnL : unsettlementPnL2;
|
|
439
|
+
return usdcPart.add(nonUSDCHoldingValue).add(pnl);
|
|
350
440
|
}
|
|
351
441
|
function positionNotionalWithOrder_by_symbol(inputs) {
|
|
352
|
-
return new
|
|
442
|
+
return new Decimal(inputs.markPrice).mul(inputs.positionQtyWithOrders);
|
|
353
443
|
}
|
|
354
444
|
function positionQtyWithOrders_by_symbol(inputs) {
|
|
355
445
|
const { positionQty, buyOrdersQty, sellOrdersQty } = inputs;
|
|
356
|
-
const positionQtyDecimal = new
|
|
446
|
+
const positionQtyDecimal = new Decimal(positionQty);
|
|
357
447
|
const qty = Math.max(
|
|
358
448
|
positionQtyDecimal.add(buyOrdersQty).abs().toNumber(),
|
|
359
449
|
positionQtyDecimal.sub(sellOrdersQty).abs().toNumber()
|
|
@@ -362,7 +452,7 @@ function positionQtyWithOrders_by_symbol(inputs) {
|
|
|
362
452
|
}
|
|
363
453
|
function IMR(inputs) {
|
|
364
454
|
const {
|
|
365
|
-
maxLeverage
|
|
455
|
+
maxLeverage,
|
|
366
456
|
baseIMR,
|
|
367
457
|
IMR_Factor,
|
|
368
458
|
positionNotional,
|
|
@@ -370,10 +460,10 @@ function IMR(inputs) {
|
|
|
370
460
|
IMR_factor_power = IMRFactorPower
|
|
371
461
|
} = inputs;
|
|
372
462
|
return Math.max(
|
|
373
|
-
1 /
|
|
463
|
+
1 / maxLeverage,
|
|
374
464
|
baseIMR,
|
|
375
|
-
new
|
|
376
|
-
new
|
|
465
|
+
new Decimal(IMR_Factor).mul(
|
|
466
|
+
new Decimal(positionNotional).add(orderNotional).abs().toPower(IMR_factor_power)
|
|
377
467
|
).toNumber()
|
|
378
468
|
);
|
|
379
469
|
}
|
|
@@ -405,85 +495,117 @@ function getPositonsAndOrdersNotionalBySymbol(inputs) {
|
|
|
405
495
|
const positionQty = getQtyFromPositions(positions, symbol);
|
|
406
496
|
const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.BUY);
|
|
407
497
|
const sellOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.SELL);
|
|
408
|
-
const markPriceDecimal = new
|
|
409
|
-
return markPriceDecimal.mul(positionQty).add(markPriceDecimal.mul(new
|
|
498
|
+
const markPriceDecimal = new Decimal(markPrice);
|
|
499
|
+
return markPriceDecimal.mul(positionQty).add(markPriceDecimal.mul(new Decimal(buyOrdersQty).add(sellOrdersQty))).abs().toNumber();
|
|
410
500
|
}
|
|
411
|
-
function
|
|
501
|
+
function calculateSymbolInitialMargin(params) {
|
|
502
|
+
const {
|
|
503
|
+
symbol,
|
|
504
|
+
positionQty,
|
|
505
|
+
buyOrdersQty,
|
|
506
|
+
sellOrdersQty,
|
|
507
|
+
markPrice,
|
|
508
|
+
IMR_Factors,
|
|
509
|
+
symbolInfo,
|
|
510
|
+
symbolMaxLeverage
|
|
511
|
+
} = params;
|
|
512
|
+
const positionQtyWithOrders = positionQtyWithOrders_by_symbol({
|
|
513
|
+
positionQty,
|
|
514
|
+
buyOrdersQty,
|
|
515
|
+
sellOrdersQty
|
|
516
|
+
});
|
|
517
|
+
const positionNotionalWithOrders = positionNotionalWithOrder_by_symbol({
|
|
518
|
+
markPrice,
|
|
519
|
+
positionQtyWithOrders
|
|
520
|
+
});
|
|
521
|
+
const markPriceDecimal = new Decimal(markPrice);
|
|
522
|
+
const imr = IMR2({
|
|
523
|
+
positionNotional: markPriceDecimal.mul(positionQty).toNumber(),
|
|
524
|
+
ordersNotional: markPriceDecimal.mul(new Decimal(buyOrdersQty).sub(sellOrdersQty)).toNumber(),
|
|
525
|
+
maxLeverage: symbolMaxLeverage,
|
|
526
|
+
IMR_Factor: IMR_Factors[symbol],
|
|
527
|
+
baseIMR: symbolInfo[symbol]("base_imr", 0)
|
|
528
|
+
});
|
|
529
|
+
return positionNotionalWithOrders.mul(imr).toNumber();
|
|
530
|
+
}
|
|
531
|
+
function IMR2(inputs) {
|
|
532
|
+
const {
|
|
533
|
+
maxLeverage,
|
|
534
|
+
baseIMR,
|
|
535
|
+
IMR_Factor,
|
|
536
|
+
positionNotional,
|
|
537
|
+
ordersNotional: orderNotional,
|
|
538
|
+
IMR_factor_power = IMRFactorPower
|
|
539
|
+
} = inputs;
|
|
540
|
+
const imr = IMR_Factor === 0 ? 0 : new Decimal(IMR_Factor).mul(
|
|
541
|
+
new Decimal(positionNotional).add(orderNotional).abs().toPower(IMR_factor_power)
|
|
542
|
+
).toNumber();
|
|
543
|
+
return Math.max(1 / maxLeverage, baseIMR, imr);
|
|
544
|
+
}
|
|
545
|
+
function totalInitialMarginWithQty(inputs) {
|
|
412
546
|
const {
|
|
413
547
|
positions,
|
|
414
548
|
orders,
|
|
415
549
|
markPrices,
|
|
416
550
|
IMR_Factors,
|
|
417
|
-
|
|
418
|
-
|
|
551
|
+
symbolInfo,
|
|
552
|
+
maxLeverageBySymbol
|
|
419
553
|
} = inputs;
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
554
|
+
const crossPositions = positions.filter(
|
|
555
|
+
(p) => p.margin_mode !== MarginMode.ISOLATED
|
|
556
|
+
);
|
|
557
|
+
const crossOrders = orders.filter(
|
|
558
|
+
(o) => o.margin_mode !== MarginMode.ISOLATED
|
|
559
|
+
);
|
|
560
|
+
const crossLeverageBySymbol = crossPositions.reduce(
|
|
561
|
+
(acc, position) => {
|
|
562
|
+
if (!acc[position.symbol] && position.leverage) {
|
|
563
|
+
acc[position.symbol] = position.leverage;
|
|
564
|
+
}
|
|
565
|
+
return acc;
|
|
566
|
+
},
|
|
567
|
+
{}
|
|
568
|
+
);
|
|
569
|
+
const symbols = extractSymbols(crossPositions, crossOrders);
|
|
570
|
+
return symbols.map((symbol) => {
|
|
571
|
+
var _a, _b;
|
|
572
|
+
const positionQty = getQtyFromPositions(crossPositions, symbol);
|
|
573
|
+
const markPrice = markPrices[symbol] || 0;
|
|
574
|
+
const buyOrdersQty = getQtyFromOrdersBySide(
|
|
575
|
+
crossOrders,
|
|
576
|
+
symbol,
|
|
577
|
+
OrderSide.BUY
|
|
578
|
+
);
|
|
425
579
|
const sellOrdersQty = getQtyFromOrdersBySide(
|
|
426
|
-
|
|
580
|
+
crossOrders,
|
|
427
581
|
symbol,
|
|
428
582
|
OrderSide.SELL
|
|
429
583
|
);
|
|
430
|
-
const
|
|
431
|
-
|
|
584
|
+
const symbolMaxLeverage = (_b = (_a = crossLeverageBySymbol[symbol]) != null ? _a : maxLeverageBySymbol == null ? void 0 : maxLeverageBySymbol[symbol]) != null ? _b : 1;
|
|
585
|
+
return calculateSymbolInitialMargin({
|
|
586
|
+
symbol,
|
|
432
587
|
positionQty,
|
|
433
588
|
buyOrdersQty,
|
|
434
|
-
sellOrdersQty
|
|
435
|
-
});
|
|
436
|
-
const position_notional_with_orders = positionNotionalWithOrder_by_symbol({
|
|
589
|
+
sellOrdersQty,
|
|
437
590
|
markPrice,
|
|
438
|
-
|
|
591
|
+
IMR_Factors,
|
|
592
|
+
symbolInfo,
|
|
593
|
+
symbolMaxLeverage
|
|
439
594
|
});
|
|
440
|
-
|
|
441
|
-
const imr = IMR({
|
|
442
|
-
positionNotional: markPriceDecimal.mul(positionQty).toNumber(),
|
|
443
|
-
ordersNotional: markPriceDecimal.mul(new Decimal3(buyOrdersQty).add(sellOrdersQty)).toNumber(),
|
|
444
|
-
maxLeverage: maxLeverage2,
|
|
445
|
-
IMR_Factor: IMR_Factors[symbol],
|
|
446
|
-
baseIMR: symbolInfo[symbol]("base_imr", 0)
|
|
447
|
-
});
|
|
448
|
-
return position_notional_with_orders.mul(imr).add(acc).toNumber();
|
|
449
|
-
}, 0);
|
|
450
|
-
return total_initial_margin_with_orders;
|
|
595
|
+
}).reduce((acc, margin) => acc.add(margin), zero).toNumber();
|
|
451
596
|
}
|
|
452
|
-
function
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const sellOrdersQty = (position == null ? void 0 : position.pending_short_qty) || 0;
|
|
462
|
-
const markPrice = markPrices[symbol] || 0;
|
|
463
|
-
const positionQtyWithOrders = positionQtyWithOrders_by_symbol({
|
|
464
|
-
positionQty,
|
|
465
|
-
buyOrdersQty,
|
|
466
|
-
sellOrdersQty
|
|
467
|
-
});
|
|
468
|
-
const position_notional_with_orders = positionNotionalWithOrder_by_symbol({
|
|
469
|
-
markPrice,
|
|
470
|
-
positionQtyWithOrders
|
|
471
|
-
});
|
|
472
|
-
const markPriceDecimal = new Decimal3(markPrice);
|
|
473
|
-
const imr = IMR({
|
|
474
|
-
positionNotional: markPriceDecimal.mul(positionQty).toNumber(),
|
|
475
|
-
ordersNotional: markPriceDecimal.mul(new Decimal3(buyOrdersQty).add(sellOrdersQty)).toNumber(),
|
|
476
|
-
maxLeverage: maxLeverage({
|
|
477
|
-
symbolLeverage: (_a = position == null ? void 0 : position.leverage) != null ? _a : inputs.maxLeverage,
|
|
478
|
-
accountLeverage: inputs.maxLeverage
|
|
479
|
-
}),
|
|
480
|
-
IMR_Factor: IMR_Factors[symbol],
|
|
481
|
-
baseIMR: symbolInfo[symbol]("base_imr", 0)
|
|
482
|
-
});
|
|
483
|
-
return position_notional_with_orders.mul(imr).add(acc).toNumber();
|
|
484
|
-
}, 0);
|
|
485
|
-
return total_initial_margin_with_orders;
|
|
597
|
+
function extractSymbols(positions, orders) {
|
|
598
|
+
const symbols = /* @__PURE__ */ new Set();
|
|
599
|
+
positions.forEach((item) => {
|
|
600
|
+
symbols.add(item.symbol);
|
|
601
|
+
});
|
|
602
|
+
orders.forEach((item) => {
|
|
603
|
+
symbols.add(item.symbol);
|
|
604
|
+
});
|
|
605
|
+
return Array.from(symbols);
|
|
486
606
|
}
|
|
607
|
+
|
|
608
|
+
// src/account/groupOrders.ts
|
|
487
609
|
function groupOrdersBySymbol(orders) {
|
|
488
610
|
const symbols = {};
|
|
489
611
|
orders.forEach((item) => {
|
|
@@ -494,7 +616,7 @@ function groupOrdersBySymbol(orders) {
|
|
|
494
616
|
});
|
|
495
617
|
return symbols;
|
|
496
618
|
}
|
|
497
|
-
function
|
|
619
|
+
function extractSymbols2(positions, orders) {
|
|
498
620
|
const symbols = /* @__PURE__ */ new Set();
|
|
499
621
|
positions.forEach((item) => {
|
|
500
622
|
symbols.add(item.symbol);
|
|
@@ -504,6 +626,23 @@ function extractSymbols(positions, orders) {
|
|
|
504
626
|
});
|
|
505
627
|
return Array.from(symbols);
|
|
506
628
|
}
|
|
629
|
+
function IMR3(inputs) {
|
|
630
|
+
const {
|
|
631
|
+
maxLeverage,
|
|
632
|
+
baseIMR,
|
|
633
|
+
IMR_Factor,
|
|
634
|
+
positionNotional,
|
|
635
|
+
ordersNotional: orderNotional,
|
|
636
|
+
IMR_factor_power = 4 / 5
|
|
637
|
+
} = inputs;
|
|
638
|
+
return Math.max(
|
|
639
|
+
1 / maxLeverage,
|
|
640
|
+
baseIMR,
|
|
641
|
+
new Decimal(IMR_Factor).mul(
|
|
642
|
+
new Decimal(positionNotional).add(orderNotional).abs().toPower(IMR_factor_power)
|
|
643
|
+
).toNumber()
|
|
644
|
+
);
|
|
645
|
+
}
|
|
507
646
|
function otherIMs(inputs) {
|
|
508
647
|
const {
|
|
509
648
|
// orders,
|
|
@@ -519,23 +658,21 @@ function otherIMs(inputs) {
|
|
|
519
658
|
console.warn("markPrices[%s] is undefined", symbol);
|
|
520
659
|
return acc;
|
|
521
660
|
}
|
|
522
|
-
const markPriceDecimal = new
|
|
661
|
+
const markPriceDecimal = new Decimal(markPrices[symbol] || 0);
|
|
523
662
|
const position = positions.find((item) => item.symbol === symbol);
|
|
524
663
|
const positionQty = getQtyFromPositions(positions, symbol);
|
|
525
664
|
const positionNotional = markPriceDecimal.mul(positionQty).toNumber();
|
|
526
665
|
const buyOrdersQty = position.pending_long_qty;
|
|
527
666
|
const sellOrdersQty = position.pending_short_qty;
|
|
528
|
-
const ordersNotional = markPriceDecimal.mul(new
|
|
667
|
+
const ordersNotional = markPriceDecimal.mul(new Decimal(buyOrdersQty).add(sellOrdersQty)).toNumber();
|
|
529
668
|
const IMR_Factor = IMR_Factors[symbol];
|
|
530
669
|
if (typeof IMR_Factor === "undefined") {
|
|
531
670
|
console.warn("IMR_Factor is not found:", symbol);
|
|
532
671
|
return acc;
|
|
533
672
|
}
|
|
534
|
-
const imr =
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
accountLeverage: inputs.maxLeverage
|
|
538
|
-
}),
|
|
673
|
+
const imr = IMR3({
|
|
674
|
+
// Use symbol + mode leverage from position directly.
|
|
675
|
+
maxLeverage: (position == null ? void 0 : position.leverage) || 1,
|
|
539
676
|
IMR_Factor,
|
|
540
677
|
baseIMR: symbolInfo[symbol]("base_imr", 0),
|
|
541
678
|
positionNotional,
|
|
@@ -551,7 +688,7 @@ function otherIMs(inputs) {
|
|
|
551
688
|
positionQtyWithOrders
|
|
552
689
|
});
|
|
553
690
|
return acc.add(positionNotionalWithOrders.mul(imr));
|
|
554
|
-
},
|
|
691
|
+
}, zero).toNumber();
|
|
555
692
|
}
|
|
556
693
|
function maxQty(side, inputs, options) {
|
|
557
694
|
if (side === OrderSide.BUY) {
|
|
@@ -565,7 +702,7 @@ function maxQtyByLong(inputs, options) {
|
|
|
565
702
|
baseMaxQty,
|
|
566
703
|
totalCollateral: totalCollateral2,
|
|
567
704
|
otherIMs: otherIMs2,
|
|
568
|
-
maxLeverage
|
|
705
|
+
maxLeverage,
|
|
569
706
|
baseIMR,
|
|
570
707
|
markPrice,
|
|
571
708
|
IMR_Factor,
|
|
@@ -576,10 +713,10 @@ function maxQtyByLong(inputs, options) {
|
|
|
576
713
|
if (totalCollateral2 === 0) {
|
|
577
714
|
return 0;
|
|
578
715
|
}
|
|
579
|
-
const totalCollateralDecimal = new
|
|
716
|
+
const totalCollateralDecimal = new Decimal(totalCollateral2);
|
|
580
717
|
const factor_1 = totalCollateralDecimal.sub(otherIMs2).div(
|
|
581
|
-
new
|
|
582
|
-
).div(markPrice).mul(0.995).sub(new
|
|
718
|
+
new Decimal(takerFeeRate).mul(2).mul(1e-4).add(Math.max(1 / maxLeverage, baseIMR))
|
|
719
|
+
).div(markPrice).mul(0.995).sub(new Decimal(positionQty).add(buyOrdersQty)).toNumber();
|
|
583
720
|
if (positionQty === 0 && buyOrdersQty === 0) {
|
|
584
721
|
return Math.min(baseMaxQty, factor_1);
|
|
585
722
|
}
|
|
@@ -587,10 +724,10 @@ function maxQtyByLong(inputs, options) {
|
|
|
587
724
|
return Math.min(baseMaxQty, factor_1);
|
|
588
725
|
}
|
|
589
726
|
const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).sub(
|
|
590
|
-
new
|
|
727
|
+
new Decimal(positionQty).add(buyOrdersQty)
|
|
591
728
|
// .abs()
|
|
592
729
|
// .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))
|
|
593
|
-
).div(new
|
|
730
|
+
).div(new Decimal(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
|
|
594
731
|
return Math.min(baseMaxQty, factor_1, factor_2);
|
|
595
732
|
} catch (error) {
|
|
596
733
|
return 0;
|
|
@@ -602,7 +739,7 @@ function maxQtyByShort(inputs, options) {
|
|
|
602
739
|
baseMaxQty,
|
|
603
740
|
totalCollateral: totalCollateral2,
|
|
604
741
|
otherIMs: otherIMs2,
|
|
605
|
-
maxLeverage
|
|
742
|
+
maxLeverage,
|
|
606
743
|
baseIMR,
|
|
607
744
|
markPrice,
|
|
608
745
|
IMR_Factor,
|
|
@@ -611,9 +748,9 @@ function maxQtyByShort(inputs, options) {
|
|
|
611
748
|
sellOrdersQty,
|
|
612
749
|
takerFeeRate
|
|
613
750
|
} = inputs;
|
|
614
|
-
const totalCollateralDecimal = new
|
|
751
|
+
const totalCollateralDecimal = new Decimal(totalCollateral2);
|
|
615
752
|
const factor_1 = totalCollateralDecimal.sub(otherIMs2).div(
|
|
616
|
-
new
|
|
753
|
+
new Decimal(takerFeeRate).mul(2).mul(1e-4).add(Math.max(1 / maxLeverage, baseIMR))
|
|
617
754
|
).div(markPrice).mul(0.995).add(positionQty).sub(Math.abs(sellOrdersQty)).toNumber();
|
|
618
755
|
if (positionQty === 0 && sellOrdersQty === 0) {
|
|
619
756
|
return Math.min(baseMaxQty, factor_1);
|
|
@@ -621,31 +758,147 @@ function maxQtyByShort(inputs, options) {
|
|
|
621
758
|
if (IMR_Factor === 0) {
|
|
622
759
|
return Math.min(baseMaxQty, factor_1);
|
|
623
760
|
}
|
|
624
|
-
const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(positionQty).sub(sellOrdersQty).div(new
|
|
761
|
+
const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(positionQty).sub(sellOrdersQty).div(new Decimal(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
|
|
625
762
|
return Math.min(baseMaxQty, factor_1, factor_2);
|
|
626
763
|
} catch (error) {
|
|
627
764
|
return 0;
|
|
628
765
|
}
|
|
629
766
|
}
|
|
767
|
+
function maxQtyForIsolatedMargin(inputs) {
|
|
768
|
+
const {
|
|
769
|
+
orderSide,
|
|
770
|
+
currentOrderReferencePrice,
|
|
771
|
+
availableBalance: availableBalance2,
|
|
772
|
+
leverage,
|
|
773
|
+
IMR_Factor,
|
|
774
|
+
markPrice,
|
|
775
|
+
positionQty,
|
|
776
|
+
pendingLongOrders,
|
|
777
|
+
pendingSellOrders,
|
|
778
|
+
symbolMaxNotional,
|
|
779
|
+
epsilon = 1
|
|
780
|
+
} = inputs;
|
|
781
|
+
const maxNotional = Math.min(
|
|
782
|
+
new Decimal(1).div(new Decimal(leverage).mul(IMR_Factor)).pow(5 / 4).toNumber(),
|
|
783
|
+
symbolMaxNotional
|
|
784
|
+
);
|
|
785
|
+
if (orderSide === OrderSide.BUY) {
|
|
786
|
+
if (positionQty >= 0) {
|
|
787
|
+
const pendingLongNotional = pendingLongOrders.reduce(
|
|
788
|
+
(acc, order) => acc + new Decimal(order.referencePrice).mul(order.quantity).toNumber(),
|
|
789
|
+
0
|
|
790
|
+
);
|
|
791
|
+
const maxQtyByBalance = new Decimal(availableBalance2).div(currentOrderReferencePrice).mul(leverage).toNumber();
|
|
792
|
+
const maxQtyByNotional = new Decimal(maxNotional).sub(new Decimal(markPrice).mul(positionQty)).sub(pendingLongNotional).div(currentOrderReferencePrice).toNumber();
|
|
793
|
+
return Math.max(0, Math.min(maxQtyByBalance, maxQtyByNotional));
|
|
794
|
+
} else {
|
|
795
|
+
return maxQtyIsolatedBinarySearch(
|
|
796
|
+
{
|
|
797
|
+
currentOrderReferencePrice,
|
|
798
|
+
availableBalance: availableBalance2,
|
|
799
|
+
leverage,
|
|
800
|
+
baseIMR: inputs.baseIMR,
|
|
801
|
+
IMR_Factor,
|
|
802
|
+
positionQty,
|
|
803
|
+
pendingLongOrders,
|
|
804
|
+
pendingSellOrders,
|
|
805
|
+
isoOrderFrozenLong: inputs.isoOrderFrozenLong,
|
|
806
|
+
isoOrderFrozenShort: inputs.isoOrderFrozenShort
|
|
807
|
+
},
|
|
808
|
+
maxNotional,
|
|
809
|
+
epsilon,
|
|
810
|
+
OrderSide.BUY
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
} else {
|
|
814
|
+
if (positionQty <= 0) {
|
|
815
|
+
const pendingSellNotional = pendingSellOrders.reduce(
|
|
816
|
+
(acc, order) => acc + new Decimal(order.referencePrice).mul(order.quantity).toNumber(),
|
|
817
|
+
0
|
|
818
|
+
);
|
|
819
|
+
const maxQtyByBalance = new Decimal(availableBalance2).div(currentOrderReferencePrice).mul(leverage).toNumber();
|
|
820
|
+
const maxQtyByNotional = new Decimal(maxNotional).sub(new Decimal(markPrice).mul(Math.abs(positionQty))).sub(pendingSellNotional).div(currentOrderReferencePrice).toNumber();
|
|
821
|
+
return Math.max(0, Math.min(maxQtyByBalance, maxQtyByNotional));
|
|
822
|
+
} else {
|
|
823
|
+
return maxQtyIsolatedBinarySearch(
|
|
824
|
+
{
|
|
825
|
+
currentOrderReferencePrice,
|
|
826
|
+
availableBalance: availableBalance2,
|
|
827
|
+
leverage,
|
|
828
|
+
baseIMR: inputs.baseIMR,
|
|
829
|
+
IMR_Factor,
|
|
830
|
+
positionQty,
|
|
831
|
+
pendingLongOrders,
|
|
832
|
+
pendingSellOrders,
|
|
833
|
+
isoOrderFrozenLong: inputs.isoOrderFrozenLong,
|
|
834
|
+
isoOrderFrozenShort: inputs.isoOrderFrozenShort
|
|
835
|
+
},
|
|
836
|
+
maxNotional,
|
|
837
|
+
epsilon,
|
|
838
|
+
OrderSide.SELL
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
function maxQtyIsolatedBinarySearch(inputs, maxNotional, epsilon, orderSide) {
|
|
844
|
+
const {
|
|
845
|
+
currentOrderReferencePrice,
|
|
846
|
+
availableBalance: availableBalance2,
|
|
847
|
+
leverage,
|
|
848
|
+
positionQty,
|
|
849
|
+
pendingLongOrders,
|
|
850
|
+
pendingSellOrders,
|
|
851
|
+
isoOrderFrozenLong,
|
|
852
|
+
isoOrderFrozenShort
|
|
853
|
+
} = inputs;
|
|
854
|
+
inputs.baseIMR;
|
|
855
|
+
inputs.IMR_Factor;
|
|
856
|
+
const pendingOrdersQty = orderSide === OrderSide.BUY ? pendingLongOrders.reduce((acc, order) => acc + order.quantity, 0) : pendingSellOrders.reduce((acc, order) => acc + order.quantity, 0);
|
|
857
|
+
let left = Math.max(0, Math.max(0, Math.abs(positionQty)) - pendingOrdersQty);
|
|
858
|
+
let right = new Decimal(maxNotional).div(currentOrderReferencePrice).add(Math.abs(positionQty)).toNumber();
|
|
859
|
+
for (let i = 0; i < 30; i++) {
|
|
860
|
+
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();
|
|
864
|
+
const newPositionQty = orderSide === OrderSide.BUY ? positionQty + mid : positionQty - mid;
|
|
865
|
+
const openNotional = new Decimal(Math.abs(newPositionQty)).mul(
|
|
866
|
+
currentOrderReferencePrice
|
|
867
|
+
);
|
|
868
|
+
const frozenOk = totalFrozenMargin <= availableBalance2;
|
|
869
|
+
const notionalOk = openNotional.lte(maxNotional);
|
|
870
|
+
if (frozenOk && notionalOk) {
|
|
871
|
+
left = mid;
|
|
872
|
+
if (new Decimal(availableBalance2).sub(totalFrozenMargin).lte(epsilon)) {
|
|
873
|
+
break;
|
|
874
|
+
}
|
|
875
|
+
} else {
|
|
876
|
+
right = mid;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return Math.max(0, left);
|
|
880
|
+
}
|
|
630
881
|
function totalMarginRatio(inputs, dp) {
|
|
631
882
|
const { totalCollateral: totalCollateral2, markPrices, positions } = inputs;
|
|
632
883
|
if (totalCollateral2 === 0) {
|
|
633
884
|
return 0;
|
|
634
885
|
}
|
|
635
|
-
const totalCollateralDecimal = new
|
|
886
|
+
const totalCollateralDecimal = new Decimal(totalCollateral2);
|
|
636
887
|
const totalPositionNotional = positions.reduce((acc, cur) => {
|
|
637
888
|
const markPrice = markPrices[cur.symbol] || 0;
|
|
638
|
-
return acc.add(new
|
|
639
|
-
},
|
|
640
|
-
if (totalPositionNotional.eq(
|
|
889
|
+
return acc.add(new Decimal(cur.position_qty).mul(markPrice).abs());
|
|
890
|
+
}, zero);
|
|
891
|
+
if (totalPositionNotional.eq(zero)) {
|
|
641
892
|
return 0;
|
|
642
893
|
}
|
|
643
894
|
return totalCollateralDecimal.div(totalPositionNotional).toNumber();
|
|
644
895
|
}
|
|
645
896
|
function totalUnrealizedROI(inputs) {
|
|
646
897
|
const { totalUnrealizedPnL: totalUnrealizedPnL2, totalValue: totalValue2 } = inputs;
|
|
647
|
-
return new
|
|
898
|
+
return new Decimal(totalUnrealizedPnL2).div(totalValue2 - totalUnrealizedPnL2).toNumber();
|
|
648
899
|
}
|
|
900
|
+
|
|
901
|
+
// src/account/leverage.ts
|
|
649
902
|
function currentLeverage(totalMarginRatio2) {
|
|
650
903
|
if (totalMarginRatio2 === 0) {
|
|
651
904
|
return 0;
|
|
@@ -654,7 +907,16 @@ function currentLeverage(totalMarginRatio2) {
|
|
|
654
907
|
}
|
|
655
908
|
function availableBalance(inputs) {
|
|
656
909
|
const { USDCHolding, unsettlementPnL: unsettlementPnL2 } = inputs;
|
|
657
|
-
return new
|
|
910
|
+
return new Decimal(USDCHolding).add(unsettlementPnL2).toNumber();
|
|
911
|
+
}
|
|
912
|
+
function availableBalanceForIsolatedMargin(inputs) {
|
|
913
|
+
return Math.max(
|
|
914
|
+
0,
|
|
915
|
+
Math.min(
|
|
916
|
+
inputs.USDCHolding,
|
|
917
|
+
new Decimal(inputs.freeCollateral).sub(Math.max(inputs.totalCrossUnsettledPnL, 0)).toNumber()
|
|
918
|
+
)
|
|
919
|
+
);
|
|
658
920
|
}
|
|
659
921
|
function MMR2(inputs) {
|
|
660
922
|
if (inputs.positionsNotional === 0) {
|
|
@@ -663,7 +925,7 @@ function MMR2(inputs) {
|
|
|
663
925
|
if (inputs.positionsMMR === 0) {
|
|
664
926
|
return null;
|
|
665
927
|
}
|
|
666
|
-
return new
|
|
928
|
+
return new Decimal(inputs.positionsMMR).div(inputs.positionsNotional).toNumber();
|
|
667
929
|
}
|
|
668
930
|
var collateralRatio = (params) => {
|
|
669
931
|
const {
|
|
@@ -674,30 +936,30 @@ var collateralRatio = (params) => {
|
|
|
674
936
|
indexPrice
|
|
675
937
|
} = params;
|
|
676
938
|
const cap = collateralCap === -1 ? collateralQty : collateralCap;
|
|
677
|
-
const K = new
|
|
678
|
-
const DCF = new
|
|
679
|
-
const qty = new
|
|
939
|
+
const K = new Decimal(1.2);
|
|
940
|
+
const DCF = new Decimal(discountFactor || 0);
|
|
941
|
+
const qty = new Decimal(Math.min(collateralQty, cap));
|
|
680
942
|
const notionalAbs = qty.mul(indexPrice).abs();
|
|
681
943
|
const dynamicWeight = DCF.mul(notionalAbs.toPower(IMRFactorPower));
|
|
682
|
-
const result = K.div(new
|
|
683
|
-
return result.lt(baseWeight) ? result : new
|
|
944
|
+
const result = K.div(new Decimal(1).add(dynamicWeight));
|
|
945
|
+
return result.lt(baseWeight) ? result : new Decimal(baseWeight);
|
|
684
946
|
};
|
|
685
947
|
var collateralContribution = (params) => {
|
|
686
948
|
const { collateralQty, collateralCap, collateralRatio: collateralRatio2, indexPrice } = params;
|
|
687
949
|
const cap = collateralCap === -1 ? collateralQty : collateralCap;
|
|
688
|
-
return new
|
|
950
|
+
return new Decimal(Math.min(collateralQty, cap)).mul(collateralRatio2).mul(indexPrice).toNumber();
|
|
689
951
|
};
|
|
690
952
|
var LTV = (params) => {
|
|
691
953
|
const { usdcBalance, upnl, assets } = params;
|
|
692
|
-
const usdcLoss = new
|
|
693
|
-
const upnlLoss = new
|
|
954
|
+
const usdcLoss = new Decimal(Math.min(usdcBalance, 0)).abs();
|
|
955
|
+
const upnlLoss = new Decimal(Math.min(upnl, 0)).abs();
|
|
694
956
|
const numerator = usdcLoss.add(upnlLoss);
|
|
695
957
|
const collateralSum = assets.reduce((acc, asset) => {
|
|
696
958
|
return acc.add(
|
|
697
|
-
new
|
|
959
|
+
new Decimal(Math.max(asset.qty, 0)).mul(new Decimal(asset.indexPrice)).mul(new Decimal(asset.weight))
|
|
698
960
|
);
|
|
699
|
-
},
|
|
700
|
-
const denominator = collateralSum.add(new
|
|
961
|
+
}, zero);
|
|
962
|
+
const denominator = collateralSum.add(new Decimal(Math.max(upnl, 0)));
|
|
701
963
|
if (numerator.isZero() || denominator.isZero()) {
|
|
702
964
|
return 0;
|
|
703
965
|
}
|
|
@@ -706,44 +968,60 @@ var LTV = (params) => {
|
|
|
706
968
|
var maxWithdrawalUSDC = (inputs) => {
|
|
707
969
|
const { USDCBalance, freeCollateral: freeCollateral2, upnl } = inputs;
|
|
708
970
|
const value = Math.min(
|
|
709
|
-
new
|
|
710
|
-
new
|
|
971
|
+
new Decimal(USDCBalance).toNumber(),
|
|
972
|
+
new Decimal(freeCollateral2).sub(Math.max(upnl, 0)).toNumber()
|
|
711
973
|
);
|
|
712
974
|
return Math.max(0, value);
|
|
713
975
|
};
|
|
714
976
|
var maxWithdrawalOtherCollateral = (inputs) => {
|
|
715
977
|
const { USDCBalance, collateralQty, freeCollateral: freeCollateral2, indexPrice, weight } = inputs;
|
|
716
|
-
const usdcBalance = new
|
|
717
|
-
const denominator = usdcBalance.isNegative() ? new
|
|
978
|
+
const usdcBalance = new Decimal(USDCBalance);
|
|
979
|
+
const denominator = usdcBalance.isNegative() ? new Decimal(indexPrice).mul(weight).mul(new Decimal(1).add(2e-3)) : new Decimal(indexPrice).mul(weight);
|
|
718
980
|
if (denominator.isZero()) {
|
|
719
|
-
return
|
|
981
|
+
return zero;
|
|
720
982
|
}
|
|
721
|
-
const qty = new
|
|
722
|
-
const maxQtyByValue = new
|
|
983
|
+
const qty = new Decimal(collateralQty);
|
|
984
|
+
const maxQtyByValue = new Decimal(freeCollateral2).div(denominator);
|
|
723
985
|
return maxQtyByValue.lt(qty) ? maxQtyByValue : qty;
|
|
724
986
|
};
|
|
725
987
|
var calcMinimumReceived = (inputs) => {
|
|
726
988
|
const { amount, slippage } = inputs;
|
|
727
|
-
const slippageRatio = new
|
|
728
|
-
return new
|
|
729
|
-
};
|
|
730
|
-
var maxLeverage = (inputs) => {
|
|
731
|
-
const { symbolLeverage, accountLeverage } = inputs;
|
|
732
|
-
return symbolLeverage != null ? symbolLeverage : 1;
|
|
989
|
+
const slippageRatio = new Decimal(slippage).div(100);
|
|
990
|
+
return new Decimal(amount).mul(new Decimal(1).minus(slippageRatio)).toNumber();
|
|
733
991
|
};
|
|
734
992
|
|
|
993
|
+
// src/account/maxAddReduce.ts
|
|
994
|
+
function maxAdd(inputs) {
|
|
995
|
+
return availableBalanceForIsolatedMargin(inputs);
|
|
996
|
+
}
|
|
997
|
+
function maxReduce(inputs) {
|
|
998
|
+
const {
|
|
999
|
+
isolatedPositionMargin,
|
|
1000
|
+
positionNotional,
|
|
1001
|
+
imr,
|
|
1002
|
+
positionUnsettledPnL
|
|
1003
|
+
} = inputs;
|
|
1004
|
+
const minRequiredMargin = positionNotional * imr;
|
|
1005
|
+
const pnlAdjustment = Math.min(0, positionUnsettledPnL);
|
|
1006
|
+
return Math.max(
|
|
1007
|
+
0,
|
|
1008
|
+
isolatedPositionMargin - minRequiredMargin + pnlAdjustment
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
735
1012
|
// src/order.ts
|
|
736
1013
|
var order_exports = {};
|
|
737
1014
|
__export(order_exports, {
|
|
738
1015
|
estLeverage: () => estLeverage,
|
|
739
1016
|
estLiqPrice: () => estLiqPrice,
|
|
1017
|
+
estLiqPriceIsolated: () => estLiqPriceIsolated,
|
|
1018
|
+
getOrderReferencePrice: () => getOrderReferencePrice,
|
|
740
1019
|
maxPrice: () => maxPrice,
|
|
741
1020
|
minPrice: () => minPrice,
|
|
742
1021
|
orderFee: () => orderFee,
|
|
743
1022
|
scopePrice: () => scopePrice,
|
|
744
1023
|
tpslROI: () => tpslROI
|
|
745
1024
|
});
|
|
746
|
-
import { Decimal as Decimal4, getTPSLDirection, zero as zero3 } from "@orderly.network/utils";
|
|
747
1025
|
function maxPrice(markprice, range) {
|
|
748
1026
|
return markprice * (1 + range);
|
|
749
1027
|
}
|
|
@@ -757,7 +1035,135 @@ function scopePrice(price, scope, side) {
|
|
|
757
1035
|
return price * (1 + scope);
|
|
758
1036
|
}
|
|
759
1037
|
function orderFee(inputs) {
|
|
760
|
-
return new
|
|
1038
|
+
return new Decimal(inputs.qty).mul(inputs.price).mul(inputs.futuresTakeFeeRate).toNumber();
|
|
1039
|
+
}
|
|
1040
|
+
function getOrderReferencePrice(order, askPrice, bidPrice) {
|
|
1041
|
+
const getMarketRefPrice = () => {
|
|
1042
|
+
if (order.side === OrderSide.BUY) {
|
|
1043
|
+
return askPrice > 0 ? askPrice : null;
|
|
1044
|
+
}
|
|
1045
|
+
return bidPrice > 0 ? bidPrice : null;
|
|
1046
|
+
};
|
|
1047
|
+
const isValidPrice = (price) => typeof price === "number" && Number.isFinite(price) && price > 0;
|
|
1048
|
+
const { orderType, orderTypeExt, side } = order;
|
|
1049
|
+
const limitPrice = isValidPrice(order.limitPrice) ? order.limitPrice : void 0;
|
|
1050
|
+
const triggerPrice = isValidPrice(order.triggerPrice) ? order.triggerPrice : void 0;
|
|
1051
|
+
if (orderType === OrderType.LIMIT && (orderTypeExt === OrderType.ASK || orderTypeExt === OrderType.BID)) {
|
|
1052
|
+
if (side === OrderSide.BUY) {
|
|
1053
|
+
return orderTypeExt === OrderType.ASK ? isValidPrice(askPrice) ? askPrice : null : isValidPrice(bidPrice) ? bidPrice : null;
|
|
1054
|
+
}
|
|
1055
|
+
return orderTypeExt === OrderType.ASK ? isValidPrice(askPrice) ? askPrice : null : isValidPrice(bidPrice) ? bidPrice : null;
|
|
1056
|
+
}
|
|
1057
|
+
switch (orderType) {
|
|
1058
|
+
case OrderType.LIMIT:
|
|
1059
|
+
case OrderType.IOC:
|
|
1060
|
+
case OrderType.FOK:
|
|
1061
|
+
case OrderType.POST_ONLY: {
|
|
1062
|
+
if (!limitPrice) {
|
|
1063
|
+
return getMarketRefPrice();
|
|
1064
|
+
}
|
|
1065
|
+
if (side === OrderSide.BUY) {
|
|
1066
|
+
return limitPrice;
|
|
1067
|
+
}
|
|
1068
|
+
const effectiveBid = isValidPrice(bidPrice) ? bidPrice : 0;
|
|
1069
|
+
return Math.max(limitPrice, effectiveBid);
|
|
1070
|
+
}
|
|
1071
|
+
case OrderType.MARKET: {
|
|
1072
|
+
return getMarketRefPrice();
|
|
1073
|
+
}
|
|
1074
|
+
case OrderType.STOP_MARKET: {
|
|
1075
|
+
if (triggerPrice) {
|
|
1076
|
+
return triggerPrice;
|
|
1077
|
+
}
|
|
1078
|
+
return getMarketRefPrice();
|
|
1079
|
+
}
|
|
1080
|
+
case OrderType.STOP_LIMIT: {
|
|
1081
|
+
if (limitPrice) {
|
|
1082
|
+
return limitPrice;
|
|
1083
|
+
}
|
|
1084
|
+
return getMarketRefPrice();
|
|
1085
|
+
}
|
|
1086
|
+
case OrderType.TRAILING_STOP: {
|
|
1087
|
+
if (triggerPrice) {
|
|
1088
|
+
return triggerPrice;
|
|
1089
|
+
}
|
|
1090
|
+
return getMarketRefPrice();
|
|
1091
|
+
}
|
|
1092
|
+
default:
|
|
1093
|
+
return null;
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
function estLiqPriceIsolated(inputs) {
|
|
1097
|
+
var _a, _b;
|
|
1098
|
+
const {
|
|
1099
|
+
isolatedPositionMargin,
|
|
1100
|
+
costPosition,
|
|
1101
|
+
positionQty,
|
|
1102
|
+
sumUnitaryFunding,
|
|
1103
|
+
lastSumUnitaryFunding,
|
|
1104
|
+
markPrice,
|
|
1105
|
+
baseMMR,
|
|
1106
|
+
baseIMR,
|
|
1107
|
+
IMR_Factor: IMRFactor,
|
|
1108
|
+
leverage,
|
|
1109
|
+
newOrder
|
|
1110
|
+
} = inputs;
|
|
1111
|
+
const signedOrderQty = (_a = newOrder == null ? void 0 : newOrder.qty) != null ? _a : 0;
|
|
1112
|
+
const newPositionQty = positionQty + signedOrderQty;
|
|
1113
|
+
if (newPositionQty === 0) {
|
|
1114
|
+
return 0;
|
|
1115
|
+
}
|
|
1116
|
+
const orderRefPrice = (_b = newOrder == null ? void 0 : newOrder.price) != null ? _b : markPrice;
|
|
1117
|
+
if (markPrice <= 0 || signedOrderQty !== 0 && orderRefPrice <= 0) {
|
|
1118
|
+
return 0;
|
|
1119
|
+
}
|
|
1120
|
+
const isSameSign = (a, b) => a > 0 && b > 0 || a < 0 && b < 0;
|
|
1121
|
+
const getScenario = () => {
|
|
1122
|
+
if (signedOrderQty === 0) return "NO_ORDER";
|
|
1123
|
+
if (positionQty === 0 || isSameSign(signedOrderQty, positionQty))
|
|
1124
|
+
return "OPEN_ADD";
|
|
1125
|
+
if (isSameSign(positionQty, newPositionQty)) return "REDUCE";
|
|
1126
|
+
return "FLIP";
|
|
1127
|
+
};
|
|
1128
|
+
const decNewPositionQty = new Decimal(newPositionQty);
|
|
1129
|
+
const decAbsNewPositionQty = decNewPositionQty.abs();
|
|
1130
|
+
const decCostPosition = new Decimal(costPosition);
|
|
1131
|
+
const decIsolatedMargin = new Decimal(isolatedPositionMargin);
|
|
1132
|
+
const decOrderCost = new Decimal(signedOrderQty).mul(orderRefPrice);
|
|
1133
|
+
let newIsolatedPositionMargin;
|
|
1134
|
+
let newCostPosition;
|
|
1135
|
+
switch (getScenario()) {
|
|
1136
|
+
case "NO_ORDER":
|
|
1137
|
+
newIsolatedPositionMargin = decIsolatedMargin;
|
|
1138
|
+
newCostPosition = decCostPosition;
|
|
1139
|
+
break;
|
|
1140
|
+
case "OPEN_ADD":
|
|
1141
|
+
newIsolatedPositionMargin = decIsolatedMargin.add(
|
|
1142
|
+
new Decimal(Math.abs(signedOrderQty)).mul(orderRefPrice).div(leverage)
|
|
1143
|
+
);
|
|
1144
|
+
newCostPosition = decCostPosition.add(decOrderCost);
|
|
1145
|
+
break;
|
|
1146
|
+
case "REDUCE":
|
|
1147
|
+
newIsolatedPositionMargin = decIsolatedMargin.mul(newPositionQty).div(positionQty);
|
|
1148
|
+
newCostPosition = decCostPosition.add(decOrderCost);
|
|
1149
|
+
break;
|
|
1150
|
+
case "FLIP":
|
|
1151
|
+
newIsolatedPositionMargin = decAbsNewPositionQty.mul(orderRefPrice).div(leverage);
|
|
1152
|
+
newCostPosition = decNewPositionQty.mul(orderRefPrice);
|
|
1153
|
+
break;
|
|
1154
|
+
}
|
|
1155
|
+
const fundingAdjustment = decNewPositionQty.mul(
|
|
1156
|
+
new Decimal(sumUnitaryFunding).sub(lastSumUnitaryFunding)
|
|
1157
|
+
);
|
|
1158
|
+
const newPositionNotional = decAbsNewPositionQty.mul(markPrice);
|
|
1159
|
+
const dynamicMMR = new Decimal(baseMMR).div(baseIMR).mul(IMRFactor).mul(newPositionNotional.toPower(IMRFactorPower)).toNumber();
|
|
1160
|
+
const newMMR = Math.max(baseMMR, dynamicMMR);
|
|
1161
|
+
const denominator = decAbsNewPositionQty.mul(newMMR).sub(decNewPositionQty);
|
|
1162
|
+
if (denominator.isZero()) {
|
|
1163
|
+
return 0;
|
|
1164
|
+
}
|
|
1165
|
+
const liquidationPrice = newIsolatedPositionMargin.sub(newCostPosition).sub(fundingAdjustment).div(denominator).toNumber();
|
|
1166
|
+
return Math.max(0, liquidationPrice);
|
|
761
1167
|
}
|
|
762
1168
|
function estLiqPrice(inputs) {
|
|
763
1169
|
var _a;
|
|
@@ -772,13 +1178,13 @@ function estLiqPrice(inputs) {
|
|
|
772
1178
|
IMR_Factor
|
|
773
1179
|
} = inputs;
|
|
774
1180
|
let currentPosition = void 0;
|
|
775
|
-
let newTotalMM =
|
|
1181
|
+
let newTotalMM = zero;
|
|
776
1182
|
const hasPosition = positions.filter((item) => item.position_qty > 0).length > 0;
|
|
777
1183
|
const basePrice = hasPosition ? markPrice : newOrder.price;
|
|
778
|
-
const newOrderNotional = new
|
|
1184
|
+
const newOrderNotional = new Decimal(newOrder.qty).mul(newOrder.price);
|
|
779
1185
|
for (let index = 0; index < positions.length; index++) {
|
|
780
1186
|
const position = positions[index];
|
|
781
|
-
let notional2 = new
|
|
1187
|
+
let notional2 = new Decimal(position.position_qty).mul(position.mark_price);
|
|
782
1188
|
if (newOrder.symbol === position.symbol) {
|
|
783
1189
|
currentPosition = position;
|
|
784
1190
|
notional2 = notional2.add(newOrderNotional);
|
|
@@ -790,26 +1196,26 @@ function estLiqPrice(inputs) {
|
|
|
790
1196
|
}
|
|
791
1197
|
const newMMR = Math.max(
|
|
792
1198
|
baseMMR,
|
|
793
|
-
new
|
|
1199
|
+
new Decimal(baseMMR).div(baseIMR).mul(IMR_Factor).mul(
|
|
794
1200
|
newOrderNotional.add(
|
|
795
|
-
!!currentPosition ? new
|
|
1201
|
+
!!currentPosition ? new Decimal(currentPosition.position_qty).mul(
|
|
796
1202
|
currentPosition.mark_price
|
|
797
|
-
) :
|
|
1203
|
+
) : zero
|
|
798
1204
|
).abs()
|
|
799
1205
|
).toPower(4 / 5).toNumber()
|
|
800
1206
|
);
|
|
801
|
-
const newQty = new
|
|
1207
|
+
const newQty = new Decimal(newOrder.qty).add(
|
|
802
1208
|
(_a = currentPosition == null ? void 0 : currentPosition.position_qty) != null ? _a : 0
|
|
803
1209
|
);
|
|
804
1210
|
if (newQty.eq(0)) {
|
|
805
1211
|
return 0;
|
|
806
1212
|
}
|
|
807
1213
|
const denominator = newQty.abs().mul(newMMR).sub(newQty);
|
|
808
|
-
if (denominator.eq(
|
|
1214
|
+
if (denominator.eq(zero)) {
|
|
809
1215
|
return 0;
|
|
810
1216
|
}
|
|
811
|
-
const price = new
|
|
812
|
-
new
|
|
1217
|
+
const price = new Decimal(basePrice).add(
|
|
1218
|
+
new Decimal(totalCollateral2).sub(newTotalMM).sub(orderFee2).div(denominator)
|
|
813
1219
|
).toNumber();
|
|
814
1220
|
return Math.max(0, price);
|
|
815
1221
|
}
|
|
@@ -820,25 +1226,25 @@ function estLeverage(inputs) {
|
|
|
820
1226
|
}
|
|
821
1227
|
let hasPosition = false;
|
|
822
1228
|
let sumPositionNotional = positions.reduce((acc, cur) => {
|
|
823
|
-
let count = new
|
|
1229
|
+
let count = new Decimal(cur.position_qty).mul(cur.mark_price);
|
|
824
1230
|
if (cur.symbol === newOrder.symbol) {
|
|
825
1231
|
hasPosition = true;
|
|
826
|
-
count = count.add(new
|
|
1232
|
+
count = count.add(new Decimal(newOrder.qty).mul(newOrder.price));
|
|
827
1233
|
}
|
|
828
1234
|
return acc.add(count.abs());
|
|
829
|
-
},
|
|
1235
|
+
}, zero);
|
|
830
1236
|
if (!hasPosition) {
|
|
831
1237
|
sumPositionNotional = sumPositionNotional.add(
|
|
832
|
-
new
|
|
1238
|
+
new Decimal(newOrder.qty).mul(newOrder.price).abs()
|
|
833
1239
|
);
|
|
834
1240
|
}
|
|
835
|
-
if (sumPositionNotional.eq(
|
|
1241
|
+
if (sumPositionNotional.eq(zero)) {
|
|
836
1242
|
return null;
|
|
837
1243
|
}
|
|
838
|
-
const totalMarginRatio2 = new
|
|
1244
|
+
const totalMarginRatio2 = new Decimal(totalCollateral2).div(
|
|
839
1245
|
sumPositionNotional
|
|
840
1246
|
);
|
|
841
|
-
return new
|
|
1247
|
+
return new Decimal(1).div(totalMarginRatio2).toDecimalPlaces(2, Decimal.ROUND_HALF_EVEN).toNumber();
|
|
842
1248
|
}
|
|
843
1249
|
function tpslROI(inputs) {
|
|
844
1250
|
const direction = getTPSLDirection({
|
|
@@ -848,13 +1254,9 @@ function tpslROI(inputs) {
|
|
|
848
1254
|
orderPrice: inputs.orderPrice
|
|
849
1255
|
});
|
|
850
1256
|
const { closePrice, orderPrice, leverage } = inputs;
|
|
851
|
-
return new
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
order_exports as orderUtils,
|
|
857
|
-
positions_exports as positions,
|
|
858
|
-
version_default as version
|
|
859
|
-
};
|
|
1257
|
+
return new Decimal(closePrice).minus(orderPrice).div(orderPrice).mul(leverage).abs().mul(direction).toNumber();
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
export { account_exports as account, order_exports as order, order_exports as orderUtils, positions_exports as positions, version_default as version };
|
|
1261
|
+
//# sourceMappingURL=index.mjs.map
|
|
860
1262
|
//# sourceMappingURL=index.mjs.map
|