@orderly.network/perp 2.0.5-rc.0 → 2.0.6

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 CHANGED
@@ -8,7 +8,7 @@ declare global {
8
8
  };
9
9
  }
10
10
  }
11
- declare const _default: "2.0.5-rc.0";
11
+ declare const _default: "2.0.6";
12
12
 
13
13
  /**
14
14
  * Calculates the notional value of a single position.
@@ -168,18 +168,18 @@ type TotalValueInputs = {
168
168
  }[];
169
169
  };
170
170
  /**
171
- * 用戶總資產價值 (USDC計價),包含無法作為保證金的資產
171
+ * User's total asset value (denominated in USDC), including assets that cannot be used as collateral.
172
172
  */
173
173
  declare function totalValue(inputs: TotalValueInputs): Decimal;
174
174
  /**
175
- * 用戶帳戶當前可用保證金的價值總和 (USDC計價)
175
+ * Total value of available collateral in the user's account (denominated in USDC).
176
176
  */
177
177
  type FreeCollateralInputs = {
178
178
  totalCollateral: Decimal;
179
179
  totalInitialMarginWithOrders: number;
180
180
  };
181
181
  /**
182
- * 计算可用保证金
182
+ * Calculate free collateral.
183
183
  */
184
184
  declare function freeCollateral(inputs: FreeCollateralInputs): Decimal;
