@kodiak-finance/orderly-perp 4.7.4
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/README.md +1 -0
- package/dist/index.d.mts +599 -0
- package/dist/index.d.ts +599 -0
- package/dist/index.js +727 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +702 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
account: () => account_exports,
|
|
24
|
+
order: () => order_exports,
|
|
25
|
+
orderUtils: () => order_exports,
|
|
26
|
+
positions: () => positions_exports,
|
|
27
|
+
version: () => version_default
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(src_exports);
|
|
30
|
+
|
|
31
|
+
// src/version.ts
|
|
32
|
+
if (typeof window !== "undefined") {
|
|
33
|
+
window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
|
|
34
|
+
window.__ORDERLY_VERSION__["@kodiak-finance/orderly-perp"] = "4.7.4";
|
|
35
|
+
}
|
|
36
|
+
var version_default = "4.7.4";
|
|
37
|
+
|
|
38
|
+
// src/positions.ts
|
|
39
|
+
var positions_exports = {};
|
|
40
|
+
__export(positions_exports, {
|
|
41
|
+
MMR: () => MMR,
|
|
42
|
+
estOffsetForTP: () => estOffsetForTP,
|
|
43
|
+
estPnLForSL: () => estPnLForSL,
|
|
44
|
+
estPnLForTP: () => estPnLForTP,
|
|
45
|
+
estPriceForTP: () => estPriceForTP,
|
|
46
|
+
estPriceFromOffsetForTP: () => estPriceFromOffsetForTP,
|
|
47
|
+
liqPrice: () => liqPrice,
|
|
48
|
+
maintenanceMargin: () => maintenanceMargin,
|
|
49
|
+
maxPositionLeverage: () => maxPositionLeverage,
|
|
50
|
+
maxPositionNotional: () => maxPositionNotional,
|
|
51
|
+
notional: () => notional,
|
|
52
|
+
totalNotional: () => totalNotional,
|
|
53
|
+
totalUnrealizedPnL: () => totalUnrealizedPnL,
|
|
54
|
+
totalUnsettlementPnL: () => totalUnsettlementPnL,
|
|
55
|
+
unrealizedPnL: () => unrealizedPnL,
|
|
56
|
+
unrealizedPnLROI: () => unrealizedPnLROI,
|
|
57
|
+
unsettlementPnL: () => unsettlementPnL
|
|
58
|
+
});
|
|
59
|
+
var import_orderly_utils = require("@kodiak-finance/orderly-utils");
|
|
60
|
+
|
|
61
|
+
// src/constants.ts
|
|
62
|
+
var IMRFactorPower = 4 / 5;
|
|
63
|
+
|
|
64
|
+
// src/positions.ts
|
|
65
|
+
function notional(qty, mark_price) {
|
|
66
|
+
return new import_orderly_utils.Decimal(qty).mul(mark_price).abs().toNumber();
|
|
67
|
+
}
|
|
68
|
+
function totalNotional(positions) {
|
|
69
|
+
return positions.reduce((acc, cur) => {
|
|
70
|
+
return acc + notional(cur.position_qty, cur.mark_price);
|
|
71
|
+
}, 0);
|
|
72
|
+
}
|
|
73
|
+
function unrealizedPnL(inputs) {
|
|
74
|
+
return new import_orderly_utils.Decimal(inputs.qty).mul(inputs.markPrice - inputs.openPrice).toNumber();
|
|
75
|
+
}
|
|
76
|
+
function unrealizedPnLROI(inputs) {
|
|
77
|
+
const { openPrice, IMR: IMR2 } = inputs;
|
|
78
|
+
if (inputs.unrealizedPnL === 0 || inputs.positionQty === 0 || openPrice === 0 || IMR2 === 0)
|
|
79
|
+
return 0;
|
|
80
|
+
return new import_orderly_utils.Decimal(inputs.unrealizedPnL).div(new import_orderly_utils.Decimal(Math.abs(inputs.positionQty)).mul(openPrice).mul(IMR2)).toNumber();
|
|
81
|
+
}
|
|
82
|
+
function totalUnrealizedPnL(positions) {
|
|
83
|
+
return positions.reduce((acc, cur) => {
|
|
84
|
+
return acc + unrealizedPnL({
|
|
85
|
+
qty: cur.position_qty,
|
|
86
|
+
openPrice: cur.average_open_price,
|
|
87
|
+
markPrice: cur.mark_price
|
|
88
|
+
});
|
|
89
|
+
}, 0);
|
|
90
|
+
}
|
|
91
|
+
function liqPrice(inputs) {
|
|
92
|
+
const { markPrice, totalCollateral: totalCollateral2, positions, positionQty, MMR: MMR3 } = inputs;
|
|
93
|
+
if (positionQty === 0 || totalCollateral2 === 0) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const totalNotional2 = positions.reduce((acc, cur) => {
|
|
97
|
+
return acc.add(
|
|
98
|
+
new import_orderly_utils.Decimal(notional(cur.position_qty, cur.mark_price)).mul(cur.mmr)
|
|
99
|
+
);
|
|
100
|
+
}, import_orderly_utils.zero);
|
|
101
|
+
return Math.max(
|
|
102
|
+
new import_orderly_utils.Decimal(markPrice).add(
|
|
103
|
+
new import_orderly_utils.Decimal(totalCollateral2).sub(totalNotional2).div(new import_orderly_utils.Decimal(positionQty).abs().mul(MMR3).sub(positionQty))
|
|
104
|
+
).toNumber(),
|
|
105
|
+
0
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
function maintenanceMargin(inputs) {
|
|
109
|
+
const { positionQty, markPrice, MMR: MMR3 } = inputs;
|
|
110
|
+
return new import_orderly_utils.Decimal(positionQty).mul(markPrice).mul(MMR3).abs().toNumber();
|
|
111
|
+
}
|
|
112
|
+
function unsettlementPnL(inputs) {
|
|
113
|
+
const {
|
|
114
|
+
positionQty,
|
|
115
|
+
markPrice,
|
|
116
|
+
costPosition,
|
|
117
|
+
sumUnitaryFunding,
|
|
118
|
+
lastSumUnitaryFunding
|
|
119
|
+
} = inputs;
|
|
120
|
+
const qty = new import_orderly_utils.Decimal(positionQty);
|
|
121
|
+
return qty.mul(markPrice).sub(costPosition).sub(qty.mul(new import_orderly_utils.Decimal(sumUnitaryFunding).sub(lastSumUnitaryFunding))).toNumber();
|
|
122
|
+
}
|
|
123
|
+
function totalUnsettlementPnL(positions) {
|
|
124
|
+
if (!Array.isArray(positions) || positions.length === 0) {
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
return positions.reduce((acc, cur) => {
|
|
128
|
+
return acc + unsettlementPnL({
|
|
129
|
+
positionQty: cur.position_qty,
|
|
130
|
+
markPrice: cur.mark_price,
|
|
131
|
+
costPosition: cur.cost_position,
|
|
132
|
+
sumUnitaryFunding: cur.sum_unitary_funding,
|
|
133
|
+
lastSumUnitaryFunding: cur.last_sum_unitary_funding
|
|
134
|
+
});
|
|
135
|
+
}, 0);
|
|
136
|
+
}
|
|
137
|
+
function MMR(inputs) {
|
|
138
|
+
const {
|
|
139
|
+
baseMMR,
|
|
140
|
+
baseIMR,
|
|
141
|
+
IMRFactor,
|
|
142
|
+
positionNotional,
|
|
143
|
+
IMR_factor_power = IMRFactorPower
|
|
144
|
+
} = inputs;
|
|
145
|
+
return Math.max(
|
|
146
|
+
baseMMR,
|
|
147
|
+
new import_orderly_utils.Decimal(baseMMR).div(baseIMR).mul(IMRFactor).mul(Math.pow(Math.abs(positionNotional), IMR_factor_power)).toNumber()
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
function estPnLForTP(inputs) {
|
|
151
|
+
return new import_orderly_utils.Decimal(inputs.positionQty).mul(new import_orderly_utils.Decimal(inputs.price).sub(inputs.entryPrice)).toNumber();
|
|
152
|
+
}
|
|
153
|
+
function estPriceForTP(inputs) {
|
|
154
|
+
return new import_orderly_utils.Decimal(inputs.pnl).add(inputs.entryPrice).div(inputs.positionQty).toNumber();
|
|
155
|
+
}
|
|
156
|
+
function estOffsetForTP(inputs) {
|
|
157
|
+
return new import_orderly_utils.Decimal(inputs.price).div(inputs.entryPrice).toNumber();
|
|
158
|
+
}
|
|
159
|
+
function estPriceFromOffsetForTP(inputs) {
|
|
160
|
+
return new import_orderly_utils.Decimal(inputs.offset).add(inputs.entryPrice).toNumber();
|
|
161
|
+
}
|
|
162
|
+
function estPnLForSL(inputs) {
|
|
163
|
+
return 0;
|
|
164
|
+
}
|
|
165
|
+
function maxPositionNotional(inputs) {
|
|
166
|
+
const { leverage, IMRFactor } = inputs;
|
|
167
|
+
return new import_orderly_utils.Decimal(1).div(new import_orderly_utils.Decimal(leverage).mul(IMRFactor)).pow(1 / 0.8).toNumber();
|
|
168
|
+
}
|
|
169
|
+
function maxPositionLeverage(inputs) {
|
|
170
|
+
const { IMRFactor, notional: notional2 } = inputs;
|
|
171
|
+
return new import_orderly_utils.Decimal(1).div(new import_orderly_utils.Decimal(IMRFactor).mul(new import_orderly_utils.Decimal(notional2).pow(0.8))).toNumber();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/account.ts
|
|
175
|
+
var account_exports = {};
|
|
176
|
+
__export(account_exports, {
|
|
177
|
+
IMR: () => IMR,
|
|
178
|
+
LTV: () => LTV,
|
|
179
|
+
MMR: () => MMR2,
|
|
180
|
+
availableBalance: () => availableBalance,
|
|
181
|
+
buyOrdersFilter_by_symbol: () => buyOrdersFilter_by_symbol,
|
|
182
|
+
calcMinimumReceived: () => calcMinimumReceived,
|
|
183
|
+
collateralContribution: () => collateralContribution,
|
|
184
|
+
collateralRatio: () => collateralRatio,
|
|
185
|
+
currentLeverage: () => currentLeverage,
|
|
186
|
+
extractSymbols: () => extractSymbols,
|
|
187
|
+
freeCollateral: () => freeCollateral,
|
|
188
|
+
getPositonsAndOrdersNotionalBySymbol: () => getPositonsAndOrdersNotionalBySymbol,
|
|
189
|
+
getQtyFromOrdersBySide: () => getQtyFromOrdersBySide,
|
|
190
|
+
getQtyFromPositions: () => getQtyFromPositions,
|
|
191
|
+
groupOrdersBySymbol: () => groupOrdersBySymbol,
|
|
192
|
+
initialMarginWithOrder: () => initialMarginWithOrder,
|
|
193
|
+
maxLeverage: () => maxLeverage,
|
|
194
|
+
maxQty: () => maxQty,
|
|
195
|
+
maxQtyByLong: () => maxQtyByLong,
|
|
196
|
+
maxQtyByShort: () => maxQtyByShort,
|
|
197
|
+
maxWithdrawalOtherCollateral: () => maxWithdrawalOtherCollateral,
|
|
198
|
+
maxWithdrawalUSDC: () => maxWithdrawalUSDC,
|
|
199
|
+
otherIMs: () => otherIMs,
|
|
200
|
+
positionNotionalWithOrder_by_symbol: () => positionNotionalWithOrder_by_symbol,
|
|
201
|
+
positionQtyWithOrders_by_symbol: () => positionQtyWithOrders_by_symbol,
|
|
202
|
+
sellOrdersFilter_by_symbol: () => sellOrdersFilter_by_symbol,
|
|
203
|
+
totalCollateral: () => totalCollateral,
|
|
204
|
+
totalInitialMarginWithOrders: () => totalInitialMarginWithOrders,
|
|
205
|
+
totalInitialMarginWithQty: () => totalInitialMarginWithQty,
|
|
206
|
+
totalMarginRatio: () => totalMarginRatio,
|
|
207
|
+
totalUnrealizedROI: () => totalUnrealizedROI,
|
|
208
|
+
totalValue: () => totalValue
|
|
209
|
+
});
|
|
210
|
+
var import_orderly_types = require("@kodiak-finance/orderly-types");
|
|
211
|
+
var import_orderly_utils2 = require("@kodiak-finance/orderly-utils");
|
|
212
|
+
function totalValue(inputs) {
|
|
213
|
+
const { totalUnsettlementPnL: totalUnsettlementPnL2, USDCHolding, nonUSDCHolding } = inputs;
|
|
214
|
+
const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {
|
|
215
|
+
return new import_orderly_utils2.Decimal(cur.holding).mul(cur.indexPrice).add(acc);
|
|
216
|
+
}, import_orderly_utils2.zero);
|
|
217
|
+
return nonUSDCHoldingValue.add(USDCHolding).add(totalUnsettlementPnL2);
|
|
218
|
+
}
|
|
219
|
+
function freeCollateral(inputs) {
|
|
220
|
+
const value = inputs.totalCollateral.sub(inputs.totalInitialMarginWithOrders);
|
|
221
|
+
return value.isNegative() ? import_orderly_utils2.zero : value;
|
|
222
|
+
}
|
|
223
|
+
function totalCollateral(inputs) {
|
|
224
|
+
const { USDCHolding, nonUSDCHolding, unsettlementPnL: unsettlementPnL2 } = inputs;
|
|
225
|
+
const nonUSDCHoldingValue = nonUSDCHolding.reduce((acc, cur) => {
|
|
226
|
+
const finalHolding = Math.min(cur.holding, cur.collateralCap);
|
|
227
|
+
const value = new import_orderly_utils2.Decimal(finalHolding).mul(cur.collateralRatio).mul(cur.indexPrice);
|
|
228
|
+
return acc.add(value);
|
|
229
|
+
}, import_orderly_utils2.zero);
|
|
230
|
+
return new import_orderly_utils2.Decimal(USDCHolding).add(nonUSDCHoldingValue).add(unsettlementPnL2);
|
|
231
|
+
}
|
|
232
|
+
function initialMarginWithOrder() {
|
|
233
|
+
}
|
|
234
|
+
function positionNotionalWithOrder_by_symbol(inputs) {
|
|
235
|
+
return new import_orderly_utils2.Decimal(inputs.markPrice).mul(inputs.positionQtyWithOrders);
|
|
236
|
+
}
|
|
237
|
+
function positionQtyWithOrders_by_symbol(inputs) {
|
|
238
|
+
const { positionQty, buyOrdersQty, sellOrdersQty } = inputs;
|
|
239
|
+
const positionQtyDecimal = new import_orderly_utils2.Decimal(positionQty);
|
|
240
|
+
const qty = Math.max(
|
|
241
|
+
positionQtyDecimal.add(buyOrdersQty).abs().toNumber(),
|
|
242
|
+
positionQtyDecimal.sub(sellOrdersQty).abs().toNumber()
|
|
243
|
+
);
|
|
244
|
+
return qty;
|
|
245
|
+
}
|
|
246
|
+
function IMR(inputs) {
|
|
247
|
+
const {
|
|
248
|
+
maxLeverage: maxLeverage2,
|
|
249
|
+
baseIMR,
|
|
250
|
+
IMR_Factor,
|
|
251
|
+
positionNotional,
|
|
252
|
+
ordersNotional: orderNotional,
|
|
253
|
+
IMR_factor_power = IMRFactorPower
|
|
254
|
+
} = inputs;
|
|
255
|
+
return Math.max(
|
|
256
|
+
1 / maxLeverage2,
|
|
257
|
+
baseIMR,
|
|
258
|
+
new import_orderly_utils2.Decimal(IMR_Factor).mul(
|
|
259
|
+
new import_orderly_utils2.Decimal(positionNotional).add(orderNotional).abs().toPower(IMR_factor_power)
|
|
260
|
+
).toNumber()
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
function buyOrdersFilter_by_symbol(orders, symbol) {
|
|
264
|
+
return orders.filter(
|
|
265
|
+
(item) => item.symbol === symbol && item.side === import_orderly_types.OrderSide.BUY
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
function sellOrdersFilter_by_symbol(orders, symbol) {
|
|
269
|
+
return orders.filter(
|
|
270
|
+
(item) => item.symbol === symbol && item.side === import_orderly_types.OrderSide.SELL
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
function getQtyFromPositions(positions, symbol) {
|
|
274
|
+
if (!positions) {
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
277
|
+
const position = positions.find((item) => item.symbol === symbol);
|
|
278
|
+
return (position == null ? void 0 : position.position_qty) || 0;
|
|
279
|
+
}
|
|
280
|
+
function getQtyFromOrdersBySide(orders, symbol, side) {
|
|
281
|
+
const ordersBySide = side === import_orderly_types.OrderSide.SELL ? sellOrdersFilter_by_symbol(orders, symbol) : buyOrdersFilter_by_symbol(orders, symbol);
|
|
282
|
+
return ordersBySide.reduce((acc, cur) => {
|
|
283
|
+
return acc + cur.quantity;
|
|
284
|
+
}, 0);
|
|
285
|
+
}
|
|
286
|
+
function getPositonsAndOrdersNotionalBySymbol(inputs) {
|
|
287
|
+
const { positions, orders, symbol, markPrice } = inputs;
|
|
288
|
+
const positionQty = getQtyFromPositions(positions, symbol);
|
|
289
|
+
const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, import_orderly_types.OrderSide.BUY);
|
|
290
|
+
const sellOrdersQty = getQtyFromOrdersBySide(orders, symbol, import_orderly_types.OrderSide.SELL);
|
|
291
|
+
const markPriceDecimal = new import_orderly_utils2.Decimal(markPrice);
|
|
292
|
+
return markPriceDecimal.mul(positionQty).add(markPriceDecimal.mul(new import_orderly_utils2.Decimal(buyOrdersQty).add(sellOrdersQty))).abs().toNumber();
|
|
293
|
+
}
|
|
294
|
+
function totalInitialMarginWithOrders(inputs) {
|
|
295
|
+
const {
|
|
296
|
+
positions,
|
|
297
|
+
orders,
|
|
298
|
+
markPrices,
|
|
299
|
+
IMR_Factors,
|
|
300
|
+
maxLeverage: maxLeverage2,
|
|
301
|
+
symbolInfo
|
|
302
|
+
} = inputs;
|
|
303
|
+
const symbols = extractSymbols(positions, orders);
|
|
304
|
+
const total_initial_margin_with_orders = symbols.reduce((acc, cur) => {
|
|
305
|
+
const symbol = cur;
|
|
306
|
+
const positionQty = getQtyFromPositions(positions, symbol);
|
|
307
|
+
const buyOrdersQty = getQtyFromOrdersBySide(orders, symbol, import_orderly_types.OrderSide.BUY);
|
|
308
|
+
const sellOrdersQty = getQtyFromOrdersBySide(
|
|
309
|
+
orders,
|
|
310
|
+
symbol,
|
|
311
|
+
import_orderly_types.OrderSide.SELL
|
|
312
|
+
);
|
|
313
|
+
const markPrice = markPrices[symbol] || 0;
|
|
314
|
+
const positionQtyWithOrders = positionQtyWithOrders_by_symbol({
|
|
315
|
+
positionQty,
|
|
316
|
+
buyOrdersQty,
|
|
317
|
+
sellOrdersQty
|
|
318
|
+
});
|
|
319
|
+
const position_notional_with_orders = positionNotionalWithOrder_by_symbol({
|
|
320
|
+
markPrice,
|
|
321
|
+
positionQtyWithOrders
|
|
322
|
+
});
|
|
323
|
+
const markPriceDecimal = new import_orderly_utils2.Decimal(markPrice);
|
|
324
|
+
const imr = IMR({
|
|
325
|
+
positionNotional: markPriceDecimal.mul(positionQty).toNumber(),
|
|
326
|
+
ordersNotional: markPriceDecimal.mul(new import_orderly_utils2.Decimal(buyOrdersQty).add(sellOrdersQty)).toNumber(),
|
|
327
|
+
maxLeverage: maxLeverage2,
|
|
328
|
+
IMR_Factor: IMR_Factors[symbol],
|
|
329
|
+
baseIMR: symbolInfo[symbol]("base_imr", 0)
|
|
330
|
+
});
|
|
331
|
+
return position_notional_with_orders.mul(imr).add(acc).toNumber();
|
|
332
|
+
}, 0);
|
|
333
|
+
return total_initial_margin_with_orders;
|
|
334
|
+
}
|
|
335
|
+
function totalInitialMarginWithQty(inputs) {
|
|
336
|
+
const { positions, markPrices, IMR_Factors, symbolInfo } = inputs;
|
|
337
|
+
const symbols = positions.map((item) => item.symbol);
|
|
338
|
+
const total_initial_margin_with_orders = symbols.reduce((acc, cur) => {
|
|
339
|
+
var _a;
|
|
340
|
+
const symbol = cur;
|
|
341
|
+
const position = positions.find((item) => item.symbol === symbol);
|
|
342
|
+
const positionQty = (position == null ? void 0 : position.position_qty) || 0;
|
|
343
|
+
const buyOrdersQty = (position == null ? void 0 : position.pending_long_qty) || 0;
|
|
344
|
+
const sellOrdersQty = (position == null ? void 0 : position.pending_short_qty) || 0;
|
|
345
|
+
const markPrice = markPrices[symbol] || 0;
|
|
346
|
+
const positionQtyWithOrders = positionQtyWithOrders_by_symbol({
|
|
347
|
+
positionQty,
|
|
348
|
+
buyOrdersQty,
|
|
349
|
+
sellOrdersQty
|
|
350
|
+
});
|
|
351
|
+
const position_notional_with_orders = positionNotionalWithOrder_by_symbol({
|
|
352
|
+
markPrice,
|
|
353
|
+
positionQtyWithOrders
|
|
354
|
+
});
|
|
355
|
+
const markPriceDecimal = new import_orderly_utils2.Decimal(markPrice);
|
|
356
|
+
const imr = IMR({
|
|
357
|
+
positionNotional: markPriceDecimal.mul(positionQty).toNumber(),
|
|
358
|
+
ordersNotional: markPriceDecimal.mul(new import_orderly_utils2.Decimal(buyOrdersQty).add(sellOrdersQty)).toNumber(),
|
|
359
|
+
maxLeverage: maxLeverage({
|
|
360
|
+
symbolLeverage: (_a = position == null ? void 0 : position.leverage) != null ? _a : inputs.maxLeverage,
|
|
361
|
+
accountLeverage: inputs.maxLeverage
|
|
362
|
+
}),
|
|
363
|
+
IMR_Factor: IMR_Factors[symbol],
|
|
364
|
+
baseIMR: symbolInfo[symbol]("base_imr", 0)
|
|
365
|
+
});
|
|
366
|
+
return position_notional_with_orders.mul(imr).add(acc).toNumber();
|
|
367
|
+
}, 0);
|
|
368
|
+
return total_initial_margin_with_orders;
|
|
369
|
+
}
|
|
370
|
+
function groupOrdersBySymbol(orders) {
|
|
371
|
+
const symbols = {};
|
|
372
|
+
orders.forEach((item) => {
|
|
373
|
+
if (!symbols[item.symbol]) {
|
|
374
|
+
symbols[item.symbol] = [];
|
|
375
|
+
}
|
|
376
|
+
symbols[item.symbol].push(item);
|
|
377
|
+
});
|
|
378
|
+
return symbols;
|
|
379
|
+
}
|
|
380
|
+
function extractSymbols(positions, orders) {
|
|
381
|
+
const symbols = /* @__PURE__ */ new Set();
|
|
382
|
+
positions.forEach((item) => {
|
|
383
|
+
symbols.add(item.symbol);
|
|
384
|
+
});
|
|
385
|
+
orders.forEach((item) => {
|
|
386
|
+
symbols.add(item.symbol);
|
|
387
|
+
});
|
|
388
|
+
return Array.from(symbols);
|
|
389
|
+
}
|
|
390
|
+
function otherIMs(inputs) {
|
|
391
|
+
const {
|
|
392
|
+
// orders,
|
|
393
|
+
positions,
|
|
394
|
+
IMR_Factors,
|
|
395
|
+
symbolInfo,
|
|
396
|
+
markPrices
|
|
397
|
+
} = inputs;
|
|
398
|
+
const symbols = positions.map((item) => item.symbol);
|
|
399
|
+
return symbols.reduce((acc, cur) => {
|
|
400
|
+
const symbol = cur;
|
|
401
|
+
if (typeof markPrices[symbol] === "undefined") {
|
|
402
|
+
console.warn("markPrices[%s] is undefined", symbol);
|
|
403
|
+
return acc;
|
|
404
|
+
}
|
|
405
|
+
const markPriceDecimal = new import_orderly_utils2.Decimal(markPrices[symbol] || 0);
|
|
406
|
+
const position = positions.find((item) => item.symbol === symbol);
|
|
407
|
+
const positionQty = getQtyFromPositions(positions, symbol);
|
|
408
|
+
const positionNotional = markPriceDecimal.mul(positionQty).toNumber();
|
|
409
|
+
const buyOrdersQty = position.pending_long_qty;
|
|
410
|
+
const sellOrdersQty = position.pending_short_qty;
|
|
411
|
+
const ordersNotional = markPriceDecimal.mul(new import_orderly_utils2.Decimal(buyOrdersQty).add(sellOrdersQty)).toNumber();
|
|
412
|
+
const IMR_Factor = IMR_Factors[symbol];
|
|
413
|
+
if (!IMR_Factor) {
|
|
414
|
+
console.warn("IMR_Factor is not found:", symbol);
|
|
415
|
+
return acc;
|
|
416
|
+
}
|
|
417
|
+
const imr = IMR({
|
|
418
|
+
maxLeverage: maxLeverage({
|
|
419
|
+
symbolLeverage: position.leverage,
|
|
420
|
+
accountLeverage: inputs.maxLeverage
|
|
421
|
+
}),
|
|
422
|
+
IMR_Factor,
|
|
423
|
+
baseIMR: symbolInfo[symbol]("base_imr", 0),
|
|
424
|
+
positionNotional,
|
|
425
|
+
ordersNotional
|
|
426
|
+
});
|
|
427
|
+
const positionQtyWithOrders = positionQtyWithOrders_by_symbol({
|
|
428
|
+
positionQty,
|
|
429
|
+
buyOrdersQty,
|
|
430
|
+
sellOrdersQty
|
|
431
|
+
});
|
|
432
|
+
const positionNotionalWithOrders = positionNotionalWithOrder_by_symbol({
|
|
433
|
+
markPrice: markPrices[symbol] || 0,
|
|
434
|
+
positionQtyWithOrders
|
|
435
|
+
});
|
|
436
|
+
return acc.add(positionNotionalWithOrders.mul(imr));
|
|
437
|
+
}, import_orderly_utils2.zero).toNumber();
|
|
438
|
+
}
|
|
439
|
+
function maxQty(side, inputs, options) {
|
|
440
|
+
if (side === import_orderly_types.OrderSide.BUY) {
|
|
441
|
+
return maxQtyByLong(inputs);
|
|
442
|
+
}
|
|
443
|
+
return maxQtyByShort(inputs);
|
|
444
|
+
}
|
|
445
|
+
function maxQtyByLong(inputs, options) {
|
|
446
|
+
try {
|
|
447
|
+
const {
|
|
448
|
+
baseMaxQty,
|
|
449
|
+
totalCollateral: totalCollateral2,
|
|
450
|
+
otherIMs: otherIMs2,
|
|
451
|
+
maxLeverage: maxLeverage2,
|
|
452
|
+
baseIMR,
|
|
453
|
+
markPrice,
|
|
454
|
+
IMR_Factor,
|
|
455
|
+
positionQty,
|
|
456
|
+
buyOrdersQty,
|
|
457
|
+
takerFeeRate
|
|
458
|
+
} = inputs;
|
|
459
|
+
if (totalCollateral2 === 0) {
|
|
460
|
+
return 0;
|
|
461
|
+
}
|
|
462
|
+
const totalCollateralDecimal = new import_orderly_utils2.Decimal(totalCollateral2);
|
|
463
|
+
const factor_1 = totalCollateralDecimal.sub(otherIMs2).div(
|
|
464
|
+
new import_orderly_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(Math.max(1 / maxLeverage2, baseIMR))
|
|
465
|
+
).div(markPrice).mul(0.995).sub(new import_orderly_utils2.Decimal(positionQty).add(buyOrdersQty)).toNumber();
|
|
466
|
+
if (positionQty === 0 && buyOrdersQty === 0) {
|
|
467
|
+
return Math.min(baseMaxQty, factor_1);
|
|
468
|
+
}
|
|
469
|
+
const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).sub(
|
|
470
|
+
new import_orderly_utils2.Decimal(positionQty).add(buyOrdersQty)
|
|
471
|
+
// .abs()
|
|
472
|
+
// .div(new Decimal(takerFeeRate).mul(2).mul(0.0001).add(1))
|
|
473
|
+
).div(new import_orderly_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
|
|
474
|
+
return Math.min(baseMaxQty, factor_1, factor_2);
|
|
475
|
+
} catch (error) {
|
|
476
|
+
return 0;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function maxQtyByShort(inputs, options) {
|
|
480
|
+
try {
|
|
481
|
+
const {
|
|
482
|
+
baseMaxQty,
|
|
483
|
+
totalCollateral: totalCollateral2,
|
|
484
|
+
otherIMs: otherIMs2,
|
|
485
|
+
maxLeverage: maxLeverage2,
|
|
486
|
+
baseIMR,
|
|
487
|
+
markPrice,
|
|
488
|
+
IMR_Factor,
|
|
489
|
+
positionQty,
|
|
490
|
+
buyOrdersQty,
|
|
491
|
+
sellOrdersQty,
|
|
492
|
+
takerFeeRate
|
|
493
|
+
} = inputs;
|
|
494
|
+
const totalCollateralDecimal = new import_orderly_utils2.Decimal(totalCollateral2);
|
|
495
|
+
const factor_1 = totalCollateralDecimal.sub(otherIMs2).div(
|
|
496
|
+
new import_orderly_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(Math.max(1 / maxLeverage2, baseIMR))
|
|
497
|
+
).div(markPrice).mul(0.995).add(positionQty).sub(Math.abs(sellOrdersQty)).toNumber();
|
|
498
|
+
if (positionQty === 0 && sellOrdersQty === 0) {
|
|
499
|
+
return Math.min(baseMaxQty, factor_1);
|
|
500
|
+
}
|
|
501
|
+
const factor_2 = totalCollateralDecimal.sub(otherIMs2).div(IMR_Factor).toPower(1 / 1.8).div(markPrice).add(positionQty).sub(sellOrdersQty).div(new import_orderly_utils2.Decimal(takerFeeRate).mul(2).mul(1e-4).add(1)).mul(0.995).toNumber();
|
|
502
|
+
return Math.min(baseMaxQty, factor_1, factor_2);
|
|
503
|
+
} catch (error) {
|
|
504
|
+
return 0;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function totalMarginRatio(inputs, dp) {
|
|
508
|
+
const { totalCollateral: totalCollateral2, markPrices, positions } = inputs;
|
|
509
|
+
if (totalCollateral2 === 0) {
|
|
510
|
+
return 0;
|
|
511
|
+
}
|
|
512
|
+
const totalCollateralDecimal = new import_orderly_utils2.Decimal(totalCollateral2);
|
|
513
|
+
const totalPositionNotional = positions.reduce((acc, cur) => {
|
|
514
|
+
const markPrice = markPrices[cur.symbol] || 0;
|
|
515
|
+
return acc.add(new import_orderly_utils2.Decimal(cur.position_qty).mul(markPrice).abs());
|
|
516
|
+
}, import_orderly_utils2.zero);
|
|
517
|
+
if (totalPositionNotional.eq(import_orderly_utils2.zero)) {
|
|
518
|
+
return 0;
|
|
519
|
+
}
|
|
520
|
+
return totalCollateralDecimal.div(totalPositionNotional).toNumber();
|
|
521
|
+
}
|
|
522
|
+
function totalUnrealizedROI(inputs) {
|
|
523
|
+
const { totalUnrealizedPnL: totalUnrealizedPnL2, totalValue: totalValue2 } = inputs;
|
|
524
|
+
return new import_orderly_utils2.Decimal(totalUnrealizedPnL2).div(totalValue2 - totalUnrealizedPnL2).toNumber();
|
|
525
|
+
}
|
|
526
|
+
function currentLeverage(totalMarginRatio2) {
|
|
527
|
+
if (totalMarginRatio2 === 0) {
|
|
528
|
+
return 0;
|
|
529
|
+
}
|
|
530
|
+
return 1 / totalMarginRatio2;
|
|
531
|
+
}
|
|
532
|
+
function availableBalance(inputs) {
|
|
533
|
+
const { USDCHolding, unsettlementPnL: unsettlementPnL2 } = inputs;
|
|
534
|
+
return new import_orderly_utils2.Decimal(USDCHolding).add(unsettlementPnL2).toNumber();
|
|
535
|
+
}
|
|
536
|
+
function MMR2(inputs) {
|
|
537
|
+
if (inputs.positionsNotional === 0) {
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
if (inputs.positionsMMR === 0) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
return new import_orderly_utils2.Decimal(inputs.positionsMMR).div(inputs.positionsNotional).toNumber();
|
|
544
|
+
}
|
|
545
|
+
var collateralRatio = (params) => {
|
|
546
|
+
const {
|
|
547
|
+
baseWeight,
|
|
548
|
+
discountFactor,
|
|
549
|
+
collateralQty,
|
|
550
|
+
collateralCap,
|
|
551
|
+
indexPrice
|
|
552
|
+
} = params;
|
|
553
|
+
const cap = collateralCap === -1 ? collateralQty : collateralCap;
|
|
554
|
+
const K = new import_orderly_utils2.Decimal(1.2);
|
|
555
|
+
const DCF = new import_orderly_utils2.Decimal(discountFactor || 0);
|
|
556
|
+
const qty = new import_orderly_utils2.Decimal(Math.min(collateralQty, cap));
|
|
557
|
+
const notionalAbs = qty.mul(indexPrice).abs();
|
|
558
|
+
const dynamicWeight = DCF.mul(notionalAbs).toPower(IMRFactorPower);
|
|
559
|
+
const result = K.div(new import_orderly_utils2.Decimal(1).add(dynamicWeight));
|
|
560
|
+
return result.lt(baseWeight) ? result : new import_orderly_utils2.Decimal(baseWeight);
|
|
561
|
+
};
|
|
562
|
+
var collateralContribution = (params) => {
|
|
563
|
+
const { collateralQty, collateralCap, collateralRatio: collateralRatio2, indexPrice } = params;
|
|
564
|
+
const cap = collateralCap === -1 ? collateralQty : collateralCap;
|
|
565
|
+
return new import_orderly_utils2.Decimal(Math.min(collateralQty, cap)).mul(collateralRatio2).mul(indexPrice).toNumber();
|
|
566
|
+
};
|
|
567
|
+
var LTV = (params) => {
|
|
568
|
+
const { usdcBalance, upnl, assets } = params;
|
|
569
|
+
const usdcLoss = new import_orderly_utils2.Decimal(Math.min(usdcBalance, 0)).abs();
|
|
570
|
+
const upnlLoss = new import_orderly_utils2.Decimal(Math.min(upnl, 0)).abs();
|
|
571
|
+
const numerator = usdcLoss.add(upnlLoss);
|
|
572
|
+
const collateralSum = assets.reduce((acc, asset) => {
|
|
573
|
+
return acc.add(
|
|
574
|
+
new import_orderly_utils2.Decimal(Math.max(asset.qty, 0)).mul(new import_orderly_utils2.Decimal(asset.indexPrice)).mul(new import_orderly_utils2.Decimal(asset.weight))
|
|
575
|
+
);
|
|
576
|
+
}, import_orderly_utils2.zero);
|
|
577
|
+
const denominator = collateralSum.add(new import_orderly_utils2.Decimal(Math.max(upnl, 0)));
|
|
578
|
+
if (numerator.isZero() || denominator.isZero()) {
|
|
579
|
+
return 0;
|
|
580
|
+
}
|
|
581
|
+
return numerator.div(denominator).toNumber();
|
|
582
|
+
};
|
|
583
|
+
var maxWithdrawalUSDC = (inputs) => {
|
|
584
|
+
const { USDCBalance, freeCollateral: freeCollateral2, upnl } = inputs;
|
|
585
|
+
const value = Math.min(
|
|
586
|
+
new import_orderly_utils2.Decimal(USDCBalance).toNumber(),
|
|
587
|
+
new import_orderly_utils2.Decimal(freeCollateral2).sub(Math.max(upnl, 0)).toNumber()
|
|
588
|
+
);
|
|
589
|
+
return Math.max(0, value);
|
|
590
|
+
};
|
|
591
|
+
var maxWithdrawalOtherCollateral = (inputs) => {
|
|
592
|
+
const { USDCBalance, collateralQty, freeCollateral: freeCollateral2, indexPrice, weight } = inputs;
|
|
593
|
+
const usdcBalance = new import_orderly_utils2.Decimal(USDCBalance);
|
|
594
|
+
const denominator = usdcBalance.isNegative() ? new import_orderly_utils2.Decimal(indexPrice).mul(weight).mul(new import_orderly_utils2.Decimal(1).add(2e-3)) : new import_orderly_utils2.Decimal(indexPrice).mul(weight);
|
|
595
|
+
if (denominator.isZero()) {
|
|
596
|
+
return import_orderly_utils2.zero;
|
|
597
|
+
}
|
|
598
|
+
const qty = new import_orderly_utils2.Decimal(collateralQty);
|
|
599
|
+
const maxQtyByValue = new import_orderly_utils2.Decimal(freeCollateral2).div(denominator);
|
|
600
|
+
return maxQtyByValue.lt(qty) ? maxQtyByValue : qty;
|
|
601
|
+
};
|
|
602
|
+
var calcMinimumReceived = (inputs) => {
|
|
603
|
+
const { amount, slippage } = inputs;
|
|
604
|
+
const slippageRatio = new import_orderly_utils2.Decimal(slippage).div(100);
|
|
605
|
+
return new import_orderly_utils2.Decimal(amount).mul(new import_orderly_utils2.Decimal(1).minus(slippageRatio)).toNumber();
|
|
606
|
+
};
|
|
607
|
+
var maxLeverage = (inputs) => {
|
|
608
|
+
const { symbolLeverage, accountLeverage } = inputs;
|
|
609
|
+
return symbolLeverage != null ? symbolLeverage : 1;
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// src/order.ts
|
|
613
|
+
var order_exports = {};
|
|
614
|
+
__export(order_exports, {
|
|
615
|
+
estLeverage: () => estLeverage,
|
|
616
|
+
estLiqPrice: () => estLiqPrice,
|
|
617
|
+
maxPrice: () => maxPrice,
|
|
618
|
+
minPrice: () => minPrice,
|
|
619
|
+
orderFee: () => orderFee,
|
|
620
|
+
scopePrice: () => scopePrice
|
|
621
|
+
});
|
|
622
|
+
var import_orderly_utils3 = require("@kodiak-finance/orderly-utils");
|
|
623
|
+
function maxPrice(markprice, range) {
|
|
624
|
+
return markprice * (1 + range);
|
|
625
|
+
}
|
|
626
|
+
function minPrice(markprice, range) {
|
|
627
|
+
return markprice * (1 - range);
|
|
628
|
+
}
|
|
629
|
+
function scopePrice(price, scope, side) {
|
|
630
|
+
if (side === "BUY") {
|
|
631
|
+
return price * (1 - scope);
|
|
632
|
+
}
|
|
633
|
+
return price * (1 + scope);
|
|
634
|
+
}
|
|
635
|
+
function orderFee(inputs) {
|
|
636
|
+
return new import_orderly_utils3.Decimal(inputs.qty).mul(inputs.price).mul(inputs.futuresTakeFeeRate).toNumber();
|
|
637
|
+
}
|
|
638
|
+
function estLiqPrice(inputs) {
|
|
639
|
+
var _a;
|
|
640
|
+
const {
|
|
641
|
+
positions,
|
|
642
|
+
newOrder,
|
|
643
|
+
totalCollateral: totalCollateral2,
|
|
644
|
+
markPrice,
|
|
645
|
+
baseIMR,
|
|
646
|
+
baseMMR,
|
|
647
|
+
orderFee: orderFee2,
|
|
648
|
+
IMR_Factor
|
|
649
|
+
} = inputs;
|
|
650
|
+
let currentPosition = void 0;
|
|
651
|
+
let newTotalMM = import_orderly_utils3.zero;
|
|
652
|
+
const hasPosition = positions.filter((item) => item.position_qty > 0).length > 0;
|
|
653
|
+
const basePrice = hasPosition ? markPrice : newOrder.price;
|
|
654
|
+
const newOrderNotional = new import_orderly_utils3.Decimal(newOrder.qty).mul(newOrder.price);
|
|
655
|
+
for (let index = 0; index < positions.length; index++) {
|
|
656
|
+
const position = positions[index];
|
|
657
|
+
let notional2 = new import_orderly_utils3.Decimal(position.position_qty).mul(position.mark_price);
|
|
658
|
+
if (newOrder.symbol === position.symbol) {
|
|
659
|
+
currentPosition = position;
|
|
660
|
+
notional2 = notional2.add(newOrderNotional);
|
|
661
|
+
}
|
|
662
|
+
newTotalMM = newTotalMM.add(notional2.abs().mul(position.mmr));
|
|
663
|
+
}
|
|
664
|
+
if (!currentPosition) {
|
|
665
|
+
newTotalMM = newTotalMM.add(newOrderNotional.mul(baseMMR));
|
|
666
|
+
}
|
|
667
|
+
const newMMR = Math.max(
|
|
668
|
+
baseMMR,
|
|
669
|
+
new import_orderly_utils3.Decimal(baseMMR).div(baseIMR).mul(IMR_Factor).mul(
|
|
670
|
+
newOrderNotional.add(
|
|
671
|
+
!!currentPosition ? new import_orderly_utils3.Decimal(currentPosition.position_qty).mul(
|
|
672
|
+
currentPosition.mark_price
|
|
673
|
+
) : import_orderly_utils3.zero
|
|
674
|
+
).abs()
|
|
675
|
+
).toPower(4 / 5).toNumber()
|
|
676
|
+
);
|
|
677
|
+
const newQty = new import_orderly_utils3.Decimal(newOrder.qty).add(
|
|
678
|
+
(_a = currentPosition == null ? void 0 : currentPosition.position_qty) != null ? _a : 0
|
|
679
|
+
);
|
|
680
|
+
if (newQty.eq(0)) {
|
|
681
|
+
return 0;
|
|
682
|
+
}
|
|
683
|
+
const denominator = newQty.abs().mul(newMMR).sub(newQty);
|
|
684
|
+
if (denominator.eq(import_orderly_utils3.zero)) {
|
|
685
|
+
return 0;
|
|
686
|
+
}
|
|
687
|
+
const price = new import_orderly_utils3.Decimal(basePrice).add(
|
|
688
|
+
new import_orderly_utils3.Decimal(totalCollateral2).sub(newTotalMM).sub(orderFee2).div(denominator)
|
|
689
|
+
).toNumber();
|
|
690
|
+
return Math.max(0, price);
|
|
691
|
+
}
|
|
692
|
+
function estLeverage(inputs) {
|
|
693
|
+
const { totalCollateral: totalCollateral2, positions, newOrder } = inputs;
|
|
694
|
+
if (totalCollateral2 <= 0) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
let hasPosition = false;
|
|
698
|
+
let sumPositionNotional = positions.reduce((acc, cur) => {
|
|
699
|
+
let count = new import_orderly_utils3.Decimal(cur.position_qty).mul(cur.mark_price);
|
|
700
|
+
if (cur.symbol === newOrder.symbol) {
|
|
701
|
+
hasPosition = true;
|
|
702
|
+
count = count.add(new import_orderly_utils3.Decimal(newOrder.qty).mul(newOrder.price));
|
|
703
|
+
}
|
|
704
|
+
return acc.add(count.abs());
|
|
705
|
+
}, import_orderly_utils3.zero);
|
|
706
|
+
if (!hasPosition) {
|
|
707
|
+
sumPositionNotional = sumPositionNotional.add(
|
|
708
|
+
new import_orderly_utils3.Decimal(newOrder.qty).mul(newOrder.price).abs()
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
if (sumPositionNotional.eq(import_orderly_utils3.zero)) {
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
const totalMarginRatio2 = new import_orderly_utils3.Decimal(totalCollateral2).div(
|
|
715
|
+
sumPositionNotional
|
|
716
|
+
);
|
|
717
|
+
return new import_orderly_utils3.Decimal(1).div(totalMarginRatio2).toDecimalPlaces(2, import_orderly_utils3.Decimal.ROUND_HALF_EVEN).toNumber();
|
|
718
|
+
}
|
|
719
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
720
|
+
0 && (module.exports = {
|
|
721
|
+
account,
|
|
722
|
+
order,
|
|
723
|
+
orderUtils,
|
|
724
|
+
positions,
|
|
725
|
+
version
|
|
726
|
+
});
|
|
727
|
+
//# sourceMappingURL=index.js.map
|