@orderly.network/perp 1.0.28 → 2.0.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 +103 -33
- package/dist/index.d.ts +103 -33
- package/dist/index.js +106 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -31,9 +31,9 @@ module.exports = __toCommonJS(src_exports);
|
|
|
31
31
|
// src/version.ts
|
|
32
32
|
if (typeof window !== "undefined") {
|
|
33
33
|
window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
|
|
34
|
-
window.__ORDERLY_VERSION__["@orderly.network/perp"] = "
|
|
34
|
+
window.__ORDERLY_VERSION__["@orderly.network/perp"] = "2.0.0";
|
|
35
35
|
}
|
|
36
|
-
var version_default = "
|
|
36
|
+
var version_default = "2.0.0";
|
|
37
37
|
|
|
38
38
|
// src/positions.ts
|
|
39
39
|
var positions_exports = {};
|
|
@@ -82,21 +82,25 @@ function totalUnrealizedPnL(positions) {
|
|
|
82
82
|
}, 0);
|
|
83
83
|
}
|
|
84
84
|
function liqPrice(inputs) {
|
|
85
|
-
const { markPrice, totalCollateral: totalCollateral2, positionQty, MMR:
|
|
86
|
-
const totalNotional2 = notional(positionQty, markPrice);
|
|
85
|
+
const { markPrice, totalCollateral: totalCollateral2, positions, positionQty, MMR: MMR3 } = inputs;
|
|
87
86
|
if (positionQty === 0) {
|
|
88
87
|
return 0;
|
|
89
88
|
}
|
|
89
|
+
const totalNotional2 = positions.reduce((acc, cur) => {
|
|
90
|
+
return acc.add(
|
|
91
|
+
new import_utils.Decimal(notional(cur.position_qty, cur.mark_price)).mul(cur.mmr)
|
|
92
|
+
);
|
|
93
|
+
}, import_utils.zero);
|
|
90
94
|
return Math.max(
|
|
91
95
|
new import_utils.Decimal(markPrice).add(
|
|
92
|
-
new import_utils.Decimal(totalCollateral2).sub(
|
|
96
|
+
new import_utils.Decimal(totalCollateral2).sub(totalNotional2).div(new import_utils.Decimal(positionQty).abs().mul(MMR3).sub(positionQty))
|
|
93
97
|
).toNumber(),
|
|
94
98
|
0
|
|
95
99
|
);
|
|
96
100
|
}
|
|
97
101
|
function maintenanceMargin(inputs) {
|
|
98
|
-
const { positionQty, markPrice, MMR:
|
|
99
|
-
return new import_utils.Decimal(positionQty).mul(markPrice).mul(
|
|
102
|
+
const { positionQty, markPrice, MMR: MMR3 } = inputs;
|
|
103
|
+
return new import_utils.Decimal(positionQty).mul(markPrice).mul(MMR3).abs().toNumber();
|
|
100
104
|
}
|
|
101
105
|
function unsettlementPnL(inputs) {
|
|
102
106
|
const {
|
|
@@ -141,6 +145,7 @@ function MMR(inputs) {
|
|
|
141
145
|
var account_exports = {};
|
|
142
146
|
__export(account_exports, {
|
|
143
147
|
IMR: () => IMR,
|
|
148
|
+
MMR: () => MMR2,
|
|
144
149
|
availableBalance: () => availableBalance,
|
|
145
150
|
buyOrdersFilter_by_symbol: () => buyOrdersFilter_by_symbol,
|
|
146
151
|
currentLeverage: () => currentLeverage,
|
|
@@ -174,7 +179,8 @@ function totalValue(inputs) {
|
|
|
174
179
|
return nonUSDCHoldingValue.add(USDCHolding).add(totalUnsettlementPnL2);
|
|
175
180
|
}
|
|
176
181
|
function freeCollateral(inputs) {
|
|
177
|
-
|
|
182
|
+
const value = inputs.totalCollateral.sub(inputs.totalInitialMarginWithOrders);
|
|
183
|
+
return value.isNegative() ? import_utils2.zero : value;
|
|
178
184
|
}
|
|
179
185
|
function totalCollateral(inputs) {
|
|
180
186
|
const { USDCHolding, nonUSDCHolding } = inputs;
|
|
@@ -366,7 +372,7 @@ function maxQty(side, inputs, options) {
|
|
|
366
372
|
}
|
|
367
373
|
return maxQtyByShort(inputs);
|
|
368
374
|
}
|
|
369
|
-
function maxQtyByLong(inputs) {
|
|
375
|
+
function maxQtyByLong(inputs, options) {
|
|
370
376
|
try {
|
|
371
377
|
const {
|
|
372
378
|
baseMaxQty,
|
|
@@ -398,7 +404,7 @@ function maxQtyByLong(inputs) {
|
|
|
398
404
|
return 0;
|
|
399
405
|
}
|
|
400
406
|
}
|
|
401
|
-
function maxQtyByShort(inputs) {
|
|
407
|
+
function maxQtyByShort(inputs, options) {
|
|
402
408
|
try {
|
|
403
409
|
const {
|
|
404
410
|
baseMaxQty,
|
|
@@ -457,19 +463,108 @@ function availableBalance(inputs) {
|
|
|
457
463
|
const { USDCHolding, unsettlementPnL: unsettlementPnL2 } = inputs;
|
|
458
464
|
return new import_utils2.Decimal(USDCHolding).add(unsettlementPnL2).toNumber();
|
|
459
465
|
}
|
|
466
|
+
function MMR2(inputs) {
|
|
467
|
+
if (inputs.positionsNotional === 0) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
return new import_utils2.Decimal(inputs.positionsMMR).div(inputs.positionsNotional).toNumber();
|
|
471
|
+
}
|
|
460
472
|
|
|
461
473
|
// src/order.ts
|
|
462
474
|
var order_exports = {};
|
|
463
475
|
__export(order_exports, {
|
|
476
|
+
estLeverage: () => estLeverage,
|
|
477
|
+
estLiqPrice: () => estLiqPrice,
|
|
464
478
|
maxPrice: () => maxPrice,
|
|
465
|
-
minPrice: () => minPrice
|
|
479
|
+
minPrice: () => minPrice,
|
|
480
|
+
scropePrice: () => scropePrice
|
|
466
481
|
});
|
|
482
|
+
var import_utils3 = require("@orderly.network/utils");
|
|
467
483
|
function maxPrice(markprice, range) {
|
|
468
484
|
return markprice * (1 + range);
|
|
469
485
|
}
|
|
470
486
|
function minPrice(markprice, range) {
|
|
471
487
|
return markprice * (1 - range);
|
|
472
488
|
}
|
|
489
|
+
function scropePrice(price, scrope, side) {
|
|
490
|
+
if (side === "BUY") {
|
|
491
|
+
return price * (1 - scrope);
|
|
492
|
+
}
|
|
493
|
+
return price * (1 + scrope);
|
|
494
|
+
}
|
|
495
|
+
function estLiqPrice(inputs) {
|
|
496
|
+
var _a;
|
|
497
|
+
const {
|
|
498
|
+
positions,
|
|
499
|
+
newOrder,
|
|
500
|
+
totalCollateral: totalCollateral2,
|
|
501
|
+
markPrice,
|
|
502
|
+
baseIMR,
|
|
503
|
+
baseMMR,
|
|
504
|
+
IMR_Factor
|
|
505
|
+
} = inputs;
|
|
506
|
+
let currentPosition = void 0;
|
|
507
|
+
let newTotalMM = import_utils3.zero;
|
|
508
|
+
const newOrderNotional = new import_utils3.Decimal(newOrder.qty).mul(newOrder.price);
|
|
509
|
+
for (let index = 0; index < positions.length; index++) {
|
|
510
|
+
const position = positions[index];
|
|
511
|
+
let notional2 = new import_utils3.Decimal(position.position_qty).mul(position.mark_price);
|
|
512
|
+
if (newOrder.symbol === position.symbol) {
|
|
513
|
+
currentPosition = position;
|
|
514
|
+
notional2 = notional2.add(newOrderNotional);
|
|
515
|
+
}
|
|
516
|
+
newTotalMM = newTotalMM.add(notional2.abs().mul(position.mmr));
|
|
517
|
+
}
|
|
518
|
+
const newMMR = Math.max(
|
|
519
|
+
baseMMR,
|
|
520
|
+
new import_utils3.Decimal(baseMMR).div(baseIMR).mul(IMR_Factor).mul(
|
|
521
|
+
newOrderNotional.add(
|
|
522
|
+
!!currentPosition ? new import_utils3.Decimal(currentPosition.position_qty).mul(
|
|
523
|
+
currentPosition.mark_price
|
|
524
|
+
) : import_utils3.zero
|
|
525
|
+
).abs()
|
|
526
|
+
).toPower(4 / 5).toNumber()
|
|
527
|
+
);
|
|
528
|
+
const newQty = new import_utils3.Decimal(newOrder.qty).add(
|
|
529
|
+
(_a = currentPosition == null ? void 0 : currentPosition.position_qty) != null ? _a : 0
|
|
530
|
+
);
|
|
531
|
+
if (newQty.eq(0)) {
|
|
532
|
+
return 0;
|
|
533
|
+
}
|
|
534
|
+
const price = new import_utils3.Decimal(markPrice).add(
|
|
535
|
+
new import_utils3.Decimal(totalCollateral2).sub(newTotalMM).div(newQty.abs().mul(newMMR).sub(newQty))
|
|
536
|
+
).toNumber();
|
|
537
|
+
return Math.max(0, price);
|
|
538
|
+
}
|
|
539
|
+
function estLeverage(inputs) {
|
|
540
|
+
const { totalCollateral: totalCollateral2, positions, newOrder } = inputs;
|
|
541
|
+
if (totalCollateral2 <= 0) {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
let hasPosition = false;
|
|
545
|
+
let sumPositionNotional = positions.reduce((acc, cur) => {
|
|
546
|
+
acc = acc.add(
|
|
547
|
+
new import_utils3.Decimal(new import_utils3.Decimal(cur.position_qty).mul(cur.mark_price).abs())
|
|
548
|
+
);
|
|
549
|
+
if (cur.symbol === newOrder.symbol) {
|
|
550
|
+
hasPosition = true;
|
|
551
|
+
acc = acc.add(new import_utils3.Decimal(newOrder.qty).mul(newOrder.price));
|
|
552
|
+
}
|
|
553
|
+
return acc;
|
|
554
|
+
}, import_utils3.zero);
|
|
555
|
+
if (!hasPosition) {
|
|
556
|
+
sumPositionNotional = sumPositionNotional.add(
|
|
557
|
+
new import_utils3.Decimal(newOrder.qty).mul(newOrder.price).abs()
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
if (sumPositionNotional.eq(import_utils3.zero)) {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
const totalMarginRatio2 = new import_utils3.Decimal(totalCollateral2).div(
|
|
564
|
+
sumPositionNotional
|
|
565
|
+
);
|
|
566
|
+
return new import_utils3.Decimal(1).div(totalMarginRatio2).toDecimalPlaces(2, import_utils3.Decimal.ROUND_HALF_EVEN).toNumber();
|
|
567
|
+
}
|
|
473
568
|
// Annotate the CommonJS export names for ESM import in node:
|
|
474
569
|
0 && (module.exports = {
|
|
475
570
|
account,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/positions.ts","../src/constants.ts","../src/account.ts","../src/order.ts"],"sourcesContent":["export { default as version } from \"./version\";\nexport * as positions from \"./positions\";\nexport * as account from \"./account\";\nexport * as orderUtils from \"./order\";\n\nexport * as order from \"./order\";\n","\ndeclare global {\n interface Window {\n __ORDERLY_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif(typeof window !== 'undefined') {\n window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};\n window.__ORDERLY_VERSION__[\"@orderly.network/perp\"] = \"1.0.28\";\n};\n\nexport default \"1.0.28\";\n","import { API } from \"@orderly.network/types\";\nimport { Decimal } from \"@orderly.network/utils\";\nimport { IMRFactorPower } from \"./constants\";\n\n/**\n * Calculates the notional value of a single position.\n * @param qty The quantity of the position.\n * @param mark_price The price of the position.\n * @returns The notional value of the position.\n */\nexport function notional(qty: number, mark_price: number): number {\n return new Decimal(qty).mul(mark_price).abs().toNumber();\n}\n\n/**\n * Calculates the total notional value of all positions.\n * @param positions The array of positions.\n * @returns The total notional value of all positions.\n * @link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Notional\n */\nexport function totalNotional(positions: API.Position[]): number {\n return positions.reduce((acc, cur) => {\n return acc + notional(cur.position_qty, cur.mark_price);\n }, 0);\n}\n\nexport type UnrealPnLInputs = {\n markPrice: number;\n openPrice: number;\n qty: number;\n};\n\n/**\n * Calculates the unrealized profit or loss of a single position.\n * @param inputs The inputs for calculating the unrealized profit or loss.\n * @returns The unrealized profit or loss of the position.\n */\nexport function unrealizedPnL(inputs: UnrealPnLInputs): number {\n return new Decimal(inputs.qty)\n .mul(inputs.markPrice - inputs.openPrice)\n .toNumber();\n}\n\nexport type UnrealPnLROIInputs = {\n positionQty: number;\n openPrice: number;\n IMR: number;\n unrealizedPnL: number;\n};\n\n/**\n * Calculates the return on investment (ROI) of a single position's unrealized profit or loss.\n * @param inputs The inputs for calculating the ROI.\n * @returns The ROI of the position's unrealized profit or loss.\n */\nexport function unrealizedPnLROI(inputs: UnrealPnLROIInputs): number {\n const { openPrice, IMR } = inputs;\n\n if (\n inputs.unrealizedPnL === 0 ||\n inputs.positionQty === 0 ||\n openPrice === 0 ||\n IMR === 0\n )\n return 0;\n\n return new Decimal(inputs.unrealizedPnL)\n .div(new Decimal(inputs.positionQty).mul(openPrice).mul(IMR))\n .toNumber();\n}\n\n/**\n * Calculates the total unrealized profit or loss of all positions.\n * @param positions The array of positions.\n * @returns The total unrealized profit or loss of all positions.\n */\nexport function totalUnrealizedPnL(positions: API.Position[]): number {\n return positions.reduce((acc, cur) => {\n return (\n acc +\n unrealizedPnL({\n qty: cur.position_qty,\n openPrice: cur.average_open_price,\n markPrice: cur.mark_price,\n })\n );\n }, 0);\n}\n\nexport type LiqPriceInputs = {\n markPrice: number;\n totalCollateral: number;\n positionQty: number;\n MMR: number;\n};\n\n/**\n * Calculates the liquidation price of a single position.\n * @param inputs The inputs for calculating the liquidation price.\n * @returns The liquidation price of the position.\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Position-Liq.-Price}\n */\nexport function liqPrice(inputs: LiqPriceInputs): number {\n const { markPrice, totalCollateral, positionQty, MMR } = inputs;\n const totalNotional = notional(positionQty, markPrice);\n\n if (positionQty === 0) {\n return 0;\n }\n\n return Math.max(\n new Decimal(markPrice)\n .add(\n new Decimal(totalCollateral)\n .sub(new Decimal(totalNotional).mul(MMR))\n .div(new Decimal(positionQty).abs().mul(MMR).sub(positionQty))\n )\n .toNumber(),\n 0\n );\n}\n\nexport type MMInputs = {\n positionQty: number;\n markPrice: number;\n MMR: number;\n};\n\n/**\n * Calculates the maintenance margin of a position.\n * @param inputs The inputs for calculating the maintenance margin.\n * @returns The maintenance margin of the position.\n */\nexport function maintenanceMargin(inputs: MMInputs) {\n const { positionQty, markPrice, MMR } = inputs;\n\n return new Decimal(positionQty).mul(markPrice).mul(MMR).abs().toNumber();\n}\n\nexport type UnsettlementPnLInputs = {\n positionQty: number;\n markPrice: number;\n costPosition: number;\n sumUnitaryFunding: number;\n lastSumUnitaryFunding: number;\n};\n\n/**\n * Calculates the unrealized profit or loss of each position.\n * @param inputs The inputs for calculating the unrealized profit or loss.\n * @returns The unrealized profit or loss of each position.\n * @link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Unsettlement-PNL-%5BinlineExtension%5D\n */\nexport function unsettlementPnL(inputs: UnsettlementPnLInputs): number {\n const {\n positionQty,\n markPrice,\n costPosition,\n sumUnitaryFunding,\n lastSumUnitaryFunding,\n } = inputs;\n\n const qty = new Decimal(positionQty);\n\n return qty\n .mul(markPrice)\n .sub(costPosition)\n .sub(qty.mul(new Decimal(sumUnitaryFunding).sub(lastSumUnitaryFunding)))\n .toNumber();\n}\n\nexport type TotalUnsettlementPnLInputs = {\n positions: (API.Position & {\n sum_unitary_funding: number;\n })[];\n sumUnitaryFunding: number;\n};\n\n/**\n * Calculates the total unrealized profit or loss of all positions.\n * @param positions The array of positions.\n * @returns The total unrealized profit or loss of all positions.\n * @link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Unsettlement-PNL-%5BinlineExtension%5D\n */\nexport function totalUnsettlementPnL(\n positions: (API.Position & {\n sum_unitary_funding: number;\n })[]\n): number {\n if (!Array.isArray(positions) || positions.length === 0) {\n return 0;\n }\n\n return positions.reduce((acc, cur) => {\n return (\n acc +\n unsettlementPnL({\n positionQty: cur.position_qty,\n markPrice: cur.mark_price,\n costPosition: cur.cost_position,\n sumUnitaryFunding: cur.sum_unitary_funding,\n lastSumUnitaryFunding: cur.last_sum_unitary_funding,\n })\n );\n }, 0);\n}\n\n/**\n * Calculates the maintenance margin requirement (MMR) of a position.\n * @param inputs The inputs for calculating the MMR.\n * @returns The MMR of the position.\n */\nexport function MMR(inputs: {\n baseMMR: number;\n baseIMR: number;\n IMRFactor: number;\n positionNotional: number;\n IMR_factor_power: number;\n}): number {\n const {\n baseMMR,\n baseIMR,\n IMRFactor,\n positionNotional,\n IMR_factor_power = IMRFactorPower,\n } = inputs;\n return Math.max(\n baseMMR,\n new Decimal(baseMMR)\n .div(baseIMR)\n .mul(IMRFactor)\n .mul(Math.abs(positionNotional))\n .toPower(IMR_factor_power)\n .toNumber()\n );\n}\n","/**\n * The power of the IMR factor.\n * @constant\n * @default\n */\nexport const IMRFactorPower = 4 / 5;\n","import { Decimal, zero } from \"@orderly.network/utils\";\nimport { IMRFactorPower } from \"./constants\";\nimport {\n API,\n OrderSide,\n OrderType,\n type WSMessage,\n} from \"@orderly.network/types\";\n\nexport type ResultOptions = {\n dp: number;\n};\n\nexport type TotalValueInputs = {\n totalUnsettlementPnL: number;\n\n USDCHolding: number;\n nonUSDCHolding: {\n holding: number;\n markPrice: number;\n //保證金替代率 暂时默认0\n discount: number;\n }[];\n};\n/**\n * 用戶總資產價值 (USDC計價),包含無法作為保證金的資產\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Value}\n */\nexport function totalValue(inputs: TotalValueInputs): Decimal {\n const { totalUnsettlementPnL, USDCHolding, nonUSDCHolding } = inputs;\n\n const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {\n return new Decimal(cur.holding).mul(cur.markPrice).add(acc);\n }, zero);\n\n return nonUSDCHoldingValue.add(USDCHolding).add(totalUnsettlementPnL);\n}\n\n/**\n * 用戶帳戶當前可用保證金的價值總和 (USDC計價)\n *\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Free-collateral}\n */\nexport type FreeCollateralInputs = {\n // 总保证金\n totalCollateral: Decimal;\n // 总初始保证金\n totalInitialMarginWithOrders: number;\n};\n/**\n * 计算可用保证金\n */\nexport function freeCollateral(inputs: FreeCollateralInputs): Decimal {\n return inputs.totalCollateral.sub(inputs.totalInitialMarginWithOrders);\n}\n\nexport type TotalCollateralValueInputs = {\n // USDC 的 holding 數量\n USDCHolding: number;\n nonUSDCHolding: {\n holding: number;\n markPrice: number;\n //保證金替代率 暂时默认0\n discount: number;\n }[];\n // 未结算盈亏\n unsettlementPnL: number;\n};\n/**\n * 计算总保证金\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-collateral-%5BinlineExtension%5D}\n */\nexport function totalCollateral(inputs: TotalCollateralValueInputs): Decimal {\n const { USDCHolding, nonUSDCHolding } = inputs;\n const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {\n return (\n acc +\n new Decimal(cur.holding).mul(cur.markPrice).mul(cur.discount).toNumber()\n );\n }, 0);\n\n return new Decimal(USDCHolding)\n .add(nonUSDCHoldingValue)\n .add(inputs.unsettlementPnL);\n}\n\nexport function initialMarginWithOrder() {}\n\nexport type PositionNotionalWithOrderInputs = {\n markPrice: number;\n positionQtyWithOrders: number;\n};\n/**\n * 單一 Symbol position / orders notional 加總\n */\nexport function positionNotionalWithOrder_by_symbol(\n inputs: PositionNotionalWithOrderInputs\n): Decimal {\n return new Decimal(inputs.markPrice).mul(inputs.positionQtyWithOrders);\n}\n\nexport type PositionQtyWithOrderInputs = {\n positionQty: number;\n // 单个Symbol的所有买单合计\n buyOrdersQty: number;\n // 单个Symbol的所有卖单合计\n sellOrdersQty: number;\n};\n/**\n * 單一 Symbol position / orders qty 加總\n */\nexport function positionQtyWithOrders_by_symbol(\n inputs: PositionQtyWithOrderInputs\n): number {\n const { positionQty, buyOrdersQty, sellOrdersQty } = inputs;\n const positionQtyDecimal = new Decimal(positionQty);\n const qty = Math.max(\n positionQtyDecimal.add(buyOrdersQty).abs().toNumber(),\n positionQtyDecimal.sub(sellOrdersQty).abs().toNumber()\n );\n\n return qty;\n}\n\nexport type IMRInputs = {\n maxLeverage: number;\n baseIMR: number;\n IMR_Factor: number;\n positionNotional: number;\n ordersNotional: number;\n IMR_factor_power?: number;\n};\n\n/**\n * 單一 Symbol 初始保證金率\n * Max(1 / Max Account Leverage, Base IMR i, IMR Factor i * Abs(Position Notional i + Order Notional i)^(4/5))\n */\nexport function IMR(inputs: IMRInputs): number {\n const {\n maxLeverage,\n baseIMR,\n IMR_Factor,\n positionNotional,\n ordersNotional: orderNotional,\n IMR_factor_power = IMRFactorPower,\n } = inputs;\n return Math.max(\n 1 / maxLeverage,\n baseIMR,\n new Decimal(IMR_Factor)\n .mul(\n new Decimal(positionNotional)\n .add(orderNotional)\n .abs()\n .toPower(IMR_factor_power)\n )\n .toNumber()\n );\n}\n\nexport function buyOrdersFilter_by_symbol(\n orders: API.Order[],\n symbol: string\n): API.Order[] {\n return orders.filter(\n (item) => item.symbol === symbol && item.side === OrderSide.BUY\n );\n}\n\nexport function sellOrdersFilter_by_symbol(\n orders: API.Order[],\n symbol: string\n): API.Order[] {\n return orders.filter(\n (item) => item.symbol === symbol && item.side === OrderSide.SELL\n );\n}\n\n/**\n * 从仓位列表中获取指定symbol的仓位数量\n */\nexport function getQtyFromPositions(\n positions: API.Position[],\n symbol: string\n): number {\n if (!positions) {\n return 0;\n }\n const position = positions.find((item) => item.symbol === symbol);\n return position?.position_qty || 0;\n}\n\n/**\n * 从订单列表中获取指定symbol的看多,看空订单数量,\n */\nexport function getQtyFromOrdersBySide(\n orders: API.Order[],\n symbol: string,\n side: OrderSide\n): number {\n const ordersBySide =\n side === OrderSide.SELL\n ? sellOrdersFilter_by_symbol(orders, symbol)\n : buyOrdersFilter_by_symbol(orders, symbol);\n return ordersBySide.reduce((acc, cur) => {\n return acc + cur.quantity;\n }, 0);\n}\n\nexport function getPositonsAndOrdersNotionalBySymbol(inputs: {\n positions: API.Position[];\n orders: API.Order[];\n symbol: string;\n markPrice: number;\n}): number {\n const { positions, orders, symbol, markPrice } = inputs;\n const positionQty = getQtyFromPositions(positions, symbol);\n const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.BUY);\n const sellOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.SELL);\n\n const markPriceDecimal = new Decimal(markPrice);\n\n return markPriceDecimal\n .mul(positionQty)\n .add(markPriceDecimal.mul(new Decimal(buyOrdersQty).add(sellOrdersQty)))\n .abs()\n .toNumber();\n}\n\nexport type TotalInitialMarginWithOrdersInputs = {\n positions: API.Position[];\n orders: API.Order[];\n // account: API.AccountInfo;\n markPrices: { [key: string]: number };\n symbolInfo: any;\n IMR_Factors: { [key: string]: number };\n} & Pick<IMRInputs, \"maxLeverage\">;\n\n/**\n * 计算用戶已使用初始保證金加總 ( 包含 position / orders )\n */\nexport function totalInitialMarginWithOrders(\n inputs: TotalInitialMarginWithOrdersInputs\n): number {\n const {\n positions,\n orders,\n markPrices,\n IMR_Factors,\n maxLeverage,\n symbolInfo,\n } = inputs;\n\n const symbols = extractSymbols(positions, orders);\n\n const total_initial_margin_with_orders = symbols.reduce((acc, cur) => {\n const symbol = cur;\n const positionQty = getQtyFromPositions(positions, symbol);\n const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.BUY);\n const sellOrdersQty = getQtyFromOrdersBySide(\n orders,\n symbol,\n OrderSide.SELL\n );\n\n const markPrice = markPrices[symbol] || 0;\n\n //---\n const positionQtyWithOrders = positionQtyWithOrders_by_symbol({\n positionQty,\n buyOrdersQty,\n sellOrdersQty,\n });\n\n //---\n const position_notional_with_orders = positionNotionalWithOrder_by_symbol({\n markPrice,\n positionQtyWithOrders,\n });\n\n //----\n const markPriceDecimal = new Decimal(markPrice);\n\n const imr = IMR({\n positionNotional: markPriceDecimal.mul(positionQty).toNumber(),\n ordersNotional: markPriceDecimal\n .mul(new Decimal(buyOrdersQty).add(sellOrdersQty))\n .toNumber(),\n maxLeverage,\n IMR_Factor: IMR_Factors[symbol],\n baseIMR: symbolInfo[symbol](\"base_imr\", 0),\n });\n\n return position_notional_with_orders.mul(imr).add(acc).toNumber();\n }, 0);\n\n return total_initial_margin_with_orders;\n}\n\n/**\n * 把订单按照symbol分组, 因为一个symbol可以有多个挂单\n */\nexport function groupOrdersBySymbol(orders: API.Order[]) {\n const symbols: { [key: string]: API.Order[] } = {};\n\n orders.forEach((item) => {\n if (!symbols[item.symbol]) {\n symbols[item.symbol] = [];\n }\n\n symbols[item.symbol].push(item);\n });\n\n return symbols;\n}\n\n/**\n * Extracts all unique symbols from positions and orders.\n * @param positions - An array of position objects.\n * @param orders - An array of order objects.\n * @returns An array of unique symbols.\n */\nexport function extractSymbols(\n positions: Pick<API.Position, \"symbol\">[],\n orders: Pick<API.Order, \"symbol\">[]\n): string[] {\n const symbols = new Set<string>();\n\n positions.forEach((item) => {\n symbols.add(item.symbol);\n });\n\n orders.forEach((item) => {\n symbols.add(item.symbol);\n });\n\n return Array.from(symbols);\n}\n\n//=========== max qty ==================\n\n// function otherIM(inputs: {}): number {}\n\nexport type OtherIMsInputs = {\n // 传入除当前symbol外的其他symbol的仓位列表\n positions: API.Position[];\n // 传入除当前symbol外的其他symbol的订单列表\n orders: API.Order[];\n\n markPrices: { [key: string]: number };\n maxLeverage: number;\n symbolInfo: any;\n IMR_Factors: { [key: string]: number };\n};\n/**\n * 除当前symbol外的其他symbol已占用的总保证金\n */\nexport function otherIMs(inputs: OtherIMsInputs): number {\n const {\n orders,\n positions,\n maxLeverage,\n IMR_Factors,\n symbolInfo,\n markPrices,\n } = inputs;\n\n const symbols = extractSymbols(positions, orders);\n\n return symbols\n .reduce((acc, cur) => {\n const symbol = cur;\n\n if (typeof markPrices[symbol] === \"undefined\") {\n console.warn(\"markPrices[%s] is undefined\", symbol);\n return acc;\n }\n\n const markPriceDecimal = new Decimal(markPrices[symbol] || 0);\n\n const positionQty = getQtyFromPositions(positions, symbol);\n const positionNotional = markPriceDecimal.mul(positionQty).toNumber();\n\n const buyOrdersQty = getQtyFromOrdersBySide(\n orders,\n symbol,\n OrderSide.BUY\n );\n const sellOrdersQty = getQtyFromOrdersBySide(\n orders,\n symbol,\n OrderSide.SELL\n );\n\n const ordersNotional = markPriceDecimal\n .mul(new Decimal(buyOrdersQty).add(sellOrdersQty))\n .toNumber();\n\n const IMR_Factor = IMR_Factors[symbol];\n\n if (!IMR_Factor) {\n console.warn(\"IMR_Factor is not found:\", symbol);\n return acc;\n }\n\n const imr = IMR({\n maxLeverage,\n\n IMR_Factor,\n baseIMR: symbolInfo[symbol](\"base_imr\", 0),\n positionNotional,\n ordersNotional,\n });\n\n const positionQtyWithOrders = positionQtyWithOrders_by_symbol({\n positionQty,\n buyOrdersQty,\n sellOrdersQty,\n });\n\n const positionNotionalWithOrders = positionNotionalWithOrder_by_symbol({\n markPrice: markPrices[symbol] || 0,\n positionQtyWithOrders,\n });\n\n return acc.add(positionNotionalWithOrders.mul(imr));\n }, zero)\n .toNumber();\n}\n\nexport type MaxQtyInputs = {\n symbol: string;\n\n //單次開倉最大 Qty 限制, /v1/public/info.base_max\n baseMaxQty: number;\n /**\n * 用户保证金总额(USDC 计价), 可以由 totalCollateral 计算得出\n * @see totalCollateral\n */\n totalCollateral: number;\n maxLeverage: number;\n baseIMR: number;\n /**\n * @see otherIMs\n */\n otherIMs: number;\n markPrice: number;\n // 已开仓数量\n positionQty: number;\n // 已挂多单数量\n buyOrdersQty: number;\n // 已挂空单数量\n sellOrdersQty: number;\n\n IMR_Factor: number;\n\n takerFeeRate: number;\n};\n\n/**\n * 最大可下单数量\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Max-Order-QTY}\n */\nexport function maxQty(\n side: OrderSide,\n inputs: MaxQtyInputs,\n options?: ResultOptions\n): number {\n if (side === OrderSide.BUY) {\n return maxQtyByLong(inputs);\n }\n return maxQtyByShort(inputs);\n}\n\nexport function maxQtyByLong(inputs: Omit<MaxQtyInputs, \"side\">): number {\n try {\n const {\n baseMaxQty,\n totalCollateral,\n otherIMs,\n maxLeverage,\n baseIMR,\n markPrice,\n IMR_Factor,\n positionQty,\n buyOrdersQty,\n takerFeeRate,\n } = inputs;\n\n if (totalCollateral === 0) {\n return 0;\n }\n\n const totalCollateralDecimal = new Decimal(totalCollateral);\n\n const factor_1 = totalCollateralDecimal\n .sub(otherIMs)\n .div(\n new Decimal(takerFeeRate)\n .mul(2)\n .mul(0.0001)\n .add(Math.max(1 / maxLeverage, baseIMR))\n )\n .div(markPrice)\n .mul(0.995)\n .sub(new Decimal(positionQty).add(buyOrdersQty))\n .toNumber();\n\n if (positionQty === 0 && buyOrdersQty === 0) {\n return Math.min(baseMaxQty, factor_1);\n }\n\n const factor_2 = totalCollateralDecimal\n .sub(otherIMs)\n .div(IMR_Factor)\n .toPower(1 / 1.8)\n .div(markPrice)\n .sub(\n new Decimal(positionQty)\n .add(buyOrdersQty)\n // .abs()\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\n )\n .mul(0.995)\n .toNumber();\n\n return Math.min(baseMaxQty, factor_1, factor_2);\n } catch (error) {\n return 0;\n }\n}\n\nexport function maxQtyByShort(inputs: Omit<MaxQtyInputs, \"side\">): number {\n try {\n const {\n baseMaxQty,\n totalCollateral,\n otherIMs,\n maxLeverage,\n baseIMR,\n markPrice,\n IMR_Factor,\n positionQty,\n buyOrdersQty,\n sellOrdersQty,\n takerFeeRate,\n } = inputs;\n\n const totalCollateralDecimal = new Decimal(totalCollateral);\n\n const factor_1 = totalCollateralDecimal\n .sub(otherIMs)\n .div(\n new Decimal(takerFeeRate)\n .mul(2)\n .mul(0.0001)\n .add(Math.max(1 / maxLeverage, baseIMR))\n )\n .div(markPrice)\n .mul(0.995)\n .add(new Decimal(positionQty).add(sellOrdersQty))\n\n .toNumber();\n\n if (positionQty === 0 && buyOrdersQty === 0) {\n return Math.min(baseMaxQty, factor_1);\n }\n\n const factor_2 = totalCollateralDecimal\n .sub(otherIMs)\n .div(IMR_Factor)\n .toPower(1 / 1.8)\n .div(markPrice)\n .add(\n new Decimal(positionQty)\n .add(sellOrdersQty)\n // .abs()\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\n )\n .mul(0.995)\n .toNumber();\n\n return Math.min(baseMaxQty, factor_1, factor_2);\n } catch (error) {\n return 0;\n }\n}\n\nexport type TotalMarginRatioInputs = {\n totalCollateral: number;\n markPrices: { [key: string]: number };\n positions: API.Position[];\n};\n/**\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Margin-Ratio}\n */\nexport function totalMarginRatio(\n inputs: TotalMarginRatioInputs,\n dp?: number\n): number {\n const { totalCollateral, markPrices, positions } = inputs;\n\n if (totalCollateral === 0) {\n return 0;\n }\n\n const totalCollateralDecimal = new Decimal(totalCollateral);\n\n const totalPositionNotional = positions.reduce((acc, cur) => {\n const markPrice = markPrices[cur.symbol] || 0;\n return acc.add(new Decimal(cur.position_qty).mul(markPrice).abs());\n }, zero);\n\n if (totalPositionNotional.eq(zero)) {\n return 0;\n }\n\n return totalCollateralDecimal.div(totalPositionNotional).toNumber();\n}\n\nexport type TotalUnrealizedROIInputs = {\n totalUnrealizedPnL: number;\n totalValue: number;\n};\n\n/**\n * totalUnrealizedROI\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Unrealized-ROI}\n */\nexport function totalUnrealizedROI(inputs: TotalUnrealizedROIInputs) {\n const { totalUnrealizedPnL, totalValue } = inputs;\n\n return new Decimal(totalUnrealizedPnL)\n .div(totalValue - totalUnrealizedPnL)\n .toNumber();\n}\n\n/**\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Current-account-leverage}\n */\nexport function currentLeverage(totalMarginRatio: number) {\n if (totalMarginRatio === 0) {\n return 0;\n }\n return 1 / totalMarginRatio;\n}\n\nexport type AvailableBalanceInputs = {\n USDCHolding: number;\n unsettlementPnL: number;\n};\nexport function availableBalance(inputs: AvailableBalanceInputs) {\n const { USDCHolding, unsettlementPnL } = inputs;\n\n return new Decimal(USDCHolding).add(unsettlementPnL).toNumber();\n}\n","/**\n * 下单时的最高价格\n * @see https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Max-price\n */\nexport function maxPrice(markprice: number, range: number) {\n return markprice * (1 + range);\n}\n\n/**\n * 下单时的最低价格\n * @see https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Min-price\n */\nexport function minPrice(markprice: number, range: number) {\n return markprice * (1 - range);\n}\n"],"mappings":"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","names":["IMR","totalCollateral","MMR","totalNotional","import_utils","totalUnsettlementPnL","totalCollateral","otherIMs","totalUnrealizedPnL","totalValue","totalMarginRatio","unsettlementPnL"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/positions.ts","../src/constants.ts","../src/account.ts","../src/order.ts"],"sourcesContent":["export { default as version } from \"./version\";\nexport * as positions from \"./positions\";\nexport * as account from \"./account\";\nexport * as orderUtils from \"./order\";\n\nexport * as order from \"./order\";\n","\ndeclare global {\n interface Window {\n __ORDERLY_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif(typeof window !== 'undefined') {\n window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};\n window.__ORDERLY_VERSION__[\"@orderly.network/perp\"] = \"2.0.0\";\n};\n\nexport default \"2.0.0\";\n","import { API } from \"@orderly.network/types\";\nimport { Decimal, zero } from \"@orderly.network/utils\";\nimport { IMRFactorPower } from \"./constants\";\n\n/**\n * Calculates the notional value of a single position.\n * @param qty The quantity of the position.\n * @param mark_price The price of the position.\n * @returns The notional value of the position.\n */\nexport function notional(qty: number, mark_price: number): number {\n return new Decimal(qty).mul(mark_price).abs().toNumber();\n}\n\n/**\n * Calculates the total notional value of all positions.\n * @param positions The array of positions.\n * @returns The total notional value of all positions.\n * @link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Notional\n */\nexport function totalNotional(positions: API.Position[]): number {\n return positions.reduce((acc, cur) => {\n return acc + notional(cur.position_qty, cur.mark_price);\n }, 0);\n}\n\nexport type UnrealPnLInputs = {\n markPrice: number;\n openPrice: number;\n qty: number;\n};\n\n/**\n * Calculates the unrealized profit or loss of a single position.\n * @param inputs The inputs for calculating the unrealized profit or loss.\n * @returns The unrealized profit or loss of the position.\n */\nexport function unrealizedPnL(inputs: UnrealPnLInputs): number {\n return new Decimal(inputs.qty)\n .mul(inputs.markPrice - inputs.openPrice)\n .toNumber();\n}\n\nexport type UnrealPnLROIInputs = {\n positionQty: number;\n openPrice: number;\n IMR: number;\n unrealizedPnL: number;\n};\n\n/**\n * Calculates the return on investment (ROI) of a single position's unrealized profit or loss.\n * @param inputs The inputs for calculating the ROI.\n * @returns The ROI of the position's unrealized profit or loss.\n */\nexport function unrealizedPnLROI(inputs: UnrealPnLROIInputs): number {\n const { openPrice, IMR } = inputs;\n\n if (\n inputs.unrealizedPnL === 0 ||\n inputs.positionQty === 0 ||\n openPrice === 0 ||\n IMR === 0\n )\n return 0;\n\n return new Decimal(inputs.unrealizedPnL)\n .div(new Decimal(inputs.positionQty).mul(openPrice).mul(IMR))\n .toNumber();\n}\n\n/**\n * Calculates the total unrealized profit or loss of all positions.\n * @param positions The array of positions.\n * @returns The total unrealized profit or loss of all positions.\n */\nexport function totalUnrealizedPnL(positions: API.Position[]): number {\n return positions.reduce((acc, cur) => {\n return (\n acc +\n unrealizedPnL({\n qty: cur.position_qty,\n openPrice: cur.average_open_price,\n markPrice: cur.mark_price,\n })\n );\n }, 0);\n}\n\nexport type LiqPriceInputs = {\n markPrice: number;\n totalCollateral: number;\n positionQty: number;\n positions: Pick<API.PositionExt, \"position_qty\" | \"mark_price\" | \"mmr\">[];\n MMR: number;\n};\n\n/**\n * Calculates the liquidation price of a single position.\n * @param inputs The inputs for calculating the liquidation price.\n * @returns The liquidation price of the position.\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Position-Liq.-Price}\n */\nexport function liqPrice(inputs: LiqPriceInputs): number {\n const { markPrice, totalCollateral, positions, positionQty, MMR } = inputs;\n\n if (positionQty === 0) {\n return 0;\n }\n\n // totalNotional of all poisitions\n const totalNotional: Decimal = positions.reduce((acc, cur) => {\n return acc.add(\n new Decimal(notional(cur.position_qty, cur.mark_price)).mul(cur.mmr)\n );\n }, zero);\n\n return Math.max(\n new Decimal(markPrice)\n .add(\n new Decimal(totalCollateral)\n .sub(totalNotional)\n .div(new Decimal(positionQty).abs().mul(MMR).sub(positionQty))\n )\n .toNumber(),\n 0\n );\n}\n\nexport type MMInputs = {\n positionQty: number;\n markPrice: number;\n MMR: number;\n};\n\n/**\n * Calculates the maintenance margin of a position.\n * @param inputs The inputs for calculating the maintenance margin.\n * @returns The maintenance margin of the position.\n */\nexport function maintenanceMargin(inputs: MMInputs) {\n const { positionQty, markPrice, MMR } = inputs;\n\n return new Decimal(positionQty).mul(markPrice).mul(MMR).abs().toNumber();\n}\n\nexport type UnsettlementPnLInputs = {\n positionQty: number;\n markPrice: number;\n costPosition: number;\n sumUnitaryFunding: number;\n lastSumUnitaryFunding: number;\n};\n\n/**\n * Calculates the unrealized profit or loss of each position.\n * @param inputs The inputs for calculating the unrealized profit or loss.\n * @returns The unrealized profit or loss of each position.\n * @link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Unsettlement-PNL-%5BinlineExtension%5D\n */\nexport function unsettlementPnL(inputs: UnsettlementPnLInputs): number {\n const {\n positionQty,\n markPrice,\n costPosition,\n sumUnitaryFunding,\n lastSumUnitaryFunding,\n } = inputs;\n\n const qty = new Decimal(positionQty);\n\n return qty\n .mul(markPrice)\n .sub(costPosition)\n .sub(qty.mul(new Decimal(sumUnitaryFunding).sub(lastSumUnitaryFunding)))\n .toNumber();\n}\n\nexport type TotalUnsettlementPnLInputs = {\n positions: (API.Position & {\n sum_unitary_funding: number;\n })[];\n sumUnitaryFunding: number;\n};\n\n/**\n * Calculates the total unrealized profit or loss of all positions.\n * @param positions The array of positions.\n * @returns The total unrealized profit or loss of all positions.\n * @link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Unsettlement-PNL-%5BinlineExtension%5D\n */\nexport function totalUnsettlementPnL(\n positions: (API.Position & {\n sum_unitary_funding: number;\n })[]\n): number {\n if (!Array.isArray(positions) || positions.length === 0) {\n return 0;\n }\n\n return positions.reduce((acc, cur) => {\n return (\n acc +\n unsettlementPnL({\n positionQty: cur.position_qty,\n markPrice: cur.mark_price,\n costPosition: cur.cost_position,\n sumUnitaryFunding: cur.sum_unitary_funding,\n lastSumUnitaryFunding: cur.last_sum_unitary_funding,\n })\n );\n }, 0);\n}\n\nexport type MMRInputs = {\n baseMMR: number;\n baseIMR: number;\n IMRFactor: number;\n positionNotional: number;\n IMR_factor_power: number;\n};\n\n/**\n * Calculates the maintenance margin requirement (MMR) of a position.\n * @param inputs The inputs for calculating the MMR.\n * @returns The MMR of the position.\n */\nexport function MMR(inputs: MMRInputs): number {\n const {\n baseMMR,\n baseIMR,\n IMRFactor,\n positionNotional,\n IMR_factor_power = IMRFactorPower,\n } = inputs;\n return Math.max(\n baseMMR,\n new Decimal(baseMMR)\n .div(baseIMR)\n .mul(IMRFactor)\n .mul(Math.abs(positionNotional))\n .toPower(IMR_factor_power)\n .toNumber()\n );\n}\n","/**\n * The power of the IMR factor.\n * @constant\n * @default\n */\nexport const IMRFactorPower = 4 / 5;\n","import { Decimal, zero } from \"@orderly.network/utils\";\nimport { IMRFactorPower } from \"./constants\";\nimport {\n API,\n OrderSide,\n OrderType,\n type WSMessage,\n} from \"@orderly.network/types\";\n\nexport type ResultOptions = {\n dp: number;\n};\n\nexport type TotalValueInputs = {\n totalUnsettlementPnL: number;\n\n USDCHolding: number;\n nonUSDCHolding: {\n holding: number;\n markPrice: number;\n //保證金替代率 暂时默认0\n discount: number;\n }[];\n};\n/**\n * 用戶總資產價值 (USDC計價),包含無法作為保證金的資產\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Value}\n */\nexport function totalValue(inputs: TotalValueInputs): Decimal {\n const { totalUnsettlementPnL, USDCHolding, nonUSDCHolding } = inputs;\n\n const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {\n return new Decimal(cur.holding).mul(cur.markPrice).add(acc);\n }, zero);\n\n return nonUSDCHoldingValue.add(USDCHolding).add(totalUnsettlementPnL);\n}\n\n/**\n * 用戶帳戶當前可用保證金的價值總和 (USDC計價)\n *\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Free-collateral}\n */\nexport type FreeCollateralInputs = {\n // 总保证金\n totalCollateral: Decimal;\n // 总初始保证金\n totalInitialMarginWithOrders: number;\n};\n/**\n * 计算可用保证金\n */\nexport function freeCollateral(inputs: FreeCollateralInputs): Decimal {\n const value = inputs.totalCollateral.sub(inputs.totalInitialMarginWithOrders);\n // free collateral cannot be less than 0\n return value.isNegative() ? zero : value;\n}\n\nexport type TotalCollateralValueInputs = {\n // USDC 的 holding 數量\n USDCHolding: number;\n nonUSDCHolding: {\n holding: number;\n markPrice: number;\n //保證金替代率 暂时默认0\n discount: number;\n }[];\n // 未结算盈亏\n unsettlementPnL: number;\n};\n/**\n * 计算总保证金\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-collateral-%5BinlineExtension%5D}\n */\nexport function totalCollateral(inputs: TotalCollateralValueInputs): Decimal {\n const { USDCHolding, nonUSDCHolding } = inputs;\n const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {\n return (\n acc +\n new Decimal(cur.holding).mul(cur.markPrice).mul(cur.discount).toNumber()\n );\n }, 0);\n\n return new Decimal(USDCHolding)\n .add(nonUSDCHoldingValue)\n .add(inputs.unsettlementPnL);\n}\n\nexport function initialMarginWithOrder() {}\n\nexport type PositionNotionalWithOrderInputs = {\n markPrice: number;\n positionQtyWithOrders: number;\n};\n/**\n * 單一 Symbol position / orders notional 加總\n */\nexport function positionNotionalWithOrder_by_symbol(\n inputs: PositionNotionalWithOrderInputs\n): Decimal {\n return new Decimal(inputs.markPrice).mul(inputs.positionQtyWithOrders);\n}\n\nexport type PositionQtyWithOrderInputs = {\n positionQty: number;\n // 单个Symbol的所有买单合计\n buyOrdersQty: number;\n // 单个Symbol的所有卖单合计\n sellOrdersQty: number;\n};\n/**\n * 單一 Symbol position / orders qty 加總\n */\nexport function positionQtyWithOrders_by_symbol(\n inputs: PositionQtyWithOrderInputs\n): number {\n const { positionQty, buyOrdersQty, sellOrdersQty } = inputs;\n const positionQtyDecimal = new Decimal(positionQty);\n const qty = Math.max(\n positionQtyDecimal.add(buyOrdersQty).abs().toNumber(),\n positionQtyDecimal.sub(sellOrdersQty).abs().toNumber()\n );\n\n return qty;\n}\n\nexport type IMRInputs = {\n maxLeverage: number;\n baseIMR: number;\n IMR_Factor: number;\n positionNotional: number;\n ordersNotional: number;\n IMR_factor_power?: number;\n};\n\n/**\n * 單一 Symbol 初始保證金率\n * Max(1 / Max Account Leverage, Base IMR i, IMR Factor i * Abs(Position Notional i + Order Notional i)^(4/5))\n */\nexport function IMR(inputs: IMRInputs): number {\n const {\n maxLeverage,\n baseIMR,\n IMR_Factor,\n positionNotional,\n ordersNotional: orderNotional,\n IMR_factor_power = IMRFactorPower,\n } = inputs;\n return Math.max(\n 1 / maxLeverage,\n baseIMR,\n new Decimal(IMR_Factor)\n .mul(\n new Decimal(positionNotional)\n .add(orderNotional)\n .abs()\n .toPower(IMR_factor_power)\n )\n .toNumber()\n );\n}\n\nexport function buyOrdersFilter_by_symbol(\n orders: API.Order[],\n symbol: string\n): API.Order[] {\n return orders.filter(\n (item) => item.symbol === symbol && item.side === OrderSide.BUY\n );\n}\n\nexport function sellOrdersFilter_by_symbol(\n orders: API.Order[],\n symbol: string\n): API.Order[] {\n return orders.filter(\n (item) => item.symbol === symbol && item.side === OrderSide.SELL\n );\n}\n\n/**\n * 从仓位列表中获取指定symbol的仓位数量\n */\nexport function getQtyFromPositions(\n positions: API.Position[],\n symbol: string\n): number {\n if (!positions) {\n return 0;\n }\n const position = positions.find((item) => item.symbol === symbol);\n return position?.position_qty || 0;\n}\n\n/**\n * 从订单列表中获取指定symbol的看多,看空订单数量,\n */\nexport function getQtyFromOrdersBySide(\n orders: API.Order[],\n symbol: string,\n side: OrderSide\n): number {\n const ordersBySide =\n side === OrderSide.SELL\n ? sellOrdersFilter_by_symbol(orders, symbol)\n : buyOrdersFilter_by_symbol(orders, symbol);\n return ordersBySide.reduce((acc, cur) => {\n return acc + cur.quantity;\n }, 0);\n}\n\nexport function getPositonsAndOrdersNotionalBySymbol(inputs: {\n positions: API.Position[];\n orders: API.Order[];\n symbol: string;\n markPrice: number;\n}): number {\n const { positions, orders, symbol, markPrice } = inputs;\n const positionQty = getQtyFromPositions(positions, symbol);\n const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.BUY);\n const sellOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.SELL);\n\n const markPriceDecimal = new Decimal(markPrice);\n\n return markPriceDecimal\n .mul(positionQty)\n .add(markPriceDecimal.mul(new Decimal(buyOrdersQty).add(sellOrdersQty)))\n .abs()\n .toNumber();\n}\n\nexport type TotalInitialMarginWithOrdersInputs = {\n positions: API.Position[];\n orders: API.Order[];\n // account: API.AccountInfo;\n markPrices: { [key: string]: number };\n symbolInfo: any;\n IMR_Factors: { [key: string]: number };\n} & Pick<IMRInputs, \"maxLeverage\">;\n\n/**\n * 计算用戶已使用初始保證金加總 ( 包含 position / orders )\n */\nexport function totalInitialMarginWithOrders(\n inputs: TotalInitialMarginWithOrdersInputs\n): number {\n const {\n positions,\n orders,\n markPrices,\n IMR_Factors,\n maxLeverage,\n symbolInfo,\n } = inputs;\n\n const symbols = extractSymbols(positions, orders);\n\n const total_initial_margin_with_orders = symbols.reduce((acc, cur) => {\n const symbol = cur;\n const positionQty = getQtyFromPositions(positions, symbol);\n const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, OrderSide.BUY);\n const sellOrdersQty = getQtyFromOrdersBySide(\n orders,\n symbol,\n OrderSide.SELL\n );\n\n const markPrice = markPrices[symbol] || 0;\n\n //---\n const positionQtyWithOrders = positionQtyWithOrders_by_symbol({\n positionQty,\n buyOrdersQty,\n sellOrdersQty,\n });\n\n //---\n const position_notional_with_orders = positionNotionalWithOrder_by_symbol({\n markPrice,\n positionQtyWithOrders,\n });\n\n //----\n const markPriceDecimal = new Decimal(markPrice);\n\n const imr = IMR({\n positionNotional: markPriceDecimal.mul(positionQty).toNumber(),\n ordersNotional: markPriceDecimal\n .mul(new Decimal(buyOrdersQty).add(sellOrdersQty))\n .toNumber(),\n maxLeverage,\n IMR_Factor: IMR_Factors[symbol],\n baseIMR: symbolInfo[symbol](\"base_imr\", 0),\n });\n\n return position_notional_with_orders.mul(imr).add(acc).toNumber();\n }, 0);\n\n return total_initial_margin_with_orders;\n}\n\n/**\n * 把订单按照symbol分组, 因为一个symbol可以有多个挂单\n */\nexport function groupOrdersBySymbol(orders: API.Order[]) {\n const symbols: { [key: string]: API.Order[] } = {};\n\n orders.forEach((item) => {\n if (!symbols[item.symbol]) {\n symbols[item.symbol] = [];\n }\n\n symbols[item.symbol].push(item);\n });\n\n return symbols;\n}\n\n/**\n * Extracts all unique symbols from positions and orders.\n * @param positions - An array of position objects.\n * @param orders - An array of order objects.\n * @returns An array of unique symbols.\n */\nexport function extractSymbols(\n positions: Pick<API.Position, \"symbol\">[],\n orders: Pick<API.Order, \"symbol\">[]\n): string[] {\n const symbols = new Set<string>();\n\n positions.forEach((item) => {\n symbols.add(item.symbol);\n });\n\n orders.forEach((item) => {\n symbols.add(item.symbol);\n });\n\n return Array.from(symbols);\n}\n\n//=========== max qty ==================\n\n// function otherIM(inputs: {}): number {}\n\nexport type OtherIMsInputs = {\n // 传入除当前symbol外的其他symbol的仓位列表\n positions: API.Position[];\n // 传入除当前symbol外的其他symbol的订单列表\n orders: API.Order[];\n\n markPrices: { [key: string]: number };\n maxLeverage: number;\n symbolInfo: any;\n IMR_Factors: { [key: string]: number };\n};\n/**\n * 除当前symbol外的其他symbol已占用的总保证金\n */\nexport function otherIMs(inputs: OtherIMsInputs): number {\n const {\n orders,\n positions,\n maxLeverage,\n IMR_Factors,\n symbolInfo,\n markPrices,\n } = inputs;\n\n const symbols = extractSymbols(positions, orders);\n\n return symbols\n .reduce((acc, cur) => {\n const symbol = cur;\n\n if (typeof markPrices[symbol] === \"undefined\") {\n console.warn(\"markPrices[%s] is undefined\", symbol);\n return acc;\n }\n\n const markPriceDecimal = new Decimal(markPrices[symbol] || 0);\n\n const positionQty = getQtyFromPositions(positions, symbol);\n const positionNotional = markPriceDecimal.mul(positionQty).toNumber();\n\n const buyOrdersQty = getQtyFromOrdersBySide(\n orders,\n symbol,\n OrderSide.BUY\n );\n const sellOrdersQty = getQtyFromOrdersBySide(\n orders,\n symbol,\n OrderSide.SELL\n );\n\n const ordersNotional = markPriceDecimal\n .mul(new Decimal(buyOrdersQty).add(sellOrdersQty))\n .toNumber();\n\n const IMR_Factor = IMR_Factors[symbol];\n\n if (!IMR_Factor) {\n console.warn(\"IMR_Factor is not found:\", symbol);\n return acc;\n }\n\n const imr = IMR({\n maxLeverage,\n\n IMR_Factor,\n baseIMR: symbolInfo[symbol](\"base_imr\", 0),\n positionNotional,\n ordersNotional,\n });\n\n const positionQtyWithOrders = positionQtyWithOrders_by_symbol({\n positionQty,\n buyOrdersQty,\n sellOrdersQty,\n });\n\n const positionNotionalWithOrders = positionNotionalWithOrder_by_symbol({\n markPrice: markPrices[symbol] || 0,\n positionQtyWithOrders,\n });\n\n return acc.add(positionNotionalWithOrders.mul(imr));\n }, zero)\n .toNumber();\n}\n\nexport type MaxQtyInputs = {\n symbol: string;\n\n //單次開倉最大 Qty 限制, /v1/public/info.base_max\n baseMaxQty: number;\n /**\n * 用户保证金总额(USDC 计价), 可以由 totalCollateral 计算得出\n * @see totalCollateral\n */\n totalCollateral: number;\n maxLeverage: number;\n baseIMR: number;\n /**\n * @see otherIMs\n */\n otherIMs: number;\n markPrice: number;\n // 已开仓数量\n positionQty: number;\n // 已挂多单数量\n buyOrdersQty: number;\n // 已挂空单数量\n sellOrdersQty: number;\n\n IMR_Factor: number;\n\n takerFeeRate: number;\n};\n\n/**\n * 最大可下单数量\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Max-Order-QTY}\n */\nexport function maxQty(\n side: OrderSide,\n inputs: MaxQtyInputs,\n options?: ResultOptions\n): number {\n if (side === OrderSide.BUY) {\n return maxQtyByLong(inputs);\n }\n return maxQtyByShort(inputs);\n}\n\nexport function maxQtyByLong(\n inputs: Omit<MaxQtyInputs, \"side\">,\n options?: ResultOptions\n): number {\n try {\n const {\n baseMaxQty,\n totalCollateral,\n otherIMs,\n maxLeverage,\n baseIMR,\n markPrice,\n IMR_Factor,\n positionQty,\n buyOrdersQty,\n takerFeeRate,\n } = inputs;\n\n if (totalCollateral === 0) {\n return 0;\n }\n\n const totalCollateralDecimal = new Decimal(totalCollateral);\n\n const factor_1 = totalCollateralDecimal\n .sub(otherIMs)\n .div(\n new Decimal(takerFeeRate)\n .mul(2)\n .mul(0.0001)\n .add(Math.max(1 / maxLeverage, baseIMR))\n )\n .div(markPrice)\n .mul(0.995)\n .sub(new Decimal(positionQty).add(buyOrdersQty))\n .toNumber();\n\n if (positionQty === 0 && buyOrdersQty === 0) {\n return Math.min(baseMaxQty, factor_1);\n }\n\n const factor_2 = totalCollateralDecimal\n .sub(otherIMs)\n .div(IMR_Factor)\n .toPower(1 / 1.8)\n .div(markPrice)\n .sub(\n new Decimal(positionQty)\n .add(buyOrdersQty)\n // .abs()\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\n )\n .mul(0.995)\n .toNumber();\n\n return Math.min(baseMaxQty, factor_1, factor_2);\n } catch (error) {\n return 0;\n }\n}\n\nexport function maxQtyByShort(\n inputs: Omit<MaxQtyInputs, \"side\">,\n options?: ResultOptions\n): number {\n try {\n const {\n baseMaxQty,\n totalCollateral,\n otherIMs,\n maxLeverage,\n baseIMR,\n markPrice,\n IMR_Factor,\n positionQty,\n buyOrdersQty,\n sellOrdersQty,\n takerFeeRate,\n } = inputs;\n\n const totalCollateralDecimal = new Decimal(totalCollateral);\n\n const factor_1 = totalCollateralDecimal\n .sub(otherIMs)\n .div(\n new Decimal(takerFeeRate)\n .mul(2)\n .mul(0.0001)\n .add(Math.max(1 / maxLeverage, baseIMR))\n )\n .div(markPrice)\n .mul(0.995)\n .add(new Decimal(positionQty).add(sellOrdersQty))\n\n .toNumber();\n\n if (positionQty === 0 && buyOrdersQty === 0) {\n return Math.min(baseMaxQty, factor_1);\n }\n\n const factor_2 = totalCollateralDecimal\n .sub(otherIMs)\n .div(IMR_Factor)\n .toPower(1 / 1.8)\n .div(markPrice)\n .add(\n new Decimal(positionQty)\n .add(sellOrdersQty)\n // .abs()\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\n )\n .mul(0.995)\n .toNumber();\n\n return Math.min(baseMaxQty, factor_1, factor_2);\n } catch (error) {\n return 0;\n }\n}\n\nexport type TotalMarginRatioInputs = {\n totalCollateral: number;\n markPrices: { [key: string]: number };\n positions: API.Position[];\n};\n/**\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Margin-Ratio}\n */\nexport function totalMarginRatio(\n inputs: TotalMarginRatioInputs,\n dp?: number\n): number {\n const { totalCollateral, markPrices, positions } = inputs;\n\n if (totalCollateral === 0) {\n return 0;\n }\n\n const totalCollateralDecimal = new Decimal(totalCollateral);\n\n const totalPositionNotional = positions.reduce((acc, cur) => {\n const markPrice = markPrices[cur.symbol] || 0;\n return acc.add(new Decimal(cur.position_qty).mul(markPrice).abs());\n }, zero);\n\n if (totalPositionNotional.eq(zero)) {\n return 0;\n }\n\n return totalCollateralDecimal.div(totalPositionNotional).toNumber();\n}\n\nexport type TotalUnrealizedROIInputs = {\n totalUnrealizedPnL: number;\n totalValue: number;\n};\n\n/**\n * totalUnrealizedROI\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Total-Unrealized-ROI}\n */\nexport function totalUnrealizedROI(inputs: TotalUnrealizedROIInputs) {\n const { totalUnrealizedPnL, totalValue } = inputs;\n\n return new Decimal(totalUnrealizedPnL)\n .div(totalValue - totalUnrealizedPnL)\n .toNumber();\n}\n\n/**\n * @see {@link https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Current-account-leverage}\n */\nexport function currentLeverage(totalMarginRatio: number) {\n if (totalMarginRatio === 0) {\n return 0;\n }\n return 1 / totalMarginRatio;\n}\n\nexport type AvailableBalanceInputs = {\n USDCHolding: number;\n unsettlementPnL: number;\n};\nexport function availableBalance(inputs: AvailableBalanceInputs) {\n const { USDCHolding, unsettlementPnL } = inputs;\n\n return new Decimal(USDCHolding).add(unsettlementPnL).toNumber();\n}\n\nexport type AccountMMRInputs = {\n // Total Maintenance Margin of all positions of the user (USDC)\n positionsMMR: number;\n /**\n * Notional sum of all positions,\n * positions.totalNotional()\n */\n positionsNotional: number;\n};\n\n/**\n * total maintenance margin ratio\n * @param inputs AccountMMRInputs\n * @returns number|null\n */\nexport function MMR(inputs: AccountMMRInputs): number | null {\n // If the user does not have any positions, return null\n if (inputs.positionsNotional === 0) {\n return null;\n }\n return new Decimal(inputs.positionsMMR)\n .div(inputs.positionsNotional)\n .toNumber();\n}\n","import { API } from \"@orderly.network/types\";\nimport { Decimal, zero } from \"@orderly.network/utils\";\nimport { notional } from \"./positions\";\n\n/**\n * Maximum price when placing an order\n * @see https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Max-price\n */\nexport function maxPrice(markprice: number, range: number) {\n return markprice * (1 + range);\n}\n\n/**\n * Minimum price when placing an order\n * @see https://wootraders.atlassian.net/wiki/spaces/WOOFI/pages/346030144/v2#Min-price\n */\nexport function minPrice(markprice: number, range: number) {\n return markprice * (1 - range);\n}\n\n/**\n * Scrope price when placing an order\n * @returns number\n */\nexport function scropePrice(\n price: number,\n scrope: number,\n side: \"BUY\" | \"SELL\"\n): number {\n if (side === \"BUY\") {\n return price * (1 - scrope);\n }\n return price * (1 + scrope);\n}\n\nexport type EstimatedLiquidationPriceInputs = {\n totalCollateral: number;\n markPrice: number;\n baseMMR: number;\n baseIMR: number;\n IMR_Factor: number;\n positions: Pick<\n API.PositionExt,\n \"position_qty\" | \"mark_price\" | \"symbol\" | \"mmr\"\n >[];\n newOrder: {\n symbol: string;\n qty: number;\n price: number;\n };\n};\n\n/**\n * Estimated liquidation price\n * @param inputs\n * @returns\n */\nexport function estLiqPrice(inputs: EstimatedLiquidationPriceInputs): number {\n const {\n positions,\n newOrder,\n totalCollateral,\n markPrice,\n baseIMR,\n baseMMR,\n IMR_Factor,\n } = inputs;\n // opened positions for the symbol\n let currentPosition:\n | Pick<API.PositionExt, \"position_qty\" | \"mark_price\" | \"symbol\" | \"mmr\">\n | undefined = undefined;\n\n let newTotalMM = zero;\n\n const newOrderNotional = new Decimal(newOrder.qty).mul(newOrder.price);\n\n for (let index = 0; index < positions.length; index++) {\n const position = positions[index];\n let notional = new Decimal(position.position_qty).mul(position.mark_price);\n if (newOrder.symbol === position.symbol) {\n currentPosition = position;\n notional = notional.add(newOrderNotional);\n }\n\n newTotalMM = newTotalMM.add(notional.abs().mul(position.mmr));\n }\n\n const newMMR = Math.max(\n baseMMR,\n new Decimal(baseMMR)\n .div(baseIMR)\n .mul(IMR_Factor)\n .mul(\n newOrderNotional\n .add(\n !!currentPosition\n ? new Decimal(currentPosition.position_qty).mul(\n currentPosition.mark_price\n )\n : zero\n )\n .abs()\n )\n .toPower(4 / 5)\n .toNumber()\n );\n\n const newQty = new Decimal(newOrder.qty).add(\n currentPosition?.position_qty ?? 0\n );\n\n if (newQty.eq(0)) {\n return 0;\n }\n\n const price = new Decimal(markPrice)\n .add(\n new Decimal(totalCollateral)\n .sub(newTotalMM)\n .div(newQty.abs().mul(newMMR).sub(newQty))\n )\n .toNumber();\n\n return Math.max(0, price);\n}\n\nexport type EstimatedLeverageInputs = {\n totalCollateral: number;\n positions: Pick<API.PositionExt, \"position_qty\" | \"mark_price\" | \"symbol\">[];\n newOrder: {\n symbol: string;\n qty: number;\n price: number;\n };\n};\n\n/**\n * Estimated leverage\n * @param inputs EstimtedLeverageInputs\n * @returns number\n */\nexport function estLeverage(inputs: EstimatedLeverageInputs): number | null {\n const { totalCollateral, positions, newOrder } = inputs;\n if (totalCollateral <= 0) {\n return null;\n }\n let hasPosition = false;\n let sumPositionNotional = positions.reduce((acc, cur) => {\n acc = acc.add(\n new Decimal(new Decimal(cur.position_qty).mul(cur.mark_price).abs())\n );\n\n if (cur.symbol === newOrder.symbol) {\n hasPosition = true;\n acc = acc.add(new Decimal(newOrder.qty).mul(newOrder.price));\n }\n\n return acc;\n }, zero);\n\n if (!hasPosition) {\n sumPositionNotional = sumPositionNotional.add(\n new Decimal(newOrder.qty).mul(newOrder.price).abs()\n );\n }\n\n if (sumPositionNotional.eq(zero)) {\n return null;\n }\n\n const totalMarginRatio = new Decimal(totalCollateral).div(\n sumPositionNotional\n );\n\n return new Decimal(1)\n .div(totalMarginRatio)\n .toDecimalPlaces(2, Decimal.ROUND_HALF_EVEN)\n .toNumber();\n}\n"],"mappings":"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","names":["IMR","totalCollateral","MMR","totalNotional","MMR","import_utils","totalUnsettlementPnL","totalCollateral","otherIMs","totalUnrealizedPnL","totalValue","totalMarginRatio","unsettlementPnL","MMR","import_utils","totalCollateral","notional","totalMarginRatio"]}
|
package/dist/index.mjs
CHANGED
|
@@ -7,9 +7,9 @@ var __export = (target, all) => {
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
if (typeof window !== "undefined") {
|
|
9
9
|
window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
|
|
10
|
-
window.__ORDERLY_VERSION__["@orderly.network/perp"] = "
|
|
10
|
+
window.__ORDERLY_VERSION__["@orderly.network/perp"] = "2.0.0";
|
|
11
11
|
}
|
|
12
|
-
var version_default = "
|
|
12
|
+
var version_default = "2.0.0";
|
|
13
13
|
|
|
14
14
|
// src/positions.ts
|
|
15
15
|
var positions_exports = {};
|
|
@@ -25,7 +25,7 @@ __export(positions_exports, {
|
|
|
25
25
|
unrealizedPnLROI: () => unrealizedPnLROI,
|
|
26
26
|
unsettlementPnL: () => unsettlementPnL
|
|
27
27
|
});
|
|
28
|
-
import { Decimal } from "@orderly.network/utils";
|
|
28
|
+
import { Decimal, zero } from "@orderly.network/utils";
|
|
29
29
|
|
|
30
30
|
// src/constants.ts
|
|
31
31
|
var IMRFactorPower = 4 / 5;
|
|
@@ -58,21 +58,25 @@ function totalUnrealizedPnL(positions) {
|
|
|
58
58
|
}, 0);
|
|
59
59
|
}
|
|
60
60
|
function liqPrice(inputs) {
|
|
61
|
-
const { markPrice, totalCollateral: totalCollateral2, positionQty, MMR:
|
|
62
|
-
const totalNotional2 = notional(positionQty, markPrice);
|
|
61
|
+
const { markPrice, totalCollateral: totalCollateral2, positions, positionQty, MMR: MMR3 } = inputs;
|
|
63
62
|
if (positionQty === 0) {
|
|
64
63
|
return 0;
|
|
65
64
|
}
|
|
65
|
+
const totalNotional2 = positions.reduce((acc, cur) => {
|
|
66
|
+
return acc.add(
|
|
67
|
+
new Decimal(notional(cur.position_qty, cur.mark_price)).mul(cur.mmr)
|
|
68
|
+
);
|
|
69
|
+
}, zero);
|
|
66
70
|
return Math.max(
|
|
67
71
|
new Decimal(markPrice).add(
|
|
68
|
-
new Decimal(totalCollateral2).sub(
|
|
72
|
+
new Decimal(totalCollateral2).sub(totalNotional2).div(new Decimal(positionQty).abs().mul(MMR3).sub(positionQty))
|
|
69
73
|
).toNumber(),
|
|
70
74
|
0
|
|
71
75
|
);
|
|
72
76
|
}
|
|
73
77
|
function maintenanceMargin(inputs) {
|
|
74
|
-
const { positionQty, markPrice, MMR:
|
|
75
|
-
return new Decimal(positionQty).mul(markPrice).mul(
|
|
78
|
+
const { positionQty, markPrice, MMR: MMR3 } = inputs;
|
|
79
|
+
return new Decimal(positionQty).mul(markPrice).mul(MMR3).abs().toNumber();
|
|
76
80
|
}
|
|
77
81
|
function unsettlementPnL(inputs) {
|
|
78
82
|
const {
|
|
@@ -117,6 +121,7 @@ function MMR(inputs) {
|
|
|
117
121
|
var account_exports = {};
|
|
118
122
|
__export(account_exports, {
|
|
119
123
|
IMR: () => IMR,
|
|
124
|
+
MMR: () => MMR2,
|
|
120
125
|
availableBalance: () => availableBalance,
|
|
121
126
|
buyOrdersFilter_by_symbol: () => buyOrdersFilter_by_symbol,
|
|
122
127
|
currentLeverage: () => currentLeverage,
|
|
@@ -140,7 +145,7 @@ __export(account_exports, {
|
|
|
140
145
|
totalUnrealizedROI: () => totalUnrealizedROI,
|
|
141
146
|
totalValue: () => totalValue
|
|
142
147
|
});
|
|
143
|
-
import { Decimal as Decimal2, zero } from "@orderly.network/utils";
|
|
148
|
+
import { Decimal as Decimal2, zero as zero2 } from "@orderly.network/utils";
|
|
144
149
|
import {
|
|
145
150
|
OrderSide
|
|
146
151
|
} from "@orderly.network/types";
|
|
@@ -148,11 +153,12 @@ function totalValue(inputs) {
|
|
|
148
153
|
const { totalUnsettlementPnL: totalUnsettlementPnL2, USDCHolding, nonUSDCHolding } = inputs;
|
|
149
154
|
const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {
|
|
150
155
|
return new Decimal2(cur.holding).mul(cur.markPrice).add(acc);
|
|
151
|
-
},
|
|
156
|
+
}, zero2);
|
|
152
157
|
return nonUSDCHoldingValue.add(USDCHolding).add(totalUnsettlementPnL2);
|
|
153
158
|
}
|
|
154
159
|
function freeCollateral(inputs) {
|
|
155
|
-
|
|
160
|
+
const value = inputs.totalCollateral.sub(inputs.totalInitialMarginWithOrders);
|
|
161
|
+
return value.isNegative() ? zero2 : value;
|
|
156
162
|
}
|
|
157
163
|
function totalCollateral(inputs) {
|
|
158
164
|
const { USDCHolding, nonUSDCHolding } = inputs;
|
|
@@ -336,7 +342,7 @@ function otherIMs(inputs) {
|
|
|
336
342
|
positionQtyWithOrders
|
|
337
343
|
});
|
|
338
344
|
return acc.add(positionNotionalWithOrders.mul(imr));
|
|
339
|
-
},
|
|
345
|
+
}, zero2).toNumber();
|
|
340
346
|
}
|
|
341
347
|
function maxQty(side, inputs, options) {
|
|
342
348
|
if (side === OrderSide.BUY) {
|
|
@@ -344,7 +350,7 @@ function maxQty(side, inputs, options) {
|
|
|
344
350
|
}
|
|
345
351
|
return maxQtyByShort(inputs);
|
|
346
352
|
}
|
|
347
|
-
function maxQtyByLong(inputs) {
|
|
353
|
+
function maxQtyByLong(inputs, options) {
|
|
348
354
|
try {
|
|
349
355
|
const {
|
|
350
356
|
baseMaxQty,
|
|
@@ -376,7 +382,7 @@ function maxQtyByLong(inputs) {
|
|
|
376
382
|
return 0;
|
|
377
383
|
}
|
|
378
384
|
}
|
|
379
|
-
function maxQtyByShort(inputs) {
|
|
385
|
+
function maxQtyByShort(inputs, options) {
|
|
380
386
|
try {
|
|
381
387
|
const {
|
|
382
388
|
baseMaxQty,
|
|
@@ -415,8 +421,8 @@ function totalMarginRatio(inputs, dp) {
|
|
|
415
421
|
const totalPositionNotional = positions.reduce((acc, cur) => {
|
|
416
422
|
const markPrice = markPrices[cur.symbol] || 0;
|
|
417
423
|
return acc.add(new Decimal2(cur.position_qty).mul(markPrice).abs());
|
|
418
|
-
},
|
|
419
|
-
if (totalPositionNotional.eq(
|
|
424
|
+
}, zero2);
|
|
425
|
+
if (totalPositionNotional.eq(zero2)) {
|
|
420
426
|
return 0;
|
|
421
427
|
}
|
|
422
428
|
return totalCollateralDecimal.div(totalPositionNotional).toNumber();
|
|
@@ -435,19 +441,108 @@ function availableBalance(inputs) {
|
|
|
435
441
|
const { USDCHolding, unsettlementPnL: unsettlementPnL2 } = inputs;
|
|
436
442
|
return new Decimal2(USDCHolding).add(unsettlementPnL2).toNumber();
|
|
437
443
|
}
|
|
444
|
+
function MMR2(inputs) {
|
|
445
|
+
if (inputs.positionsNotional === 0) {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
return new Decimal2(inputs.positionsMMR).div(inputs.positionsNotional).toNumber();
|
|
449
|
+
}
|
|
438
450
|
|
|
439
451
|
// src/order.ts
|
|
440
452
|
var order_exports = {};
|
|
441
453
|
__export(order_exports, {
|
|
454
|
+
estLeverage: () => estLeverage,
|
|
455
|
+
estLiqPrice: () => estLiqPrice,
|
|
442
456
|
maxPrice: () => maxPrice,
|
|
443
|
-
minPrice: () => minPrice
|
|
457
|
+
minPrice: () => minPrice,
|
|
458
|
+
scropePrice: () => scropePrice
|
|
444
459
|
});
|
|
460
|
+
import { Decimal as Decimal3, zero as zero3 } from "@orderly.network/utils";
|
|
445
461
|
function maxPrice(markprice, range) {
|
|
446
462
|
return markprice * (1 + range);
|
|
447
463
|
}
|
|
448
464
|
function minPrice(markprice, range) {
|
|
449
465
|
return markprice * (1 - range);
|
|
450
466
|
}
|
|
467
|
+
function scropePrice(price, scrope, side) {
|
|
468
|
+
if (side === "BUY") {
|
|
469
|
+
return price * (1 - scrope);
|
|
470
|
+
}
|
|
471
|
+
return price * (1 + scrope);
|
|
472
|
+
}
|
|
473
|
+
function estLiqPrice(inputs) {
|
|
474
|
+
var _a;
|
|
475
|
+
const {
|
|
476
|
+
positions,
|
|
477
|
+
newOrder,
|
|
478
|
+
totalCollateral: totalCollateral2,
|
|
479
|
+
markPrice,
|
|
480
|
+
baseIMR,
|
|
481
|
+
baseMMR,
|
|
482
|
+
IMR_Factor
|
|
483
|
+
} = inputs;
|
|
484
|
+
let currentPosition = void 0;
|
|
485
|
+
let newTotalMM = zero3;
|
|
486
|
+
const newOrderNotional = new Decimal3(newOrder.qty).mul(newOrder.price);
|
|
487
|
+
for (let index = 0; index < positions.length; index++) {
|
|
488
|
+
const position = positions[index];
|
|
489
|
+
let notional2 = new Decimal3(position.position_qty).mul(position.mark_price);
|
|
490
|
+
if (newOrder.symbol === position.symbol) {
|
|
491
|
+
currentPosition = position;
|
|
492
|
+
notional2 = notional2.add(newOrderNotional);
|
|
493
|
+
}
|
|
494
|
+
newTotalMM = newTotalMM.add(notional2.abs().mul(position.mmr));
|
|
495
|
+
}
|
|
496
|
+
const newMMR = Math.max(
|
|
497
|
+
baseMMR,
|
|
498
|
+
new Decimal3(baseMMR).div(baseIMR).mul(IMR_Factor).mul(
|
|
499
|
+
newOrderNotional.add(
|
|
500
|
+
!!currentPosition ? new Decimal3(currentPosition.position_qty).mul(
|
|
501
|
+
currentPosition.mark_price
|
|
502
|
+
) : zero3
|
|
503
|
+
).abs()
|
|
504
|
+
).toPower(4 / 5).toNumber()
|
|
505
|
+
);
|
|
506
|
+
const newQty = new Decimal3(newOrder.qty).add(
|
|
507
|
+
(_a = currentPosition == null ? void 0 : currentPosition.position_qty) != null ? _a : 0
|
|
508
|
+
);
|
|
509
|
+
if (newQty.eq(0)) {
|
|
510
|
+
return 0;
|
|
511
|
+
}
|
|
512
|
+
const price = new Decimal3(markPrice).add(
|
|
513
|
+
new Decimal3(totalCollateral2).sub(newTotalMM).div(newQty.abs().mul(newMMR).sub(newQty))
|
|
514
|
+
).toNumber();
|
|
515
|
+
return Math.max(0, price);
|
|
516
|
+
}
|
|
517
|
+
function estLeverage(inputs) {
|
|
518
|
+
const { totalCollateral: totalCollateral2, positions, newOrder } = inputs;
|
|
519
|
+
if (totalCollateral2 <= 0) {
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
let hasPosition = false;
|
|
523
|
+
let sumPositionNotional = positions.reduce((acc, cur) => {
|
|
524
|
+
acc = acc.add(
|
|
525
|
+
new Decimal3(new Decimal3(cur.position_qty).mul(cur.mark_price).abs())
|
|
526
|
+
);
|
|
527
|
+
if (cur.symbol === newOrder.symbol) {
|
|
528
|
+
hasPosition = true;
|
|
529
|
+
acc = acc.add(new Decimal3(newOrder.qty).mul(newOrder.price));
|
|
530
|
+
}
|
|
531
|
+
return acc;
|
|
532
|
+
}, zero3);
|
|
533
|
+
if (!hasPosition) {
|
|
534
|
+
sumPositionNotional = sumPositionNotional.add(
|
|
535
|
+
new Decimal3(newOrder.qty).mul(newOrder.price).abs()
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
if (sumPositionNotional.eq(zero3)) {
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
const totalMarginRatio2 = new Decimal3(totalCollateral2).div(
|
|
542
|
+
sumPositionNotional
|
|
543
|
+
);
|
|
544
|
+
return new Decimal3(1).div(totalMarginRatio2).toDecimalPlaces(2, Decimal3.ROUND_HALF_EVEN).toNumber();
|
|
545
|
+
}
|
|
451
546
|
export {
|
|
452
547
|
account_exports as account,
|
|
453
548
|
order_exports as order,
|