185
185
  type TotalCollateralValueInputs = {
@@ -192,7 +192,7 @@ type TotalCollateralValueInputs = {
192
192
  unsettlementPnL: number;
193
193
  };
194
194
  /**
195
- * 计算总保证金
195
+ * Calculate total collateral.
196
196
  */
197
197
  declare function totalCollateral(inputs: TotalCollateralValueInputs): Decimal;
198
198
  declare function initialMarginWithOrder(): void;
@@ -201,7 +201,7 @@ type PositionNotionalWithOrderInputs = {
201
201
  positionQtyWithOrders: number;
202
202
  };
203
203
  /**
204
- * 單一 Symbol position / orders notional 加總
204
+ * Sum of notional value for a symbol's position and orders.
205
205
  */
206
206
  declare function positionNotionalWithOrder_by_symbol(inputs: PositionNotionalWithOrderInputs): Decimal;
207
207
  type PositionQtyWithOrderInputs = {
@@ -210,7 +210,7 @@ type PositionQtyWithOrderInputs = {
210
210
  sellOrdersQty: number;
211
211
  };
212
212
  /**
213
- * 單一 Symbol position / orders qty 加總
213
+ * Sum of position quantity and orders quantity for a symbol.
214
214
  */
215
215
  declare function positionQtyWithOrders_by_symbol(inputs: PositionQtyWithOrderInputs): number;
216
216
  type IMRInputs = {
@@ -222,18 +222,18 @@ type IMRInputs = {
222
222
  IMR_factor_power?: number;
223
223
  };
224
224
  /**
225
- * 單一 Symbol 初始保證金率
225
+ * Initial margin rate for a symbol.
226
226
  * Max(1 / Max Account Leverage, Base IMR i, IMR Factor i * Abs(Position Notional i + Order Notional i)^(4/5))
227
227
  */
228
228
  declare function IMR(inputs: IMRInputs): number;
229
229
  declare function buyOrdersFilter_by_symbol(orders: API.Order[], symbol: string): API.Order[];
230
230
  declare function sellOrdersFilter_by_symbol(orders: API.Order[], symbol: string): API.Order[];
231
231
  /**
232
- * 从仓位列表中获取指定symbol的仓位数量
232
+ * Get the quantity of a specified symbol from the list of positions.
233
233
  */
234
234
  declare function getQtyFromPositions(positions: API.Position[], symbol: string): number;
235
235
  /**
236
- * 从订单列表中获取指定symbol的看多,看空订单数量,
236
+ * Get the quantity of long and short orders for a specified symbol from the list of orders.
237
237
  */
238
238
  declare function getQtyFromOrdersBySide(orders: API.Order[], symbol: string, side: OrderSide): number;
239
239
  declare function getPositonsAndOrdersNotionalBySymbol(inputs: {
@@ -254,11 +254,11 @@ type TotalInitialMarginWithOrdersInputs = {
254
254
  };
255
255
  } & Pick<IMRInputs, "maxLeverage">;
256
256
  /**
257
- * 计算用戶已使用初始保證金加總 ( 包含 position / orders )
257
+ * Calculate the total initial margin used by the user (including positions and orders).
258
258
  */
259
259
  declare function totalInitialMarginWithOrders(inputs: TotalInitialMarginWithOrdersInputs): number;
260
260
  /**
261
- * 把订单按照symbol分组, 因为一个symbol可以有多个挂单
261
+ * Group orders by symbol, as a symbol can have multiple orders.
262
262
  */
263
263
  declare function groupOrdersBySymbol(orders: API.Order[]): {
264
264
  [key: string]: API.Order[];
@@ -283,14 +283,14 @@ type OtherIMsInputs = {
283
283
  };
284
284
  };
285
285
  /**
286
- * 除当前symbol外的其他symbol已占用的总保证金
286
+ * Total margin used by other symbols (except the current symbol).
287
287
  */
288
288
  declare function otherIMs(inputs: OtherIMsInputs): number;
289
289
  type MaxQtyInputs = {
290
290
  symbol: string;
291
291
  baseMaxQty: number;
292
292
  /**
293
- * 用户保证金总额(USDC 计价), 可以由 totalCollateral 计算得出
293
+ * Total collateral of the user (denominated in USDC), can be calculated from totalCollateral.
294
294
  * @see totalCollateral
295
295
  */
296
296
  totalCollateral: number;
@@ -308,7 +308,7 @@ type MaxQtyInputs = {
308
308
  takerFeeRate: number;
309
309
  };
310
310
  /**
311
- * 最大可下单数量
311
+ * Maximum order quantity.
312
312
  */
313
313
  declare function maxQty(side: OrderSide, inputs: MaxQtyInputs, options?: ResultOptions): number;
314
314
  declare function maxQtyByLong(inputs: Omit<MaxQtyInputs, "side">, options?: ResultOptions): number;
@@ -450,12 +450,24 @@ declare function minPrice(markprice: number, range: number): number;
450
450
  * @returns number
451
451
  */
452
452
  declare function scropePrice(price: number, scrope: number, side: "BUY" | "SELL"): number;
453
+ /**
454
+ * Calculate the order fee
455
+ */
456
+ declare function orderFee(inputs: {
457
+ /**
458
+ * Order quantity
459
+ */
460
+ qty: number;
461
+ price: number;
462
+ futuresTakeFeeRate: number;
463
+ }): number;
453
464
  type EstimatedLiquidationPriceInputs = {
454
465
  totalCollateral: number;
455
466
  markPrice: number;
456
467
  baseMMR: number;
457
468
  baseIMR: number;
458
469
  IMR_Factor: number;
470
+ orderFee: number;
459
471
  positions: Pick<API.PositionExt, "position_qty" | "mark_price" | "symbol" | "mmr">[];
460
472
  newOrder: {
461
473
  symbol: string;
@@ -491,6 +503,7 @@ declare const order_estLeverage: typeof estLeverage;
491
503
  declare const order_estLiqPrice: typeof estLiqPrice;
492
504
  declare const order_maxPrice: typeof maxPrice;
493
505
  declare const order_minPrice: typeof minPrice;
506
+ declare const order_orderFee: typeof orderFee;
494
507
  declare const order_scropePrice: typeof scropePrice;
495
508
  declare namespace order {
496
509
  export {
@@ -500,6 +513,7 @@ declare namespace order {
500
513
  order_estLiqPrice as estLiqPrice,
501
514
  order_maxPrice as maxPrice,
502
515
  order_minPrice as minPrice,
516
+ order_orderFee as orderFee,
503
517
  order_scropePrice as scropePrice,
504
518
  };
505
519
  }
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ declare global {
8
8
  };
9
9
  }
10
10
  }
11
- declare const _default: "2.0.5-rc.0";
11
+ declare const _default: "2.0.6";
12
12
 
13
13
  /**
14
14
  * Calculates the notional value of a single position.
@@ -168,18 +168,18 @@ type TotalValueInputs = {
168
168
  }[];
169
169
  };
170
170
  /**
171
- * 用戶總資產價值 (USDC計價),包含無法作為保證金的資產
171
+ * User's total asset value (denominated in USDC), including assets that cannot be used as collateral.
172
172
  */
173
173
  declare function totalValue(inputs: TotalValueInputs): Decimal;
174
174
  /**
175
- * 用戶帳戶當前可用保證金的價值總和 (USDC計價)
175
+ * Total value of available collateral in the user's account (denominated in USDC).
176
176
  */
177
177
  type FreeCollateralInputs = {
178
178
  totalCollateral: Decimal;
179
179
  totalInitialMarginWithOrders: number;
180
180
  };
181
181
  /**
182
- * 计算可用保证金
182
+ * Calculate free collateral.
183
183
  */
184
184
  declare function freeCollateral(inputs: FreeCollateralInputs): Decimal;
185
185
  type TotalCollateralValueInputs = {
@@ -192,7 +192,7 @@ type TotalCollateralValueInputs = {
192
192
  unsettlementPnL: number;
193
193
  };
194
194
  /**
195
- * 计算总保证金
195
+ * Calculate total collateral.
196
196
  */
197
197
  declare function totalCollateral(inputs: TotalCollateralValueInputs): Decimal;
198
198
  declare function initialMarginWithOrder(): void;
@@ -201,7 +201,7 @@ type PositionNotionalWithOrderInputs = {
201
201
  positionQtyWithOrders: number;
202
202
  };
203
203
  /**
204
- * 單一 Symbol position / orders notional 加總
204
+ * Sum of notional value for a symbol's position and orders.
205
205
  */
206
206
  declare function positionNotionalWithOrder_by_symbol(inputs: PositionNotionalWithOrderInputs): Decimal;
207
207
  type PositionQtyWithOrderInputs = {
@@ -210,7 +210,7 @@ type PositionQtyWithOrderInputs = {
210
210
  sellOrdersQty: number;
211
211
  };
212
212
  /**
213
- * 單一 Symbol position / orders qty 加總
213
+ * Sum of position quantity and orders quantity for a symbol.
214
214
  */
215
215
  declare function positionQtyWithOrders_by_symbol(inputs: PositionQtyWithOrderInputs): number;
216
216
  type IMRInputs = {
@@ -222,18 +222,18 @@ type IMRInputs = {
222
222
  IMR_factor_power?: number;
223
223
  };
224
224
  /**
225
- * 單一 Symbol 初始保證金率
225
+ * Initial margin rate for a symbol.
226
226
  * Max(1 / Max Account Leverage, Base IMR i, IMR Factor i * Abs(Position Notional i + Order Notional i)^(4/5))
227
227
  */
228
228
  declare function IMR(inputs: IMRInputs): number;
229
229
  declare function buyOrdersFilter_by_symbol(orders: API.Order[], symbol: string): API.Order[];
230
230
  declare function sellOrdersFilter_by_symbol(orders: API.Order[], symbol: string): API.Order[];
231
231
  /**
232
- * 从仓位列表中获取指定symbol的仓位数量
232
+ * Get the quantity of a specified symbol from the list of positions.
233
233
  */
234
234
  declare function getQtyFromPositions(positions: API.Position[], symbol: string): number;
235
235
  /**
236
- * 从订单列表中获取指定symbol的看多,看空订单数量,
236
+ * Get the quantity of long and short orders for a specified symbol from the list of orders.
237
237
  */
238
238
  declare function getQtyFromOrdersBySide(orders: API.Order[], symbol: string, side: OrderSide): number;
239
239
  declare function getPositonsAndOrdersNotionalBySymbol(inputs: {
@@ -254,11 +254,11 @@ type TotalInitialMarginWithOrdersInputs = {
254
254
  };
255
255
  } & Pick<IMRInputs, "maxLeverage">;
256
256
  /**
257
- * 计算用戶已使用初始保證金加總 ( 包含 position / orders )
257
+ * Calculate the total initial margin used by the user (including positions and orders).
258
258
  */
259
259
  declare function totalInitialMarginWithOrders(inputs: TotalInitialMarginWithOrdersInputs): number;
260
260
  /**
261
- * 把订单按照symbol分组, 因为一个symbol可以有多个挂单
261
+ * Group orders by symbol, as a symbol can have multiple orders.
262
262
  */
263
263
  declare function groupOrdersBySymbol(orders: API.Order[]): {
264
264
  [key: string]: API.Order[];
@@ -283,14 +283,14 @@ type OtherIMsInputs = {
283
283
  };
284
284
  };
285
285
  /**
286
- * 除当前symbol外的其他symbol已占用的总保证金
286
+ * Total margin used by other symbols (except the current symbol).
287
287
  */
288
288
  declare function otherIMs(inputs: OtherIMsInputs): number;
289
289
  type MaxQtyInputs = {
290
290
  symbol: string;
291
291
  baseMaxQty: number;
292
292
  /**
293
- * 用户保证金总额(USDC 计价), 可以由 totalCollateral 计算得出
293
+ * Total collateral of the user (denominated in USDC), can be calculated from totalCollateral.
294
294
  * @see totalCollateral
295
295
  */
296
296
  totalCollateral: number;
@@ -308,7 +308,7 @@ type MaxQtyInputs = {
308
308
  takerFeeRate: number;
309
309
  };
310
310
  /**
311
- * 最大可下单数量
311
+ * Maximum order quantity.
312
312
  */
313
313
  declare function maxQty(side: OrderSide, inputs: MaxQtyInputs, options?: ResultOptions): number;
314
314
  declare function maxQtyByLong(inputs: Omit<MaxQtyInputs, "side">, options?: ResultOptions): number;
@@ -450,12 +450,24 @@ declare function minPrice(markprice: number, range: number): number;
450
450
  * @returns number
451
451
  */
452
452
  declare function scropePrice(price: number, scrope: number, side: "BUY" | "SELL"): number;
453
+ /**
454
+ * Calculate the order fee
455
+ */
456
+ declare function orderFee(inputs: {
457
+ /**
458
+ * Order quantity
459
+ */
460
+ qty: number;
461
+ price: number;
462
+ futuresTakeFeeRate: number;
463
+ }): number;
453
464
  type EstimatedLiquidationPriceInputs = {
454
465
  totalCollateral: number;
455
466
  markPrice: number;
456
467
  baseMMR: number;
457
468
  baseIMR: number;
458
469
  IMR_Factor: number;
470
+ orderFee: number;
459
471
  positions: Pick<API.PositionExt, "position_qty" | "mark_price" | "symbol" | "mmr">[];
460
472
  newOrder: {
461
473
  symbol: string;
@@ -491,6 +503,7 @@ declare const order_estLeverage: typeof estLeverage;
491
503
  declare const order_estLiqPrice: typeof estLiqPrice;
492
504
  declare const order_maxPrice: typeof maxPrice;
493
505
  declare const order_minPrice: typeof minPrice;
506
+ declare const order_orderFee: typeof orderFee;
494
507
  declare const order_scropePrice: typeof scropePrice;
495
508
  declare namespace order {
496
509
  export {
@@ -500,6 +513,7 @@ declare namespace order {
500
513
  order_estLiqPrice as estLiqPrice,
501
514
  order_maxPrice as maxPrice,
502
515
  order_minPrice as minPrice,
516
+ order_orderFee as orderFee,
503
517
  order_scropePrice as scropePrice,
504
518
  };
505
519
  }
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"] = "2.0.5-rc.0";
34
+ window.__ORDERLY_VERSION__["@orderly.network/perp"] = "2.0.6";
35
35
  }
36
- var version_default = "2.0.5-rc.0";
36
+ var version_default = "2.0.6";
37
37
 
38
38
  // src/positions.ts
39
39
  var positions_exports = {};
@@ -397,8 +397,10 @@ function maxQtyByLong(inputs, options) {
397
397
  return Math.min(baseMaxQty, factor_1);
398
398
  }
399
399
  const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).sub(
400
- new import_utils2.Decimal(positionQty).add(buyOrdersQty).div(new import_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(1))
401
- ).mul(0.995).toNumber();
400
+ new import_utils2.Decimal(positionQty).add(buyOrdersQty)
401
+ // .abs()
402
+ // .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))
403
+ ).div(new import_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
402
404
  return Math.min(baseMaxQty, factor_1, factor_2);
403
405
  } catch (error) {
404
406
  return 0;
@@ -422,13 +424,11 @@ function maxQtyByShort(inputs, options) {
422
424
  const totalCollateralDecimal = new import_utils2.Decimal(totalCollateral2);
423
425
  const factor_1 = totalCollateralDecimal.sub(otherIMs2).div(
424
426
  new import_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(Math.max(1 / maxLeverage, baseIMR))
425
- ).div(markPrice).mul(0.995).add(new import_utils2.Decimal(positionQty).add(sellOrdersQty)).toNumber();
427
+ ).div(markPrice).mul(0.995).add(positionQty).sub(sellOrdersQty).toNumber();
426
428
  if (positionQty === 0 && buyOrdersQty === 0) {
427
429
  return Math.min(baseMaxQty, factor_1);
428
430
  }
429
- const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(
430
- new import_utils2.Decimal(positionQty).add(sellOrdersQty).div(new import_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(1))
431
- ).mul(0.995).toNumber();
431
+ const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(positionQty).sub(sellOrdersQty).div(new import_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
432
432
  return Math.min(baseMaxQty, factor_1, factor_2);
433
433
  } catch (error) {
434
434
  return 0;
@@ -477,6 +477,7 @@ __export(order_exports, {
477
477
  estLiqPrice: () => estLiqPrice,
478
478
  maxPrice: () => maxPrice,
479
479
  minPrice: () => minPrice,
480
+ orderFee: () => orderFee,
480
481
  scropePrice: () => scropePrice
481
482
  });
482
483
  var import_utils3 = require("@orderly.network/utils");
@@ -492,6 +493,9 @@ function scropePrice(price, scrope, side) {
492
493
  }
493
494
  return price * (1 + scrope);
494
495
  }
496
+ function orderFee(inputs) {
497
+ return new import_utils3.Decimal(inputs.qty).mul(inputs.price).mul(inputs.futuresTakeFeeRate).toNumber();
498
+ }
495
499
  function estLiqPrice(inputs) {
496
500
  var _a;
497
501
  const {
@@ -501,6 +505,7 @@ function estLiqPrice(inputs) {
501
505
  markPrice,
502
506
  baseIMR,
503
507
  baseMMR,
508
+ orderFee: orderFee2,
504
509
  IMR_Factor
505
510
  } = inputs;
506
511
  let currentPosition = void 0;
@@ -515,6 +520,9 @@ function estLiqPrice(inputs) {
515
520
  }
516
521
  newTotalMM = newTotalMM.add(notional2.abs().mul(position.mmr));
517
522
  }
523
+ if (!currentPosition) {
524
+ newTotalMM = newTotalMM.add(newOrderNotional.mul(baseMMR));
525
+ }
518
526
  const newMMR = Math.max(
519
527
  baseMMR,
520
528
  new import_utils3.Decimal(baseMMR).div(baseIMR).mul(IMR_Factor).mul(
@@ -532,7 +540,7 @@ function estLiqPrice(inputs) {
532
540
  return 0;
533
541
  }
534
542
  const price = new import_utils3.Decimal(markPrice).add(
535
- new import_utils3.Decimal(totalCollateral2).sub(newTotalMM).div(newQty.abs().mul(newMMR).sub(newQty))
543
+ new import_utils3.Decimal(totalCollateral2).sub(newTotalMM).sub(orderFee2).div(newQty.abs().mul(newMMR).sub(newQty))
536
544
  ).toNumber();
537
545
  return Math.max(0, price);
538
546
  }
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\"] = \"2.0.5-rc.0\";\n};\n\nexport default \"2.0.5-rc.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 */\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(Math.abs(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 */\nexport function liqPrice(inputs: LiqPriceInputs): number | null {\n const { markPrice, totalCollateral, positions, positionQty, MMR } = inputs;\n\n // console.log(\"inputs\", inputs);\n\n if (positionQty === 0 || totalCollateral === 0) {\n return null;\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 */\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 */\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.pow(Math.abs(positionNotional), IMR_factor_power))\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 */\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 */\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 */\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 */\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 * 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 */\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 * 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 */\nexport function maxPrice(markprice: number, range: number) {\n return markprice * (1 + range);\n}\n\n/**\n * Minimum price when placing an order\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"]}
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.6\";\n};\n\nexport default \"2.0.6\";\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 */\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(Math.abs(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 */\nexport function liqPrice(inputs: LiqPriceInputs): number | null {\n const { markPrice, totalCollateral, positions, positionQty, MMR } = inputs;\n\n // console.log(\"inputs\", inputs);\n\n if (positionQty === 0 || totalCollateral === 0) {\n return null;\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 */\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 */\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.pow(Math.abs(positionNotional), IMR_factor_power))\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 //Margin replacement rate, currently default to 0\n discount: number;\n }[];\n};\n/**\n * User's total asset value (denominated in USDC), including assets that cannot be used as collateral.\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 * Total value of available collateral in the user's account (denominated in USDC).\n */\nexport type FreeCollateralInputs = {\n // Total collateral\n totalCollateral: Decimal;\n // Total initial margin with orders\n totalInitialMarginWithOrders: number;\n};\n/**\n * Calculate free collateral.\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 // Quantity of USDC holdings\n USDCHolding: number;\n nonUSDCHolding: {\n holding: number;\n markPrice: number;\n // Margin replacement rate, currently default to 0\n discount: number;\n }[];\n // Unsettled profit and loss\n unsettlementPnL: number;\n};\n/**\n * Calculate total collateral.\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 * Sum of notional value for a symbol's position and orders.\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 // Total quantity of buy orders for a symbol\n buyOrdersQty: number;\n // Total quantity of sell orders for a symbol\n sellOrdersQty: number;\n};\n/**\n * Sum of position quantity and orders quantity for a symbol.\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 * Initial margin rate for a 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 * Get the quantity of a specified symbol from the list of positions.\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 * Get the quantity of long and short orders for a specified symbol from the list of orders.\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 * Calculate the total initial margin used by the user (including positions and 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 * Group orders by symbol, as a symbol can have multiple orders.\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 // the position list for other symbols except the current symbol\n positions: API.Position[];\n // the order list for other symbols except the current 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 * Total margin used by other symbols (except the current 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 // Maximum quantity limit for opening a single position, /v1/public/info.base_max\n baseMaxQty: number;\n /**\n * Total collateral of the user (denominated in USDC), can be calculated from 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 // Quantity of open positions\n positionQty: number;\n // Quantity of long orders\n buyOrdersQty: number;\n // Quantity of short orders\n sellOrdersQty: number;\n\n IMR_Factor: number;\n\n takerFeeRate: number;\n};\n\n/**\n * Maximum order quantity.\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).add(buyOrdersQty)\n // .abs()\n // .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\n )\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\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 .add(positionQty)\n .sub(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 // )\n .add(positionQty)\n .sub(sellOrdersQty)\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\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 * 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 */\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 * 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 as orderUtils } 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 */\nexport function maxPrice(markprice: number, range: number) {\n return markprice * (1 + range);\n}\n\n/**\n * Minimum price when placing an order\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\n/**\n * Calculate the order fee\n */\nexport function orderFee(inputs: {\n /**\n * Order quantity\n */\n qty: number;\n price: number;\n futuresTakeFeeRate: number;\n}): number {\n return new Decimal(inputs.qty)\n .mul(inputs.price)\n .mul(inputs.futuresTakeFeeRate)\n .toNumber();\n}\n\nexport type EstimatedLiquidationPriceInputs = {\n totalCollateral: number;\n markPrice: number;\n baseMMR: number;\n baseIMR: number;\n IMR_Factor: number;\n orderFee: number;\n positions: Pick<\n orderUtils.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 orderFee,\n IMR_Factor,\n } = inputs;\n // opened positions for the symbol\n let currentPosition:\n | Pick<\n orderUtils.PositionExt,\n \"position_qty\" | \"mark_price\" | \"symbol\" | \"mmr\"\n >\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 // if no position\n if (!currentPosition) {\n newTotalMM = newTotalMM.add(newOrderNotional.mul(baseMMR));\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 .sub(orderFee)\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<\n orderUtils.PositionExt,\n \"position_qty\" | \"mark_price\" | \"symbol\"\n >[];\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","orderFee","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"] = "2.0.5-rc.0";
10
+ window.__ORDERLY_VERSION__["@orderly.network/perp"] = "2.0.6";
11
11
  }
12
- var version_default = "2.0.5-rc.0";
12
+ var version_default = "2.0.6";
13
13
 
14
14
  // src/positions.ts
15
15
  var positions_exports = {};
@@ -375,8 +375,10 @@ function maxQtyByLong(inputs, options) {
375
375
  return Math.min(baseMaxQty, factor_1);
376
376
  }
377
377
  const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).sub(
378
- new Decimal2(positionQty).add(buyOrdersQty).div(new Decimal2(takerFeeRate).mul(2).mul(1e-4).add(1))
379
- ).mul(0.995).toNumber();
378
+ new Decimal2(positionQty).add(buyOrdersQty)
379
+ // .abs()
380
+ // .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))
381
+ ).div(new Decimal2(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
380
382
  return Math.min(baseMaxQty, factor_1, factor_2);
381
383
  } catch (error) {
382
384
  return 0;
@@ -400,13 +402,11 @@ function maxQtyByShort(inputs, options) {
400
402
  const totalCollateralDecimal = new Decimal2(totalCollateral2);
401
403
  const factor_1 = totalCollateralDecimal.sub(otherIMs2).div(
402
404
  new Decimal2(takerFeeRate).mul(2).mul(1e-4).add(Math.max(1 / maxLeverage, baseIMR))
403
- ).div(markPrice).mul(0.995).add(new Decimal2(positionQty).add(sellOrdersQty)).toNumber();
405
+ ).div(markPrice).mul(0.995).add(positionQty).sub(sellOrdersQty).toNumber();
404
406
  if (positionQty === 0 && buyOrdersQty === 0) {
405
407
  return Math.min(baseMaxQty, factor_1);
406
408
  }
407
- const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(
408
- new Decimal2(positionQty).add(sellOrdersQty).div(new Decimal2(takerFeeRate).mul(2).mul(1e-4).add(1))
409
- ).mul(0.995).toNumber();
409
+ const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(positionQty).sub(sellOrdersQty).div(new Decimal2(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
410
410
  return Math.min(baseMaxQty, factor_1, factor_2);
411
411
  } catch (error) {
412
412
  return 0;
@@ -455,6 +455,7 @@ __export(order_exports, {
455
455
  estLiqPrice: () => estLiqPrice,
456
456
  maxPrice: () => maxPrice,
457
457
  minPrice: () => minPrice,
458
+ orderFee: () => orderFee,
458
459
  scropePrice: () => scropePrice
459
460
  });
460
461
  import { Decimal as Decimal3, zero as zero3 } from "@orderly.network/utils";
@@ -470,6 +471,9 @@ function scropePrice(price, scrope, side) {
470
471
  }
471
472
  return price * (1 + scrope);
472
473
  }
474
+ function orderFee(inputs) {
475
+ return new Decimal3(inputs.qty).mul(inputs.price).mul(inputs.futuresTakeFeeRate).toNumber();
476
+ }
473
477
  function estLiqPrice(inputs) {
474
478
  var _a;
475
479
  const {
@@ -479,6 +483,7 @@ function estLiqPrice(inputs) {
479
483
  markPrice,
480
484
  baseIMR,
481
485
  baseMMR,
486
+ orderFee: orderFee2,
482
487
  IMR_Factor
483
488
  } = inputs;
484
489
  let currentPosition = void 0;
@@ -493,6 +498,9 @@ function estLiqPrice(inputs) {
493
498
  }
494
499
  newTotalMM = newTotalMM.add(notional2.abs().mul(position.mmr));
495
500
  }
501
+ if (!currentPosition) {
502
+ newTotalMM = newTotalMM.add(newOrderNotional.mul(baseMMR));
503
+ }
496
504
  const newMMR = Math.max(
497
505
  baseMMR,
498
506
  new Decimal3(baseMMR).div(baseIMR).mul(IMR_Factor).mul(
@@ -510,7 +518,7 @@ function estLiqPrice(inputs) {
510
518
  return 0;
511
519
  }
512
520
  const price = new Decimal3(markPrice).add(
513
- new Decimal3(totalCollateral2).sub(newTotalMM).div(newQty.abs().mul(newMMR).sub(newQty))
521
+ new Decimal3(totalCollateral2).sub(newTotalMM).sub(orderFee2).div(newQty.abs().mul(newMMR).sub(newQty))
514
522
  ).toNumber();
515
523
  return Math.max(0, price);
516
524
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/positions.ts","../src/constants.ts","../src/account.ts","../src/order.ts"],"sourcesContent":["\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.5-rc.0\";\n};\n\nexport default \"2.0.5-rc.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 */\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(Math.abs(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 */\nexport function liqPrice(inputs: LiqPriceInputs): number | null {\n const { markPrice, totalCollateral, positions, positionQty, MMR } = inputs;\n\n // console.log(\"inputs\", inputs);\n\n if (positionQty === 0 || totalCollateral === 0) {\n return null;\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 */\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 */\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.pow(Math.abs(positionNotional), IMR_factor_power))\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 */\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 */\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 */\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 */\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 * 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 */\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 * 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 */\nexport function maxPrice(markprice: number, range: number) {\n return markprice * (1 + range);\n}\n\n/**\n * Minimum price when placing an order\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","Decimal","zero","totalUnsettlementPnL","Decimal","zero","totalCollateral","otherIMs","totalUnrealizedPnL","totalValue","totalMarginRatio","unsettlementPnL","MMR","Decimal","zero","totalCollateral","notional","totalMarginRatio"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/positions.ts","../src/constants.ts","../src/account.ts","../src/order.ts"],"sourcesContent":["\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.6\";\n};\n\nexport default \"2.0.6\";\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 */\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(Math.abs(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 */\nexport function liqPrice(inputs: LiqPriceInputs): number | null {\n const { markPrice, totalCollateral, positions, positionQty, MMR } = inputs;\n\n // console.log(\"inputs\", inputs);\n\n if (positionQty === 0 || totalCollateral === 0) {\n return null;\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 */\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 */\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.pow(Math.abs(positionNotional), IMR_factor_power))\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 //Margin replacement rate, currently default to 0\n discount: number;\n }[];\n};\n/**\n * User's total asset value (denominated in USDC), including assets that cannot be used as collateral.\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 * Total value of available collateral in the user's account (denominated in USDC).\n */\nexport type FreeCollateralInputs = {\n // Total collateral\n totalCollateral: Decimal;\n // Total initial margin with orders\n totalInitialMarginWithOrders: number;\n};\n/**\n * Calculate free collateral.\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 // Quantity of USDC holdings\n USDCHolding: number;\n nonUSDCHolding: {\n holding: number;\n markPrice: number;\n // Margin replacement rate, currently default to 0\n discount: number;\n }[];\n // Unsettled profit and loss\n unsettlementPnL: number;\n};\n/**\n * Calculate total collateral.\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 * Sum of notional value for a symbol's position and orders.\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 // Total quantity of buy orders for a symbol\n buyOrdersQty: number;\n // Total quantity of sell orders for a symbol\n sellOrdersQty: number;\n};\n/**\n * Sum of position quantity and orders quantity for a symbol.\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 * Initial margin rate for a 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 * Get the quantity of a specified symbol from the list of positions.\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 * Get the quantity of long and short orders for a specified symbol from the list of orders.\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 * Calculate the total initial margin used by the user (including positions and 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 * Group orders by symbol, as a symbol can have multiple orders.\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 // the position list for other symbols except the current symbol\n positions: API.Position[];\n // the order list for other symbols except the current 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 * Total margin used by other symbols (except the current 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 // Maximum quantity limit for opening a single position, /v1/public/info.base_max\n baseMaxQty: number;\n /**\n * Total collateral of the user (denominated in USDC), can be calculated from 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 // Quantity of open positions\n positionQty: number;\n // Quantity of long orders\n buyOrdersQty: number;\n // Quantity of short orders\n sellOrdersQty: number;\n\n IMR_Factor: number;\n\n takerFeeRate: number;\n};\n\n/**\n * Maximum order quantity.\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).add(buyOrdersQty)\n // .abs()\n // .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\n )\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\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 .add(positionQty)\n .sub(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 // )\n .add(positionQty)\n .sub(sellOrdersQty)\n .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))\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 * 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 */\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 * 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 as orderUtils } 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 */\nexport function maxPrice(markprice: number, range: number) {\n return markprice * (1 + range);\n}\n\n/**\n * Minimum price when placing an order\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\n/**\n * Calculate the order fee\n */\nexport function orderFee(inputs: {\n /**\n * Order quantity\n */\n qty: number;\n price: number;\n futuresTakeFeeRate: number;\n}): number {\n return new Decimal(inputs.qty)\n .mul(inputs.price)\n .mul(inputs.futuresTakeFeeRate)\n .toNumber();\n}\n\nexport type EstimatedLiquidationPriceInputs = {\n totalCollateral: number;\n markPrice: number;\n baseMMR: number;\n baseIMR: number;\n IMR_Factor: number;\n orderFee: number;\n positions: Pick<\n orderUtils.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 orderFee,\n IMR_Factor,\n } = inputs;\n // opened positions for the symbol\n let currentPosition:\n | Pick<\n orderUtils.PositionExt,\n \"position_qty\" | \"mark_price\" | \"symbol\" | \"mmr\"\n >\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 // if no position\n if (!currentPosition) {\n newTotalMM = newTotalMM.add(newOrderNotional.mul(baseMMR));\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 .sub(orderFee)\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<\n orderUtils.PositionExt,\n \"position_qty\" | \"mark_price\" | \"symbol\"\n >[];\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","Decimal","zero","totalUnsettlementPnL","Decimal","zero","totalCollateral","otherIMs","totalUnrealizedPnL","totalValue","totalMarginRatio","unsettlementPnL","MMR","Decimal","zero","totalCollateral","orderFee","notional","totalMarginRatio"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orderly.network/perp",
3
- "version": "2.0.5-rc.0",
3
+ "version": "2.0.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -8,7 +8,7 @@
8
8
  "author": "leo",
9
9
  "license": "ISC",
10
10
  "peerDependencies": {
11
- "@orderly.network/types": "0.2.5-rc.0"
11
+ "@orderly.network/types": "0.2.6"
12
12
  },
13
13
  "files": [
14
14
  "dist"
@@ -23,11 +23,11 @@
23
23
  "tsup": "^7.1.0",
24
24
  "typedoc": "^0.24.8",
25
25
  "typescript": "^5.1.6",
26
- "tsconfig": "0.1.5-rc.0"
26
+ "tsconfig": "0.1.6"
27
27
  },
28
28
  "dependencies": {
29
- "@orderly.network/utils": "0.1.5-rc.0",
30
- "@orderly.network/types": "0.2.5-rc.0"
29
+ "@orderly.network/types": "0.2.6",
30
+ "@orderly.network/utils": "0.1.6"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
@@ -36,6 +36,6 @@
36
36
  "dev": "tsup --watch --tsconfig tsconfig.build.json",
37
37
  "build": "tsup --tsconfig tsconfig.build.json",
38
38
  "doc": "typedoc --out docs src",
39
- "test": "echo \"Error: no test specified\" && exit 1"
39
+ "test": "jest"
40
40
  }
41
41
  }