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